zidane 5.3.0 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/{agent-CYpPKn5Z.d.ts → agent-BXRCCHeq.d.ts} +557 -5
- package/dist/agent-BXRCCHeq.d.ts.map +1 -0
- package/dist/chat.d.ts +310 -6
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/{errors-COmsomd5.js → errors-Byb0F8B9.js} +44 -2
- package/dist/errors-Byb0F8B9.js.map +1 -0
- package/dist/{index-D-cTScN3.d.ts → index-BPk8-Slm.d.ts} +81 -10
- package/dist/index-BPk8-Slm.d.ts.map +1 -0
- package/dist/{index-Cc-q1hLT.d.ts → index-CT5_p-3P.d.ts} +2 -2
- package/dist/{index-Cc-q1hLT.d.ts.map → index-CT5_p-3P.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +10 -10
- package/dist/{interpolate-BhmHKD6x.js → interpolate-ERgZUxgg.js} +2 -2
- package/dist/{interpolate-BhmHKD6x.js.map → interpolate-ERgZUxgg.js.map} +1 -1
- package/dist/{login-BXVt5wuA.js → login-DrBZ15G7.js} +3 -3
- package/dist/{login-BXVt5wuA.js.map → login-DrBZ15G7.js.map} +1 -1
- package/dist/{mcp-B1psg7jf.js → mcp-DhmmJfxK.js} +16 -3
- package/dist/mcp-DhmmJfxK.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-DsbMYNmt.js → messages-D0xT979U.js} +631 -68
- package/dist/messages-D0xT979U.js.map +1 -0
- package/dist/{presets-tvD28pCu.js → presets-0_IRJAYF.js} +29 -10
- package/dist/presets-0_IRJAYF.js.map +1 -0
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-v1Rn2rqG.js → providers-x3LZByR5.js} +38 -6
- package/dist/providers-x3LZByR5.js.map +1 -0
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +3 -3
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.js +1 -1
- package/dist/{session-DOJgRXvF.js → session-BHZwxmfr.js} +2 -2
- package/dist/{session-DOJgRXvF.js.map → session-BHZwxmfr.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{tools-CMVruxF0.js → tools-CCsL5SCO.js} +516 -140
- package/dist/tools-CCsL5SCO.js.map +1 -0
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +2 -2
- package/dist/{transcript-anchors-eyhlGeBI.d.ts → transcript-anchors-DSk8LlWt.d.ts} +28 -4
- package/dist/transcript-anchors-DSk8LlWt.d.ts.map +1 -0
- package/dist/tui.d.ts +29 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +365 -80
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-Y7e15gJf.js → turn-operations-CutZin8X.js} +678 -33
- package/dist/turn-operations-CutZin8X.js.map +1 -0
- package/dist/types-IcokUOyC.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/SKILL.md +23 -1
- package/package.json +1 -1
- package/dist/agent-CYpPKn5Z.d.ts.map +0 -1
- package/dist/errors-COmsomd5.js.map +0 -1
- package/dist/index-D-cTScN3.d.ts.map +0 -1
- package/dist/mcp-B1psg7jf.js.map +0 -1
- package/dist/messages-DsbMYNmt.js.map +0 -1
- package/dist/presets-tvD28pCu.js.map +0 -1
- package/dist/providers-v1Rn2rqG.js.map +0 -1
- package/dist/tools-CMVruxF0.js.map +0 -1
- package/dist/transcript-anchors-eyhlGeBI.d.ts.map +0 -1
- package/dist/turn-operations-Y7e15gJf.js.map +0 -1
|
@@ -14,7 +14,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
14
14
|
* unclassified errors in `AgentProviderError` automatically.
|
|
15
15
|
*/
|
|
16
16
|
/** Kind of classified provider error */
|
|
17
|
-
type ClassifiedErrorKind = 'context_exceeded' | 'provider_error' | 'aborted';
|
|
17
|
+
type ClassifiedErrorKind = 'context_exceeded' | 'provider_error' | 'aborted' | 'tool_pairing_corruption';
|
|
18
18
|
/** Structured classification returned by `Provider.classifyError` */
|
|
19
19
|
interface ClassifiedError {
|
|
20
20
|
kind: ClassifiedErrorKind;
|
|
@@ -75,6 +75,49 @@ declare class AgentAbortedError extends Error {
|
|
|
75
75
|
cause?: unknown;
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Thrown by the pre-send pairing repair when {@link AgentBehavior.strictToolPairing}
|
|
80
|
+
* is `true` and {@link ensureToolResultPairing} would otherwise patch over
|
|
81
|
+
* corruption. Strict mode opts into fail-fast for training-data collectors and
|
|
82
|
+
* any consumer that prefers to bail out rather than ship a transcript carrying
|
|
83
|
+
* a {@link SYNTHETIC_TOOL_RESULT_PLACEHOLDER}.
|
|
84
|
+
*
|
|
85
|
+
* The `repairs` field carries every repair the loop would have made — useful
|
|
86
|
+
* for postmortems and for surfacing exactly which transcripts were rejected.
|
|
87
|
+
*
|
|
88
|
+
* Note: callers consuming the chat layer (TUI/SDK presets) typically leave
|
|
89
|
+
* `strictToolPairing` off so user-facing sessions auto-heal instead of
|
|
90
|
+
* crashing.
|
|
91
|
+
*/
|
|
92
|
+
declare class AgentToolPairingError extends Error {
|
|
93
|
+
readonly code: "tool_pairing_corruption";
|
|
94
|
+
/** Provider whose wire format the corruption would have hit. */
|
|
95
|
+
readonly provider?: string;
|
|
96
|
+
/** Upstream error code when the corruption was detected from a 400 response. */
|
|
97
|
+
readonly providerCode?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Repairs the harness would have performed had strict mode been off.
|
|
100
|
+
* Preserves the full diagnostic so consumers can route to telemetry,
|
|
101
|
+
* `/rewind` flows, or training-data quarantine without re-walking the
|
|
102
|
+
* transcript.
|
|
103
|
+
*/
|
|
104
|
+
readonly repairs: ReadonlyArray<{
|
|
105
|
+
mode: string;
|
|
106
|
+
callId?: string;
|
|
107
|
+
messageIndex: number;
|
|
108
|
+
}>;
|
|
109
|
+
constructor(options: {
|
|
110
|
+
message: string;
|
|
111
|
+
provider?: string;
|
|
112
|
+
providerCode?: string;
|
|
113
|
+
repairs: ReadonlyArray<{
|
|
114
|
+
mode: string;
|
|
115
|
+
callId?: string;
|
|
116
|
+
messageIndex: number;
|
|
117
|
+
}>;
|
|
118
|
+
cause?: unknown;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
78
121
|
/**
|
|
79
122
|
* Thrown (well — constructed; attach via the `tool:gate` block signal) when the
|
|
80
123
|
* union of `allowed-tools` across active skills does not permit a tool call.
|
|
@@ -123,7 +166,7 @@ declare function errorMessage(err: unknown): string;
|
|
|
123
166
|
/**
|
|
124
167
|
* Convert a `ClassifiedError` + underlying cause into the matching typed error instance.
|
|
125
168
|
*/
|
|
126
|
-
declare function toTypedError(classification: ClassifiedError, provider: string, cause: unknown): AgentContextExceededError | AgentProviderError | AgentAbortedError;
|
|
169
|
+
declare function toTypedError(classification: ClassifiedError, provider: string, cause: unknown): AgentContextExceededError | AgentProviderError | AgentAbortedError | AgentToolPairingError;
|
|
127
170
|
//#endregion
|
|
128
171
|
//#region src/types.d.ts
|
|
129
172
|
/**
|
|
@@ -437,7 +480,7 @@ interface AgentBehavior {
|
|
|
437
480
|
*
|
|
438
481
|
* ```ts
|
|
439
482
|
* // Always cache by full input — every identical re-call dedups.
|
|
440
|
-
* dedupTools: {
|
|
483
|
+
* dedupTools: { my_pure_tool: input => JSON.stringify(input) }
|
|
441
484
|
*
|
|
442
485
|
* // Cache by a normalized subset; non-cacheable shapes opt out.
|
|
443
486
|
* dedupTools: {
|
|
@@ -655,6 +698,26 @@ interface AgentBehavior {
|
|
|
655
698
|
* Default: `undefined`.
|
|
656
699
|
*/
|
|
657
700
|
persistDir?: string;
|
|
701
|
+
/**
|
|
702
|
+
* Fail-fast instead of repair when the pre-send pairing pass detects
|
|
703
|
+
* corruption (orphan `tool_use` / `tool_result`, duplicate ids,
|
|
704
|
+
* compaction-stranded blocks). Throws {@link AgentToolPairingError} from
|
|
705
|
+
* the next `agent.run()` turn carrying the structured repair list the
|
|
706
|
+
* loop would have performed.
|
|
707
|
+
*
|
|
708
|
+
* Use case: training-data collectors that must reject any transcript
|
|
709
|
+
* containing the synthetic `SYNTHETIC_TOOL_RESULT_PLACEHOLDER` rather
|
|
710
|
+
* than ship poisoned data to the fine-tuning pipeline. User-facing chat
|
|
711
|
+
* sessions should leave this off (the repair-on-the-fly behavior is the
|
|
712
|
+
* point of the pass).
|
|
713
|
+
*
|
|
714
|
+
* Telemetry note: `pairing:repair` still fires for every repair before
|
|
715
|
+
* the throw, so observability handlers see exactly what would have
|
|
716
|
+
* happened.
|
|
717
|
+
*
|
|
718
|
+
* Default: `false`.
|
|
719
|
+
*/
|
|
720
|
+
strictToolPairing?: boolean;
|
|
658
721
|
}
|
|
659
722
|
/**
|
|
660
723
|
* One block of a multimodal user prompt.
|
|
@@ -1040,6 +1103,28 @@ interface ToolHookContext {
|
|
|
1040
1103
|
/** Aliased (wire) name — equal to `name` when no alias is defined. */
|
|
1041
1104
|
displayName: string;
|
|
1042
1105
|
input: Record<string, unknown>;
|
|
1106
|
+
/**
|
|
1107
|
+
* The run this tool call belongs to (the `SessionRun.id`). Lets a single
|
|
1108
|
+
* `tool:*` listener disambiguate calls across parallel runs / subagent
|
|
1109
|
+
* trees without subscribing to the `child:tool:*` bubble events.
|
|
1110
|
+
*/
|
|
1111
|
+
runId?: string;
|
|
1112
|
+
/**
|
|
1113
|
+
* Parent run id when this tool call's agent is a subagent — i.e. the
|
|
1114
|
+
* `SessionRun.parentRunId` of the run that owns the call. Absent on
|
|
1115
|
+
* top-level runs. Useful for observability stitching: a UI grouping
|
|
1116
|
+
* subagent-scoped state (e.g. todowrite, edit batches) by parent
|
|
1117
|
+
* run can read this directly off `tool:before` / `tool:after`
|
|
1118
|
+
* without resolving the run row.
|
|
1119
|
+
*/
|
|
1120
|
+
parentRunId?: string;
|
|
1121
|
+
/**
|
|
1122
|
+
* Subagent depth for this tool call. 0 = top-level, 1 = first-level
|
|
1123
|
+
* child, etc. Mirrors `ToolContext.depth` so hook consumers don't
|
|
1124
|
+
* have to cross-reference the tool context. Omitted on top-level
|
|
1125
|
+
* runs (treated as 0).
|
|
1126
|
+
*/
|
|
1127
|
+
depth?: number;
|
|
1043
1128
|
}
|
|
1044
1129
|
/**
|
|
1045
1130
|
* Base context for MCP tool hooks.
|
|
@@ -1059,6 +1144,12 @@ interface McpToolHookContext {
|
|
|
1059
1144
|
/** Aliased wire name for this MCP tool, or the canonical `mcp_{server}_{tool}` name. */
|
|
1060
1145
|
displayName: string;
|
|
1061
1146
|
input: Record<string, unknown>;
|
|
1147
|
+
/** Owning run id — same semantics as `ToolHookContext.runId`. */
|
|
1148
|
+
runId?: string;
|
|
1149
|
+
/** Parent run id when this tool call's agent is a subagent — see `ToolHookContext.parentRunId`. */
|
|
1150
|
+
parentRunId?: string;
|
|
1151
|
+
/** Subagent depth — see `ToolHookContext.depth`. */
|
|
1152
|
+
depth?: number;
|
|
1062
1153
|
}
|
|
1063
1154
|
/** Base context for session hooks */
|
|
1064
1155
|
interface SessionHookContext {
|
|
@@ -1357,6 +1448,100 @@ interface OpenRouterParams {
|
|
|
1357
1448
|
*/
|
|
1358
1449
|
declare function openrouter(params?: OpenRouterParams): Provider;
|
|
1359
1450
|
//#endregion
|
|
1451
|
+
//#region src/providers/schema-sanitize.d.ts
|
|
1452
|
+
/**
|
|
1453
|
+
* JSON Schema sanitizer for tool `inputSchema` forwarded to LLM providers.
|
|
1454
|
+
*
|
|
1455
|
+
* Why this exists: MCP servers ship arbitrary JSON Schema in `tools/list`.
|
|
1456
|
+
* Anthropic and (to a lesser extent) OpenAI reject specific keyword
|
|
1457
|
+
* combinations with a 400 on `messages.create`, and the error message
|
|
1458
|
+
* lands deep inside an SDK exception that consumers blame on their own
|
|
1459
|
+
* code. The most common failure modes in the wild:
|
|
1460
|
+
*
|
|
1461
|
+
* - Root `$ref` (server-published schema lives under `#/$defs/X`).
|
|
1462
|
+
* - Root `oneOf` / `anyOf` / `allOf` (Anthropic allows neither at the
|
|
1463
|
+
* top level; expects `type: 'object'`).
|
|
1464
|
+
* - `type: ['object', 'null']` at the root (nullable variants of an
|
|
1465
|
+
* otherwise valid object schema).
|
|
1466
|
+
* - Missing `properties` on an object root.
|
|
1467
|
+
* - `nullable: true` (Swagger / OpenAPI 3.0 idiom — not standard JSON
|
|
1468
|
+
* Schema, ignored by every modern provider but Anthropic warns).
|
|
1469
|
+
* - Nested `$ref` pointing at `#/definitions/X` without the schema
|
|
1470
|
+
* actually inlining the referenced definition.
|
|
1471
|
+
*
|
|
1472
|
+
* Pure rewrite. Returns a new schema (or the same reference when nothing
|
|
1473
|
+
* needed to change — the hot path on stable tool registries) and a list
|
|
1474
|
+
* of `warnings` describing each rewrite. Providers call
|
|
1475
|
+
* `sanitizeToolSpecs` from `formatTools` so every tool — eager MCP, lazy
|
|
1476
|
+
* MCP, native, skill — gets the same treatment, and warnings surface
|
|
1477
|
+
* through `console.warn` once per batch (the seen-set in
|
|
1478
|
+
* `sanitizeToolSpecs` is local to one call, so a stable bad schema logs
|
|
1479
|
+
* once per request rather than every turn).
|
|
1480
|
+
*
|
|
1481
|
+
* Scope:
|
|
1482
|
+
* - Pure function. No I/O, no globals.
|
|
1483
|
+
* - Bounded recursion (`MAX_DEPTH = 32`) so a malicious server can't
|
|
1484
|
+
* wedge the agent with a deeply self-referential schema.
|
|
1485
|
+
* - Bounded `$ref` resolution (`MAX_REF_HOPS = 16`) for the same
|
|
1486
|
+
* reason. Cycles fall back to `{}` (permissive) rather than
|
|
1487
|
+
* throwing — the request still succeeds, the schema is just looser.
|
|
1488
|
+
*
|
|
1489
|
+
* Non-goals:
|
|
1490
|
+
* - Validating that the schema is internally consistent.
|
|
1491
|
+
* - Cleaning up tool *descriptions* (handled elsewhere).
|
|
1492
|
+
* - Provider-side feature detection (handled by the provider's own
|
|
1493
|
+
* `formatTools`; this module is a syntactic guard, not a semantic one).
|
|
1494
|
+
*/
|
|
1495
|
+
/** Strictness profile — picks which transformations to apply. */
|
|
1496
|
+
type SchemaSanitizeProfile = 'anthropic' | 'openai' | 'permissive';
|
|
1497
|
+
interface SchemaSanitizeOptions {
|
|
1498
|
+
/** Strictness profile. Defaults to `'permissive'`. */
|
|
1499
|
+
profile?: SchemaSanitizeProfile;
|
|
1500
|
+
/**
|
|
1501
|
+
* Tool name for context in warnings. Optional — when set, every warning
|
|
1502
|
+
* is prefixed with `[tool:<name>] ` so log lines correlate to the tool.
|
|
1503
|
+
*/
|
|
1504
|
+
toolName?: string;
|
|
1505
|
+
}
|
|
1506
|
+
interface SchemaSanitizeResult {
|
|
1507
|
+
/** Sanitized schema, safe to forward to the provider. */
|
|
1508
|
+
schema: Record<string, unknown>;
|
|
1509
|
+
/**
|
|
1510
|
+
* Human-readable strings describing each rewrite the sanitizer performed.
|
|
1511
|
+
* Empty on a clean schema. Consumers may log these (recommended) or
|
|
1512
|
+
* thread them through a hook for observability.
|
|
1513
|
+
*/
|
|
1514
|
+
warnings: string[];
|
|
1515
|
+
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Sanitize a single tool's `inputSchema` for safe forwarding to the
|
|
1518
|
+
* provider. Returns the rewritten schema + a list of warnings describing
|
|
1519
|
+
* everything that changed.
|
|
1520
|
+
*
|
|
1521
|
+
* Never mutates the input. Returns the **same reference** when no rewrite
|
|
1522
|
+
* was needed (clean-schema fast path) — `sanitizeToolSpecs` relies on
|
|
1523
|
+
* this to keep the formatTools hot loop allocation-free across turns
|
|
1524
|
+
* when the registered tool set is already wire-valid.
|
|
1525
|
+
*/
|
|
1526
|
+
declare function sanitizeToolSchema(input: unknown, options?: SchemaSanitizeOptions): SchemaSanitizeResult;
|
|
1527
|
+
/**
|
|
1528
|
+
* Convenience: sanitize a batch of tools and emit a single de-duped
|
|
1529
|
+
* `console.warn` per unique warning line. Returns the rewritten tools
|
|
1530
|
+
* preserving original ordering and reference identity for clean schemas
|
|
1531
|
+
* (no reallocation when nothing needed to change).
|
|
1532
|
+
*
|
|
1533
|
+
* The sanitiser runs every request, so log noise from a stable bad
|
|
1534
|
+
* schema would multiply across turns; the de-dupe keeps the signal
|
|
1535
|
+
* useful in production logs without dropping the first occurrence.
|
|
1536
|
+
*/
|
|
1537
|
+
declare function sanitizeToolSpecs<T extends {
|
|
1538
|
+
name: string;
|
|
1539
|
+
inputSchema?: unknown;
|
|
1540
|
+
}>(tools: readonly T[], options?: {
|
|
1541
|
+
profile?: SchemaSanitizeProfile;
|
|
1542
|
+
onWarning?: (line: string) => void;
|
|
1543
|
+
}): T[];
|
|
1544
|
+
//#endregion
|
|
1360
1545
|
//#region src/providers/index.d.ts
|
|
1361
1546
|
interface ToolSpec {
|
|
1362
1547
|
name: string;
|
|
@@ -1378,6 +1563,25 @@ interface ToolResult {
|
|
|
1378
1563
|
* Use `toolResultToText(content)` when a downstream consumer only handles strings.
|
|
1379
1564
|
*/
|
|
1380
1565
|
content: string | ToolResultContent[];
|
|
1566
|
+
/**
|
|
1567
|
+
* Marks this result as an error. Propagates to `tool_result.is_error: true`
|
|
1568
|
+
* on the Anthropic wire (and to the equivalent on every other provider that
|
|
1569
|
+
* exposes the field). Models treat error-flagged results as "the tool tried
|
|
1570
|
+
* but failed" — distinct from "the tool returned this string" — so they can
|
|
1571
|
+
* decide whether to retry, fall back, or surface the error to the user.
|
|
1572
|
+
*
|
|
1573
|
+
* Set by the loop on:
|
|
1574
|
+
* - Tool body throws (`tool:error` path).
|
|
1575
|
+
* - Gate refusal (`Blocked: <reason>`).
|
|
1576
|
+
* - Validation rejection (`Validation error: …`).
|
|
1577
|
+
* - Mid-tool abort (`INTERRUPT_MESSAGE_FOR_TOOL_USE`).
|
|
1578
|
+
* - Sequential-batch skips when a sibling threw / a steering message
|
|
1579
|
+
* arrived.
|
|
1580
|
+
*
|
|
1581
|
+
* Custom tools may set it via the `tool:error` hook's `ctx.result`
|
|
1582
|
+
* substitute when they want the framework to flag a structured error.
|
|
1583
|
+
*/
|
|
1584
|
+
isError?: boolean;
|
|
1381
1585
|
}
|
|
1382
1586
|
/**
|
|
1383
1587
|
* Provider-level capability flags used by the agent loop to route tool results
|
|
@@ -1539,6 +1743,151 @@ declare function toOpenAI(msg: SessionMessage): {
|
|
|
1539
1743
|
role: string;
|
|
1540
1744
|
content: unknown;
|
|
1541
1745
|
};
|
|
1746
|
+
/**
|
|
1747
|
+
* Placeholder content inserted into a synthetic `tool_result` when the harness
|
|
1748
|
+
* has to repair an orphan `tool_use`. Exported so downstream consumers
|
|
1749
|
+
* (training-data collectors, HFI submission) can reject any payload containing
|
|
1750
|
+
* it — the marker satisfies the wire-level pairing contract structurally but
|
|
1751
|
+
* the content itself is fake and would poison fine-tuning data.
|
|
1752
|
+
*/
|
|
1753
|
+
declare const SYNTHETIC_TOOL_RESULT_PLACEHOLDER = "[Tool result missing due to internal error]";
|
|
1754
|
+
/**
|
|
1755
|
+
* Replacement text for an assistant message whose every content block was
|
|
1756
|
+
* stripped during pairing repair (e.g. the only blocks were orphan
|
|
1757
|
+
* `tool_call`s). Providers reject empty `content` arrays — the marker keeps
|
|
1758
|
+
* the turn shape valid while signaling "this assistant turn lost its
|
|
1759
|
+
* outputs" to the model so it can recover.
|
|
1760
|
+
*/
|
|
1761
|
+
declare const TOOL_USE_INTERRUPTED_MARKER = "[Tool use interrupted]";
|
|
1762
|
+
/**
|
|
1763
|
+
* Replacement text for a user message whose every content block was a
|
|
1764
|
+
* `tool_result` with no matching upstream `tool_call` (e.g. the assistant
|
|
1765
|
+
* pair was stripped by an earlier compaction). Same role as
|
|
1766
|
+
* {@link TOOL_USE_INTERRUPTED_MARKER} on the user side.
|
|
1767
|
+
*/
|
|
1768
|
+
declare const ORPHANED_TOOL_RESULT_MARKER = "[Orphaned tool result removed due to conversation resume]";
|
|
1769
|
+
/**
|
|
1770
|
+
* Classification of a single repair the pairing pass performed. Surfaced via
|
|
1771
|
+
* {@link EnsureToolResultPairingOptions.onRepair} so consumers can wire
|
|
1772
|
+
* telemetry, debug logs, or strict-mode rejection without re-implementing the
|
|
1773
|
+
* walk.
|
|
1774
|
+
*
|
|
1775
|
+
* Each entry corresponds to one of the corruption modes documented on
|
|
1776
|
+
* {@link ensureToolResultPairing}.
|
|
1777
|
+
*/
|
|
1778
|
+
type PairingRepairMode = 'orphan-tool-use-prepend' | 'orphan-tool-use-append' | 'orphan-tool-result-strip' | 'duplicate-tool-use-strip' | 'duplicate-tool-result-strip' | 'empty-assistant-marker';
|
|
1779
|
+
interface PairingRepair {
|
|
1780
|
+
mode: PairingRepairMode;
|
|
1781
|
+
/** Tool-use / tool-result id this repair concerns. Absent for empty-marker repairs. */
|
|
1782
|
+
callId?: string;
|
|
1783
|
+
/** Zero-based index into the INPUT `messages` array where the corruption was found. */
|
|
1784
|
+
messageIndex: number;
|
|
1785
|
+
}
|
|
1786
|
+
interface EnsureToolResultPairingOptions {
|
|
1787
|
+
/**
|
|
1788
|
+
* Fired once per repair the pass performed. Synchronous so the loop can
|
|
1789
|
+
* stay on its hot path. Throwing from the callback aborts the pass —
|
|
1790
|
+
* consumers wanting fail-fast (strict mode) can re-throw with their own
|
|
1791
|
+
* typed error.
|
|
1792
|
+
*/
|
|
1793
|
+
onRepair?: (repair: PairingRepair) => void;
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* Defensive repair pass that rewrites a message list so it satisfies the
|
|
1797
|
+
* wire-level `tool_use` ↔ `tool_result` adjacency contract every modern
|
|
1798
|
+
* provider enforces.
|
|
1799
|
+
*
|
|
1800
|
+
* Anthropic 400s on orphans with `'tool_use' ids were found without
|
|
1801
|
+
* 'tool_result' blocks immediately after` (and its inverse, `tool_result
|
|
1802
|
+
* must be preceded by a tool_call with the same toolCallId`). OpenAI's
|
|
1803
|
+
* Chat Completions API rejects most mismatches with a 400 too.
|
|
1804
|
+
*
|
|
1805
|
+
* Six repair modes — modeled after Anthropic's Claude Code defenses:
|
|
1806
|
+
*
|
|
1807
|
+
* | # | Corruption | Repair |
|
|
1808
|
+
* |---|------------|--------|
|
|
1809
|
+
* | 1 | assistant `tool_use` whose next user msg lacks a matching `tool_result` | **Prepend** a synthetic `tool_result` block carrying {@link SYNTHETIC_TOOL_RESULT_PLACEHOLDER} with `isError: true` |
|
|
1810
|
+
* | 2 | assistant `tool_use` followed by nothing (or by a non-user msg) | **Insert** a new synthetic user message with the same placeholder |
|
|
1811
|
+
* | 3 | user `tool_result` with no preceding assistant `tool_call` | **Strip** the orphan block; if it empties the msg, replace with {@link ORPHANED_TOOL_RESULT_MARKER} text block |
|
|
1812
|
+
* | 4 | duplicate `tool_call.id` across assistant messages (CC-1212) | **Strip** later instances + their matching tool_results |
|
|
1813
|
+
* | 5 | duplicate `tool_result.callId` within a single user message | **Dedupe** by `callId`, keep first |
|
|
1814
|
+
* | 6 | assistant message emptied by mode-4 stripping | **Replace** content with {@link TOOL_USE_INTERRUPTED_MARKER} text block |
|
|
1815
|
+
*
|
|
1816
|
+
* **Repair, not drop.** Earlier versions of this pass simply dropped orphan
|
|
1817
|
+
* blocks, which (a) silently rewrote history the model had reasoned over and
|
|
1818
|
+
* (b) cascaded — dropping an assistant tool_call would orphan its
|
|
1819
|
+
* tool_result, which would then get dropped too, removing any trace of
|
|
1820
|
+
* "what the model tried to do" from the transcript. The repair-based pass
|
|
1821
|
+
* preserves the model's tool_use shape and patches the dangling result with
|
|
1822
|
+
* an `is_error` placeholder so the model sees "I tried X, the result was
|
|
1823
|
+
* lost" and can retry intelligently.
|
|
1824
|
+
*
|
|
1825
|
+
* Adjacency contract: `tool_result` blocks must live in the user message
|
|
1826
|
+
* IMMEDIATELY following the assistant message that emitted the matching
|
|
1827
|
+
* `tool_use`. The pass enforces strict adjacency — a tool_result two
|
|
1828
|
+
* messages downstream of its tool_call is still an orphan.
|
|
1829
|
+
*
|
|
1830
|
+
* Idempotent: returns the input reference unchanged when no repairs were
|
|
1831
|
+
* necessary. Re-running on already-repaired output is a no-op.
|
|
1832
|
+
*
|
|
1833
|
+
* Pure: does not mutate input messages or their content arrays — every
|
|
1834
|
+
* repair allocates a fresh array / object.
|
|
1835
|
+
*/
|
|
1836
|
+
declare function ensureToolResultPairing(messages: SessionMessage[], options?: EnsureToolResultPairingOptions): SessionMessage[];
|
|
1837
|
+
/**
|
|
1838
|
+
* Drop ASSISTANT turns whose every `tool_call` block is unresolved
|
|
1839
|
+
* (no matching `tool_result` block anywhere later in the transcript).
|
|
1840
|
+
* Tool_call blocks with at least one matching tool_result are kept — modes
|
|
1841
|
+
* 1/3 of {@link ensureToolResultPairing} handle the partial-pair case at
|
|
1842
|
+
* wire-send time.
|
|
1843
|
+
*
|
|
1844
|
+
* Use case: session resume. A turn that emitted three `tool_use` blocks but
|
|
1845
|
+
* never persisted the matching `tool_result` turn (process death, crash,
|
|
1846
|
+
* `kill -9`) leaves the transcript with an orphan that Anthropic rejects on
|
|
1847
|
+
* the FIRST API call after reload. Dropping the whole assistant turn — not
|
|
1848
|
+
* just the orphan blocks — preserves text-only turns that legitimately
|
|
1849
|
+
* carry reasoning the model wants to see again.
|
|
1850
|
+
*
|
|
1851
|
+
* Does NOT mint fresh ids: re-id'ing on every resume would cause
|
|
1852
|
+
* exponential transcript growth across repeated resumes of an interrupted
|
|
1853
|
+
* session.
|
|
1854
|
+
*
|
|
1855
|
+
* Pure: returns the input reference unchanged when no turn was dropped.
|
|
1856
|
+
*/
|
|
1857
|
+
declare function filterUnresolvedToolUses<T extends {
|
|
1858
|
+
role: string;
|
|
1859
|
+
content: SessionContentBlock[];
|
|
1860
|
+
}>(turns: T[]): T[];
|
|
1861
|
+
/**
|
|
1862
|
+
* Classification of a session's tail state for resume purposes.
|
|
1863
|
+
*
|
|
1864
|
+
* - `'clean'` — the trailing turn is a user message (the model would respond
|
|
1865
|
+
* next), or the transcript is empty. Safe to resume by appending a fresh
|
|
1866
|
+
* user prompt.
|
|
1867
|
+
* - `'interrupted'` — the trailing turn is an assistant message that has at
|
|
1868
|
+
* least one `tool_call` block with no matching `tool_result` anywhere
|
|
1869
|
+
* later. The run was almost certainly killed between persisting the
|
|
1870
|
+
* assistant turn and persisting its tool-results turn. Hosts that want
|
|
1871
|
+
* Claude-Code-style auto-resume can detect this and inject a
|
|
1872
|
+
* `"Continue from where you left off."` user message before the next run.
|
|
1873
|
+
* - `'completed'` — the trailing turn is an assistant message with no
|
|
1874
|
+
* orphan tool_calls. The model considers itself done. Hosts that want to
|
|
1875
|
+
* resume must supply a new prompt; auto-continuation here would be a
|
|
1876
|
+
* non-sequitur.
|
|
1877
|
+
*/
|
|
1878
|
+
type TurnInterruptionState = 'clean' | 'interrupted' | 'completed';
|
|
1879
|
+
/**
|
|
1880
|
+
* Inspect a session's trailing turn to classify whether the run was
|
|
1881
|
+
* interrupted mid-tool-call. Pure / synchronous — does not modify the input.
|
|
1882
|
+
*
|
|
1883
|
+
* Pair with {@link filterUnresolvedToolUses} on the resume path: filter
|
|
1884
|
+
* first so the result reflects the post-cleanup state (a turn whose orphans
|
|
1885
|
+
* were stripped reads as 'completed', not 'interrupted').
|
|
1886
|
+
*/
|
|
1887
|
+
declare function detectTurnInterruption<T extends {
|
|
1888
|
+
role: string;
|
|
1889
|
+
content: SessionContentBlock[];
|
|
1890
|
+
}>(turns: T[]): TurnInterruptionState;
|
|
1542
1891
|
declare function autoDetectAndConvert(msg: {
|
|
1543
1892
|
role: string;
|
|
1544
1893
|
content: unknown;
|
|
@@ -1866,6 +2215,76 @@ interface SkillsConfig {
|
|
|
1866
2215
|
trustProjectSkills?: boolean;
|
|
1867
2216
|
}
|
|
1868
2217
|
//#endregion
|
|
2218
|
+
//#region src/tools/read-state.d.ts
|
|
2219
|
+
interface ReadStateEntry {
|
|
2220
|
+
contentHash: string;
|
|
2221
|
+
/** Slice parameters for the last read. */
|
|
2222
|
+
offset: number;
|
|
2223
|
+
limit: number;
|
|
2224
|
+
maxBytes: number;
|
|
2225
|
+
/**
|
|
2226
|
+
* Whether the prior read emitted line-number prefixes. Tracked so a
|
|
2227
|
+
* read with `lineNumbers: true` doesn't dedup against one with
|
|
2228
|
+
* `lineNumbers: false` (or vice versa) — the dedup stub would mislead
|
|
2229
|
+
* the model about the prior output's shape.
|
|
2230
|
+
*/
|
|
2231
|
+
lineNumbers?: boolean;
|
|
2232
|
+
/** Wall-clock at last read — diagnostic only, not used for invalidation. */
|
|
2233
|
+
mtimeMs: number;
|
|
2234
|
+
}
|
|
2235
|
+
type ReadStateMap = Map<string, ReadStateEntry>;
|
|
2236
|
+
/**
|
|
2237
|
+
* Get or lazily create the per-session read-state map. Returns `undefined`
|
|
2238
|
+
* when no session is provided.
|
|
2239
|
+
*
|
|
2240
|
+
* Most tool callers should prefer {@link resolveReadStateMap}, which
|
|
2241
|
+
* additionally honors an explicit `ctx.readState` (the path
|
|
2242
|
+
* `spawn`'s `shareReadState: true` uses to forward the parent's map
|
|
2243
|
+
* into a sessionless child). Use this helper directly only when the
|
|
2244
|
+
* Session-keyed map is exactly what you want and you don't need to
|
|
2245
|
+
* accept an override.
|
|
2246
|
+
*/
|
|
2247
|
+
declare function getReadState(session: Session | undefined): ReadStateMap | undefined;
|
|
2248
|
+
/**
|
|
2249
|
+
* Resolve the active read-state map from a tool context. An explicit
|
|
2250
|
+
* `ctx.readState` wins (used by `spawn`'s `shareReadState` opt-in to
|
|
2251
|
+
* forward the parent's map into a sessionless child); otherwise the
|
|
2252
|
+
* usual `Session`-keyed lookup applies.
|
|
2253
|
+
*
|
|
2254
|
+
* Tools should call this helper instead of `getReadState(ctx.session)`
|
|
2255
|
+
* directly so the `shareReadState` plumbing is honored uniformly.
|
|
2256
|
+
*/
|
|
2257
|
+
declare function resolveReadStateMap(ctx: {
|
|
2258
|
+
session?: Session;
|
|
2259
|
+
readState?: ReadStateMap;
|
|
2260
|
+
}): ReadStateMap | undefined;
|
|
2261
|
+
/**
|
|
2262
|
+
* Canonical read-state key for a `(cwd, path)` pair.
|
|
2263
|
+
*
|
|
2264
|
+
* `ctx.execution.readFile(handle, path)` resolves the model-provided
|
|
2265
|
+
* path against `handle.cwd` before touching disk — so `src/App.tsx`,
|
|
2266
|
+
* `./src/App.tsx`, and `/abs/cwd/src/App.tsx` all read the **same**
|
|
2267
|
+
* bytes. The read-state map MUST mirror that resolution: without it,
|
|
2268
|
+
* a model that reads `src/App.tsx` and then edits `./src/App.tsx`
|
|
2269
|
+
* trips the `requireReadBeforeEdit` gate for a file it demonstrably
|
|
2270
|
+
* already saw (the gate's "has not been read in this session" message
|
|
2271
|
+
* fires on a stale key).
|
|
2272
|
+
*
|
|
2273
|
+
* `node:path`'s `resolve(cwd, path)` short-circuits when `path` is
|
|
2274
|
+
* already absolute, so absolute and relative shapes converge on the
|
|
2275
|
+
* same canonical form. We don't `realpath()` symlinks — the file IS
|
|
2276
|
+
* the path the model addressed, not the realpath behind it; the host's
|
|
2277
|
+
* execution context decides how to dereference.
|
|
2278
|
+
*/
|
|
2279
|
+
declare function readStateKey(cwd: string, path: string): string;
|
|
2280
|
+
/**
|
|
2281
|
+
* FNV-1a 32-bit hash, hex-encoded. Fast, non-cryptographic — we only need
|
|
2282
|
+
* collision resistance against accidental matches between different file
|
|
2283
|
+
* contents within one session (~1 in 4 billion). Cheaper than allocating
|
|
2284
|
+
* a Buffer and pulling in `crypto`.
|
|
2285
|
+
*/
|
|
2286
|
+
declare function hashContent(text: string): string;
|
|
2287
|
+
//#endregion
|
|
1869
2288
|
//#region src/tools/types.d.ts
|
|
1870
2289
|
/**
|
|
1871
2290
|
* Runtime context passed to every tool execution.
|
|
@@ -1921,12 +2340,30 @@ interface ToolContext {
|
|
|
1921
2340
|
* the subagent tree can be reconstructed from a persisted session.
|
|
1922
2341
|
*/
|
|
1923
2342
|
runId?: string;
|
|
2343
|
+
/**
|
|
2344
|
+
* Parent run id when the agent owning this tool call is a subagent.
|
|
2345
|
+
* Mirrors `SessionRun.parentRunId`; absent on top-level runs. Tools
|
|
2346
|
+
* that need to walk up to the spawning run (telemetry, scoped
|
|
2347
|
+
* caches, todowrite-style state keyed by the parent thread) read it
|
|
2348
|
+
* directly off the context instead of resolving via the session.
|
|
2349
|
+
*/
|
|
2350
|
+
parentRunId?: string;
|
|
1924
2351
|
/**
|
|
1925
2352
|
* The agent's session, when one was provided to `createAgent`. Tools that
|
|
1926
2353
|
* want to persist their own state (or, in the case of `spawn`, inherit the
|
|
1927
2354
|
* parent's session for child persistence) can read from here.
|
|
1928
2355
|
*/
|
|
1929
2356
|
session?: Session;
|
|
2357
|
+
/**
|
|
2358
|
+
* Explicit read-state map forwarded from the agent's options. When set,
|
|
2359
|
+
* tools should prefer it over the `Session`-keyed lookup so the
|
|
2360
|
+
* `requireReadBeforeEdit` gate and `dedupReads` cache honor cross-context
|
|
2361
|
+
* sharing — `spawn`'s `shareReadState` opt-in is the canonical caller.
|
|
2362
|
+
* Resolve uniformly via `resolveReadStateMap(ctx)` (see
|
|
2363
|
+
* `tools/read-state.ts`); custom tools that need read tracking should do
|
|
2364
|
+
* the same.
|
|
2365
|
+
*/
|
|
2366
|
+
readState?: ReadStateMap;
|
|
1930
2367
|
/**
|
|
1931
2368
|
* Subagent depth for the agent owning this tool call. 0 = top-level,
|
|
1932
2369
|
* 1 = first-level child, … Used by spawn to enforce a `maxDepth` cap.
|
|
@@ -2139,6 +2576,23 @@ interface AgentHooks {
|
|
|
2139
2576
|
delta: string;
|
|
2140
2577
|
thinking: string;
|
|
2141
2578
|
}) => void;
|
|
2579
|
+
/**
|
|
2580
|
+
* Fires when the provider's stream rejects BEFORE `stream:end` — provider
|
|
2581
|
+
* errors, network blips, malformed `tools` payloads (400 invalid_request_error).
|
|
2582
|
+
*
|
|
2583
|
+
* `err` is the original thrown value, not the typed `AgentProviderError`
|
|
2584
|
+
* the loop subsequently constructs; subscribe here to capture the native
|
|
2585
|
+
* SDK exception (status codes, request ids) for telemetry without having
|
|
2586
|
+
* to walk `cause` chains. Observational — the loop still wraps + throws
|
|
2587
|
+
* after this hook resolves, so handlers cannot suppress the failure.
|
|
2588
|
+
*
|
|
2589
|
+
* Does NOT fire on user-initiated aborts; those land on `agent:abort`
|
|
2590
|
+
* instead. Use `err instanceof Error && err.name === 'AbortError'` to
|
|
2591
|
+
* distinguish if you also subscribe here for raw error logging.
|
|
2592
|
+
*/
|
|
2593
|
+
'stream:error': (ctx: StreamHookContext & {
|
|
2594
|
+
err: unknown;
|
|
2595
|
+
}) => void;
|
|
2142
2596
|
'oauth:refresh': (ctx: OAuthRefreshHookContext) => void;
|
|
2143
2597
|
/**
|
|
2144
2598
|
* Fires before validation, `tool:before`, and `execute`. Two ways to
|
|
@@ -2190,6 +2644,54 @@ interface AgentHooks {
|
|
|
2190
2644
|
*/
|
|
2191
2645
|
priorContent?: string;
|
|
2192
2646
|
}) => void;
|
|
2647
|
+
/**
|
|
2648
|
+
* Symmetric notification fired ONCE per call the model dispatched,
|
|
2649
|
+
* regardless of the path the call ultimately took through the loop.
|
|
2650
|
+
* Pair with `tool:after` (which also fires uniformly across paths) to
|
|
2651
|
+
* get a guaranteed `tool` ↔ `tool-result` event pairing for downstream
|
|
2652
|
+
* consumers reconstructing message history from live events.
|
|
2653
|
+
*
|
|
2654
|
+
* Distinct from `tool:before`: `tool:before` only fires when the tool
|
|
2655
|
+
* body is about to execute (the legacy "I'm running this tool" notification),
|
|
2656
|
+
* skipping gate-block / gate-substitute / unknown-tool / validation-reject
|
|
2657
|
+
* paths. `tool:dispatched` fires on all five paths with an `outcome`
|
|
2658
|
+
* discriminator so live consumers never see a `tool:after` whose
|
|
2659
|
+
* matching dispatch event was suppressed.
|
|
2660
|
+
*
|
|
2661
|
+
* Strict ordering: `tool:dispatched` fires AFTER `tool:gate` /
|
|
2662
|
+
* `validation:reject` / `tool:unknown` so the resolved `outcome` is
|
|
2663
|
+
* always accurate. Fires BEFORE `tool:before` on the execute path so
|
|
2664
|
+
* consumers binding both events see dispatched-then-before.
|
|
2665
|
+
*
|
|
2666
|
+
* `reason` is set only when `outcome === 'gate-block'` and carries the
|
|
2667
|
+
* gate's refusal text (so consumers can render denied-diff badges, etc.
|
|
2668
|
+
* without a side channel).
|
|
2669
|
+
*/
|
|
2670
|
+
'tool:dispatched': (ctx: ToolHookContext & {
|
|
2671
|
+
outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input';
|
|
2672
|
+
reason?: string;
|
|
2673
|
+
runToolCounts: Readonly<Record<string, number>>;
|
|
2674
|
+
}) => void;
|
|
2675
|
+
/**
|
|
2676
|
+
* Fires after a tool body produced a result (the execute path) or a
|
|
2677
|
+
* `tool:gate` listener substituted one via `ctx.result` (the Z20
|
|
2678
|
+
* cache-substitute path). Carries the post-`tool:transform` payload —
|
|
2679
|
+
* what the model actually sees on the wire.
|
|
2680
|
+
*
|
|
2681
|
+
* Does NOT fire on gate-block / unknown-tool / validation-reject
|
|
2682
|
+
* paths: the loop synthesizes their `tool_result` text inline and
|
|
2683
|
+
* sends it back to the model, but no tool body produced output and
|
|
2684
|
+
* no `tool:transform` ran. Consumers wanting symmetric per-call
|
|
2685
|
+
* notification across every dispatch path should listen to
|
|
2686
|
+
* `tool:dispatched` instead (which fires once per call regardless of
|
|
2687
|
+
* path, with an `outcome` discriminator).
|
|
2688
|
+
*
|
|
2689
|
+
* This narrow contract is deliberate: tracing spans opened in
|
|
2690
|
+
* `tool:before` only get closed where they were opened, byte budgets
|
|
2691
|
+
* only count real tool output, and chat-layer transcript renderers
|
|
2692
|
+
* keep their `tool` ↔ `tool-result` pairing without special-casing
|
|
2693
|
+
* the synthesized paths.
|
|
2694
|
+
*/
|
|
2193
2695
|
'tool:after': (ctx: ToolHookContext & {
|
|
2194
2696
|
result: string | ToolResultContent[];
|
|
2195
2697
|
outputBytes: number;
|
|
@@ -2301,6 +2803,12 @@ interface AgentHooks {
|
|
|
2301
2803
|
childId: string;
|
|
2302
2804
|
depth: number;
|
|
2303
2805
|
}) => void;
|
|
2806
|
+
/** Bubbled `stream:error` from a subagent's turn. See {@link AgentHooks['stream:error']}. */
|
|
2807
|
+
'child:stream:error': (ctx: StreamHookContext & {
|
|
2808
|
+
err: unknown;
|
|
2809
|
+
childId: string;
|
|
2810
|
+
depth: number;
|
|
2811
|
+
}) => void;
|
|
2304
2812
|
/**
|
|
2305
2813
|
* Gate-style child events. Unlike the other `child:*` events, the bubble
|
|
2306
2814
|
* passes the **same `ctx` reference** the subagent's loop is awaiting on:
|
|
@@ -2342,6 +2850,19 @@ interface AgentHooks {
|
|
|
2342
2850
|
*/
|
|
2343
2851
|
priorContent?: string;
|
|
2344
2852
|
}) => void;
|
|
2853
|
+
/**
|
|
2854
|
+
* Bubbled sibling of {@link AgentHooks['tool:dispatched']} — fires when a
|
|
2855
|
+
* subagent dispatches a call. Symmetric with `child:tool:after` so live
|
|
2856
|
+
* UI rendering of subagent transcripts stays paired across all five
|
|
2857
|
+
* dispatch paths (gate-block/gate-substitute/unknown/invalid-input/execute).
|
|
2858
|
+
*/
|
|
2859
|
+
'child:tool:dispatched': (ctx: ToolHookContext & {
|
|
2860
|
+
outcome: 'execute' | 'gate-substitute' | 'gate-block' | 'unknown' | 'invalid-input';
|
|
2861
|
+
reason?: string;
|
|
2862
|
+
runToolCounts: Readonly<Record<string, number>>;
|
|
2863
|
+
childId: string;
|
|
2864
|
+
depth: number;
|
|
2865
|
+
}) => void;
|
|
2345
2866
|
'child:tool:after': (ctx: ToolHookContext & {
|
|
2346
2867
|
result: string | ToolResultContent[];
|
|
2347
2868
|
outputBytes: number;
|
|
@@ -2539,6 +3060,26 @@ interface AgentHooks {
|
|
|
2539
3060
|
skill: SkillConfig;
|
|
2540
3061
|
reason: DeactivationReason;
|
|
2541
3062
|
}) => void;
|
|
3063
|
+
/**
|
|
3064
|
+
* Fires once per repair performed by the pre-send pairing pass
|
|
3065
|
+
* ({@link ensureToolResultPairing}). The pass runs immediately before every
|
|
3066
|
+
* provider call and patches over the wire-level corruption modes that
|
|
3067
|
+
* Anthropic / OpenAI 400 on (orphan `tool_use` / `tool_result`, duplicate
|
|
3068
|
+
* ids, compaction-stranded blocks).
|
|
3069
|
+
*
|
|
3070
|
+
* Observational — handlers can mirror to Sentry/PostHog/etc. for
|
|
3071
|
+
* postmortems on new corruption sources but cannot suppress the repair.
|
|
3072
|
+
* The companion `behavior.strictToolPairing` flag is the consumer escape
|
|
3073
|
+
* hatch for "throw instead of repair" (training-data collectors).
|
|
3074
|
+
*
|
|
3075
|
+
* `turnId` lets handlers correlate a repair burst with the run-loop turn
|
|
3076
|
+
* that observed it. Absent on repairs detected from the synthetic
|
|
3077
|
+
* fallback path in `agent.run()`'s error catch (the orphan-tool_use
|
|
3078
|
+
* fallback for crash recovery), where no turn is in flight.
|
|
3079
|
+
*/
|
|
3080
|
+
'pairing:repair': (ctx: PairingRepair & {
|
|
3081
|
+
turnId?: string;
|
|
3082
|
+
}) => void;
|
|
2542
3083
|
'usage': (ctx: {
|
|
2543
3084
|
turn: number;
|
|
2544
3085
|
turnId: string;
|
|
@@ -2645,6 +3186,16 @@ interface AgentOptions {
|
|
|
2645
3186
|
mcpServers?: McpServerConfig[];
|
|
2646
3187
|
/** Session for identity, turn persistence, and run tracking */
|
|
2647
3188
|
session?: Session;
|
|
3189
|
+
/**
|
|
3190
|
+
* Explicit read-state map for `read_file` dedup + `requireReadBeforeEdit`
|
|
3191
|
+
* tracking. When omitted, the read-state lives in a `WeakMap<Session, …>`
|
|
3192
|
+
* keyed by the agent's session; providing an explicit map lets a parent
|
|
3193
|
+
* agent share its tracking with a sessionless child (the canonical caller
|
|
3194
|
+
* is `spawn`'s `shareReadState: true` option). Tools resolve uniformly
|
|
3195
|
+
* via `resolveReadStateMap(ctx)` so the explicit map (when present)
|
|
3196
|
+
* wins over the session-keyed lookup.
|
|
3197
|
+
*/
|
|
3198
|
+
readState?: ReadStateMap;
|
|
2648
3199
|
/** Skills configuration */
|
|
2649
3200
|
skills?: SkillsConfig;
|
|
2650
3201
|
/**
|
|
@@ -2751,11 +3302,12 @@ declare function createAgent({
|
|
|
2751
3302
|
execution,
|
|
2752
3303
|
mcpServers,
|
|
2753
3304
|
session,
|
|
3305
|
+
readState: agentReadState,
|
|
2754
3306
|
skills: agentSkills,
|
|
2755
3307
|
mcpConnector,
|
|
2756
3308
|
eager,
|
|
2757
3309
|
hooks: initialHooks
|
|
2758
3310
|
}: AgentOptions): Agent;
|
|
2759
3311
|
//#endregion
|
|
2760
|
-
export {
|
|
2761
|
-
//# sourceMappingURL=agent-
|
|
3312
|
+
export { fromOpenAI as $, ThinkingLevel as $t, SkillSource as A, cerebras as At, createRemoteStore as B, OAuthRefreshHookContext as Bt, getReadState as C, OpenAICompatParams as Ct, SkillConfig as D, OpenAIParams as Dt, resolveReadStateMap as E, openaiCompat as Et, SessionRun as F, AgentStats as Ft, SYNTHETIC_TOOL_RESULT_PLACEHOLDER as G, RunHookMap as Gt, ORPHANED_TOOL_RESULT_MARKER as H, PromptImagePart as Ht, SessionStore as I, ChildRunStats as It, autoDetectAndConvert as J, SessionHookContext as Jt, TOOL_USE_INTERRUPTED_MARKER as K, SessionContentBlock as Kt, createSession as L, McpServerConfig as Lt, CreateSessionOptions as M, anthropic as Mt, Session as N, AgentBehavior as Nt, SkillDiagnostic as O, openai as Ot, SessionData as P, AgentRunOptions as Pt, fromAnthropic as Q, StreamHookContext as Qt, loadSession as R, McpToolHookContext as Rt, ReadStateMap as S, OpenAICompatHttpError as St, readStateKey as T, mapOAIFinishReason as Tt, PairingRepair as U, PromptPart as Ut, EnsureToolResultPairingOptions as V, PromptDocumentPart as Vt, PairingRepairMode as W, PromptTextPart as Wt, ensureToolResultPairing as X, SessionTurn as Xt, detectTurnInterruption as Y, SessionMessage as Yt, filterUnresolvedToolUses as Z, SpawnHookContext as Zt, resultToString as _, errorMessage as _n, sanitizeToolSchema as _t, createAgent as a, TurnFinishReason as an, createFileMapStore as at, ToolMap as b, openrouter as bt, DeactivationReason as c, toolResultToText as cn, StreamCallbacks as ct, createSkillActivationState as d, AgentProviderError as dn, ToolResult as dt, ToolExecutionMode as en, toAnthropic as et, ConnectMcpServersOptions as f, AgentToolNotAllowedError as fn, ToolSpec as ft, normalizeMcpServers as g, ClassifiedErrorKind as gn, SchemaSanitizeResult as gt, normalizeMcpBlocks as h, ClassifiedError as hn, SchemaSanitizeProfile as ht, AgentOptions as i, ToolResultTextContent as in, FileMapStoreOptions as it, SkillsConfig as j, AnthropicParams as jt, SkillResource as k, CerebrasParams as kt, SkillActivationState as l, AgentAbortedError as ln, StreamOptions as lt, connectMcpServers as m, CONTEXT_EXCEEDED_MESSAGE_PATTERNS as mn, SchemaSanitizeOptions as mt, AgentHookMap as n, ToolResultContent as nn, createMemoryStore as nt, ActivationVia as o, TurnUsage as on, Provider as ot, McpConnection as p, AgentToolPairingError as pn, TurnResult as pt, TurnInterruptionState as q, SessionEndStatus as qt, AgentHooks as r, ToolResultImageContent as rn, FileMapAdapter as rt, ActiveSkill as s, toolOutputByteLength as sn, ProviderCapabilities as st, Agent as t, ToolHookContext as tn, toOpenAI as tt, SkillActivationStateOptions as u, AgentContextExceededError as un, ToolCall as ut, ToolContext as v, matchesContextExceeded as vn, sanitizeToolSpecs as vt, hashContent as w, classifyOpenAICompatError as wt, ReadStateEntry as x, OpenAICompatAuthHeader as xt, ToolDef as y, toTypedError as yn, OpenRouterParams as yt, RemoteStoreOptions as z, McpToolSchema as zt };
|
|
3313
|
+
//# sourceMappingURL=agent-BXRCCHeq.d.ts.map
|