Skip to content

Call sendAvailableCommandsUpdate after /clear and other command-surface-mutating events #657

@Seluj78

Description

@Seluj78

Note: Claude handled the investigation and prose via back-and-forth. Idea, decisions, and everything else are mine. — @Seluj78

Problem

sendAvailableCommandsUpdate(sessionId) is called in four places in acp-agent.js:

acp-agent.js:338  newSession
acp-agent.js:353  unstable_forkSession
acp-agent.js:361  resumeSession
acp-agent.js:370  loadSession

It is not called when the available command surface changes mid-session. Several common operations mutate the SDK's command list but leave the ACP client's cached availableCommands stale:

  • /clear — Clears the internal conversation; the next assistant turn runs in a fresh SDK session. Plugins / skills / MCP servers attached to the new internal session may differ from those at original newSession time.
  • /login / /logout — Changes auth state and (potentially) which commands are exposed (cost, gated capabilities).
  • Plugin install (out-of-band, via the SDK's plugin manifest reload).
  • Skill load (project-level skills picked up after newSession).
  • MCP server attach (mid-session config reload).

When any of these happen, ACP clients keep showing the stale slash palette until the user manually creates a new session. The user installs a new MCP server, runs /clear to start fresh on a task that needs it, and the slash palette in the client doesn't show the new MCP-exposed commands.

What we'd like

Call sendAvailableCommandsUpdate(sessionId) in every code path that mutates the SDK's command surface for an active session. Specifically:

/clear handler

Wherever the adapter recognises /clear completed (system message subtype, SDK callback, or wherever the clear boundary lands in the message stream): add a setTimeout(() => this.sendAvailableCommandsUpdate(sessionId), 0) matching the pattern at acp-agent.js:338.

/login / /logout

Same shape. After the auth state transition completes, push a fresh command list.

Plugin / skill / MCP reload paths

If the SDK exposes a "command surface changed" event (similar to how it surfaces compact_boundary), the adapter should subscribe and emit sendAvailableCommandsUpdate on each fire. If no such event exists, that's an SDK-side ask: at minimum, an internal callback the adapter can subscribe to.

Why this matters

Today, the only way to refresh the slash palette in an ACP client is to tear down the session and create a new one. That:

  • Loses the cached acp_session_id (so resume-on-restart breaks for that session).
  • Forces clients to UX-around "you have to reattach to see new commands."
  • Mismatches user mental model: "I just installed a thing, my client should see it."

The fix is a handful of one-line sendAvailableCommandsUpdate calls in existing handlers.

Concrete behavioral asks

  1. Identify each adapter-side handler that mutates getAvailableSlashCommands's output set. The two obvious ones are /clear and /login//logout. Plugin / skill / MCP mid-session reload depends on SDK plumbing.
  2. Call sendAvailableCommandsUpdate(sessionId) from each one.
  3. Document the contract in the adapter README: "available commands are refreshed on the following events" with the list.

Open question

Is there an SDK-side signal already exposed (similar to compact_boundary system message) that the adapter could subscribe to for "command surface changed"? If yes, prefer that over manual call-site instrumentation. If no, the per-handler approach is the right v1.

Context

Filed from the agent-of-empires side as the upstream half of njbrake/agent-of-empires#1101 (cockpit /clear UX gap). The aoe-side fix can clear its cached availableCommands defensively on /clear detection, but the population side is upstream-only: without sendAvailableCommandsUpdate firing, the cleared palette stays empty until a fresh session create.

Adapter source inspected at dist/acp-agent.js:331-372 (the four current sendAvailableCommandsUpdate call sites) and dist/acp-agent.js:1124,1796 (sendAvailableCommandsUpdate and getAvailableSlashCommands definitions).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions