github / github/copilot-sdk

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

Offen
#1,273 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
enhancement
Vorherrschende Sprache
Java
Sterne
10.5k
Forks
1.5k
Ø Merge
1 T. 11 Std.
Gemergte PRs (30 T.)
128

Beschreibung

### 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)
```

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

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