agents 0.24.0 → 0.26.0

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.
Files changed (170) hide show
  1. package/dist/{agent-routing-B2XLNMxq.d.ts → agent-routing-0DR0Tk2v.d.ts} +205 -132
  2. package/dist/agent-routing.d.ts +1 -1
  3. package/dist/agent-routing.js.map +1 -1
  4. package/dist/agent-tool-types.d.ts +28 -22
  5. package/dist/agent-tool-types.js +23 -1
  6. package/dist/agent-tool-types.js.map +1 -1
  7. package/dist/{agent-tools-y7zLfw4Q.js → agent-tools-CdJC-8Dc.js} +72 -9
  8. package/dist/agent-tools-CdJC-8Dc.js.map +1 -0
  9. package/dist/{agent-tools-Dj5Mzlw7.d.ts → agent-tools-YrATZJu2.d.ts} +34 -20
  10. package/dist/agent-tools.d.ts +20 -18
  11. package/dist/agent-tools.js.map +1 -1
  12. package/dist/ai-fm7xx1BK.js +312 -0
  13. package/dist/ai-fm7xx1BK.js.map +1 -0
  14. package/dist/base64-redaction-C1Uu29t5.js +59 -0
  15. package/dist/base64-redaction-C1Uu29t5.js.map +1 -0
  16. package/dist/browser/ai-sdk.d.ts +90 -0
  17. package/dist/browser/ai-sdk.js +51 -0
  18. package/dist/browser/ai-sdk.js.map +1 -0
  19. package/dist/browser/ai.d.ts +4 -4
  20. package/dist/browser/ai.js +1 -347
  21. package/dist/browser/index.d.ts +81 -79
  22. package/dist/browser/index.js +361 -2
  23. package/dist/browser/index.js.map +1 -0
  24. package/dist/browser/tanstack-ai.d.ts +96 -1
  25. package/dist/browser/tanstack-ai.js +62 -2
  26. package/dist/browser/tanstack-ai.js.map +1 -1
  27. package/dist/browser-DE3d-RLk.d.ts +275 -0
  28. package/dist/browser-tool-CQ10e6Kj.js +480 -0
  29. package/dist/browser-tool-CQ10e6Kj.js.map +1 -0
  30. package/dist/browser-tool-DuNdlwZ9.d.ts +73 -0
  31. package/dist/capability-B4WbF81e.js.map +1 -1
  32. package/dist/{capability-runner-BUBa6Ake.d.ts → capability-runner-DBAnGr6L.d.ts} +7 -2
  33. package/dist/chat/index.d.ts +340 -234
  34. package/dist/chat/index.js +592 -66
  35. package/dist/chat/index.js.map +1 -1
  36. package/dist/chat/react.d.ts +42 -2
  37. package/dist/chat/react.js +191 -35
  38. package/dist/chat/react.js.map +1 -1
  39. package/dist/chat/transport.d.ts +1 -1
  40. package/dist/chat/transport.js +1 -1
  41. package/dist/chat-sdk/index.d.ts +17 -3
  42. package/dist/chat-sdk/index.js +28 -2
  43. package/dist/chat-sdk/index.js.map +1 -1
  44. package/dist/{client-C9DAjZIY.js → client-4OlMIJx-.js} +102 -29
  45. package/dist/client-4OlMIJx-.js.map +1 -0
  46. package/dist/{client-BxdkCuVy.d.ts → client-je3koD9Z.d.ts} +45 -10
  47. package/dist/client.d.ts +7 -5
  48. package/dist/client.js +2 -2
  49. package/dist/{connector-CptFKzRh.js → connector-58XDGvc3.js} +251 -120
  50. package/dist/connector-58XDGvc3.js.map +1 -0
  51. package/dist/{connector-CkQD4MK3.d.ts → connector-Cl-VqPmA.d.ts} +244 -146
  52. package/dist/context/index.d.ts +29 -0
  53. package/dist/context/index.js +64 -17
  54. package/dist/context/index.js.map +1 -1
  55. package/dist/current-agent-DhoDkSnH.js.map +1 -1
  56. package/dist/{current-agent-C4w86kcN.d.ts → current-agent-vAk_5JMt.d.ts} +4 -4
  57. package/dist/{durable-object-lifecycle-ei7M7lqB.d.ts → durable-object-lifecycle-HhgOMWq9.d.ts} +15 -7
  58. package/dist/harness/pi/index.d.ts +344 -0
  59. package/dist/harness/pi/index.js +873 -0
  60. package/dist/harness/pi/index.js.map +1 -0
  61. package/dist/images-iiTDSyRu.js +1631 -0
  62. package/dist/images-iiTDSyRu.js.map +1 -0
  63. package/dist/{index-Dlgtd3Mj.d.ts → index-BreL0YrQ.d.ts} +2 -2
  64. package/dist/index-kbSUIer3.d.ts +343 -0
  65. package/dist/index.d.ts +46 -44
  66. package/dist/index.js +1 -1
  67. package/dist/internal_context.d.ts +1 -1
  68. package/dist/lifecycle/index.d.ts +3 -3
  69. package/dist/lifecycle/index.js +1 -1
  70. package/dist/{lifecycle-Mm_jQh7r.js → lifecycle-CFu6OV03.js} +39 -10
  71. package/dist/{lifecycle-Mm_jQh7r.js.map → lifecycle-CFu6OV03.js.map} +1 -1
  72. package/dist/mcp/client/index.d.ts +20 -20
  73. package/dist/mcp/client/x402.js +21 -19
  74. package/dist/mcp/client/x402.js.map +1 -1
  75. package/dist/mcp/index.d.ts +35 -35
  76. package/dist/mcp/index.js +1 -1
  77. package/dist/{message-builder-BymO4N_D.js → message-builder-DAl9AhHH.js} +89 -4
  78. package/dist/message-builder-DAl9AhHH.js.map +1 -0
  79. package/dist/models/ai-sdk/index.d.ts +353 -0
  80. package/dist/models/ai-sdk/index.js +2443 -0
  81. package/dist/models/ai-sdk/index.js.map +1 -0
  82. package/dist/models/pi-ai/index.d.ts +313 -0
  83. package/dist/models/pi-ai/index.js +1795 -0
  84. package/dist/models/pi-ai/index.js.map +1 -0
  85. package/dist/observability/ai/index.js +20 -4
  86. package/dist/observability/ai/index.js.map +1 -1
  87. package/dist/{protocol-B0nh6KNf.js → protocol-kHsr-f0X.js} +26 -12
  88. package/dist/{protocol-B0nh6KNf.js.map → protocol-kHsr-f0X.js.map} +1 -1
  89. package/dist/queue/index.d.ts +3 -3
  90. package/dist/queue/index.js +1 -1
  91. package/dist/{queue-BC9F5cUo.js → queue-BB-zfIYF.js} +2 -2
  92. package/dist/{queue-BC9F5cUo.js.map → queue-BB-zfIYF.js.map} +1 -1
  93. package/dist/react.d.ts +6 -6
  94. package/dist/react.js +160 -64
  95. package/dist/react.js.map +1 -1
  96. package/dist/{retries-D9B2UCq3.d.ts → retries-CV6AkXmQ.d.ts} +18 -9
  97. package/dist/retries.d.ts +11 -9
  98. package/dist/retries.js +11 -1
  99. package/dist/retries.js.map +1 -1
  100. package/dist/routing/index.d.ts +2 -2
  101. package/dist/routing/index.js +1 -1
  102. package/dist/{scheduler-D_KHqxBa.js → scheduler-DZ3xQfeK.js} +2 -2
  103. package/dist/{scheduler-D_KHqxBa.js.map → scheduler-DZ3xQfeK.js.map} +1 -1
  104. package/dist/{scheduler-BGq6M5Kd.d.ts → scheduler-RdACNXDP.d.ts} +3 -3
  105. package/dist/schedules/index.d.ts +1 -1
  106. package/dist/schedules/index.js +1 -1
  107. package/dist/serializable.d.ts +1 -1
  108. package/dist/sessions/index.d.ts +70 -3
  109. package/dist/sessions/index.js +276 -67
  110. package/dist/sessions/index.js.map +1 -1
  111. package/dist/skills/index.d.ts +29 -314
  112. package/dist/socket-address.d.ts +16 -0
  113. package/dist/socket-address.js +19 -0
  114. package/dist/socket-address.js.map +1 -0
  115. package/dist/{src-BNU3ZiJM.js → src-BZeu-SCD.js} +423 -115
  116. package/dist/src-BZeu-SCD.js.map +1 -0
  117. package/dist/state/index.d.ts +1 -1
  118. package/dist/state/index.js +1 -1
  119. package/dist/streams/index.d.ts +1 -1
  120. package/dist/streams/index.js +1 -1
  121. package/dist/{streams-BcE8JP2X.d.ts → streams-Cmkj9QfW.d.ts} +4 -2
  122. package/dist/{streams-CCPRV6dt.js → streams-DW-UCOUc.js} +9 -2
  123. package/dist/streams-DW-UCOUc.js.map +1 -0
  124. package/dist/sub-routing.d.ts +12 -12
  125. package/dist/tasks/index.d.ts +1 -1
  126. package/dist/tasks/index.js +1 -1
  127. package/dist/{tasks-D4nLqVSI.js → tasks-68DESxf0.js} +2 -2
  128. package/dist/{tasks-D4nLqVSI.js.map → tasks-68DESxf0.js.map} +1 -1
  129. package/dist/{tasks-V2lCT8ZV.d.ts → tasks-9YxYtByh.d.ts} +2 -2
  130. package/dist/transport-PfFnt-Ld.d.ts +525 -0
  131. package/dist/{types-DCD6BNZH.d.ts → types-BA4anrjI.d.ts} +2 -2
  132. package/dist/voice/index.d.ts +2 -2
  133. package/dist/websockets/index.d.ts +23 -6
  134. package/dist/websockets/index.js +1 -1
  135. package/dist/{websockets-D7IzWbZb.js → websockets-Ci-LZFHH.js} +45 -20
  136. package/dist/{websockets-D7IzWbZb.js.map → websockets-Ci-LZFHH.js.map} +1 -1
  137. package/dist/wire-types-CnMt6_HR.js.map +1 -1
  138. package/dist/wire-types-CrjKvDyi.d.ts +300 -0
  139. package/dist/workflow-types.d.ts +25 -25
  140. package/dist/workflows.d.ts +21 -21
  141. package/dist/workflows.js +1 -1
  142. package/dist/{ws-chat-transport-UNRIS2xl.d.ts → ws-chat-transport-BbT1A5Lc.d.ts} +51 -2
  143. package/dist/{ws-chat-transport-rWwta645.js → ws-chat-transport-cqMKq3IY.js} +143 -16
  144. package/dist/ws-chat-transport-cqMKq3IY.js.map +1 -0
  145. package/docs/agent-tools.md +29 -4
  146. package/docs/browse-the-web.md +87 -5
  147. package/docs/chat-agents.md +124 -16
  148. package/docs/context.md +27 -0
  149. package/docs/durable-execution.md +2 -0
  150. package/docs/harnesses/pi.md +173 -0
  151. package/docs/human-in-the-loop.md +4 -0
  152. package/docs/index.md +3 -0
  153. package/docs/lifecycle.md +20 -4
  154. package/docs/models-pi-ai.md +325 -0
  155. package/docs/models.md +504 -0
  156. package/docs/resumable-streaming.md +2 -0
  157. package/docs/routing.md +13 -13
  158. package/docs/sessions.md +36 -1
  159. package/docs/state.md +1 -0
  160. package/docs/sub-agents.md +9 -0
  161. package/package.json +40 -2
  162. package/dist/agent-tools-y7zLfw4Q.js.map +0 -1
  163. package/dist/browser/ai.js.map +0 -1
  164. package/dist/client-C9DAjZIY.js.map +0 -1
  165. package/dist/client-tools-aIBO0Fk7.d.ts +0 -53
  166. package/dist/connector-CptFKzRh.js.map +0 -1
  167. package/dist/message-builder-BymO4N_D.js.map +0 -1
  168. package/dist/src-BNU3ZiJM.js.map +0 -1
  169. package/dist/streams-CCPRV6dt.js.map +0 -1
  170. package/dist/ws-chat-transport-rWwta645.js.map +0 -1
@@ -1,36 +1,40 @@
1
1
  import {
2
- $ as DetachedAgentToolConfig,
3
- B as AgentToolInterruptedReason,
2
+ $ as ChatCapableAgentClass,
3
+ B as AgentToolFailure,
4
4
  F as AgentToolDisplayMetadata,
5
- G as AgentToolRunInfo,
6
- H as AgentToolMilestone,
5
+ G as AgentToolProgressSnapshot,
6
+ H as AgentToolLifecycleResult,
7
7
  I as AgentToolEvent,
8
- J as AgentToolRunState,
9
- K as AgentToolRunInspection,
10
- L as AgentToolEventMessage,
8
+ J as AgentToolRunPart,
9
+ K as AgentToolRunInfo,
10
+ L as AgentToolEventDelivery,
11
11
  M as AGENT_TOOL_MILESTONE_PART,
12
12
  N as AGENT_TOOL_PROGRESS_PART,
13
13
  P as AgentToolChildAdapter,
14
- Q as ChatCapableAgentClass,
15
- R as AgentToolEventState,
16
- U as AgentToolProgress,
17
- V as AgentToolLifecycleResult,
18
- W as AgentToolProgressSnapshot,
19
- X as AgentToolStoredChunk,
20
- Y as AgentToolRunStatus,
21
- Z as AgentToolTerminalStatus,
22
- et as DetachedRunAgentToolResult,
23
- nt as RunAgentToolResult,
24
- q as AgentToolRunPart,
25
- tt as RunAgentToolOptions,
26
- z as AgentToolFailure
27
- } from "./agent-routing-B2XLNMxq.js";
14
+ Q as AgentToolTerminalStatus,
15
+ R as AgentToolEventMessage,
16
+ U as AgentToolMilestone,
17
+ V as AgentToolInterruptedReason,
18
+ W as AgentToolProgress,
19
+ X as AgentToolRunStatus,
20
+ Y as AgentToolRunState,
21
+ Z as AgentToolStoredChunk,
22
+ at as isPositionlessAgentToolChunk,
23
+ et as DetachedAgentToolConfig,
24
+ it as isAgentToolLifecycleChunk,
25
+ nt as RunAgentToolOptions,
26
+ q as AgentToolRunInspection,
27
+ rt as RunAgentToolResult,
28
+ tt as DetachedRunAgentToolResult,
29
+ z as AgentToolEventState
30
+ } from "./agent-routing-0DR0Tk2v.js";
28
31
  export {
29
32
  AGENT_TOOL_MILESTONE_PART,
30
33
  AGENT_TOOL_PROGRESS_PART,
31
34
  AgentToolChildAdapter,
32
35
  AgentToolDisplayMetadata,
33
36
  AgentToolEvent,
37
+ AgentToolEventDelivery,
34
38
  AgentToolEventMessage,
35
39
  AgentToolEventState,
36
40
  AgentToolFailure,
@@ -50,5 +54,7 @@ export {
50
54
  DetachedAgentToolConfig,
51
55
  DetachedRunAgentToolResult,
52
56
  RunAgentToolOptions,
53
- RunAgentToolResult
57
+ RunAgentToolResult,
58
+ isAgentToolLifecycleChunk,
59
+ isPositionlessAgentToolChunk
54
60
  };
@@ -14,7 +14,29 @@ const AGENT_TOOL_PROGRESS_PART = "data-agent-progress";
14
14
  * re-resolves milestone waiters. See `design/rfc-detached-agent-tools.md`.
15
15
  */
16
16
  const AGENT_TOOL_MILESTONE_PART = "data-agent-milestone";
17
+ /**
18
+ * Whether a chunk body is a progress or milestone frame. These are broadcast
19
+ * but never written to the child's chunk store, so they have no stored-chunk
20
+ * position and must not take part in stored-position numbering or dedupe.
21
+ */
22
+ function isAgentToolLifecycleChunk(body) {
23
+ if (!body.includes("data-agent-progress") && !body.includes("data-agent-milestone")) return false;
24
+ try {
25
+ const type = JSON.parse(body)?.type;
26
+ return type === "data-agent-progress" || type === "data-agent-milestone";
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Whether a forwarded chunk has no stored-chunk position: a progress or
33
+ * milestone frame, or a chunk too large to store. Such chunks carry the next
34
+ * stored position without consuming it.
35
+ */
36
+ function isPositionlessAgentToolChunk(chunk) {
37
+ return chunk.unstoredId !== void 0 || isAgentToolLifecycleChunk(chunk.body);
38
+ }
17
39
  //#endregion
18
- export { AGENT_TOOL_MILESTONE_PART, AGENT_TOOL_PROGRESS_PART };
40
+ export { AGENT_TOOL_MILESTONE_PART, AGENT_TOOL_PROGRESS_PART, isAgentToolLifecycleChunk, isPositionlessAgentToolChunk };
19
41
 
20
42
  //# sourceMappingURL=agent-tool-types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tool-types.js","names":[],"sources":["../src/agent-tool-types.ts"],"sourcesContent":["import type { Agent, SubAgentClass } from \"./index\";\n\nexport type AgentToolRunStatus =\n | \"starting\"\n | \"running\"\n | \"completed\"\n | \"error\"\n | \"aborted\"\n | \"interrupted\";\n\nexport type AgentToolTerminalStatus = Extract<\n AgentToolRunStatus,\n \"completed\" | \"error\" | \"aborted\" | \"interrupted\"\n>;\n\n/**\n * Machine-readable cause of an `interrupted` seal (#1630 follow-up). Lets a\n * caller branch on WHY a run was abandoned without parsing the human-readable\n * `error` prose, which is not a stable contract.\n *\n * - `no-progress` — the child went silent for a full no-progress window while\n * the parent was tailing it (genuinely stalled / hung).\n * - `window-exceeded` — a finite `agentToolReattachMaxWindowMs` ceiling elapsed\n * while the child was still non-terminal. Only fires when an integrator opts\n * into a hard wall-clock cap (the default ceiling is `Infinity`).\n * - `not-tailable` — the child runtime cannot live-tail, so the parent could\n * not re-attach to its stream to follow it to terminal.\n * - `inspect-timeout` — inspecting the child timed out during parent recovery.\n * - `inspect-failed` — inspecting the child failed during parent recovery.\n * - `recovery-deadline` — the overall parent-recovery deadline elapsed before\n * this run could be reconciled.\n * - `budget-exceeded` — a detached run's absolute `maxBudgetMs` ceiling elapsed\n * before it reached a terminal. The parent gave up watching and tore the\n * child down. Like `window-exceeded` this is a soft seal: a child that\n * completes anyway can still repair the run and re-fire the completion hook.\n */\nexport type AgentToolInterruptedReason =\n | \"no-progress\"\n | \"window-exceeded\"\n | \"not-tailable\"\n | \"inspect-timeout\"\n | \"inspect-failed\"\n | \"recovery-deadline\"\n | \"budget-exceeded\";\n\n/**\n * Structured failure envelope an `agentTool()` returns when a sub-agent run\n * does not complete. Instead of an opaque error string the parent model would\n * parrot back to the user, the caller (or an orchestration harness) gets a\n * machine-readable signal:\n *\n * - `status` mirrors the underlying terminal status (`error` | `aborted` |\n * `interrupted`).\n * - `retryable` is `true` only for a transient interruption — the child was\n * reset or superseded by a deploy / parent recovery and never reached a\n * logical outcome, so re-dispatching the same run is the right move. A\n * genuine `error` or an intentional `aborted` is `false`.\n * - `error` stays human-readable for logs and UI.\n */\nexport type AgentToolFailure = {\n ok: false;\n status: Exclude<AgentToolTerminalStatus, \"completed\">;\n error: string;\n retryable: boolean;\n /** Present only when `status` is `interrupted` — machine-readable cause. */\n reason?: AgentToolInterruptedReason;\n /**\n * Present only when `status` is `interrupted`. `true` when the child facet was\n * still non-terminal (running / advancing) at the moment the parent stopped\n * waiting; `false` once the parent has torn the child down so it is no longer\n * doing work. Lets a caller decide between re-dispatching vs. reconnecting.\n */\n childStillRunning?: boolean;\n};\n\nexport type AgentToolDisplayMetadata = {\n name?: string;\n icon?: string;\n} & Record<string, unknown>;\n\n/**\n * Reserved chunk type a sub-agent emits via `reportProgress` while it runs.\n * Rides the child's own UI-message stream as a **transient** data part, so it\n * re-broadcasts to the parent's clients (via the parent's tail) and surfaces in\n * `useAgentToolEvents` without persisting into the child's stored message parts.\n * See `design/rfc-detached-agent-tools.md` §\"Progress and milestone signaling\".\n */\nexport const AGENT_TOOL_PROGRESS_PART = \"data-agent-progress\";\n\n/**\n * Reserved chunk type a sub-agent emits via `reportProgress({ milestone })`.\n * Unlike the ephemeral progress part this rides the child's stream as a\n * **persisted** data part, so it survives eviction, replays on drill-in, and\n * re-resolves milestone waiters. See `design/rfc-detached-agent-tools.md`.\n */\nexport const AGENT_TOOL_MILESTONE_PART = \"data-agent-milestone\";\n\n/**\n * Ephemeral progress signal a running sub-agent emits with `reportProgress`. The\n * well-known fields drive generic UI (a bar + status line) with no per-app\n * convention; `data` is an app-specific escape hatch that is **live-only** by\n * default (not persisted) unless `reportProgress(p, { persist: true })`. Naming a\n * `milestone` promotes the signal to the **durable** tier: it persists as one row\n * per milestone, replays, and (with `data`) is retained.\n */\nexport type AgentToolProgress<T = unknown> = {\n /** 0..1 — drives a progress bar. */\n fraction?: number;\n /** Human-readable status line, e.g. \"Ingested 40k/80k rows\". */\n message?: string;\n /** Coarse stage label, e.g. \"scaffolding\" | \"deploying\". */\n phase?: string;\n /**\n * Present ⇒ a **durable** milestone: persisted, replayable, and surfaced as a\n * distinct row in `AgentToolRunState.milestones` / `inspectAgentToolRun`. Use\n * for named phase boundaries (\"schema-ready\", \"preview-ready\", \"deployed\").\n */\n milestone?: string;\n /** App-specific payload; live-only for progress, persisted for milestones. */\n data?: T;\n};\n\n/**\n * A durable milestone a sub-agent reached, projected onto `AgentToolRunState`\n * and `inspectAgentToolRun`. `sequence` is monotonic per run so replay/live\n * races dedupe on `(runId, sequence)`.\n */\nexport type AgentToolMilestone = {\n name: string;\n /** Monotonic per-run ordinal; dedupe key for replay vs live races. */\n sequence: number;\n /** Epoch ms the milestone was reached. */\n at: number;\n /** App-specific payload carried with the milestone (persisted). */\n data?: unknown;\n};\n\n/**\n * Latest progress snapshot persisted on the child run row and surfaced through\n * `inspectAgentToolRun` + `AgentToolRunState`. Only the safe-to-inspect fields\n * are retained by default; `at` is the emit timestamp (drives the resetting\n * no-progress budget).\n */\nexport type AgentToolProgressSnapshot = {\n fraction?: number;\n message?: string;\n phase?: string;\n /**\n * Set when this signal was a durable milestone (`reportProgress({ milestone })`).\n * Lets an `onProgress` consumer branch on milestone vs. ephemeral progress.\n */\n milestone?: string;\n /** Epoch ms of the latest signal. */\n at: number;\n /** Present only when the emitter opted into persisting `data`. */\n data?: unknown;\n};\n\nexport type AgentToolRunInfo = {\n runId: string;\n parentToolCallId?: string;\n agentType: string;\n inputPreview?: unknown;\n status: AgentToolRunStatus;\n display?: AgentToolDisplayMetadata;\n /**\n * Caller-controlled `metadata.source` for chat-agent `detached.notify`\n * completions. Present only for detached notify runs that supplied one.\n */\n notifySource?: string;\n displayOrder: number;\n startedAt: number;\n completedAt?: number;\n};\n\nexport type AgentToolLifecycleResult = {\n status: AgentToolTerminalStatus;\n summary?: string;\n error?: string;\n /** Present only when `status` is `interrupted` — machine-readable cause. */\n reason?: AgentToolInterruptedReason;\n /**\n * Present only when `status` is `interrupted`. Whether the child facet was\n * still non-terminal when the parent stopped waiting (before any teardown).\n */\n childStillRunning?: boolean;\n};\n\n/**\n * Configuration for a detached (\"background\") agent-tool run. See\n * `design/rfc-detached-agent-tools.md`.\n *\n * Callbacks are referenced by **method name** on the dispatching agent (the same\n * durable, eviction-surviving pattern as `Agent.schedule`) — never closures,\n * which cannot be rehydrated after the Durable Object is evicted.\n *\n * `Self` is threaded from `runAgentTool(cls, options)` so the method names are\n * type-checked against the calling agent's own methods.\n */\nexport type DetachedAgentToolConfig<Self = Record<string, unknown>> = {\n /**\n * Method invoked once per terminal delivery. Branch on `result.status`:\n * `\"completed\" | \"error\" | \"aborted\" | \"interrupted\"`. A budget give-up\n * arrives as `status: \"interrupted\"` with `reason: \"budget-exceeded\"`; because\n * `interrupted` is soft, a child that later completes can fire the hook again\n * with `\"completed\"`, so a give-up never hides a late real result. Make the\n * handler idempotent.\n */\n onFinish?: Extract<keyof Self, string>;\n /**\n * Absolute safety ceiling — a backstop against a child that runs forever. On\n * expiry the parent gives up watching (delivers `onFinish` with\n * `interrupted` / `budget-exceeded`) and tears the child down. Defaults to the\n * parent-level `detachedMaxBudgetMs`.\n */\n maxBudgetMs?: number;\n /**\n * Per-run override of the resetting no-progress window (ms). Once the child\n * emits its first `reportProgress`, the parent gives up if it then goes silent\n * for this long (resets on each signal). Defaults to the parent-level\n * `detachedNoProgressBudgetMs` (1h). `0`/`Infinity` disables it.\n */\n noProgressBudgetMs?: number;\n /**\n * Chat-agent convenience (`@cloudflare/think` / `AIChatAgent`): when the run\n * finishes, inject a message into the chat so the model can react to the\n * result, instead of you wiring `onFinish` by hand. Sugar that auto-targets\n * the agent's `_cfDetachedNotifyFinish` hook; ignored on a base `Agent` that\n * does not implement it, and ignored when `onFinish` is also set (an explicit\n * `onFinish` wins). Pass `{ source }` to fit the injected message into your\n * app's existing metadata taxonomy. Override `formatDetachedCompletion()` to\n * customize the injected text.\n */\n notify?: boolean | { source?: string };\n /**\n * Chat-agent convenience: milestone names that, when the detached run reaches\n * them, surface an idempotent synthetic message in the chat BEFORE the run\n * finishes. Each `(runId, name)` fires at most once (idempotency-keyed),\n * whether observed live or reconciled after eviction. Override the wording via\n * `formatDetachedMilestone()`. Requires a chat host (`@cloudflare/think`); a\n * no-op on a base `Agent`.\n *\n * Two delivery modes (the string-array shorthand defaults to `\"narrate\"`):\n * - `\"narrate\"` (default) — inject a synthetic **assistant** message directly\n * (no inference): a cheap, honest status line (\"Found 2 sources…\") that does\n * not trigger a model turn. Best for pure progress narration.\n * - `\"react\"` — inject a **user-role** turn so the model responds to the\n * milestone (steer, start dependent work, narrate with context). Costs a\n * model turn. Opt in for milestones the agent should *act on*.\n */\n onMilestones?: string[] | { names: string[]; mode?: \"react\" | \"narrate\" };\n};\n\nexport type RunAgentToolOptions<\n Input = unknown,\n Self = Record<string, unknown>\n> = {\n input: Input;\n runId?: string;\n parentToolCallId?: string;\n displayOrder?: number;\n signal?: AbortSignal;\n inputPreview?: unknown;\n display?: AgentToolDisplayMetadata;\n /**\n * Run the sub-agent **detached**: dispatch it, let the current turn continue,\n * and (optionally) get a durable callback when it finishes. `true` is\n * fire-and-forget (observe via `agent-tool-event` frames + the global\n * `onAgentToolFinish` hook); an object adds the targeted, eviction-surviving\n * `onFinish` callback. A detached run does NOT inherit `options.signal` — it\n * must outlive the spawning turn; cancel it explicitly via `cancelAgentTool`.\n */\n detached?: boolean | DetachedAgentToolConfig<Self>;\n};\n\n/**\n * Result of dispatching a detached run. Returns immediately after dispatch\n * rather than after completion.\n */\nexport type DetachedRunAgentToolResult = {\n runId: string;\n agentType: string;\n /**\n * `\"running\"` on a successful dispatch; `\"error\"` if dispatch itself failed\n * (e.g. the `maxConcurrentAgentTools` cap was exceeded — rejected\n * synchronously, no child started, no callback wired).\n */\n status: \"running\" | \"error\";\n error?: string;\n};\n\nexport type RunAgentToolResult<Output = unknown> = {\n runId: string;\n agentType: string;\n status: AgentToolTerminalStatus;\n output?: Output;\n summary?: string;\n error?: string;\n /**\n * Present only when `status` is `interrupted` — a machine-readable cause so\n * callers don't pattern-match the `error` prose (#1630 follow-up).\n */\n reason?: AgentToolInterruptedReason;\n /**\n * Present only when `status` is `interrupted`. `true` when the child facet was\n * still non-terminal (running / advancing) at the moment the parent stopped\n * waiting and before any teardown; `false` once the parent has torn the child\n * down so it is no longer doing work.\n */\n childStillRunning?: boolean;\n};\n\nexport type ChatCapableAgentClass<T extends Agent = Agent> = SubAgentClass<T>;\n\nexport type AgentToolRunInspection<Output = unknown> = {\n runId: string;\n status: Exclude<AgentToolRunStatus, \"interrupted\">;\n requestId?: string;\n streamId?: string;\n output?: Output;\n summary?: string;\n error?: string;\n startedAt: number;\n completedAt?: number;\n /**\n * Latest progress snapshot the child has persisted, so a rehydrated parent\n * (recovery / backbone reconcile) can reconstruct \"where is this run\" and\n * reset the resetting no-progress budget without having tailed the live\n * stream. Absent until the child emits its first `reportProgress`.\n */\n progress?: AgentToolProgressSnapshot;\n /**\n * Durable milestones the child has persisted, ordered by `sequence`. Lets a\n * rehydrated parent (recovery / backbone reconcile) replay milestone-gated\n * work and milestone notifications without having observed the live stream.\n */\n milestones?: AgentToolMilestone[];\n};\n\nexport type AgentToolStoredChunk = {\n sequence: number;\n body: string;\n};\n\nexport type AgentToolChildAdapter<Input = unknown, Output = unknown> = {\n startAgentToolRun(\n input: Input,\n options: { runId: string; signal?: AbortSignal }\n ): Promise<AgentToolRunInspection<Output>>;\n cancelAgentToolRun(runId: string, reason?: unknown): Promise<void>;\n inspectAgentToolRun(\n runId: string\n ): Promise<AgentToolRunInspection<Output> | null>;\n getAgentToolChunks(\n runId: string,\n options?: { afterSequence?: number }\n ): Promise<AgentToolStoredChunk[]>;\n tailAgentToolRun?(\n runId: string,\n options?: { afterSequence?: number; signal?: AbortSignal }\n ): Promise<ReadableStream<AgentToolStoredChunk>>;\n};\n\nexport type AgentToolEvent =\n | {\n kind: \"started\";\n runId: string;\n agentType: string;\n inputPreview?: unknown;\n order: number;\n display?: AgentToolDisplayMetadata;\n }\n | {\n kind: \"chunk\";\n runId: string;\n body: string;\n }\n | {\n kind: \"finished\";\n runId: string;\n summary: string;\n }\n | {\n kind: \"error\";\n runId: string;\n error: string;\n }\n | {\n kind: \"aborted\";\n runId: string;\n reason?: string;\n }\n | {\n kind: \"interrupted\";\n runId: string;\n error: string;\n /** Machine-readable cause of the interrupt (#1630 follow-up). */\n reason?: AgentToolInterruptedReason;\n /**\n * Whether the child facet was still non-terminal when the parent stopped\n * waiting (before any teardown). Lets a UI distinguish a still-running\n * child from one the parent has torn down.\n */\n childStillRunning?: boolean;\n };\n\nexport type AgentToolEventMessage = {\n type: \"agent-tool-event\";\n parentToolCallId?: string;\n sequence: number;\n replay?: true;\n event: AgentToolEvent;\n};\n\nexport type AgentToolRunPart = { type: string };\n\nexport type AgentToolRunState<\n Part extends AgentToolRunPart = AgentToolRunPart\n> = {\n runId: string;\n agentType: string;\n parentToolCallId?: string;\n inputPreview?: unknown;\n order: number;\n display?: AgentToolDisplayMetadata;\n status: \"running\" | \"completed\" | \"error\" | \"aborted\" | \"interrupted\";\n /**\n * Message parts reconstructed from the child agent's streamed chunks.\n *\n * The default stays framework-neutral so importing `agents` does not require\n * an AI SDK peer. AI SDK consumers can use\n * `AgentToolRunState<UIMessage[\"parts\"][number]>` when they need its exact\n * discriminated union.\n */\n parts: Part[];\n summary?: string;\n error?: string;\n /**\n * Present only when `status` is `interrupted` — machine-readable cause and\n * whether the child is still running, mirrored from the wire event so a UI\n * can render the reason without parsing `error` (#1630 follow-up).\n */\n reason?: AgentToolInterruptedReason;\n childStillRunning?: boolean;\n /**\n * Latest progress snapshot, projected from the child's transient\n * `data-agent-progress` signals so a UI can render a bar / ETA / phase label\n * for a running (especially detached / background) run without drilling in.\n */\n progress?: AgentToolProgressSnapshot;\n /**\n * Durable milestones the run has reached, ordered by `sequence` (deduped\n * across replay/live races). Drives milestone chips / a phase timeline.\n */\n milestones?: AgentToolMilestone[];\n subAgent: { agent: string; name: string };\n};\n\nexport type AgentToolEventState<\n Part extends AgentToolRunPart = AgentToolRunPart\n> = {\n runsById: Record<string, AgentToolRunState<Part>>;\n runsByToolCallId: Record<string, AgentToolRunState<Part>[]>;\n unboundRuns: AgentToolRunState<Part>[];\n};\n"],"mappings":";;;;;;;;AAuFA,MAAa,2BAA2B;;;;;;;AAQxC,MAAa,4BAA4B"}
1
+ {"version":3,"file":"agent-tool-types.js","names":[],"sources":["../src/agent-tool-types.ts"],"sourcesContent":["import type { Agent, SubAgentClass } from \"./index\";\n\nexport type AgentToolRunStatus =\n | \"starting\"\n | \"running\"\n | \"completed\"\n | \"error\"\n | \"aborted\"\n | \"interrupted\";\n\nexport type AgentToolTerminalStatus = Extract<\n AgentToolRunStatus,\n \"completed\" | \"error\" | \"aborted\" | \"interrupted\"\n>;\n\n/**\n * Machine-readable cause of an `interrupted` seal (#1630 follow-up). Lets a\n * caller branch on WHY a run was abandoned without parsing the human-readable\n * `error` prose, which is not a stable contract.\n *\n * - `no-progress` — the child went silent for a full no-progress window while\n * the parent was tailing it (genuinely stalled / hung).\n * - `window-exceeded` — a finite `agentToolReattachMaxWindowMs` ceiling elapsed\n * while the child was still non-terminal. Only fires when an integrator opts\n * into a hard wall-clock cap (the default ceiling is `Infinity`).\n * - `not-tailable` — the child runtime cannot live-tail, so the parent could\n * not re-attach to its stream to follow it to terminal.\n * - `inspect-timeout` — inspecting the child timed out during parent recovery.\n * - `inspect-failed` — inspecting the child failed during parent recovery.\n * - `recovery-deadline` — the overall parent-recovery deadline elapsed before\n * this run could be reconciled.\n * - `budget-exceeded` — a detached run's absolute `maxBudgetMs` ceiling elapsed\n * before it reached a terminal. The parent gave up watching and tore the\n * child down. Like `window-exceeded` this is a soft seal: a child that\n * completes anyway can still repair the run and re-fire the completion hook.\n */\nexport type AgentToolInterruptedReason =\n | \"no-progress\"\n | \"window-exceeded\"\n | \"not-tailable\"\n | \"inspect-timeout\"\n | \"inspect-failed\"\n | \"recovery-deadline\"\n | \"budget-exceeded\";\n\n/**\n * Structured failure envelope an `agentTool()` returns when a sub-agent run\n * does not complete. Instead of an opaque error string the parent model would\n * parrot back to the user, the caller (or an orchestration harness) gets a\n * machine-readable signal:\n *\n * - `status` mirrors the underlying terminal status (`error` | `aborted` |\n * `interrupted`).\n * - `retryable` is `true` only for a transient interruption — the child was\n * reset or superseded by a deploy / parent recovery and never reached a\n * logical outcome, so re-dispatching the same run is the right move. A\n * genuine `error` or an intentional `aborted` is `false`.\n * - `error` stays human-readable for logs and UI.\n */\nexport type AgentToolFailure = {\n ok: false;\n status: Exclude<AgentToolTerminalStatus, \"completed\">;\n error: string;\n retryable: boolean;\n /** Present only when `status` is `interrupted` — machine-readable cause. */\n reason?: AgentToolInterruptedReason;\n /**\n * Present only when `status` is `interrupted`. `true` when the child facet was\n * still non-terminal (running / advancing) at the moment the parent stopped\n * waiting; `false` once the parent has torn the child down so it is no longer\n * doing work. Lets a caller decide between re-dispatching vs. reconnecting.\n */\n childStillRunning?: boolean;\n};\n\nexport type AgentToolDisplayMetadata = {\n name?: string;\n icon?: string;\n} & Record<string, unknown>;\n\n/**\n * Reserved chunk type a sub-agent emits via `reportProgress` while it runs.\n * Rides the child's own UI-message stream as a **transient** data part, so it\n * re-broadcasts to the parent's clients (via the parent's tail) and surfaces in\n * `useAgentToolEvents` without persisting into the child's stored message parts.\n * See `design/rfc-detached-agent-tools.md` §\"Progress and milestone signaling\".\n */\nexport const AGENT_TOOL_PROGRESS_PART = \"data-agent-progress\";\n\n/**\n * Reserved chunk type a sub-agent emits via `reportProgress({ milestone })`.\n * Unlike the ephemeral progress part this rides the child's stream as a\n * **persisted** data part, so it survives eviction, replays on drill-in, and\n * re-resolves milestone waiters. See `design/rfc-detached-agent-tools.md`.\n */\nexport const AGENT_TOOL_MILESTONE_PART = \"data-agent-milestone\";\n\n/**\n * Whether a chunk body is a progress or milestone frame. These are broadcast\n * but never written to the child's chunk store, so they have no stored-chunk\n * position and must not take part in stored-position numbering or dedupe.\n */\nexport function isAgentToolLifecycleChunk(body: string): boolean {\n if (\n !body.includes(AGENT_TOOL_PROGRESS_PART) &&\n !body.includes(AGENT_TOOL_MILESTONE_PART)\n ) {\n return false;\n }\n try {\n const type = (JSON.parse(body) as { type?: unknown } | null)?.type;\n return (\n type === AGENT_TOOL_PROGRESS_PART || type === AGENT_TOOL_MILESTONE_PART\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Whether a forwarded chunk has no stored-chunk position: a progress or\n * milestone frame, or a chunk too large to store. Such chunks carry the next\n * stored position without consuming it.\n */\nexport function isPositionlessAgentToolChunk(\n chunk: AgentToolStoredChunk\n): boolean {\n return (\n chunk.unstoredId !== undefined || isAgentToolLifecycleChunk(chunk.body)\n );\n}\n\n/**\n * Ephemeral progress signal a running sub-agent emits with `reportProgress`. The\n * well-known fields drive generic UI (a bar + status line) with no per-app\n * convention; `data` is an app-specific escape hatch that is **live-only** by\n * default (not persisted) unless `reportProgress(p, { persist: true })`. Naming a\n * `milestone` promotes the signal to the **durable** tier: it persists as one row\n * per milestone, replays, and (with `data`) is retained.\n */\nexport type AgentToolProgress<T = unknown> = {\n /** 0..1 — drives a progress bar. */\n fraction?: number;\n /** Human-readable status line, e.g. \"Ingested 40k/80k rows\". */\n message?: string;\n /** Coarse stage label, e.g. \"scaffolding\" | \"deploying\". */\n phase?: string;\n /**\n * Present ⇒ a **durable** milestone: persisted, replayable, and surfaced as a\n * distinct row in `AgentToolRunState.milestones` / `inspectAgentToolRun`. Use\n * for named phase boundaries (\"schema-ready\", \"preview-ready\", \"deployed\").\n */\n milestone?: string;\n /** App-specific payload; live-only for progress, persisted for milestones. */\n data?: T;\n};\n\n/**\n * A durable milestone a sub-agent reached, projected onto `AgentToolRunState`\n * and `inspectAgentToolRun`. `sequence` is monotonic per run so replay/live\n * races dedupe on `(runId, sequence)`.\n */\nexport type AgentToolMilestone = {\n name: string;\n /** Monotonic per-run ordinal; dedupe key for replay vs live races. */\n sequence: number;\n /** Epoch ms the milestone was reached. */\n at: number;\n /** App-specific payload carried with the milestone (persisted). */\n data?: unknown;\n};\n\n/**\n * Latest progress snapshot persisted on the child run row and surfaced through\n * `inspectAgentToolRun` + `AgentToolRunState`. Only the safe-to-inspect fields\n * are retained by default; `at` is the emit timestamp (drives the resetting\n * no-progress budget).\n */\nexport type AgentToolProgressSnapshot = {\n fraction?: number;\n message?: string;\n phase?: string;\n /**\n * Set when this signal was a durable milestone (`reportProgress({ milestone })`).\n * Lets an `onProgress` consumer branch on milestone vs. ephemeral progress.\n */\n milestone?: string;\n /** Epoch ms of the latest signal. */\n at: number;\n /** Present only when the emitter opted into persisting `data`. */\n data?: unknown;\n};\n\nexport type AgentToolRunInfo = {\n runId: string;\n parentToolCallId?: string;\n agentType: string;\n inputPreview?: unknown;\n status: AgentToolRunStatus;\n display?: AgentToolDisplayMetadata;\n /**\n * Caller-controlled `metadata.source` for chat-agent `detached.notify`\n * completions. Present only for detached notify runs that supplied one.\n */\n notifySource?: string;\n displayOrder: number;\n startedAt: number;\n completedAt?: number;\n};\n\nexport type AgentToolLifecycleResult = {\n status: AgentToolTerminalStatus;\n summary?: string;\n error?: string;\n /** Present only when `status` is `interrupted` — machine-readable cause. */\n reason?: AgentToolInterruptedReason;\n /**\n * Present only when `status` is `interrupted`. Whether the child facet was\n * still non-terminal when the parent stopped waiting (before any teardown).\n */\n childStillRunning?: boolean;\n};\n\n/**\n * Configuration for a detached (\"background\") agent-tool run. See\n * `design/rfc-detached-agent-tools.md`.\n *\n * Callbacks are referenced by **method name** on the dispatching agent (the same\n * durable, eviction-surviving pattern as `Agent.schedule`) — never closures,\n * which cannot be rehydrated after the Durable Object is evicted.\n *\n * `Self` is threaded from `runAgentTool(cls, options)` so the method names are\n * type-checked against the calling agent's own methods.\n */\nexport type DetachedAgentToolConfig<Self = Record<string, unknown>> = {\n /**\n * Method invoked once per terminal delivery. Branch on `result.status`:\n * `\"completed\" | \"error\" | \"aborted\" | \"interrupted\"`. A budget give-up\n * arrives as `status: \"interrupted\"` with `reason: \"budget-exceeded\"`; because\n * `interrupted` is soft, a child that later completes can fire the hook again\n * with `\"completed\"`, so a give-up never hides a late real result. Make the\n * handler idempotent.\n */\n onFinish?: Extract<keyof Self, string>;\n /**\n * Absolute safety ceiling — a backstop against a child that runs forever. On\n * expiry the parent gives up watching (delivers `onFinish` with\n * `interrupted` / `budget-exceeded`) and tears the child down. Defaults to the\n * parent-level `detachedMaxBudgetMs`.\n */\n maxBudgetMs?: number;\n /**\n * Per-run override of the resetting no-progress window (ms). Once the child\n * emits its first `reportProgress`, the parent gives up if it then goes silent\n * for this long (resets on each signal). Defaults to the parent-level\n * `detachedNoProgressBudgetMs` (1h). `0`/`Infinity` disables it.\n */\n noProgressBudgetMs?: number;\n /**\n * Chat-agent convenience (`@cloudflare/think` / `AIChatAgent`): when the run\n * finishes, inject a message into the chat so the model can react to the\n * result, instead of you wiring `onFinish` by hand. Sugar that auto-targets\n * the agent's `_cfDetachedNotifyFinish` hook; ignored on a base `Agent` that\n * does not implement it, and ignored when `onFinish` is also set (an explicit\n * `onFinish` wins). Pass `{ source }` to fit the injected message into your\n * app's existing metadata taxonomy. Override `formatDetachedCompletion()` to\n * customize the injected text.\n */\n notify?: boolean | { source?: string };\n /**\n * Chat-agent convenience: milestone names that, when the detached run reaches\n * them, surface an idempotent synthetic message in the chat BEFORE the run\n * finishes. Each `(runId, name)` fires at most once (idempotency-keyed),\n * whether observed live or reconciled after eviction. Override the wording via\n * `formatDetachedMilestone()`. Requires a chat host (`@cloudflare/think`); a\n * no-op on a base `Agent`.\n *\n * Two delivery modes (the string-array shorthand defaults to `\"narrate\"`):\n * - `\"narrate\"` (default) — inject a synthetic **assistant** message directly\n * (no inference): a cheap, honest status line (\"Found 2 sources…\") that does\n * not trigger a model turn. Best for pure progress narration.\n * - `\"react\"` — inject a **user-role** turn so the model responds to the\n * milestone (steer, start dependent work, narrate with context). Costs a\n * model turn. Opt in for milestones the agent should *act on*.\n */\n onMilestones?: string[] | { names: string[]; mode?: \"react\" | \"narrate\" };\n};\n\nexport type RunAgentToolOptions<\n Input = unknown,\n Self = Record<string, unknown>\n> = {\n input: Input;\n runId?: string;\n parentToolCallId?: string;\n displayOrder?: number;\n signal?: AbortSignal;\n inputPreview?: unknown;\n display?: AgentToolDisplayMetadata;\n /**\n * Run the sub-agent **detached**: dispatch it, let the current turn continue,\n * and (optionally) get a durable callback when it finishes. `true` is\n * fire-and-forget (observe via `agent-tool-event` frames + the global\n * `onAgentToolFinish` hook); an object adds the targeted, eviction-surviving\n * `onFinish` callback. A detached run does NOT inherit `options.signal` — it\n * must outlive the spawning turn; cancel it explicitly via `cancelAgentTool`.\n */\n detached?: boolean | DetachedAgentToolConfig<Self>;\n /**\n * Which child events reach the parent's clients. `\"full\"` (default) forwards\n * every streamed chunk. `\"terminal\"` forwards only lifecycle events: started,\n * progress and milestone frames, and the terminal event. The child still\n * persists its whole stream, and the parent still tails it for completion,\n * cancellation, progress and recovery. Use it for a headless parent with no\n * client watching the child. Not supported with `detached`.\n */\n eventDelivery?: AgentToolEventDelivery;\n};\n\nexport type AgentToolEventDelivery = \"full\" | \"terminal\";\n\n/**\n * Result of dispatching a detached run. Returns immediately after dispatch\n * rather than after completion.\n */\nexport type DetachedRunAgentToolResult = {\n runId: string;\n agentType: string;\n /**\n * `\"running\"` on a successful dispatch; `\"error\"` if dispatch itself failed\n * (e.g. the `maxConcurrentAgentTools` cap was exceeded — rejected\n * synchronously, no child started, no callback wired).\n */\n status: \"running\" | \"error\";\n error?: string;\n};\n\nexport type RunAgentToolResult<Output = unknown> = {\n runId: string;\n agentType: string;\n status: AgentToolTerminalStatus;\n output?: Output;\n summary?: string;\n error?: string;\n /**\n * Present only when `status` is `interrupted` — a machine-readable cause so\n * callers don't pattern-match the `error` prose (#1630 follow-up).\n */\n reason?: AgentToolInterruptedReason;\n /**\n * Present only when `status` is `interrupted`. `true` when the child facet was\n * still non-terminal (running / advancing) at the moment the parent stopped\n * waiting and before any teardown; `false` once the parent has torn the child\n * down so it is no longer doing work.\n */\n childStillRunning?: boolean;\n};\n\nexport type ChatCapableAgentClass<T extends Agent = Agent> = SubAgentClass<T>;\n\nexport type AgentToolRunInspection<Output = unknown> = {\n runId: string;\n status: Exclude<AgentToolRunStatus, \"interrupted\">;\n requestId?: string;\n streamId?: string;\n output?: Output;\n summary?: string;\n error?: string;\n startedAt: number;\n completedAt?: number;\n /**\n * Latest progress snapshot the child has persisted, so a rehydrated parent\n * (recovery / backbone reconcile) can reconstruct \"where is this run\" and\n * reset the resetting no-progress budget without having tailed the live\n * stream. Absent until the child emits its first `reportProgress`.\n */\n progress?: AgentToolProgressSnapshot;\n /**\n * Durable milestones the child has persisted, ordered by `sequence`. Lets a\n * rehydrated parent (recovery / backbone reconcile) replay milestone-gated\n * work and milestone notifications without having observed the live stream.\n */\n milestones?: AgentToolMilestone[];\n};\n\nexport type AgentToolStoredChunk = {\n sequence: number;\n body: string;\n /**\n * Set when the child broadcast this chunk but could not store it (it exceeds\n * the stored-chunk size limit). The chunk is never replayed, so it carries\n * the next stored position without consuming it and dedupes on this id.\n */\n unstoredId?: string;\n};\n\nexport type AgentToolChildAdapter<Input = unknown, Output = unknown> = {\n startAgentToolRun(\n input: Input,\n options: {\n runId: string;\n signal?: AbortSignal;\n /**\n * `\"terminal\"` means no client is watching this run's chunks, so the\n * child can skip broadcasting them.\n */\n eventDelivery?: AgentToolEventDelivery;\n }\n ): Promise<AgentToolRunInspection<Output>>;\n cancelAgentToolRun(runId: string, reason?: unknown): Promise<void>;\n inspectAgentToolRun(\n runId: string,\n options?: {\n /**\n * `false` reports the stored row as-is instead of first reconciling\n * (and possibly sealing) a stale run. Defaults to `true`.\n */\n reconcile?: boolean;\n }\n ): Promise<AgentToolRunInspection<Output> | null>;\n getAgentToolChunks(\n runId: string,\n options?: { afterSequence?: number }\n ): Promise<AgentToolStoredChunk[]>;\n tailAgentToolRun?(\n runId: string,\n options?: { afterSequence?: number; signal?: AbortSignal }\n ): Promise<ReadableStream<AgentToolStoredChunk>>;\n};\n\nexport type AgentToolEvent =\n | {\n kind: \"started\";\n runId: string;\n agentType: string;\n inputPreview?: unknown;\n order: number;\n display?: AgentToolDisplayMetadata;\n }\n | {\n kind: \"chunk\";\n runId: string;\n body: string;\n /** See {@link AgentToolStoredChunk.unstoredId}. */\n unstoredId?: string;\n }\n | {\n kind: \"finished\";\n runId: string;\n summary: string;\n }\n | {\n kind: \"error\";\n runId: string;\n error: string;\n }\n | {\n kind: \"aborted\";\n runId: string;\n reason?: string;\n }\n | {\n kind: \"interrupted\";\n runId: string;\n error: string;\n /** Machine-readable cause of the interrupt (#1630 follow-up). */\n reason?: AgentToolInterruptedReason;\n /**\n * Whether the child facet was still non-terminal when the parent stopped\n * waiting (before any teardown). Lets a UI distinguish a still-running\n * child from one the parent has torn down.\n */\n childStillRunning?: boolean;\n };\n\nexport type AgentToolEventMessage = {\n type: \"agent-tool-event\";\n parentToolCallId?: string;\n sequence: number;\n replay?: true;\n event: AgentToolEvent;\n};\n\nexport type AgentToolRunPart = { type: string };\n\nexport type AgentToolRunState<\n Part extends AgentToolRunPart = AgentToolRunPart\n> = {\n runId: string;\n agentType: string;\n parentToolCallId?: string;\n inputPreview?: unknown;\n order: number;\n display?: AgentToolDisplayMetadata;\n status: \"running\" | \"completed\" | \"error\" | \"aborted\" | \"interrupted\";\n /**\n * Message parts reconstructed from the child agent's streamed chunks.\n *\n * The default stays framework-neutral so importing `agents` does not require\n * an AI SDK peer. AI SDK consumers can use\n * `AgentToolRunState<UIMessage[\"parts\"][number]>` when they need its exact\n * discriminated union.\n */\n parts: Part[];\n summary?: string;\n error?: string;\n /**\n * Present only when `status` is `interrupted` — machine-readable cause and\n * whether the child is still running, mirrored from the wire event so a UI\n * can render the reason without parsing `error` (#1630 follow-up).\n */\n reason?: AgentToolInterruptedReason;\n childStillRunning?: boolean;\n /**\n * Latest progress snapshot, projected from the child's transient\n * `data-agent-progress` signals so a UI can render a bar / ETA / phase label\n * for a running (especially detached / background) run without drilling in.\n */\n progress?: AgentToolProgressSnapshot;\n /**\n * Durable milestones the run has reached, ordered by `sequence` (deduped\n * across replay/live races). Drives milestone chips / a phase timeline.\n */\n milestones?: AgentToolMilestone[];\n subAgent: { agent: string; name: string };\n};\n\nexport type AgentToolEventState<\n Part extends AgentToolRunPart = AgentToolRunPart\n> = {\n runsById: Record<string, AgentToolRunState<Part>>;\n runsByToolCallId: Record<string, AgentToolRunState<Part>[]>;\n unboundRuns: AgentToolRunState<Part>[];\n};\n"],"mappings":";;;;;;;;AAuFA,MAAa,2BAA2B;;;;;;;AAQxC,MAAa,4BAA4B;;;;;;AAOzC,SAAgB,0BAA0B,MAAuB;CAC/D,IACE,CAAC,KAAK,SAAA,qBAAiC,KACvC,CAAC,KAAK,SAAA,sBAAkC,GAExC,OAAO;CAET,IAAI;EACF,MAAM,OAAQ,KAAK,MAAM,IAAI,CAAC,EAAgC;EAC9D,OACE,SAAA,yBAAqC,SAAA;CAEzC,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,SAAgB,6BACd,OACS;CACT,OACE,MAAM,eAAe,KAAA,KAAa,0BAA0B,MAAM,IAAI;AAE1E"}
@@ -1,5 +1,21 @@
1
- import { AGENT_TOOL_MILESTONE_PART, AGENT_TOOL_PROGRESS_PART } from "./agent-tool-types.js";
2
- import { t as applyChunkToParts } from "./message-builder-BymO4N_D.js";
1
+ import { AGENT_TOOL_MILESTONE_PART, AGENT_TOOL_PROGRESS_PART, isAgentToolLifecycleChunk } from "./agent-tool-types.js";
2
+ import { t as applyChunkToParts } from "./message-builder-DAl9AhHH.js";
3
+ //#region src/chat/chunk-size.ts
4
+ const textEncoder = new TextEncoder();
5
+ /** Maximum serialized chunk body size before skipping storage (bytes). */
6
+ const CHUNK_MAX_BYTES = 18e5;
7
+ /** Byte size of a chunk body in its stored (JSON-escaped) encoding. */
8
+ function storedChunkBytes(body) {
9
+ return textEncoder.encode(JSON.stringify(body)).byteLength;
10
+ }
11
+ /**
12
+ * Whether `ResumableStream.storeChunk` skips storing this body: it is still
13
+ * broadcast live, but absent from replay.
14
+ */
15
+ function isChunkTooLargeToStore(body) {
16
+ return storedChunkBytes(body) > CHUNK_MAX_BYTES;
17
+ }
18
+ //#endregion
3
19
  //#region src/chat/agent-tools.ts
4
20
  /**
5
21
  * Pull a reserved `data-agent-progress` chunk (emitted by a running sub-agent's
@@ -91,6 +107,7 @@ var AgentToolProgressEmitter = class {
91
107
  };
92
108
  this.hooks.broadcast(requestId, JSON.stringify({
93
109
  type: AGENT_TOOL_PROGRESS_PART,
110
+ id: crypto.randomUUID(),
94
111
  transient: true,
95
112
  data: wire
96
113
  }));
@@ -250,6 +267,42 @@ function createAgentToolEventState() {
250
267
  unboundRuns: []
251
268
  };
252
269
  }
270
+ /**
271
+ * Identity of an agent-tool event for replay-vs-live dedupe. Ordinary chunks
272
+ * key on the broadcast `sequence`, which is their stored-chunk position on
273
+ * both the live and replay paths. Lifecycle events key on their content: a
274
+ * reattached run can be interrupted again with a different reason, and the
275
+ * reducer overwrites on lifecycle events, so re-applying one is harmless.
276
+ * Milestones key on their own persisted sequence. Progress frames and chunks
277
+ * too large to store reuse the next stored chunk's sequence without consuming
278
+ * it and are never replayed, so they key on their own emitter-assigned id.
279
+ */
280
+ function agentToolEventDedupeKey(message) {
281
+ const { event } = message;
282
+ let identity;
283
+ if (event.kind !== "chunk") identity = `event:${JSON.stringify(event)}`;
284
+ else if (event.unstoredId !== void 0) identity = `unstored:${event.unstoredId}`;
285
+ else {
286
+ let milestone;
287
+ let progressId;
288
+ let progress = false;
289
+ if (event.body.includes("data-agent-milestone") || event.body.includes("data-agent-progress")) try {
290
+ const parsed = JSON.parse(event.body);
291
+ milestone = readAgentToolMilestoneChunk(parsed);
292
+ progress = readAgentToolProgressChunk(parsed) !== void 0;
293
+ const id = parsed.id;
294
+ if (typeof id === "string") progressId = id;
295
+ } catch {
296
+ milestone = void 0;
297
+ }
298
+ identity = milestone ? `milestone:${milestone.sequence}` : progress ? progressId !== void 0 ? `progress:${progressId}` : `progress:${message.sequence}:${event.body}` : `seq:${message.sequence}`;
299
+ }
300
+ return [
301
+ message.parentToolCallId ?? "",
302
+ event.runId,
303
+ identity
304
+ ].join("\0");
305
+ }
253
306
  function applyAgentToolEvent(state, message) {
254
307
  if (message.type !== "agent-tool-event") return state;
255
308
  const runId = message.event.runId;
@@ -276,29 +329,39 @@ function applyAgentToolEvent(state, message) {
276
329
  * error capture never depends on tailer timing. A frame belongs to a run iff it
277
330
  * carries that run's turn request id, so concurrent runs can't cross-contaminate
278
331
  * each other's progress or error state.
332
+ *
333
+ * Returns the run id when the frame is one of that run's content chunks, so a
334
+ * host can skip broadcasting chunks no client is watching.
279
335
  */
280
336
  function interceptAgentToolBroadcast(msg, hooks) {
281
- if ((hooks.forwarders.size > 0 || hooks.liveSequences.size > 0) && typeof msg === "string") try {
337
+ if ((hooks.forwarders.size > 0 || hooks.liveSequences.size > 0 || (hooks.terminalOnlyRuns?.size ?? 0) > 0) && typeof msg === "string") try {
282
338
  const parsed = JSON.parse(msg);
283
339
  if (parsed.type === hooks.responseType && typeof parsed.id === "string") {
284
340
  const runId = hooks.runForRequest(parsed.id);
285
341
  if (runId !== null) {
286
- if (parsed.error === true && typeof parsed.body === "string") hooks.lastErrors.set(runId, parsed.body);
287
- else if (typeof parsed.body === "string" && parsed.body.length > 0) {
342
+ if (parsed.error === true && typeof parsed.body === "string") {
343
+ hooks.lastErrors.set(runId, parsed.body);
344
+ hooks.onError?.(runId, parsed.body);
345
+ } else if (typeof parsed.body === "string" && parsed.body.length > 0) {
288
346
  const sequence = hooks.liveSequences.get(runId) ?? 0;
289
- hooks.liveSequences.set(runId, sequence + 1);
347
+ const lifecycle = isAgentToolLifecycleChunk(parsed.body);
348
+ const unstored = !lifecycle && isChunkTooLargeToStore(parsed.body);
349
+ hooks.liveSequences.set(runId, lifecycle || unstored ? sequence : sequence + 1);
290
350
  const chunk = {
291
351
  sequence,
292
- body: parsed.body
352
+ body: parsed.body,
353
+ ...unstored ? { unstoredId: crypto.randomUUID() } : {}
293
354
  };
294
355
  const forwarders = hooks.forwarders.get(runId);
295
356
  if (forwarders) for (const forward of forwarders) forward(chunk);
357
+ return runId;
296
358
  }
297
359
  }
298
360
  }
299
361
  } catch {}
362
+ return null;
300
363
  }
301
364
  //#endregion
302
- export { interceptAgentToolBroadcast as i, applyAgentToolEvent as n, createAgentToolEventState as r, AgentToolProgressEmitter as t };
365
+ export { interceptAgentToolBroadcast as a, createAgentToolEventState as i, agentToolEventDedupeKey as n, CHUNK_MAX_BYTES as o, applyAgentToolEvent as r, storedChunkBytes as s, AgentToolProgressEmitter as t };
303
366
 
304
- //# sourceMappingURL=agent-tools-y7zLfw4Q.js.map
367
+ //# sourceMappingURL=agent-tools-CdJC-8Dc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tools-CdJC-8Dc.js","names":[],"sources":["../src/chat/chunk-size.ts","../src/chat/agent-tools.ts"],"sourcesContent":["const textEncoder = new TextEncoder();\n\n/** Maximum serialized chunk body size before skipping storage (bytes). */\nexport const CHUNK_MAX_BYTES = 1_800_000;\n\n/** Byte size of a chunk body in its stored (JSON-escaped) encoding. */\nexport function storedChunkBytes(body: string): number {\n return textEncoder.encode(JSON.stringify(body)).byteLength;\n}\n\n/**\n * Whether `ResumableStream.storeChunk` skips storing this body: it is still\n * broadcast live, but absent from replay.\n */\nexport function isChunkTooLargeToStore(body: string): boolean {\n return storedChunkBytes(body) > CHUNK_MAX_BYTES;\n}\n","import { applyChunkToParts, type MessagePart } from \"./message-builder\";\nimport { isChunkTooLargeToStore } from \"./chunk-size\";\nimport {\n AGENT_TOOL_MILESTONE_PART,\n AGENT_TOOL_PROGRESS_PART,\n isAgentToolLifecycleChunk,\n isPositionlessAgentToolChunk\n} from \"../agent-tool-types\";\nimport type {\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolMilestone,\n AgentToolProgress,\n AgentToolProgressSnapshot,\n AgentToolRunPart,\n AgentToolRunState,\n AgentToolStoredChunk\n} from \"../agent-tool-types\";\n\n/**\n * Pull a reserved `data-agent-progress` chunk (emitted by a running sub-agent's\n * `reportProgress`) into a latest-wins snapshot. Returns `undefined` for any\n * other chunk so the caller keeps the prior snapshot.\n */\nfunction readAgentToolProgressChunk(\n chunk: unknown\n): AgentToolProgressSnapshot | undefined {\n if (\n typeof chunk !== \"object\" ||\n chunk === null ||\n (chunk as { type?: unknown }).type !== AGENT_TOOL_PROGRESS_PART\n ) {\n return undefined;\n }\n const data = (chunk as { data?: AgentToolProgress }).data ?? {};\n return {\n ...(typeof data.fraction === \"number\" ? { fraction: data.fraction } : {}),\n ...(typeof data.message === \"string\" ? { message: data.message } : {}),\n ...(typeof data.phase === \"string\" ? { phase: data.phase } : {}),\n ...(data.data !== undefined ? { data: data.data } : {}),\n at: Date.now()\n };\n}\n\n/**\n * Pull a reserved `data-agent-milestone` chunk into a durable milestone record,\n * or `undefined` for any other chunk. Milestones carry their own monotonic\n * `sequence` so the caller can dedupe replay-vs-live races.\n */\nfunction readAgentToolMilestoneChunk(\n chunk: unknown\n): AgentToolMilestone | undefined {\n if (\n typeof chunk !== \"object\" ||\n chunk === null ||\n (chunk as { type?: unknown }).type !== AGENT_TOOL_MILESTONE_PART\n ) {\n return undefined;\n }\n const data = (chunk as { data?: Partial<AgentToolMilestone> }).data ?? {};\n if (typeof data.name !== \"string\") return undefined;\n return {\n name: data.name,\n sequence: typeof data.sequence === \"number\" ? data.sequence : 0,\n at: typeof data.at === \"number\" ? data.at : Date.now(),\n ...(data.data !== undefined ? { data: data.data } : {})\n };\n}\n\n/**\n * Merge a milestone into a run's ordered milestone list, deduping on `sequence`\n * (idempotent across replay + live races) and keeping the list sorted.\n */\nfunction mergeMilestone(\n existing: AgentToolMilestone[] | undefined,\n milestone: AgentToolMilestone\n): AgentToolMilestone[] {\n // Returns `existing` unchanged (same reference) when the milestone is a dup,\n // so callers can identity-compare to detect a genuinely new milestone.\n if (existing?.some((m) => m.sequence === milestone.sequence)) return existing;\n const list = existing ? [...existing, milestone] : [milestone];\n list.sort((a, b) => a.sequence - b.sequence);\n return list;\n}\n\n/** Latest-wins coalescing window for `reportProgress` emits (per run). */\nconst AGENT_TOOL_PROGRESS_COALESCE_MS = 200;\n\nexport type AgentToolProgressEmitResult = \"emitted\" | \"coalesced\" | \"inactive\";\n\n/**\n * Host-injected seams the shared progress emitter needs. Keeps the per-host\n * `reportProgress` thin: Think / AIChatAgent supply how to resolve the active\n * agent-tool run, how to broadcast a chat-response frame, and how to persist the\n * latest snapshot on their own child-run table.\n */\nexport type AgentToolProgressEmitHooks = {\n /** The agent-tool run currently executing in this turn, or null. */\n resolveActiveRun: () => { runId: string; requestId: string } | null;\n /** Broadcast a chat-response frame (id = requestId) to clients/tailers. */\n broadcast: (requestId: string, chunkBody: string) => void;\n /** Persist the latest snapshot + signal timestamp on the child run row. */\n persistSnapshot: (\n runId: string,\n snapshot: {\n fraction?: number;\n message?: string;\n phase?: string;\n data?: unknown;\n },\n at: number\n ) => void;\n /**\n * Persist a durable milestone row, bump the run's signal timestamp, and return\n * the assigned monotonic per-run `sequence` (used to dedupe replay/live races).\n */\n persistMilestone: (\n runId: string,\n name: string,\n data: unknown,\n at: number\n ) => number;\n};\n\n/**\n * Shared implementation of `reportProgress` for chat hosts. Builds the reserved\n * transient `data-agent-progress` wire frame, coalesces bursts to a bounded\n * cadence (latest-wins; a `fraction >= 1` \"done\" frame always flushes), and\n * persists a latest snapshot. `data` rides the live frame but is only persisted\n * when the caller opts in via `{ persist: true }`.\n */\nexport class AgentToolProgressEmitter {\n private readonly _lastEmitAt = new Map<string, number>();\n\n constructor(private readonly hooks: AgentToolProgressEmitHooks) {}\n\n report(\n progress: AgentToolProgress,\n options?: { persist?: boolean }\n ): AgentToolProgressEmitResult {\n const active = this.hooks.resolveActiveRun();\n if (!active) return \"inactive\";\n const { runId, requestId } = active;\n const now = Date.now();\n\n // Durable milestone: never coalesced (each named boundary must land,\n // persist, and replay). Rides the stream as a PERSISTED data part.\n if (typeof progress.milestone === \"string\" && progress.milestone) {\n this._lastEmitAt.set(runId, now);\n const sequence = this.hooks.persistMilestone(\n runId,\n progress.milestone,\n progress.data,\n now\n );\n this.hooks.broadcast(\n requestId,\n JSON.stringify({\n type: AGENT_TOOL_MILESTONE_PART,\n data: {\n name: progress.milestone,\n sequence,\n at: now,\n ...(typeof progress.fraction === \"number\"\n ? { fraction: progress.fraction }\n : {}),\n ...(typeof progress.message === \"string\"\n ? { message: progress.message }\n : {}),\n ...(typeof progress.phase === \"string\"\n ? { phase: progress.phase }\n : {}),\n ...(progress.data !== undefined ? { data: progress.data } : {})\n }\n })\n );\n return \"emitted\";\n }\n\n const last = this._lastEmitAt.get(runId) ?? 0;\n const isDone =\n typeof progress.fraction === \"number\" && progress.fraction >= 1;\n if (now - last < AGENT_TOOL_PROGRESS_COALESCE_MS && !isDone) {\n return \"coalesced\";\n }\n this._lastEmitAt.set(runId, now);\n\n const wire: AgentToolProgress = {\n ...(typeof progress.fraction === \"number\"\n ? { fraction: progress.fraction }\n : {}),\n ...(typeof progress.message === \"string\"\n ? { message: progress.message }\n : {}),\n ...(typeof progress.phase === \"string\" ? { phase: progress.phase } : {}),\n ...(progress.data !== undefined ? { data: progress.data } : {})\n };\n // Identical payloads must not dedupe against each other on a client that\n // keeps seen keys for its connection's lifetime, including across a child\n // restart, so the id is unique rather than a per-instance counter.\n this.hooks.broadcast(\n requestId,\n JSON.stringify({\n type: AGENT_TOOL_PROGRESS_PART,\n id: crypto.randomUUID(),\n transient: true,\n data: wire\n })\n );\n this.hooks.persistSnapshot(\n runId,\n {\n ...(typeof progress.fraction === \"number\"\n ? { fraction: progress.fraction }\n : {}),\n ...(typeof progress.message === \"string\"\n ? { message: progress.message }\n : {}),\n ...(typeof progress.phase === \"string\"\n ? { phase: progress.phase }\n : {}),\n ...(options?.persist && progress.data !== undefined\n ? { data: progress.data }\n : {})\n },\n now\n );\n return \"emitted\";\n }\n\n /** Drop coalescing state for a settled run (called on terminal). */\n forget(runId: string): void {\n this._lastEmitAt.delete(runId);\n }\n}\n\nfunction sortRuns<Part extends AgentToolRunPart>(\n runs: AgentToolRunState<Part>[]\n): AgentToolRunState<Part>[] {\n return [...runs].sort((a, b) => {\n if (a.order !== b.order) return a.order - b.order;\n return a.runId.localeCompare(b.runId);\n });\n}\n\nfunction rebuildIndexes<Part extends AgentToolRunPart>(\n runsById: Record<string, AgentToolRunState<Part>>\n): Pick<AgentToolEventState<Part>, \"runsByToolCallId\" | \"unboundRuns\"> {\n const grouped: Record<string, AgentToolRunState<Part>[]> = {};\n const unboundRuns: AgentToolRunState<Part>[] = [];\n for (const run of Object.values(runsById)) {\n if (run.parentToolCallId) {\n grouped[run.parentToolCallId] = grouped[run.parentToolCallId] ?? [];\n grouped[run.parentToolCallId].push(run);\n } else {\n unboundRuns.push(run);\n }\n }\n for (const [toolCallId, runs] of Object.entries(grouped)) {\n grouped[toolCallId] = sortRuns(runs);\n }\n return { runsByToolCallId: grouped, unboundRuns: sortRuns(unboundRuns) };\n}\n\nfunction emptyRun<Part extends AgentToolRunPart>(\n message: AgentToolEventMessage\n): AgentToolRunState<Part> | undefined {\n const { event } = message;\n if (event.kind === \"started\") {\n return {\n runId: event.runId,\n agentType: event.agentType,\n parentToolCallId: message.parentToolCallId,\n inputPreview: event.inputPreview,\n order: event.order,\n display: event.display,\n status: \"running\",\n parts: [],\n subAgent: { agent: event.agentType, name: event.runId }\n };\n }\n return undefined;\n}\n\nfunction applyToRun<Part extends AgentToolRunPart>(\n prev: AgentToolRunState<Part> | undefined,\n message: AgentToolEventMessage\n): AgentToolRunState<Part> | undefined {\n const seeded = prev ?? emptyRun(message);\n const { event } = message;\n\n switch (event.kind) {\n case \"started\":\n if (\n seeded?.status === \"completed\" ||\n seeded?.status === \"error\" ||\n seeded?.status === \"aborted\" ||\n seeded?.status === \"interrupted\"\n ) {\n return seeded;\n }\n return {\n ...seeded,\n runId: event.runId,\n agentType: event.agentType,\n parentToolCallId: message.parentToolCallId,\n inputPreview: event.inputPreview,\n order: event.order,\n display: event.display,\n status: \"running\",\n parts: seeded?.parts ?? [],\n subAgent: { agent: event.agentType, name: event.runId }\n };\n case \"chunk\": {\n if (!seeded) return undefined;\n // `applyChunkToParts` mutates part objects in place (e.g.\n // `lastTextPart.text += delta`). A shallow array copy (`[...seeded.parts]`)\n // keeps the *element* references shared with the previous state, so those\n // in-place mutations leak back into `prev`. React double-invokes setState\n // updaters in StrictMode / dev hydration, replaying each chunk against the\n // same (already-mutated) `prev` and doubling the text (#1835). Clone each\n // part so the reducer stays pure — every mutation here is to a top-level\n // field, so a per-part shallow copy is sufficient.\n const parts = seeded.parts.map((part) => ({ ...part }) as Part);\n let parsed: unknown;\n try {\n parsed = JSON.parse(event.body);\n applyChunkToParts(\n parts as MessagePart[],\n parsed as Parameters<typeof applyChunkToParts>[1]\n );\n } catch {\n return seeded;\n }\n // Project a reserved `data-agent-progress` part onto the run's latest\n // progress snapshot so a tray can render a bar/phase without drilling in.\n // The part is transient (not persisted into `parts`), so it is read here\n // off the raw chunk rather than from the reduced parts array.\n const progress = readAgentToolProgressChunk(parsed);\n if (progress) {\n return { ...seeded, parts, progress };\n }\n // Durable milestones land as a persisted `data-agent-milestone` part:\n // append (deduped by sequence) to the run's milestone list, and reflect\n // any progress fields the milestone carried onto the latest snapshot.\n const milestone = readAgentToolMilestoneChunk(parsed);\n if (milestone) {\n const milestones = mergeMilestone(seeded.milestones, milestone);\n // Only advance the snapshot for a genuinely new, not-older milestone, so\n // a late replay of an earlier milestone never rolls `progress` backward.\n const isNew = milestones !== seeded.milestones;\n const notOlder =\n seeded.progress === undefined || milestone.at >= seeded.progress.at;\n if (!isNew || !notOlder) {\n return { ...seeded, parts, milestones };\n }\n const data = (parsed as { data?: AgentToolProgress }).data ?? {};\n const snapshot: AgentToolProgressSnapshot = {\n ...(typeof data.fraction === \"number\"\n ? { fraction: data.fraction }\n : {}),\n ...(typeof data.message === \"string\"\n ? { message: data.message }\n : {}),\n ...(typeof data.phase === \"string\" ? { phase: data.phase } : {}),\n milestone: milestone.name,\n at: milestone.at\n };\n return { ...seeded, parts, progress: snapshot, milestones };\n }\n return { ...seeded, parts };\n }\n case \"finished\":\n if (!seeded) return undefined;\n return {\n ...seeded,\n status: \"completed\",\n summary: event.summary,\n error: undefined\n };\n case \"error\":\n if (!seeded) return undefined;\n return { ...seeded, status: \"error\", error: event.error };\n case \"aborted\":\n if (!seeded) return undefined;\n return { ...seeded, status: \"aborted\", error: event.reason };\n case \"interrupted\":\n if (!seeded) return undefined;\n return {\n ...seeded,\n status: \"interrupted\",\n error: event.error,\n reason: event.reason,\n childStillRunning: event.childStillRunning\n };\n }\n}\n\nexport function createAgentToolEventState<\n Part extends AgentToolRunPart = AgentToolRunPart\n>(): AgentToolEventState<Part> {\n return {\n runsById: {},\n runsByToolCallId: {},\n unboundRuns: []\n };\n}\n\n/**\n * Identity of an agent-tool event for replay-vs-live dedupe. Ordinary chunks\n * key on the broadcast `sequence`, which is their stored-chunk position on\n * both the live and replay paths. Lifecycle events key on their content: a\n * reattached run can be interrupted again with a different reason, and the\n * reducer overwrites on lifecycle events, so re-applying one is harmless.\n * Milestones key on their own persisted sequence. Progress frames and chunks\n * too large to store reuse the next stored chunk's sequence without consuming\n * it and are never replayed, so they key on their own emitter-assigned id.\n */\nexport function agentToolEventDedupeKey(\n message: AgentToolEventMessage\n): string {\n const { event } = message;\n let identity: string;\n if (event.kind !== \"chunk\") {\n identity = `event:${JSON.stringify(event)}`;\n } else if (event.unstoredId !== undefined) {\n identity = `unstored:${event.unstoredId}`;\n } else {\n let milestone: AgentToolMilestone | undefined;\n let progressId: string | undefined;\n let progress = false;\n if (\n event.body.includes(AGENT_TOOL_MILESTONE_PART) ||\n event.body.includes(AGENT_TOOL_PROGRESS_PART)\n ) {\n try {\n const parsed: unknown = JSON.parse(event.body);\n milestone = readAgentToolMilestoneChunk(parsed);\n progress = readAgentToolProgressChunk(parsed) !== undefined;\n const id = (parsed as { id?: unknown }).id;\n if (typeof id === \"string\") progressId = id;\n } catch {\n milestone = undefined;\n }\n }\n identity = milestone\n ? `milestone:${milestone.sequence}`\n : progress\n ? progressId !== undefined\n ? `progress:${progressId}`\n : `progress:${message.sequence}:${event.body}`\n : `seq:${message.sequence}`;\n }\n return [message.parentToolCallId ?? \"\", event.runId, identity].join(\"\\0\");\n}\n\nexport function applyAgentToolEvent<\n Part extends AgentToolRunPart = AgentToolRunPart\n>(\n state: AgentToolEventState<Part>,\n message: AgentToolEventMessage\n): AgentToolEventState<Part> {\n if (message.type !== \"agent-tool-event\") return state;\n const runId = message.event.runId;\n const nextRun = applyToRun(state.runsById[runId], message);\n if (!nextRun) return state;\n\n const runsById = { ...state.runsById, [runId]: nextRun };\n return { runsById, ...rebuildIndexes(runsById) };\n}\n\nexport { isPositionlessAgentToolChunk };\n\nexport type {\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolRunPart,\n AgentToolRunState\n} from \"../agent-tool-types\";\n\n/**\n * @internal Host substrate the {@link interceptAgentToolBroadcast} snoop reads,\n * abstracting the divergent per-host run-lookup and response-frame constant.\n */\nexport interface AgentToolBroadcastHooks {\n /** Live tailers per run; iterated to forward each progress chunk. */\n forwarders: Map<string, Set<(chunk: AgentToolStoredChunk) => void>>;\n /**\n * Per-run live counter of stored chunks; advanced even with no tailer\n * attached, so a stored chunk's live sequence equals its stored chunk_index.\n *\n * Progress/milestone frames (`reportProgress`) ride the same\n * `USE_CHAT_RESPONSE` wire type and are forwarded here, but persist\n * out-of-band (progress snapshot / milestone rows) and have no store\n * position. Neither do chunks too large to store (they carry an\n * `unstoredId`). Both carry the next position WITHOUT consuming it, and\n * tails emit them outside the stored-position high-water dedupe; counting\n * them would push later stored chunks past their stored index, so a chunk\n * stored and broadcast during a tail's drain would be emitted twice. A tail\n * seeds a cold counter from the stored high-water before it attaches.\n */\n liveSequences: Map<string, number>;\n /** Per-run last error body, captured for replay to a late-attaching tailer. */\n lastErrors: Map<string, string>;\n /**\n * Called after a run's error body is captured, so the host can record it\n * durably on the still-open run row (the in-memory {@link lastErrors} entry\n * is lost if the DO is evicted before the run is finalized).\n */\n onError?: (runId: string, body: string) => void;\n /** The host's use-chat-response wire type (`CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE`). */\n responseType: string;\n /** Resolve the agent-tool run that owns a turn request id, or null. */\n runForRequest: (requestId: string) => string | null;\n /**\n * Runs whose chunks the host suppresses (`eventDelivery: \"terminal\"`). Keeps\n * inspection on after a restart empties the other maps, so a recovered\n * turn's chunks are still attributed and suppressed.\n */\n terminalOnlyRuns?: ReadonlySet<string>;\n}\n\n/**\n * Snoop a host's outgoing chat frames while any agent-tool run is in flight and\n * forward the owning run's streamed body to its live tailers (or capture its\n * error), without altering the frame — the caller still broadcasts it (#1575).\n *\n * Shared verbatim by `@cloudflare/ai-chat` and `@cloudflare/think`; the only\n * per-host variance (the response-frame type constant and the run-lookup, whose\n * SQL differs) is supplied via {@link AgentToolBroadcastHooks}. Inspection runs\n * for a run's whole lifecycle (live sequences exist even with no tailer), so\n * error capture never depends on tailer timing. A frame belongs to a run iff it\n * carries that run's turn request id, so concurrent runs can't cross-contaminate\n * each other's progress or error state.\n *\n * Returns the run id when the frame is one of that run's content chunks, so a\n * host can skip broadcasting chunks no client is watching.\n */\nexport function interceptAgentToolBroadcast(\n msg: string | ArrayBuffer | ArrayBufferView,\n hooks: AgentToolBroadcastHooks\n): string | null {\n if (\n (hooks.forwarders.size > 0 ||\n hooks.liveSequences.size > 0 ||\n (hooks.terminalOnlyRuns?.size ?? 0) > 0) &&\n typeof msg === \"string\"\n ) {\n try {\n const parsed = JSON.parse(msg) as {\n type?: unknown;\n body?: unknown;\n error?: unknown;\n id?: unknown;\n };\n if (parsed.type === hooks.responseType && typeof parsed.id === \"string\") {\n const runId = hooks.runForRequest(parsed.id);\n if (runId !== null) {\n if (parsed.error === true && typeof parsed.body === \"string\") {\n hooks.lastErrors.set(runId, parsed.body);\n hooks.onError?.(runId, parsed.body);\n } else if (\n typeof parsed.body === \"string\" &&\n parsed.body.length > 0\n ) {\n // Advance the live sequence even with no tailer attached so a tailer\n // registering mid-run resumes at the right offset. Progress,\n // milestone, and unstored frames carry the next position without\n // consuming it.\n const sequence = hooks.liveSequences.get(runId) ?? 0;\n const lifecycle = isAgentToolLifecycleChunk(parsed.body);\n const unstored = !lifecycle && isChunkTooLargeToStore(parsed.body);\n hooks.liveSequences.set(\n runId,\n lifecycle || unstored ? sequence : sequence + 1\n );\n const chunk: AgentToolStoredChunk = {\n sequence,\n body: parsed.body,\n ...(unstored ? { unstoredId: crypto.randomUUID() } : {})\n };\n const forwarders = hooks.forwarders.get(runId);\n if (forwarders) {\n for (const forward of forwarders) forward(chunk);\n }\n return runId;\n }\n }\n }\n } catch {\n // Non-chat frames pass through unchanged.\n }\n }\n return null;\n}\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import {
2
- L as AgentToolEventMessage,
3
- R as AgentToolEventState,
4
- U as AgentToolProgress,
5
- X as AgentToolStoredChunk,
6
- q as AgentToolRunPart
7
- } from "./agent-routing-B2XLNMxq.js";
2
+ J as AgentToolRunPart,
3
+ R as AgentToolEventMessage,
4
+ W as AgentToolProgress,
5
+ Z as AgentToolStoredChunk,
6
+ z as AgentToolEventState
7
+ } from "./agent-routing-0DR0Tk2v.js";
8
8
 
9
9
  //#region src/chat/agent-tools.d.ts
10
10
  type AgentToolProgressEmitResult = "emitted" | "coalesced" | "inactive";
@@ -81,27 +81,38 @@ interface AgentToolBroadcastHooks {
81
81
  /** Live tailers per run; iterated to forward each progress chunk. */
82
82
  forwarders: Map<string, Set<(chunk: AgentToolStoredChunk) => void>>;
83
83
  /**
84
- * Per-run forwarded-chunk counter; advanced even with no tailer attached.
84
+ * Per-run live counter of stored chunks; advanced even with no tailer
85
+ * attached, so a stored chunk's live sequence equals its stored chunk_index.
85
86
  *
86
- * This is deliberately a SEPARATE counter from the resumable stream's stored
87
- * chunk_index — do NOT try to "simplify" it away by sequencing off the store
88
- * position. Not every forwarded frame is durably stored: progress/milestone
89
- * frames (`reportProgress`) ride the same `USE_CHAT_RESPONSE` wire type and
90
- * are snooped + forwarded here, but persist out-of-band (progress snapshot /
91
- * milestone rows), so they have no store position. Sourcing the sequence from
92
- * the store would give them a colliding position and the tail's high-water
93
- * dedupe (`emit`) would silently drop them, breaking live progress/milestone
94
- * delivery to the parent. This counter sequences stored AND non-stored frames
95
- * on one monotonic line; the tail realigns it to the stored high-water on each
96
- * (re)attach so a replay→live handoff stays gap/duplicate-free.
87
+ * Progress/milestone frames (`reportProgress`) ride the same
88
+ * `USE_CHAT_RESPONSE` wire type and are forwarded here, but persist
89
+ * out-of-band (progress snapshot / milestone rows) and have no store
90
+ * position. Neither do chunks too large to store (they carry an
91
+ * `unstoredId`). Both carry the next position WITHOUT consuming it, and
92
+ * tails emit them outside the stored-position high-water dedupe; counting
93
+ * them would push later stored chunks past their stored index, so a chunk
94
+ * stored and broadcast during a tail's drain would be emitted twice. A tail
95
+ * seeds a cold counter from the stored high-water before it attaches.
97
96
  */
98
97
  liveSequences: Map<string, number>;
99
98
  /** Per-run last error body, captured for replay to a late-attaching tailer. */
100
99
  lastErrors: Map<string, string>;
100
+ /**
101
+ * Called after a run's error body is captured, so the host can record it
102
+ * durably on the still-open run row (the in-memory {@link lastErrors} entry
103
+ * is lost if the DO is evicted before the run is finalized).
104
+ */
105
+ onError?: (runId: string, body: string) => void;
101
106
  /** The host's use-chat-response wire type (`CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE`). */
102
107
  responseType: string;
103
108
  /** Resolve the agent-tool run that owns a turn request id, or null. */
104
109
  runForRequest: (requestId: string) => string | null;
110
+ /**
111
+ * Runs whose chunks the host suppresses (`eventDelivery: "terminal"`). Keeps
112
+ * inspection on after a restart empties the other maps, so a recovered
113
+ * turn's chunks are still attributed and suppressed.
114
+ */
115
+ terminalOnlyRuns?: ReadonlySet<string>;
105
116
  }
106
117
  /**
107
118
  * Snoop a host's outgoing chat frames while any agent-tool run is in flight and
@@ -115,11 +126,14 @@ interface AgentToolBroadcastHooks {
115
126
  * error capture never depends on tailer timing. A frame belongs to a run iff it
116
127
  * carries that run's turn request id, so concurrent runs can't cross-contaminate
117
128
  * each other's progress or error state.
129
+ *
130
+ * Returns the run id when the frame is one of that run's content chunks, so a
131
+ * host can skip broadcasting chunks no client is watching.
118
132
  */
119
133
  declare function interceptAgentToolBroadcast(
120
134
  msg: string | ArrayBuffer | ArrayBufferView,
121
135
  hooks: AgentToolBroadcastHooks
122
- ): void;
136
+ ): string | null;
123
137
  //#endregion
124
138
  export {
125
139
  applyAgentToolEvent as a,
@@ -130,4 +144,4 @@ export {
130
144
  interceptAgentToolBroadcast as s,
131
145
  AgentToolBroadcastHooks as t
132
146
  };
133
- //# sourceMappingURL=agent-tools-Dj5Mzlw7.d.ts.map
147
+ //# sourceMappingURL=agent-tools-YrATZJu2.d.ts.map
@@ -1,25 +1,26 @@
1
1
  import {
2
- $ as DetachedAgentToolConfig,
3
- B as AgentToolInterruptedReason,
2
+ $ as ChatCapableAgentClass,
3
+ B as AgentToolFailure,
4
4
  F as AgentToolDisplayMetadata,
5
- G as AgentToolRunInfo,
5
+ H as AgentToolLifecycleResult,
6
6
  I as AgentToolEvent,
7
- J as AgentToolRunState,
8
- K as AgentToolRunInspection,
9
- L as AgentToolEventMessage,
7
+ J as AgentToolRunPart,
8
+ K as AgentToolRunInfo,
9
+ L as AgentToolEventDelivery,
10
10
  P as AgentToolChildAdapter,
11
- Q as ChatCapableAgentClass,
12
- R as AgentToolEventState,
13
- V as AgentToolLifecycleResult,
14
- X as AgentToolStoredChunk,
15
- Y as AgentToolRunStatus,
16
- Z as AgentToolTerminalStatus,
17
- et as DetachedRunAgentToolResult,
18
- nt as RunAgentToolResult,
19
- q as AgentToolRunPart,
20
- tt as RunAgentToolOptions,
21
- z as AgentToolFailure
22
- } from "./agent-routing-B2XLNMxq.js";
11
+ Q as AgentToolTerminalStatus,
12
+ R as AgentToolEventMessage,
13
+ V as AgentToolInterruptedReason,
14
+ X as AgentToolRunStatus,
15
+ Y as AgentToolRunState,
16
+ Z as AgentToolStoredChunk,
17
+ et as DetachedAgentToolConfig,
18
+ nt as RunAgentToolOptions,
19
+ q as AgentToolRunInspection,
20
+ rt as RunAgentToolResult,
21
+ tt as DetachedRunAgentToolResult,
22
+ z as AgentToolEventState
23
+ } from "./agent-routing-0DR0Tk2v.js";
23
24
  import { FlexibleSchema, InferSchema, Tool } from "ai";
24
25
 
25
26
  //#region src/agent-tools.d.ts
@@ -63,6 +64,7 @@ export {
63
64
  type AgentToolChildAdapter,
64
65
  type AgentToolDisplayMetadata,
65
66
  type AgentToolEvent,
67
+ type AgentToolEventDelivery,
66
68
  type AgentToolEventMessage,
67
69
  type AgentToolEventState,
68
70
  type AgentToolFactoryOptions,
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tools.js","names":["agentContext","createTool"],"sources":["../src/agent-tools.ts"],"sourcesContent":["import {\n asSchema,\n tool,\n type FlexibleSchema,\n type InferSchema,\n type Tool\n} from \"ai\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"./internal_context\";\nimport type {\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult,\n AgentToolDisplayMetadata,\n AgentToolFailure\n} from \"./agent-tool-types\";\n\ntype ParseSchema<Output = unknown> = {\n parse(value: unknown): Output;\n};\n\ntype AgentToolOutputSchema<Output> =\n | FlexibleSchema<Output>\n | ParseSchema<Output>;\n\ntype AgentToolFactoryOptions<Output = unknown, Input = unknown> = {\n description: string;\n inputSchema: FlexibleSchema<Input>;\n outputSchema?: AgentToolOutputSchema<Output>;\n displayName?: string;\n icon?: string;\n display?: AgentToolDisplayMetadata;\n};\n\n// Capture the concrete schema type so the overload below can derive its input\n// with InferSchema. AgentToolFactoryOptions remains available for callers that\n// explicitly supply agentTool<Input, Output>() type arguments.\ntype InferredAgentToolFactoryOptions<\n InputSchema extends FlexibleSchema,\n Output\n> = Omit<AgentToolFactoryOptions<Output>, \"inputSchema\"> & {\n inputSchema: InputSchema;\n};\n\ntype ToolExecutionOptions = {\n toolCallId?: string;\n abortSignal?: AbortSignal;\n};\n\ntype AgentToolRunner = {\n runAgentTool<Input, Output>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>>;\n};\n\n/**\n * Preserve the existing Zod-style `.parse()` output-schema contract while\n * extending validation to the other formats supported by AI SDK FlexibleSchema.\n */\nasync function validateOutput<Output>(\n schema: AgentToolOutputSchema<Output>,\n value: unknown\n): Promise<Output> {\n if (\n typeof schema === \"object\" &&\n schema !== null &&\n \"parse\" in schema &&\n typeof schema.parse === \"function\"\n ) {\n return schema.parse(value);\n }\n\n const validate = asSchema(schema as FlexibleSchema<Output>).validate;\n if (!validate) {\n throw new Error(\"agentTool outputSchema must provide runtime validation\");\n }\n\n const result = await validate(value);\n if (!result.success) throw result.error;\n return result.value;\n}\n\nfunction currentAgentToolRunner(): AgentToolRunner {\n const agent = agentContext.getStore()?.agent;\n if (\n agent === null ||\n typeof agent !== \"object\" ||\n typeof (agent as { runAgentTool?: unknown }).runAgentTool !== \"function\"\n ) {\n throw new Error(\n \"agentTool() can only run inside an Agent turn. Use it from getTools() on an Agent subclass.\"\n );\n }\n return agent as AgentToolRunner;\n}\n\nfunction failure(\n status: AgentToolFailure[\"status\"],\n error: string,\n retryable: boolean,\n extra?: Pick<AgentToolFailure, \"reason\" | \"childStillRunning\">\n): AgentToolFailure {\n return {\n ok: false,\n status,\n error,\n retryable,\n ...(extra?.reason !== undefined ? { reason: extra.reason } : {}),\n ...(extra?.childStillRunning !== undefined\n ? { childStillRunning: extra.childStillRunning }\n : {})\n };\n}\n\n/**\n * Create an AI SDK tool that dispatches a chat-capable sub-agent through\n * `Agent.runAgentTool`.\n */\nexport function agentTool<InputSchema extends FlexibleSchema, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: InferredAgentToolFactoryOptions<InputSchema, Output>\n): Tool<InferSchema<InputSchema>, string | Output | AgentToolFailure>;\n// Preserve existing callers that explicitly provide agentTool<Input, Output>().\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure>;\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure> {\n const createTool = tool as unknown as <I, O>(config: {\n description: string;\n inputSchema: unknown;\n execute: (input: I, options?: ToolExecutionOptions) => Promise<O>;\n }) => Tool<I, O>;\n\n return createTool<Input, string | Output | AgentToolFailure>({\n description: options.description,\n inputSchema: options.inputSchema,\n execute: async (input: Input, executeOptions?: ToolExecutionOptions) => {\n const display: AgentToolDisplayMetadata | undefined =\n options.displayName || options.icon || options.display\n ? {\n ...options.display,\n ...(options.displayName ? { name: options.displayName } : {}),\n ...(options.icon ? { icon: options.icon } : {})\n }\n : undefined;\n\n // Derive a STABLE runId from the tool call id (#1630). A tool call's id is\n // preserved in the transcript, so when a parent turn is re-run by chat\n // recovery after a deploy / eviction, the same `agentTool()` call resolves\n // to the same runId — turning the re-issue into a duplicate that\n // `runAgentTool` re-attaches to the still-running child, instead of a\n // fresh `nanoid` that spawns a brand-new child and re-runs already-\n // completed work (\"the agent went all the way back\"). Falls back to a\n // fresh id only when there is no tool call id (rare; preserves prior\n // behavior).\n const runId = executeOptions?.toolCallId\n ? `agent-tool:${executeOptions.toolCallId}`\n : undefined;\n\n const result = await currentAgentToolRunner().runAgentTool<Input, Output>(\n cls,\n {\n input,\n runId,\n parentToolCallId: executeOptions?.toolCallId,\n signal: executeOptions?.abortSignal,\n display\n }\n );\n\n if (result.status === \"completed\") {\n if (options.outputSchema) {\n if (result.output === undefined) {\n return failure(\n \"error\",\n \"agent tool completed without structured output required by outputSchema\",\n false\n );\n }\n return validateOutput(options.outputSchema, result.output);\n }\n return result.summary ?? \"\";\n }\n\n if (result.status === \"aborted\") {\n // Intentional cancellation (parent/user stopped the run) — not retryable.\n return failure(\n \"aborted\",\n result.error ?? \"agent tool run was cancelled\",\n false\n );\n }\n if (result.status === \"interrupted\") {\n // The child was reset/superseded by a deploy or parent recovery before\n // it reached a logical outcome. Re-dispatching the run can succeed, so\n // surface it as retryable rather than a terminal failure the parent\n // would report to the user as final. `retryable` is intentionally COARSE\n // (always true for `interrupted`); callers that want to distinguish a\n // self-healing child from an exhausted one branch on `reason` /\n // `childStillRunning` instead.\n return failure(\n \"interrupted\",\n result.error ??\n \"agent tool run was interrupted before it finished; it can be retried\",\n true,\n { reason: result.reason, childStillRunning: result.childStillRunning }\n );\n }\n return failure(\"error\", result.error ?? \"agent tool run failed\", false);\n }\n });\n}\n\nexport type { AgentToolFactoryOptions };\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolFailure,\n AgentToolInterruptedReason,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunPart,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n DetachedAgentToolConfig,\n DetachedRunAgentToolResult,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n"],"mappings":";;;;;;;;AA2DA,eAAe,eACb,QACA,OACiB;CACjB,IACE,OAAO,WAAW,YAClB,WAAW,QACX,WAAW,UACX,OAAO,OAAO,UAAU,YAExB,OAAO,OAAO,MAAM,KAAK;CAG3B,MAAM,WAAW,SAAS,MAAgC,CAAC,CAAC;CAC5D,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,wDAAwD;CAG1E,MAAM,SAAS,MAAM,SAAS,KAAK;CACnC,IAAI,CAAC,OAAO,SAAS,MAAM,OAAO;CAClC,OAAO,OAAO;AAChB;AAEA,SAAS,yBAA0C;CACjD,MAAM,QAAQA,sCAAa,SAAS,CAAC,EAAE;CACvC,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAqC,iBAAiB,YAE9D,MAAM,IAAI,MACR,6FACF;CAEF,OAAO;AACT;AAEA,SAAS,QACP,QACA,OACA,WACA,OACkB;CAClB,OAAO;EACL,IAAI;EACJ;EACA;EACA;EACA,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EAC9D,GAAI,OAAO,sBAAsB,KAAA,IAC7B,EAAE,mBAAmB,MAAM,kBAAkB,IAC7C,CAAC;CACP;AACF;AAeA,SAAgB,UACd,KACA,SACiD;CAOjD,OAAOC,KAAsD;EAC3D,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,SAAS,OAAO,OAAc,mBAA0C;GACtE,MAAM,UACJ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,UAC3C;IACE,GAAG,QAAQ;IACX,GAAI,QAAQ,cAAc,EAAE,MAAM,QAAQ,YAAY,IAAI,CAAC;IAC3D,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;GAC/C,IACA,KAAA;GAWN,MAAM,QAAQ,gBAAgB,aAC1B,cAAc,eAAe,eAC7B,KAAA;GAEJ,MAAM,SAAS,MAAM,uBAAuB,CAAC,CAAC,aAC5C,KACA;IACE;IACA;IACA,kBAAkB,gBAAgB;IAClC,QAAQ,gBAAgB;IACxB;GACF,CACF;GAEA,IAAI,OAAO,WAAW,aAAa;IACjC,IAAI,QAAQ,cAAc;KACxB,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,QACL,SACA,2EACA,KACF;KAEF,OAAO,eAAe,QAAQ,cAAc,OAAO,MAAM;IAC3D;IACA,OAAO,OAAO,WAAW;GAC3B;GAEA,IAAI,OAAO,WAAW,WAEpB,OAAO,QACL,WACA,OAAO,SAAS,gCAChB,KACF;GAEF,IAAI,OAAO,WAAW,eAQpB,OAAO,QACL,eACA,OAAO,SACL,wEACF,MACA;IAAE,QAAQ,OAAO;IAAQ,mBAAmB,OAAO;GAAkB,CACvE;GAEF,OAAO,QAAQ,SAAS,OAAO,SAAS,yBAAyB,KAAK;EACxE;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"agent-tools.js","names":["agentContext","createTool"],"sources":["../src/agent-tools.ts"],"sourcesContent":["import {\n asSchema,\n tool,\n type FlexibleSchema,\n type InferSchema,\n type Tool\n} from \"ai\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"./internal_context\";\nimport type {\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult,\n AgentToolDisplayMetadata,\n AgentToolFailure\n} from \"./agent-tool-types\";\n\ntype ParseSchema<Output = unknown> = {\n parse(value: unknown): Output;\n};\n\ntype AgentToolOutputSchema<Output> =\n | FlexibleSchema<Output>\n | ParseSchema<Output>;\n\ntype AgentToolFactoryOptions<Output = unknown, Input = unknown> = {\n description: string;\n inputSchema: FlexibleSchema<Input>;\n outputSchema?: AgentToolOutputSchema<Output>;\n displayName?: string;\n icon?: string;\n display?: AgentToolDisplayMetadata;\n};\n\n// Capture the concrete schema type so the overload below can derive its input\n// with InferSchema. AgentToolFactoryOptions remains available for callers that\n// explicitly supply agentTool<Input, Output>() type arguments.\ntype InferredAgentToolFactoryOptions<\n InputSchema extends FlexibleSchema,\n Output\n> = Omit<AgentToolFactoryOptions<Output>, \"inputSchema\"> & {\n inputSchema: InputSchema;\n};\n\ntype ToolExecutionOptions = {\n toolCallId?: string;\n abortSignal?: AbortSignal;\n};\n\ntype AgentToolRunner = {\n runAgentTool<Input, Output>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>>;\n};\n\n/**\n * Preserve the existing Zod-style `.parse()` output-schema contract while\n * extending validation to the other formats supported by AI SDK FlexibleSchema.\n */\nasync function validateOutput<Output>(\n schema: AgentToolOutputSchema<Output>,\n value: unknown\n): Promise<Output> {\n if (\n typeof schema === \"object\" &&\n schema !== null &&\n \"parse\" in schema &&\n typeof schema.parse === \"function\"\n ) {\n return schema.parse(value);\n }\n\n const validate = asSchema(schema as FlexibleSchema<Output>).validate;\n if (!validate) {\n throw new Error(\"agentTool outputSchema must provide runtime validation\");\n }\n\n const result = await validate(value);\n if (!result.success) throw result.error;\n return result.value;\n}\n\nfunction currentAgentToolRunner(): AgentToolRunner {\n const agent = agentContext.getStore()?.agent;\n if (\n agent === null ||\n typeof agent !== \"object\" ||\n typeof (agent as { runAgentTool?: unknown }).runAgentTool !== \"function\"\n ) {\n throw new Error(\n \"agentTool() can only run inside an Agent turn. Use it from getTools() on an Agent subclass.\"\n );\n }\n return agent as AgentToolRunner;\n}\n\nfunction failure(\n status: AgentToolFailure[\"status\"],\n error: string,\n retryable: boolean,\n extra?: Pick<AgentToolFailure, \"reason\" | \"childStillRunning\">\n): AgentToolFailure {\n return {\n ok: false,\n status,\n error,\n retryable,\n ...(extra?.reason !== undefined ? { reason: extra.reason } : {}),\n ...(extra?.childStillRunning !== undefined\n ? { childStillRunning: extra.childStillRunning }\n : {})\n };\n}\n\n/**\n * Create an AI SDK tool that dispatches a chat-capable sub-agent through\n * `Agent.runAgentTool`.\n */\nexport function agentTool<InputSchema extends FlexibleSchema, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: InferredAgentToolFactoryOptions<InputSchema, Output>\n): Tool<InferSchema<InputSchema>, string | Output | AgentToolFailure>;\n// Preserve existing callers that explicitly provide agentTool<Input, Output>().\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure>;\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure> {\n const createTool = tool as unknown as <I, O>(config: {\n description: string;\n inputSchema: unknown;\n execute: (input: I, options?: ToolExecutionOptions) => Promise<O>;\n }) => Tool<I, O>;\n\n return createTool<Input, string | Output | AgentToolFailure>({\n description: options.description,\n inputSchema: options.inputSchema,\n execute: async (input: Input, executeOptions?: ToolExecutionOptions) => {\n const display: AgentToolDisplayMetadata | undefined =\n options.displayName || options.icon || options.display\n ? {\n ...options.display,\n ...(options.displayName ? { name: options.displayName } : {}),\n ...(options.icon ? { icon: options.icon } : {})\n }\n : undefined;\n\n // Derive a STABLE runId from the tool call id (#1630). A tool call's id is\n // preserved in the transcript, so when a parent turn is re-run by chat\n // recovery after a deploy / eviction, the same `agentTool()` call resolves\n // to the same runId — turning the re-issue into a duplicate that\n // `runAgentTool` re-attaches to the still-running child, instead of a\n // fresh `nanoid` that spawns a brand-new child and re-runs already-\n // completed work (\"the agent went all the way back\"). Falls back to a\n // fresh id only when there is no tool call id (rare; preserves prior\n // behavior).\n const runId = executeOptions?.toolCallId\n ? `agent-tool:${executeOptions.toolCallId}`\n : undefined;\n\n const result = await currentAgentToolRunner().runAgentTool<Input, Output>(\n cls,\n {\n input,\n runId,\n parentToolCallId: executeOptions?.toolCallId,\n signal: executeOptions?.abortSignal,\n display\n }\n );\n\n if (result.status === \"completed\") {\n if (options.outputSchema) {\n if (result.output === undefined) {\n return failure(\n \"error\",\n \"agent tool completed without structured output required by outputSchema\",\n false\n );\n }\n return validateOutput(options.outputSchema, result.output);\n }\n return result.summary ?? \"\";\n }\n\n if (result.status === \"aborted\") {\n // Intentional cancellation (parent/user stopped the run) — not retryable.\n return failure(\n \"aborted\",\n result.error ?? \"agent tool run was cancelled\",\n false\n );\n }\n if (result.status === \"interrupted\") {\n // The child was reset/superseded by a deploy or parent recovery before\n // it reached a logical outcome. Re-dispatching the run can succeed, so\n // surface it as retryable rather than a terminal failure the parent\n // would report to the user as final. `retryable` is intentionally COARSE\n // (always true for `interrupted`); callers that want to distinguish a\n // self-healing child from an exhausted one branch on `reason` /\n // `childStillRunning` instead.\n return failure(\n \"interrupted\",\n result.error ??\n \"agent tool run was interrupted before it finished; it can be retried\",\n true,\n { reason: result.reason, childStillRunning: result.childStillRunning }\n );\n }\n return failure(\"error\", result.error ?? \"agent tool run failed\", false);\n }\n });\n}\n\nexport type { AgentToolFactoryOptions };\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventDelivery,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolFailure,\n AgentToolInterruptedReason,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunPart,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n DetachedAgentToolConfig,\n DetachedRunAgentToolResult,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n"],"mappings":";;;;;;;;AA2DA,eAAe,eACb,QACA,OACiB;CACjB,IACE,OAAO,WAAW,YAClB,WAAW,QACX,WAAW,UACX,OAAO,OAAO,UAAU,YAExB,OAAO,OAAO,MAAM,KAAK;CAG3B,MAAM,WAAW,SAAS,MAAgC,CAAC,CAAC;CAC5D,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,wDAAwD;CAG1E,MAAM,SAAS,MAAM,SAAS,KAAK;CACnC,IAAI,CAAC,OAAO,SAAS,MAAM,OAAO;CAClC,OAAO,OAAO;AAChB;AAEA,SAAS,yBAA0C;CACjD,MAAM,QAAQA,sCAAa,SAAS,CAAC,EAAE;CACvC,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAqC,iBAAiB,YAE9D,MAAM,IAAI,MACR,6FACF;CAEF,OAAO;AACT;AAEA,SAAS,QACP,QACA,OACA,WACA,OACkB;CAClB,OAAO;EACL,IAAI;EACJ;EACA;EACA;EACA,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EAC9D,GAAI,OAAO,sBAAsB,KAAA,IAC7B,EAAE,mBAAmB,MAAM,kBAAkB,IAC7C,CAAC;CACP;AACF;AAeA,SAAgB,UACd,KACA,SACiD;CAOjD,OAAOC,KAAsD;EAC3D,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,SAAS,OAAO,OAAc,mBAA0C;GACtE,MAAM,UACJ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,UAC3C;IACE,GAAG,QAAQ;IACX,GAAI,QAAQ,cAAc,EAAE,MAAM,QAAQ,YAAY,IAAI,CAAC;IAC3D,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;GAC/C,IACA,KAAA;GAWN,MAAM,QAAQ,gBAAgB,aAC1B,cAAc,eAAe,eAC7B,KAAA;GAEJ,MAAM,SAAS,MAAM,uBAAuB,CAAC,CAAC,aAC5C,KACA;IACE;IACA;IACA,kBAAkB,gBAAgB;IAClC,QAAQ,gBAAgB;IACxB;GACF,CACF;GAEA,IAAI,OAAO,WAAW,aAAa;IACjC,IAAI,QAAQ,cAAc;KACxB,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,QACL,SACA,2EACA,KACF;KAEF,OAAO,eAAe,QAAQ,cAAc,OAAO,MAAM;IAC3D;IACA,OAAO,OAAO,WAAW;GAC3B;GAEA,IAAI,OAAO,WAAW,WAEpB,OAAO,QACL,WACA,OAAO,SAAS,gCAChB,KACF;GAEF,IAAI,OAAO,WAAW,eAQpB,OAAO,QACL,eACA,OAAO,SACL,wEACF,MACA;IAAE,QAAQ,OAAO;IAAQ,mBAAmB,OAAO;GAAkB,CACvE;GAEF,OAAO,QAAQ,SAAS,OAAO,SAAS,yBAAyB,KAAK;EACxE;CACF,CAAC;AACH"}