github / github/copilot-sdk

`session.disconnect()` is cooperative; doesn't abort `sendAndWait` or close the transport

Đang mở
#1,273 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
enhancement
Ngôn ngữ chính
Java
Star
10.5k
Fork
1.5k
Merge trung bình
1 ngày 11 giờ
Pull request đã merge (30 ngày)
128

Mô tả

### Summary

`session.disconnect()` sends `session.destroy` over RPC and clears local handlers, but does not close the underlying `MessageConnection`. Any in-flight `sendAndWait()` continues to await events from the CLI for up to TCP-timeout duration. The method name implies abortive semantics; the behavior is cooperative signaling.

### Repro

```ts
const client = new CopilotClient();
await client.start();
const session = await client.createSession({ /* ... */ });

// Start a long-running call
const inflight = session.sendAndWait({ prompt: "Write a very long story..." });

// Try to abort after 5 seconds
setTimeout(async () => {
await session.disconnect();
console.log("disconnect() returned");
}, 5000);

// `inflight` does NOT reject after disconnect returns; it continues to
// pend for up to 30–90 minutes (until the CLI's natural completion or
// TCP timeout).
await inflight;
```

### Expected

`disconnect()` returns → underlying transport closed → in-flight `sendAndWait()` rejects with a clean `SessionAborted` (or similar) error → consumer can release resources immediately.

### Actual

`disconnect()` returns immediately but the JSON-RPC transport stays open. The in-flight `sendAndWait()` is unaffected and continues running until the CLI naturally returns or TCP times out (often 30+ minutes).

### Evidence (SDK source)

`nodejs/src/session.ts` (v0.3.0): `disconnect()` calls `sendRequest("session.destroy", { sessionId })` and clears local `eventHandlers`. No call to `connection.close()` or transport-level termination. `session.abort()` (same file, line ~1073) sends `session.abort` to cancel the current message at the CLI but also doesn't close the SDK-side transport.

### Workaround (consumer-side)

Layer an `AbortController` on the polling layer plus a "session result ignored" flag so the eventually-resolving `sendAndWait` doesn't pollute downstream state. ~50–100 LOC of scaffolding that every consumer with reliability requirements has to reinvent.

### Suggested fix (pick one)

- **Enhance `abort()`** to also reject in-flight `sendAndWait` with a clean `SessionAborted` error, preserving session validity for new messages. Suits "cancel and retry" consumers.
- **Add `session.disconnect({ force: true })`** (or `session.kill()`) that closes the underlying JSON-RPC connection immediately. Suits "tear down for good" consumers — the watchdog scenario above. Keep current cooperative `disconnect()` behavior as the default.

### Related

- #590 — "Long-running prompt suddenly hangs forever with no error or exception" — describes the symptom from the consumer side. The disconnect-doesn't-abort behavior is one mechanism that contributes to this symptom: even when the consumer notices the hang and tries to recover, `disconnect()` doesn't free the in-flight call cleanly.

### Environment

```
- SDK: @github/copilot-sdk@0.3.0
- CLI: @github/copilot@1.0.45
- Node: 22 LTS
- OS: Windows 11 (primary), macOS 14 (secondary)
- Model: claude-sonnet-4-6 (CLI default routing)
```

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.