[BUG]: extensions_reload and extensions_manage tools deadlock permanently when project has a joinSession() extension
- 主要語言
- Shell
- 星號
- 11.2k
- 分支
- 1.9k
- 平均合併
- 14 小時 16 分鐘
- 30 天內合併 PR
- 6
描述
### Describe the bug
Calling `extensions_reload` or `extensions_manage` tools in a session where a project-level extension (using `joinSession()` from `@github/copilot-sdk/extension`) is active results in a permanent hang that requires the user to manually cancel the tool call. The CLI never recovers from the hang — the tool call must be interrupted every time.
### Root cause analysis
The deadlock is caused by a circular IPC dependency during the reload sequence:
1. `extensions_reload` is invoked → the CLI main process **blocks synchronously**, waiting for the reload to complete.
2. The existing extension subprocess is terminated.
3. A new `extension_bootstrap.mjs` subprocess is spawned and loads the extension module.
4. The extension module calls `await joinSession()` at the top level — this sends a handshake message **back to the CLI main process** to register tools and establish the session.
5. The CLI main process **cannot respond** to the handshake because it is blocked in step 1.
6. → **Permanent deadlock**: parent waits for child, child waits for parent.
The same deadlock occurs with `extensions_manage` because it goes through the same extension management subsystem.
### Affected version
GitHub Copilot CLI `1.0.12`
### Steps to reproduce
1. Create a project-level extension in `.github/extensions/my-ext/extension.mjs` with a top-level `await joinSession(...)` call (standard SDK pattern from the documentation).
2. Start a Copilot CLI session in that project directory. The extension loads successfully.
3. In the session, call the `extensions_reload` tool (or `extensions_manage` with operation `list`/`inspect`).
4. Observe: the tool call **never returns**. The CLI is permanently unresponsive until the tool call is manually cancelled.
5. Repeat step 3 after cancelling — same result every time.
### Expected behavior
- `extensions_reload` should complete successfully and the extension should be re-registered.
- If the reload mechanism requires a subprocess handshake, the main process should handle IPC messages asynchronously (non-blocking) during the reload wait, so the new extension subprocess can complete its `joinSession()` registration.
### Additional context
**Environment:**
- OS: Linux (Ubuntu)
- Copilot CLI version: `1.0.12`
- Extension type: project-level (`.github/extensions/`), JS/ESM, using `@github/copilot-sdk/extension`
**Workaround:**
- Skills and agent `.md` files are effective immediately on save (no reload needed).
- For changes to `extension.mjs` JS code: close the terminal and re-open a new session.
**Process evidence** (at time of hang):
```
# Two extension_bootstrap.mjs subprocesses observed — both blocked
PID 230448 EXTENSION_PATH=.github/extensions/my-ext/extension.mjs COPILOT_LOADER_PID=230374
PID 245405 EXTENSION_PATH=.github/extensions/my-ext/extension.mjs COPILOT_LOADER_PID=210913
# stdin/stdout of each subprocess are sockets (IPC channels), confirming the
# joinSession() handshake is attempted but the parent is not reading from them.
fd 0 -> socket:[...]
fd 1 -> socket:[...]
```
貢獻指南
評估
這個 Issue 還沒有評估資料。