CL-6499: Fix /<agent> slash-command grammar regression, friendlier unknown-command message - #233
Merged
Merged
Conversation
…regression Covers CL-6499: /jimmy <text> should route to the agent named jimmy via the existing workflow-command plugin, an unknown command should name what IS available, and a plain message that merely starts with '/' (e.g. a path) must never be misread as a command attempt.
A message that merely starts with '/' — a path, a URL — used to be parsed as a command name (spaces-only split, no shape check) and answered with a raw 'Unknown command' error instead of posting normally. Command names are now constrained to the same [\w-]+ shape the composer's own slash popover already commits to. Also makes the unknown-command message name what commands ARE available (built-ins plus every invitable agent's own workflow command) instead of a bare error, since every invitable agent already gets a /<name> command for free via createWorkflowCommandPlugin — this is how '/jimmy hello' invokes Jimmy directly today, with no new command system needed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The owner asked for typing
/jimmyin workbench chat to invoke that agent directly, the same way@Jimmydoes. Turns out this mechanism already exists and is already wired up end-to-end — no new command system needed:packages/commandsalready has a generic/name argsand@name argsgrammar, a command registry, andcreateWorkflowCommandPlugin, which derives one command per tenant per invitable agent definition (never a hardcoded list — CL-6451/CL-6471 already built this).packages/chat/src/routes.ts'sdispatchWorkbenchCommandalready intercepts a leading/on an incoming message and dispatches through that registry.startWorkflowCommand/forcedRecipientAddressinpackages/chat/src/workbench-service.tsalready routes a command to a resident agent's existing run, or invites+launches it./straight through as a message when it doesn't match one of the composer's own fixed UI commands (/invite,/summarize,/routine,/agents,/help) — so/jimmy hiwas already reaching the backend command intercept with no client change needed.So
/jimmy throw me a gif for shipping codealready worked today, as long as an agent namedjimmyis invitable in the tenant. This PR fixes two real gaps found while verifying that:packages/commands/src/grammar.ts'sparseWithPrefixonly split on the first space — it never validated the command-name shape. A plain message that merely starts with/(a filesystem path like/usr/local/bin, a URL) was parsed as a command name and, on no match, answered with a raw"Unknown command: /usr/local/bin"message that replaced the user's own text on the timeline. Command names are now constrained to[\w-]+— the same shape the composer's ownactiveSlashQueryalready commits to — so a path-shaped message now posts normally.dispatch.ts's unknown-command result used to be a bare"Unknown command: /nope". It now names what commands ARE available ("Unknown command: /nope. Available: /jimmy, /scout.", or a "no agent commands are available yet" message when the tenant has none) — never a silent no-op, never a raw error with no next step.What I checked before building anything
packages/chat-ui/src/slash-commands.ts— the composer's own fixed UI-command catalog (invite/summarize/routine/agents/help). Confirmed it does NOT intercept unmatched/wordtext; that falls through to an ordinarysend().packages/chat/src/mentions.ts+workbench-service.ts'sforcedRecipientAddress— the hook the task suggested. Already exactly whatstartWorkflowCommanduses.packages/agent-directory— confirmed the command registry derives fromlistInvitableDefinitionsper tenant, not a hardcoded agent list.packages/commands— the actual command grammar/registry/dispatch package, already fully wired into the hub (apps/hub/src/index.tsregisterscreateWorkflowCommandPlugin).Discoverability/autocomplete: deferred, per the task's own escape hatch. The composer's slash popover only lists its fixed 5 UI commands today; wiring it to also list per-tenant agent commands (fetching
GET /commands, merging, handling arbitrary execution results client-side) is a larger change than this timebox allows. Working invocation already existed and is now regression-fixed; discovery is left as a follow-up.Tests (red then green, tests-first commit)
packages/commands/test/grammar.test.ts— path-shaped slash text (/usr/local/bin) parses toundefined; hyphenated names still parse.packages/commands/test/dispatch.test.ts— unknown command names available commands; path-shaped text never dispatches.packages/commands/test/workflow-commands.test.ts—/jimmy <text>routes to the definition namedjimmywith the remainder asargs(proves the agent-directory-derived, non-hardcoded path).packages/chat/test/commands.test.ts— full route-level test:/jimmy throw me a gif for shipping code→workflow-startedforjimmy, mail delivered with that text; a path-shaped message posts normally and is never swallowed; unknown-command message updated.Verification (partial — see note)
Per an urgent note mid-task: the owner's machine OOM'd from concurrent lanes running full-monorepo
bun run check. I did not run repo-rootbun run checkor repo-root lint.Ran only, package-scoped, one at a time:
packages/commands:bun test→ 30 pass, 0 failpackages/chat:bun test→ 640 pass, 24 skip, 0 fail (full package suite, not just the touched file)Not run: repo-root typecheck, repo-root lint, full-workspace
bun run check. CI should cover these.