feat(setpath, use): autocomplete + tilde expansion#59
feat(setpath, use): autocomplete + tilde expansion#59danfranks wants to merge 1 commit intobevibing:mainfrom
Conversation
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
RoundTable02
left a comment
There was a problem hiding this comment.
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.
| const query = (focused.value || '').toLowerCase(); | ||
| const home = homedir(); | ||
|
|
||
| if (focused.name === 'path') { |
There was a problem hiding this comment.
[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.
| .slice(0, 25) | ||
| .map(p => ({ | ||
| name: p.replace(home, '~').slice(0, 100), | ||
| value: p |
There was a problem hiding this comment.
[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.
What this PR adds
Two UX wins that users hit on day one:
1.
/use aliasautocompleteThe
aliasfield 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 pathautocompleteThe
pathfield scans~/Projects/for git repos (one level deep) and offers them as choices. No more typing or recalling absolute paths from a phone.The
aliasfield on/setpathalso gets autocomplete: union of existing registered aliases + names derived from repo dir basenames (with theclient-prefix stripped, since that's a common convention).3. Tilde expansion in
/setpath pathDiscord passes raw strings into the bot — there's no shell in the middle to expand
~/foo. Today, a user typing~/Projects/scale-data-cloudgets that exact literal string stored indata.json, which then fails whenserveManagertries to spawnopencodeagainst a path that doesn't exist.This PR adds an
expandTilde()helper that resolves~,~/footo absolute homedir-prefixed paths insetpath.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:
/setpath path:~/Projects/scale-data-cloudsucceeded but later failed at execute time because~wasn't expanded./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
setAutocomplete(true)+ anautocomplete()handler. The bot'sinteractionHandler.tsalready dispatchesinteraction.isAutocomplete()tocommand.autocomplete, so no changes needed there.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.slice(0, 25)after filtering. Names are alsoslice(0, 100)per Discord's name-length cap.Tests
All 171 existing tests pass. Build is clean (
npm run build,npm test).Files