github / github/copilot-sdk

Extension command.execute can be accepted but never delivered, hanging slash-command invocation

Offen
#2,665 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
bug runtime runtime triage
Vorherrschende Sprache
Java
Sterne
10.5k
Forks
1.5k
Ø Merge
1 T. 11 Std.
Gemergte PRs (30 T.)
127

Beschreibung

> Drafted by GIthub Copilot with human review.

## Summary

An extension slash command can be recognized by Copilot CLI and dispatched as `command.execute`, yet never reach the owning extension handler. The invocation then hangs silently because the runtime waits indefinitely for `session.commands.handlePendingCommand` and no timeout or delivery error is surfaced.

This is exposed through the public extension SDK, but the captured failure occurs in runtime command-event routing before SDK handler entry. Please triage as a runtime-root-cause bug.

## Environment

- Copilot CLI: `1.0.84-8`
- OS: Windows 11
- Extension API: `@github/copilot-sdk/extension` via `joinSession({ commands: [...] })`
- Reproduced: September 15, 2026

## Reproduction

1. Load an extension that registers a slash command through `joinSession`, for example:

```js
await joinSession({
commands: [{
name: "bookmarks",
description: "Open the session bookmark manager",
handler: async () => {
// Instrument handler entry here.
},
}],
});
```

2. Reload extensions.
3. Confirm the extension reaches `=== ready ===` and can service another registered callback. In this reproduction, its canvas provider successfully handled rehydration.
4. Invoke `/bookmarks` interactively.

## Actual behavior

- CLI recognizes and invokes the registered slash command.
- Runtime emits `command.execute` event ID `537170aa-2e69-41b6-a37b-ad0e505ea166`.
- The detached host-delivery queue starts and reports successful completion.
- The owning extension never enters the command handler.
- No `command.completed` event is emitted.
- No `No client found for command` error is emitted.
- The invocation remains pending indefinitely without user-visible failure.

Relevant runtime timeline:

```text
2026-09-15T08:44:56.142Z slash_command_invoked
2026-09-15T08:44:56.143Z Detached host delivery started
delivery_kind="reserved_event"
event_type="command.execute"
event_id="537170aa-2e69-41b6-a37b-ad0e505ea166"
2026-09-15T08:44:56.146Z Detached host delivery completed
2026-09-15T08:44:56.146Z Detached host delivery retirement decision completed
```

Temporary instrumentation around command-handler entry, `session.rpc.canvas.open`, and the canvas provider confirmed that neither the command handler nor downstream canvas call was reached. The same extension process had successfully handled canvas-provider rehydration approximately 35 seconds earlier.

## Expected behavior

One of the following should happen deterministically:

1. `command.execute` reaches the registered owner, the handler runs, and `command.completed` resolves the invocation; or
2. Delivery failure/disconnection is detected and the pending invocation fails promptly with an actionable error.

A request-like control-plane event must not be considered successfully delivered merely because it was queued somewhere that may never drain.

## Suspected runtime area

Runtime source currently:

- resolves a targeted owner for `command.execute`;
- calls `publish_session_event` for that connection;
- treats an event queued in `post_response_notifications` behind a `gated_sessions` dispatch token as successfully published; and
- waits on the pending command response without a timeout.

This makes a stale or unreleased create/resume response gate one plausible mechanism: publication reports success, so no undelivered-command rejection occurs, but the owner never receives the event. The logs do not expose the connection ID or gate token, so this is a hypothesis rather than a proven precise race.

## Relationship to #2368

This appears to be a sibling or incomplete-fix path for #2368, not necessarily the identical implementation defect:

- #2368 concerned lost `external_tool.requested` events and SDK event-forwarder lag.
- This reproduction concerns targeted `command.execute` delivery after extension reload.
- Both turn a lost request-like event into an indefinite hang because no timeout or disconnect failure resolves the pending request.

## Requested fix

- Guarantee delivery or explicit rejection for targeted `command.execute` events.
- Do not treat indefinitely gated notifications as successful delivery.
- Add a bounded timeout/disconnection failure for pending command execution as defense in depth.
- Add a regression test covering extension reload/resume followed by immediate slash-command invocation.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Start at the runtime command-event routing path, especially targeted-owner resolution, publish_session_event, post_response_notifications, gated_sessions, and the pending command response wait. Trace the extension reload/resume flow and add the requested regression coverage for immediate slash-command invocation; done means command.execute reaches its owner and completes, or delivery failure resolves promptly with an actionable error.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
javascript
Bereich
backend-api-design, distributed-systems
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
38/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.