github / github/copilot-sdk

Feature request: Plumb AbortSignal through ToolInvocation so session.abort() can cancel in-flight tool handlers

Abierto
#1,433 1 comentario 0 reacciones 0 asignados Ver en GitHub
enhancement
Lenguaje dominante
Java
Estrellas
10.5k
Forks
1.5k
Merge medio
1 d 11 h
PR fusionados (30 d)
128

Descripción

# Feature request: Plumb AbortSignal through ToolInvocation so session.abort() can cancel in-flight tool handlers

## Summary

`session.abort()` cancels the agentic loop (no further tool calls scheduled) but does not propagate cancellation into a currently-executing tool handler. The handler runs to completion regardless. This forces SDK consumers building wedge-recovery to implement OS-level process tree kills at their own layer, when the cooperative cancellation primitive could live in the SDK.

## Verified state at `@github/copilot-sdk` (`dist/`)

**1. `ToolInvocation` interface (`types.d.ts:224-233`):**
```ts
export interface ToolInvocation {
sessionId: string;
toolCallId: string;
toolName: string;
arguments: unknown;
/** W3C Trace Context traceparent from the CLI's execute_tool span. */
traceparent?: string;
/** W3C Trace Context tracestate from the CLI's execute_tool span. */
tracestate?: string;
}
```
No `signal`, no `abortSignal`, no cancellation handle.

**2. `_executeToolAndRespond` (`session.js:278-309`):**
```ts
async _executeToolAndRespond(requestId, toolName, toolCallId, args, handler, traceparent, tracestate) {
try {
const rawResult = await handler(args, { sessionId, toolCallId, toolName, arguments: args, traceparent, tracestate });
...
} catch (error) { ... }
}
```
Handler is awaited synchronously; no signal threaded through; no race against an abort source.

**3. `session.abort()` (`session.js:765-769`):**
```ts
async abort() {
await this.connection.sendRequest("session.abort", { sessionId: this.sessionId });
}
```
JSDoc: "and can continue to be used for new messages" + "resolves when the abort request is **acknowledged**." Confirms scope is the agentic loop, not the handler.

**4. Searched `node_modules/@github/copilot-sdk/dist/` for `AbortSignal|AbortController|signal:|cancel\(|cancellation`:** zero matches.

## Proposed API

Add an optional `AbortSignal` to `ToolInvocation` that aborts when `session.abort()` (or a new `session.cancelToolCall(toolCallId)`) is called:

```ts
export interface ToolInvocation {
sessionId: string;
toolCallId: string;
toolName: string;
arguments: unknown;
/** Aborts when session.abort() or session.cancelToolCall(toolCallId) is invoked. */
signal: AbortSignal;
traceparent?: string;
tracestate?: string;
}
```

Optional addition: a more granular `session.cancelToolCall(toolCallId)` that cancels a specific in-flight handler without aborting the broader agentic loop.

## Why it matters

Without handler-level cancellation, consumers building wedge-recovery (long-running shell handlers, network calls, file I/O on large files) must:
1. Track child PIDs at handler-spawn or via shell tool event streams,
2. Issue OS-level kills (Windows `taskkill /F /T /PID`, POSIX `SIGKILL` fan-out across descendant tree),
3. Re-probe survivors with bounded wait,
4. Manage orphan-leak edge cases.

That's ~125 lines of code per consumer plus cross-platform paths. A cooperative `AbortSignal` in the SDK lets handlers self-terminate cleanly — `fetch(url, { signal })`, `await sleep(ms, { signal })`, `child_process.spawn(...).on(signal.aborted, kill)` — which is the well-trodden Node.js cancellation idiom.

## Backwards compatibility

`AbortSignal` is non-required for handlers that don't consume it (existing handlers continue to work). Handlers that opt in get cooperative cancellation; the SDK keeps its existing process-isolation guarantees.

## Concrete consumer evidence

Parley (multi-agent orchestration system built on `@github/copilot-sdk`) ships at present a 313-line wedge-kill primitive in our orchestrator (Windows `taskkill /F /T /PID` + POSIX SIGKILL fan-out + bounded post-kill verify + tracker reset) that exists specifically because `session.abort()` doesn't propagate. With this feature, that primitive would be ~30 lines of `if (signal.aborted) cleanup()` in the consumer's tool handlers.

## Workaround until landed

OS-level process tree kill via tracked child PIDs from tool start events, gated by a bounded post-kill verify. Functional but not durable. Issue tracks the durable layer.

## Affected versions

Verified against `@github/copilot-sdk` shipped in current Parley `node_modules` snapshot (May 2026). Please confirm whether the proposed API has been considered or is on the roadmap.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.