github / github/copilot-sdk

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

未关闭
#2,665 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
bug runtime runtime triage
主要语言
Java
星标
10.5k
派生
1.5k
平均合并
1 天 14 小时
30 天内合并 PR
129

描述

> 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.

贡献指南

打开贡献指南

调研方向

从 runtime 命令事件路由路径开始,重点检查目标所有者解析、publish_session_event、post_response_notifications、gated_sessions 以及等待待处理命令响应的逻辑。跟踪扩展的重新加载/恢复流程,并为立即调用 slash 命令添加所要求的回归覆盖;完成的标准是 command.execute 到达其所有者并完成,或者传递失败能够及时通过一个可采取行动的错误得到解决。

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript
领域
backend-api-design, distributed-systems
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
38/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。