Skip to content

[Bug]: ACP Registry provider skills are missing from the / menu in a new thread until the first message is sent #26460

Closed as duplicate

Description

@bhaaratkrishnan

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Summary

With an ACP Registry provider selected, on a freshly started app the composer's / menu is empty for a brand-new thread in a project — every skill returns "No matching command." The skills only show up after the first message of the thread is sent.

Related issues (searched, but this looks distinct)

Steps to reproduce

  1. Fresh-launch T3 Code (quit the app first, then start it).

  2. Open a project, create a new thread.

  3. Select an ACP Registry provider (in my case the z-ai ACP harness, model "DeepSeek V4.1 Flash (latest)").

  4. In the composer, type /grill.

    → Menu shows "No matching command." No ACP skills are listed (also nothing under $).

  5. Send any first message (even just "Hi").

  6. Once the agent starts working, type /grill again in the composer.

    → Now all ACP skills appear: /grill-me, /grilling, /grill-with-docs, /loop-me, /git-guardrails-claude-code, /improve-codebase-architecture, /triage, ...

Expected behavior

The ACP provider's skills/commands should be available in the / menu as soon as a new thread opens, without requiring a first message.

Actual behavior

The command list is empty for the new thread until the first message is sent. After the session starts (first message), the skills appear and continue to work.

Impact

Low-to-medium: the agent runtime actually has the skills, and typing the full name of the command as the first message still works — it's mainly the composer menu that starts empty. But it makes skills undiscoverable right when starting a fresh thread, and users think their skills are broken (I did).

Version or commit

T3 Code 0.1.3 (Beta), Linux desktop build.

Environment

  • Pop!_OS 22.04 LTS (Linux)
  • T3 Code desktop 0.1.3 (Beta)
  • Connection: local
  • Provider: ACP Registry harness (z-ai), model "DeepSeek V4.1 Flash (latest)"

Logs or stack traces

None visible in the UI; happy to pull ~/.t3/userdata/logs spans if that helps pin down which probe/snapshot populates the composer list late.

Workaround

Send any first message (even "Hi") — skills load immediately afterwards. Alternatively type the full command name as the first message; the forward still works.

Activity

  1. juliusmarminge commented on Oct 28, 2026

    @juliusmarminge
    Member

    Tried to reproduce this on current main (eb751fa) and couldn't. Linux, web client against the dev server, fresh database, ACP Registry providers set up, server restarted, then a brand-new thread in a project:

    • Kilo (kilo, the opencode fork, via npx): typing /gril in a new draft lists /grill-me and /grilling before any message is sent.
    • pi ACP (pi-acp): / lists /model and the /skill:* entries before any message.
    • Talking to the agents directly over ACP (Kilo, pi-acp, GLM Agent, Claude Agent, OpenCode), each sends available_commands_update at the same moment it answers session/new. That is when T3 Code's startup probe reads the command list, so it gets the full list. The server's working directory (project, $HOME, or /) made no difference.

    T3 Code's startup probe waits only briefly after session/new for the command list. An agent that sends it later, or a probe that fails, would give exactly what you describe: an empty menu until the first message opens a real session. To tell which:

    1. Which agent is the "z-ai ACP harness"? Its ACP Registry id (Settings → Providers → the provider → Registry agent ID), or the local command if you added it with "Local ACP command".
    2. In Settings → Providers, what status does that provider show right after a fresh launch?
    3. If you wait about a minute after launch before typing /, does the menu fill in?
    4. From ~/.t3/userdata/logs, any lines from the minute after launch that mention AcpRegistryProbe, probe_failed, or that provider's instance id (e.g. acpRegistry_…).
  2. bhaaratkrishnan commented on Nov 3, 2026

    @bhaaratkrishnan
    Author

    Answers to your questions + span data from the session where I hit it:

    1. Which agent / Registry agent ID

    It's a Local ACP command, not a harvested registry entry: the harness is cmd acp (Command Code's own ACP harness, which advertises its bundled skills — hence /grill, /grilling, /grill-with-docs, …). Provider instance id: acpRegistry_command_code (display name "Command Code", driver acpRegistry, config.source: "local", commandPath: "cmd", commandArgs: ["acp"]).

    2. Provider status right after launch

    The probe reports Success — no failure. From ~/.t3/userdata/logs/server.trace.ndjson in the epoch of my repro:

    19:36:48.21 → 19:36:52.31  AcpRegistryDriver.checkProviderStatus   4097.5ms  Success
    19:36:48.21 → 19:36:52.31  AcpRegistryProbe.probeConfiguration    4097.5ms  Success
    19:39:00.05 → 19:39:03.12  AcpRegistryDriver.checkProviderStatus   3183.1ms  Success
    19:39:00.05 → 19:39:03.12  AcpRegistryProbe.probeConfiguration    3183.1ms  Success
    

    No probe_failed entries. (Will re-check what the Settings panel shows next fresh launch, but the server-side probe itself is healthy.)

    3. Does waiting ~1 minute fill the menu?

    No — the client kept polling refreshProviders well past the probe finishing and the menu stayed empty. Spans show this races exactly like the (closed/fixed for Claude) #11575: the workspace snapshot is stitched from the pending placeholder before the probe returns, and later refreshes early-exit, so nothing ever revisits it:

    19:36:48.21 AcpRegistryDriver.checkProviderStatus starts (4.1s probe)
    19:36:49.97 ws.rpc.server.refreshProviders → refreshWorkspaceSnapshot  0.18ms  ← snapshot taken while probe still in flight
    19:36:52.31 probe finishes with the full command list                ← nothing consumes this for the workspace
    19:37:41.99 refreshProviders → refreshWorkspaceSnapshot               0.04ms  ← early exit, snapshot already exists
    19:37:47.29 refreshProviders → refreshWorkspaceSnapshot               0.03ms  ← early exit
    19:38:36.38 refreshProviders → refreshWorkspaceSnapshot               0.03ms  ← early exit (2+ min after launch, still empty)
    19:39:00 (app restart) same pattern repeats: probe 19:39:00→03.2, snapshot 19:39:04.09, then early exits at 19:39:46 / 19:40:10 / 19:40:21
    19:41:51 — FIRST MESSAGE sent (ProviderTurnStartService.start); skills appear only now
    

    4. Log lines

    The AcpRegistryProbe spans are above; nothing matching probe_failed. The interesting event isn't a failure — it's that refreshWorkspaceSnapshot returns early whenever a snapshot for the cwd already exists (mirroring the mechanism described in #11575), and the probe takes 3–4s here (spawning cmd acp + ACP handshake), so the first workspace snapshot for the thread's project cwd always comes from the placeholder. The skills only reach the composer once the real session starts (first message) and the live available_commands_update from the session is consulted.

    So alongside your "agent sends available_commands_update later" possibility, there's a second one your repro wouldn't show: the local-command agent probes fine, but slower than the first workspace snapshot. Consistent with the #11575 suggested fix — keep snapshotting the workspace while the machine snapshot is still pending, and refresh existing workspace snapshots when the machine-level slashCommands change.

    Replied using CommandCode and T3Codes

  3. bhaaratkrishnan commented on Nov 4, 2026

    @bhaaratkrishnan
    Author

    Root cause confirmed — it's the server-cwd probe from #24375, and there's a fix up in #30668.

    What's happening: the ACP Registry driver probes available_commands with cwd: host.paths.cwd (the server process cwd) and implements no snapshotForCwd, so refreshWorkspaceSnapshot never stores per-project workspace snapshots. The composer falls back to the machine snapshot's command list, which was probed with the wrong cwd. Project-scoped commands are missing until the first message opens a real session — its available_commands_update (with the thread's real cwd) reaches the machine snapshot via watchAvailableCommands, which is exactly the "skills appear only after the first message" symptom.

    Verified with a direct ACP handshake against this harness (cmd acp, the "Command Code" provider — a Local ACP command, instance id acpRegistry_command_code, commandPath: cmd, commandArgs: ["acp"]):

    • project cwd (~/blueswype/thiranly/thiranly-monorepo) → 50 commands including /grill-me, /grilling, /grill-with-docs, /loop-me, /triage, …
    • $HOME or / (what the server-cwd probe effectively sees) → 12 built-ins only, none of the above

    That's also why the repro with Kilo/pi-acp doesn't show it: their commands are all global, so the server cwd makes no difference for them. The span data from my earlier comment fits: the probe succeeded (3–4s), but its result was probed with the wrong cwd, and no later snapshot revisit could fix it.

    Answers to the remaining questions:

    • Provider status right after fresh launch: "Available" — the probe itself is healthy and completes a few seconds after launch; it just probes the wrong cwd (span timeline in my previous comment).
    • Waiting a minute: doesn't help — the workspace snapshot for the cwd never exists for ACP providers (no snapshotForCwd), so there is nothing to revisit.

    Fix: #30668 adds snapshotForCwd to the ACP Registry driver (per-workspace probe with the requested cwd, 15-min per-cwd cache, bounded concurrency, cache cleared on logout/auth changes). With it, a brand-new thread lists all project skills before any message:

    Fresh thread shows project skills before any message

    Happy to split or reshape the change however you'd prefer (e.g. moving the per-cwd probe into the runtime coordinator instead of the driver).

  4. juliusmarminge commented on Nov 12, 2026

    @juliusmarminge
    Member

    This is the same problem as #24375, so I'm closing it in favour of that one. If it is different, say how and it will be reopened.

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

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