From 3d8bc655eb6f8d8ace7fd198113ef7a399f09289 Mon Sep 17 00:00:00 2001 From: agent_coder Date: Sat, 11 Jul 2026 05:34:46 +0300 Subject: [PATCH] =?UTF-8?q?docs(mcp):=20=D1=82=D0=BE=D1=87=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=20toolAbort?= =?UTF-8?q?Signal=20=E2=80=94=20set-and-leave,=20=D0=BD=D0=B5=20restore=20?= =?UTF-8?q?(#487,=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20nit)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Внутреннее ревью: docstring поля/метода toolAbortSignal утверждал «restores the prior value on unwind», но wrapInAppToolWithCap намеренно НЕ восстанавливает сигнал (set-and-leave) — именно это заставляет брошенного проигравшего race бросить на следующем safe-point; корректность держится на свежем клиенте на ход + перезаписи следующим вызовом. Комментарии приведены в соответствие с механизмом. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/mcp/src/client/context.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/mcp/src/client/context.ts b/packages/mcp/src/client/context.ts index 661e204a..a1fddf8a 100644 --- a/packages/mcp/src/client/context.ts +++ b/packages/mcp/src/client/context.ts @@ -171,8 +171,11 @@ export abstract class DocmostClientContext { // still land — a documented limitation (#487). // // SINGLE-WRITER by phase-1 assumption: exactly one DocmostClient is built per - // turn and shared by every tool call; the host sets this per call and restores - // the prior value when the call unwinds. If the model emits PARALLEL in-app + // turn and shared by every tool call; the host sets this per call and does NOT + // restore the prior value on unwind (set-and-leave) — a fresh client per turn + // plus overwrite-by-the-next-call keeps it correct, and leaving a settled + // call's signal in place is what makes a discarded race-loser throw on its + // next safe-point. If the model emits PARALLEL in-app // tool calls they share this one field, so the per-call CAP of one call is not // guaranteed to bound another's in-flight pagination — but every composite the // host sets carries the SAME turn Stop signal, so a Stop still aborts whichever @@ -182,9 +185,10 @@ export abstract class DocmostClientContext { /** * #487: set (or clear with null) the in-app tool abort signal governing the * NEXT client call's safe-points. The host wraps each in-app tool call: it sets - * the composite (Stop + per-call cap) here before invoking the tool and - * restores the prior value afterwards. Public so the server-side tool wrapper - * can reach it; harmless (a no-op) when never set. + * the composite (Stop + per-call cap) here before invoking the tool and leaves + * it in place afterwards (set-and-leave, NOT restored) — the next call + * overwrites it, and a fresh client is built per turn. Public so the + * server-side tool wrapper can reach it; harmless (a no-op) when never set. */ public setToolAbortSignal(signal: AbortSignal | null): void { this.toolAbortSignal = signal;