Skip to content

feat(setpath, use): autocomplete + tilde expansion#59

Open
danfranks wants to merge 1 commit intobevibing:mainfrom
danfranks:feat/setpath-use-autocomplete
Open

feat(setpath, use): autocomplete + tilde expansion#59
danfranks wants to merge 1 commit intobevibing:mainfrom
danfranks:feat/setpath-use-autocomplete

Conversation

@danfranks
Copy link
Copy Markdown

What this PR adds

Two UX wins that users hit on day one:

1. /use alias autocomplete

The alias field now opens a dropdown of all registered projects, formatted as <alias> → <path> with the home dir abbreviated to ~. Users can filter by typing partial alias or partial path.

Before: had to recall / type the alias from memory, error if wrong.
After: open the field, scroll, click.

2. /setpath path autocomplete

The path field scans ~/Projects/ for git repos (one level deep) and offers them as choices. No more typing or recalling absolute paths from a phone.

The alias field on /setpath also gets autocomplete: union of existing registered aliases + names derived from repo dir basenames (with the client- prefix stripped, since that's a common convention).

3. Tilde expansion in /setpath path

Discord passes raw strings into the bot — there's no shell in the middle to expand ~/foo. Today, a user typing ~/Projects/scale-data-cloud gets that exact literal string stored in data.json, which then fails when serveManager tries to spawn opencode against a path that doesn't exist.

This PR adds an expandTilde() helper that resolves ~, ~/foo to absolute homedir-prefixed paths in setpath.execute. Users can mix raw absolute paths and ~ paths interchangeably.

Why these specifically

I just wired the bot up locally, ran the README's example commands, and hit both gotchas in the first 60 seconds:

  1. /setpath path:~/Projects/scale-data-cloud succeeded but later failed at execute time because ~ wasn't expanded.
  2. /use alias: had no dropdown — required me to remember the exact alias I'd registered.

Both felt like the kind of thing that should "just work."

Implementation notes

  • Uses Discord.js's setAutocomplete(true) + an autocomplete() handler. The bot's interactionHandler.ts already dispatches interaction.isAutocomplete() to command.autocomplete, so no changes needed there.
  • Filesystem scan happens per-keystroke via readdirSync + existsSync. Cheap on local disk; would need rethinking if the bot ever ran headless on a different machine than the workspace, but the project's design already assumes co-location.
  • Discord caps autocomplete results at 25, so I slice(0, 25) after filtering. Names are also slice(0, 100) per Discord's name-length cap.

Tests

All 171 existing tests pass. Build is clean (npm run build, npm test).

Files

src/commands/use.ts     | +24 -1
src/commands/setpath.ts | +71 -7

Two UX improvements that users hit immediately after running
`remote-opencode setup`:

## /use alias autocomplete
The `alias` parameter now offers autocomplete sourced from
`dataStore.getProjects()`. Users see all registered projects in a
dropdown like:
  scale       →  ~/Projects/scale-data-cloud
  stout       →  ~/Projects/client-stouttent
Matches both the alias substring and the path substring, so users can
filter by either.

## /setpath path autocomplete
The `path` parameter now scans `~/Projects/` (one level deep) for
directories containing `.git/` and offers them as choices. No more
recalling/typing absolute paths from a phone.

The `alias` parameter on /setpath also gets autocomplete: existing
aliases plus suggestions derived from repo dir basenames (with the
`client-` prefix stripped, since multi-tenant repo names tend to
follow that convention).

## Tilde expansion in /setpath path
Discord passes raw strings to the bot — there's no shell to expand
`~/foo`, so paths typed by hand were stored literally and failed
later when serveManager tried to access them. Adds `expandTilde()`
that turns `~`, `~/foo` into proper homedir-prefixed paths.

## Tests
All 171 existing tests still pass. Build is clean.

## Files
- src/commands/use.ts: +24 -1
- src/commands/setpath.ts: +71 -7
Copy link
Copy Markdown
Collaborator

@RoundTable02 RoundTable02 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the autocomplete improvements. I found one authorization leak that should be fixed before merge, plus one Discord API limit issue that can make suggestions fail for long paths.

Comment thread src/commands/setpath.ts
const query = (focused.value || '').toLowerCase();
const home = homedir();

if (focused.name === 'path') {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] This autocomplete path now exposes local project metadata before the allowlist check runs. handleInteraction processes autocomplete interactions before isAuthorized, so an unauthorized user in a shared Discord server can type /setpath and receive scanned ~/Projects repo names/paths. Please gate autocomplete interactions with the same allowlist check and return an empty suggestion list for unauthorized users.

Comment thread src/commands/setpath.ts
.slice(0, 25)
.map(p => ({
name: p.replace(home, '~').slice(0, 100),
value: p
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] The displayed choice name is capped at 100 characters, but the autocomplete choice value is still the full absolute path. Discord also limits string choice values to 100 characters, so a long repo path can cause interaction.respond(matches) to reject and return no suggestions. Since execution now expands ~, consider using a tilde-relative value when possible and filtering out values that still exceed the limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants