agents 0.16.2 → 0.17.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.
- package/README.md +11 -8
- package/dist/{agent-tool-types-CTw3UJUP.d.ts → agent-tool-types-Cd1TZPfB.d.ts} +587 -137
- package/dist/agent-tool-types.d.ts +34 -18
- package/dist/agent-tool-types.js +20 -1
- package/dist/agent-tool-types.js.map +1 -0
- package/dist/agent-tools-BXlsuX0d.js +304 -0
- package/dist/agent-tools-BXlsuX0d.js.map +1 -0
- package/dist/agent-tools-_E8wxUIK.d.ts +119 -0
- package/dist/agent-tools.d.ts +24 -18
- package/dist/agent-tools.js.map +1 -1
- package/dist/ai-chat-agent.d.ts +1 -1
- package/dist/ai-chat-agent.js +1 -2
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.d.ts +1 -1
- package/dist/ai-chat-v5-migration.js +1 -2
- package/dist/ai-chat-v5-migration.js.map +1 -1
- package/dist/ai-react.d.ts +1 -1
- package/dist/ai-react.js +1 -2
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +1 -7
- package/dist/ai-types.js +2 -8
- package/dist/ai-types.js.map +1 -1
- package/dist/browser/ai.js +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/chat/index.d.ts +1918 -72
- package/dist/chat/index.js +1730 -245
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +602 -0
- package/dist/chat/react.js +1506 -0
- package/dist/chat/react.js.map +1 -0
- package/dist/chat-sdk/index.d.ts +4 -4
- package/dist/{classPrivateFieldGet2-CZ7QjTXN.js → classPrivateFieldGet2-DZBYAB34.js} +5 -5
- package/dist/{classPrivateMethodInitSpec-D-0__zd9.js → classPrivateMethodInitSpec-qMjJ6sHQ.js} +2 -2
- package/dist/{client-BXJ9n2f7.js → client-BZ-B3NhC.js} +2 -2
- package/dist/client-BZ-B3NhC.js.map +1 -0
- package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
- package/dist/client.d.ts +76 -57
- package/dist/client.js +33 -5
- package/dist/client.js.map +1 -1
- package/dist/{connector-CrKhowfD.js → connector-CdldGF3h.js} +5 -5
- package/dist/{connector-CrKhowfD.js.map → connector-CdldGF3h.js.map} +1 -1
- package/dist/email.js +1 -1
- package/dist/email.js.map +1 -1
- package/dist/{index-B7IbEeze.d.ts → index-CcbnKkNh.d.ts} +188 -14
- package/dist/index.d.ts +91 -71
- package/dist/index.js +562 -24
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +18 -14
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/index.d.ts +30 -30
- package/dist/mcp/index.js +7 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/{agent-tools-3zLG7MgA.js → message-builder-BymO4N_D.js} +45 -126
- package/dist/message-builder-BymO4N_D.js.map +1 -0
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js +4 -2
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +123 -110
- package/dist/react.js +44 -11
- package/dist/react.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/skills/compile.js +1 -1
- package/dist/skills/compile.js.map +1 -1
- package/dist/skills/index.js +5 -5
- package/dist/skills/index.js.map +1 -1
- package/dist/sub-routing.d.ts +6 -6
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/vite.js +5 -5
- package/dist/vite.js.map +1 -1
- package/dist/wire-types-nflOzNuU.js +240 -0
- package/dist/wire-types-nflOzNuU.js.map +1 -0
- package/dist/{workflow-types-SrZK_o9p.d.ts → workflow-types-Baz_PO5v.d.ts} +42 -22
- package/dist/workflow-types.d.ts +25 -21
- package/dist/workflow-types.js.map +1 -1
- package/dist/workflows.d.ts +22 -21
- package/dist/workflows.js +31 -7
- package/dist/workflows.js.map +1 -1
- package/docs/adding-to-existing-project.md +450 -0
- package/docs/agent-class.md +503 -0
- package/docs/agent-tools.md +552 -0
- package/docs/browse-the-web.md +430 -0
- package/docs/callable-methods.md +627 -0
- package/docs/chat-agents.md +1687 -0
- package/docs/chat-sdk.md +181 -0
- package/docs/client-sdk.md +520 -0
- package/docs/client-tools-continuation.md +177 -0
- package/docs/codemode.md +440 -0
- package/docs/configuration.md +775 -0
- package/docs/cross-domain-authentication.md +171 -0
- package/docs/durable-execution.md +537 -0
- package/docs/email.md +663 -0
- package/docs/get-current-agent.md +204 -0
- package/docs/getting-started.md +305 -0
- package/docs/http-websockets.md +668 -0
- package/docs/human-in-the-loop.md +661 -0
- package/docs/index.md +151 -0
- package/docs/long-running-agents.md +730 -0
- package/docs/mcp-client.md +620 -0
- package/docs/mcp-servers.md +526 -0
- package/docs/mcp-transports.md +308 -0
- package/docs/migration-to-ai-sdk-v5.md +96 -0
- package/docs/migration-to-ai-sdk-v6.md +163 -0
- package/docs/observability.md +261 -0
- package/docs/push-notifications.md +367 -0
- package/docs/queue.md +329 -0
- package/docs/readonly-connections.md +278 -0
- package/docs/resumable-streaming.md +127 -0
- package/docs/retries.md +444 -0
- package/docs/routing.md +749 -0
- package/docs/scheduling.md +898 -0
- package/docs/securing-mcp-servers.md +359 -0
- package/docs/server-driven-messages.md +477 -0
- package/docs/sessions.md +1024 -0
- package/docs/state.md +512 -0
- package/docs/sub-agents.md +389 -0
- package/docs/webhooks.md +604 -0
- package/docs/workflows.md +877 -0
- package/package.json +41 -14
- package/dist/agent-tools-3zLG7MgA.js.map +0 -1
- package/dist/agent-tools-DZhI5F6Q.d.ts +0 -14
- package/dist/client-BXJ9n2f7.js.map +0 -1
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
C as DetachedRunAgentToolResult,
|
|
3
|
+
S as DetachedAgentToolConfig,
|
|
4
|
+
T as RunAgentToolResult,
|
|
5
|
+
_ as AgentToolRunState,
|
|
6
|
+
a as AgentToolEvent,
|
|
7
|
+
b as AgentToolTerminalStatus,
|
|
8
|
+
c as AgentToolFailure,
|
|
9
|
+
d as AgentToolMilestone,
|
|
10
|
+
f as AgentToolProgress,
|
|
11
|
+
g as AgentToolRunPart,
|
|
12
|
+
h as AgentToolRunInspection,
|
|
13
|
+
i as AgentToolDisplayMetadata,
|
|
14
|
+
l as AgentToolInterruptedReason,
|
|
15
|
+
m as AgentToolRunInfo,
|
|
16
|
+
n as AGENT_TOOL_PROGRESS_PART,
|
|
17
|
+
o as AgentToolEventMessage,
|
|
18
|
+
p as AgentToolProgressSnapshot,
|
|
19
|
+
r as AgentToolChildAdapter,
|
|
20
|
+
s as AgentToolEventState,
|
|
21
|
+
t as AGENT_TOOL_MILESTONE_PART,
|
|
22
|
+
u as AgentToolLifecycleResult,
|
|
23
|
+
v as AgentToolRunStatus,
|
|
24
|
+
w as RunAgentToolOptions,
|
|
25
|
+
x as ChatCapableAgentClass,
|
|
26
|
+
y as AgentToolStoredChunk
|
|
27
|
+
} from "./agent-tool-types-Cd1TZPfB.js";
|
|
20
28
|
export {
|
|
29
|
+
AGENT_TOOL_MILESTONE_PART,
|
|
30
|
+
AGENT_TOOL_PROGRESS_PART,
|
|
21
31
|
AgentToolChildAdapter,
|
|
22
32
|
AgentToolDisplayMetadata,
|
|
23
33
|
AgentToolEvent,
|
|
@@ -26,13 +36,19 @@ export {
|
|
|
26
36
|
AgentToolFailure,
|
|
27
37
|
AgentToolInterruptedReason,
|
|
28
38
|
AgentToolLifecycleResult,
|
|
39
|
+
AgentToolMilestone,
|
|
40
|
+
AgentToolProgress,
|
|
41
|
+
AgentToolProgressSnapshot,
|
|
29
42
|
AgentToolRunInfo,
|
|
30
43
|
AgentToolRunInspection,
|
|
44
|
+
AgentToolRunPart,
|
|
31
45
|
AgentToolRunState,
|
|
32
46
|
AgentToolRunStatus,
|
|
33
47
|
AgentToolStoredChunk,
|
|
34
48
|
AgentToolTerminalStatus,
|
|
35
49
|
ChatCapableAgentClass,
|
|
50
|
+
DetachedAgentToolConfig,
|
|
51
|
+
DetachedRunAgentToolResult,
|
|
36
52
|
RunAgentToolOptions,
|
|
37
53
|
RunAgentToolResult
|
|
38
54
|
};
|
package/dist/agent-tool-types.js
CHANGED
|
@@ -1 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/agent-tool-types.ts
|
|
2
|
+
/**
|
|
3
|
+
* Reserved chunk type a sub-agent emits via `reportProgress` while it runs.
|
|
4
|
+
* Rides the child's own UI-message stream as a **transient** data part, so it
|
|
5
|
+
* re-broadcasts to the parent's clients (via the parent's tail) and surfaces in
|
|
6
|
+
* `useAgentToolEvents` without persisting into the child's stored message parts.
|
|
7
|
+
* See `design/rfc-detached-agent-tools.md` §"Progress and milestone signaling".
|
|
8
|
+
*/
|
|
9
|
+
const AGENT_TOOL_PROGRESS_PART = "data-agent-progress";
|
|
10
|
+
/**
|
|
11
|
+
* Reserved chunk type a sub-agent emits via `reportProgress({ milestone })`.
|
|
12
|
+
* Unlike the ephemeral progress part this rides the child's stream as a
|
|
13
|
+
* **persisted** data part, so it survives eviction, replays on drill-in, and
|
|
14
|
+
* re-resolves milestone waiters. See `design/rfc-detached-agent-tools.md`.
|
|
15
|
+
*/
|
|
16
|
+
const AGENT_TOOL_MILESTONE_PART = "data-agent-milestone";
|
|
17
|
+
//#endregion
|
|
18
|
+
export { AGENT_TOOL_MILESTONE_PART, AGENT_TOOL_PROGRESS_PART };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=agent-tool-types.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,304 @@
|
|
|
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";
|
|
3
|
+
//#region src/chat/agent-tools.ts
|
|
4
|
+
/**
|
|
5
|
+
* Pull a reserved `data-agent-progress` chunk (emitted by a running sub-agent's
|
|
6
|
+
* `reportProgress`) into a latest-wins snapshot. Returns `undefined` for any
|
|
7
|
+
* other chunk so the caller keeps the prior snapshot.
|
|
8
|
+
*/
|
|
9
|
+
function readAgentToolProgressChunk(chunk) {
|
|
10
|
+
if (typeof chunk !== "object" || chunk === null || chunk.type !== "data-agent-progress") return;
|
|
11
|
+
const data = chunk.data ?? {};
|
|
12
|
+
return {
|
|
13
|
+
...typeof data.fraction === "number" ? { fraction: data.fraction } : {},
|
|
14
|
+
...typeof data.message === "string" ? { message: data.message } : {},
|
|
15
|
+
...typeof data.phase === "string" ? { phase: data.phase } : {},
|
|
16
|
+
...data.data !== void 0 ? { data: data.data } : {},
|
|
17
|
+
at: Date.now()
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Pull a reserved `data-agent-milestone` chunk into a durable milestone record,
|
|
22
|
+
* or `undefined` for any other chunk. Milestones carry their own monotonic
|
|
23
|
+
* `sequence` so the caller can dedupe replay-vs-live races.
|
|
24
|
+
*/
|
|
25
|
+
function readAgentToolMilestoneChunk(chunk) {
|
|
26
|
+
if (typeof chunk !== "object" || chunk === null || chunk.type !== "data-agent-milestone") return;
|
|
27
|
+
const data = chunk.data ?? {};
|
|
28
|
+
if (typeof data.name !== "string") return void 0;
|
|
29
|
+
return {
|
|
30
|
+
name: data.name,
|
|
31
|
+
sequence: typeof data.sequence === "number" ? data.sequence : 0,
|
|
32
|
+
at: typeof data.at === "number" ? data.at : Date.now(),
|
|
33
|
+
...data.data !== void 0 ? { data: data.data } : {}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Merge a milestone into a run's ordered milestone list, deduping on `sequence`
|
|
38
|
+
* (idempotent across replay + live races) and keeping the list sorted.
|
|
39
|
+
*/
|
|
40
|
+
function mergeMilestone(existing, milestone) {
|
|
41
|
+
if (existing?.some((m) => m.sequence === milestone.sequence)) return existing;
|
|
42
|
+
const list = existing ? [...existing, milestone] : [milestone];
|
|
43
|
+
list.sort((a, b) => a.sequence - b.sequence);
|
|
44
|
+
return list;
|
|
45
|
+
}
|
|
46
|
+
/** Latest-wins coalescing window for `reportProgress` emits (per run). */
|
|
47
|
+
const AGENT_TOOL_PROGRESS_COALESCE_MS = 200;
|
|
48
|
+
/**
|
|
49
|
+
* Shared implementation of `reportProgress` for chat hosts. Builds the reserved
|
|
50
|
+
* transient `data-agent-progress` wire frame, coalesces bursts to a bounded
|
|
51
|
+
* cadence (latest-wins; a `fraction >= 1` "done" frame always flushes), and
|
|
52
|
+
* persists a latest snapshot. `data` rides the live frame but is only persisted
|
|
53
|
+
* when the caller opts in via `{ persist: true }`.
|
|
54
|
+
*/
|
|
55
|
+
var AgentToolProgressEmitter = class {
|
|
56
|
+
constructor(hooks) {
|
|
57
|
+
this.hooks = hooks;
|
|
58
|
+
this._lastEmitAt = /* @__PURE__ */ new Map();
|
|
59
|
+
}
|
|
60
|
+
report(progress, options) {
|
|
61
|
+
const active = this.hooks.resolveActiveRun();
|
|
62
|
+
if (!active) return "inactive";
|
|
63
|
+
const { runId, requestId } = active;
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
if (typeof progress.milestone === "string" && progress.milestone) {
|
|
66
|
+
this._lastEmitAt.set(runId, now);
|
|
67
|
+
const sequence = this.hooks.persistMilestone(runId, progress.milestone, progress.data, now);
|
|
68
|
+
this.hooks.broadcast(requestId, JSON.stringify({
|
|
69
|
+
type: AGENT_TOOL_MILESTONE_PART,
|
|
70
|
+
data: {
|
|
71
|
+
name: progress.milestone,
|
|
72
|
+
sequence,
|
|
73
|
+
at: now,
|
|
74
|
+
...typeof progress.fraction === "number" ? { fraction: progress.fraction } : {},
|
|
75
|
+
...typeof progress.message === "string" ? { message: progress.message } : {},
|
|
76
|
+
...typeof progress.phase === "string" ? { phase: progress.phase } : {},
|
|
77
|
+
...progress.data !== void 0 ? { data: progress.data } : {}
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
return "emitted";
|
|
81
|
+
}
|
|
82
|
+
const last = this._lastEmitAt.get(runId) ?? 0;
|
|
83
|
+
const isDone = typeof progress.fraction === "number" && progress.fraction >= 1;
|
|
84
|
+
if (now - last < AGENT_TOOL_PROGRESS_COALESCE_MS && !isDone) return "coalesced";
|
|
85
|
+
this._lastEmitAt.set(runId, now);
|
|
86
|
+
const wire = {
|
|
87
|
+
...typeof progress.fraction === "number" ? { fraction: progress.fraction } : {},
|
|
88
|
+
...typeof progress.message === "string" ? { message: progress.message } : {},
|
|
89
|
+
...typeof progress.phase === "string" ? { phase: progress.phase } : {},
|
|
90
|
+
...progress.data !== void 0 ? { data: progress.data } : {}
|
|
91
|
+
};
|
|
92
|
+
this.hooks.broadcast(requestId, JSON.stringify({
|
|
93
|
+
type: AGENT_TOOL_PROGRESS_PART,
|
|
94
|
+
transient: true,
|
|
95
|
+
data: wire
|
|
96
|
+
}));
|
|
97
|
+
this.hooks.persistSnapshot(runId, {
|
|
98
|
+
...typeof progress.fraction === "number" ? { fraction: progress.fraction } : {},
|
|
99
|
+
...typeof progress.message === "string" ? { message: progress.message } : {},
|
|
100
|
+
...typeof progress.phase === "string" ? { phase: progress.phase } : {},
|
|
101
|
+
...options?.persist && progress.data !== void 0 ? { data: progress.data } : {}
|
|
102
|
+
}, now);
|
|
103
|
+
return "emitted";
|
|
104
|
+
}
|
|
105
|
+
/** Drop coalescing state for a settled run (called on terminal). */
|
|
106
|
+
forget(runId) {
|
|
107
|
+
this._lastEmitAt.delete(runId);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
function sortRuns(runs) {
|
|
111
|
+
return [...runs].sort((a, b) => {
|
|
112
|
+
if (a.order !== b.order) return a.order - b.order;
|
|
113
|
+
return a.runId.localeCompare(b.runId);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function rebuildIndexes(runsById) {
|
|
117
|
+
const grouped = {};
|
|
118
|
+
const unboundRuns = [];
|
|
119
|
+
for (const run of Object.values(runsById)) if (run.parentToolCallId) {
|
|
120
|
+
grouped[run.parentToolCallId] = grouped[run.parentToolCallId] ?? [];
|
|
121
|
+
grouped[run.parentToolCallId].push(run);
|
|
122
|
+
} else unboundRuns.push(run);
|
|
123
|
+
for (const [toolCallId, runs] of Object.entries(grouped)) grouped[toolCallId] = sortRuns(runs);
|
|
124
|
+
return {
|
|
125
|
+
runsByToolCallId: grouped,
|
|
126
|
+
unboundRuns: sortRuns(unboundRuns)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function emptyRun(message) {
|
|
130
|
+
const { event } = message;
|
|
131
|
+
if (event.kind === "started") return {
|
|
132
|
+
runId: event.runId,
|
|
133
|
+
agentType: event.agentType,
|
|
134
|
+
parentToolCallId: message.parentToolCallId,
|
|
135
|
+
inputPreview: event.inputPreview,
|
|
136
|
+
order: event.order,
|
|
137
|
+
display: event.display,
|
|
138
|
+
status: "running",
|
|
139
|
+
parts: [],
|
|
140
|
+
subAgent: {
|
|
141
|
+
agent: event.agentType,
|
|
142
|
+
name: event.runId
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function applyToRun(prev, message) {
|
|
147
|
+
const seeded = prev ?? emptyRun(message);
|
|
148
|
+
const { event } = message;
|
|
149
|
+
switch (event.kind) {
|
|
150
|
+
case "started":
|
|
151
|
+
if (seeded?.status === "completed" || seeded?.status === "error" || seeded?.status === "aborted" || seeded?.status === "interrupted") return seeded;
|
|
152
|
+
return {
|
|
153
|
+
...seeded,
|
|
154
|
+
runId: event.runId,
|
|
155
|
+
agentType: event.agentType,
|
|
156
|
+
parentToolCallId: message.parentToolCallId,
|
|
157
|
+
inputPreview: event.inputPreview,
|
|
158
|
+
order: event.order,
|
|
159
|
+
display: event.display,
|
|
160
|
+
status: "running",
|
|
161
|
+
parts: seeded?.parts ?? [],
|
|
162
|
+
subAgent: {
|
|
163
|
+
agent: event.agentType,
|
|
164
|
+
name: event.runId
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
case "chunk": {
|
|
168
|
+
if (!seeded) return void 0;
|
|
169
|
+
const parts = [...seeded.parts];
|
|
170
|
+
let parsed;
|
|
171
|
+
try {
|
|
172
|
+
parsed = JSON.parse(event.body);
|
|
173
|
+
applyChunkToParts(parts, parsed);
|
|
174
|
+
} catch {
|
|
175
|
+
return seeded;
|
|
176
|
+
}
|
|
177
|
+
const progress = readAgentToolProgressChunk(parsed);
|
|
178
|
+
if (progress) return {
|
|
179
|
+
...seeded,
|
|
180
|
+
parts,
|
|
181
|
+
progress
|
|
182
|
+
};
|
|
183
|
+
const milestone = readAgentToolMilestoneChunk(parsed);
|
|
184
|
+
if (milestone) {
|
|
185
|
+
const milestones = mergeMilestone(seeded.milestones, milestone);
|
|
186
|
+
const isNew = milestones !== seeded.milestones;
|
|
187
|
+
const notOlder = seeded.progress === void 0 || milestone.at >= seeded.progress.at;
|
|
188
|
+
if (!isNew || !notOlder) return {
|
|
189
|
+
...seeded,
|
|
190
|
+
parts,
|
|
191
|
+
milestones
|
|
192
|
+
};
|
|
193
|
+
const data = parsed.data ?? {};
|
|
194
|
+
const snapshot = {
|
|
195
|
+
...typeof data.fraction === "number" ? { fraction: data.fraction } : {},
|
|
196
|
+
...typeof data.message === "string" ? { message: data.message } : {},
|
|
197
|
+
...typeof data.phase === "string" ? { phase: data.phase } : {},
|
|
198
|
+
milestone: milestone.name,
|
|
199
|
+
at: milestone.at
|
|
200
|
+
};
|
|
201
|
+
return {
|
|
202
|
+
...seeded,
|
|
203
|
+
parts,
|
|
204
|
+
progress: snapshot,
|
|
205
|
+
milestones
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
...seeded,
|
|
210
|
+
parts
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
case "finished":
|
|
214
|
+
if (!seeded) return void 0;
|
|
215
|
+
return {
|
|
216
|
+
...seeded,
|
|
217
|
+
status: "completed",
|
|
218
|
+
summary: event.summary,
|
|
219
|
+
error: void 0
|
|
220
|
+
};
|
|
221
|
+
case "error":
|
|
222
|
+
if (!seeded) return void 0;
|
|
223
|
+
return {
|
|
224
|
+
...seeded,
|
|
225
|
+
status: "error",
|
|
226
|
+
error: event.error
|
|
227
|
+
};
|
|
228
|
+
case "aborted":
|
|
229
|
+
if (!seeded) return void 0;
|
|
230
|
+
return {
|
|
231
|
+
...seeded,
|
|
232
|
+
status: "aborted",
|
|
233
|
+
error: event.reason
|
|
234
|
+
};
|
|
235
|
+
case "interrupted":
|
|
236
|
+
if (!seeded) return void 0;
|
|
237
|
+
return {
|
|
238
|
+
...seeded,
|
|
239
|
+
status: "interrupted",
|
|
240
|
+
error: event.error,
|
|
241
|
+
reason: event.reason,
|
|
242
|
+
childStillRunning: event.childStillRunning
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function createAgentToolEventState() {
|
|
247
|
+
return {
|
|
248
|
+
runsById: {},
|
|
249
|
+
runsByToolCallId: {},
|
|
250
|
+
unboundRuns: []
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function applyAgentToolEvent(state, message) {
|
|
254
|
+
if (message.type !== "agent-tool-event") return state;
|
|
255
|
+
const runId = message.event.runId;
|
|
256
|
+
const nextRun = applyToRun(state.runsById[runId], message);
|
|
257
|
+
if (!nextRun) return state;
|
|
258
|
+
const runsById = {
|
|
259
|
+
...state.runsById,
|
|
260
|
+
[runId]: nextRun
|
|
261
|
+
};
|
|
262
|
+
return {
|
|
263
|
+
runsById,
|
|
264
|
+
...rebuildIndexes(runsById)
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Snoop a host's outgoing chat frames while any agent-tool run is in flight and
|
|
269
|
+
* forward the owning run's streamed body to its live tailers (or capture its
|
|
270
|
+
* error), without altering the frame — the caller still broadcasts it (#1575).
|
|
271
|
+
*
|
|
272
|
+
* Shared verbatim by `@cloudflare/ai-chat` and `@cloudflare/think`; the only
|
|
273
|
+
* per-host variance (the response-frame type constant and the run-lookup, whose
|
|
274
|
+
* SQL differs) is supplied via {@link AgentToolBroadcastHooks}. Inspection runs
|
|
275
|
+
* for a run's whole lifecycle (live sequences exist even with no tailer), so
|
|
276
|
+
* error capture never depends on tailer timing. A frame belongs to a run iff it
|
|
277
|
+
* carries that run's turn request id, so concurrent runs can't cross-contaminate
|
|
278
|
+
* each other's progress or error state.
|
|
279
|
+
*/
|
|
280
|
+
function interceptAgentToolBroadcast(msg, hooks) {
|
|
281
|
+
if ((hooks.forwarders.size > 0 || hooks.liveSequences.size > 0) && typeof msg === "string") try {
|
|
282
|
+
const parsed = JSON.parse(msg);
|
|
283
|
+
if (parsed.type === hooks.responseType && typeof parsed.id === "string") {
|
|
284
|
+
const runId = hooks.runForRequest(parsed.id);
|
|
285
|
+
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) {
|
|
288
|
+
const sequence = hooks.liveSequences.get(runId) ?? 0;
|
|
289
|
+
hooks.liveSequences.set(runId, sequence + 1);
|
|
290
|
+
const chunk = {
|
|
291
|
+
sequence,
|
|
292
|
+
body: parsed.body
|
|
293
|
+
};
|
|
294
|
+
const forwarders = hooks.forwarders.get(runId);
|
|
295
|
+
if (forwarders) for (const forward of forwarders) forward(chunk);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
} catch {}
|
|
300
|
+
}
|
|
301
|
+
//#endregion
|
|
302
|
+
export { interceptAgentToolBroadcast as i, applyAgentToolEvent as n, createAgentToolEventState as r, AgentToolProgressEmitter as t };
|
|
303
|
+
|
|
304
|
+
//# sourceMappingURL=agent-tools-BXlsuX0d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-tools-BXlsuX0d.js","names":[],"sources":["../src/chat/agent-tools.ts"],"sourcesContent":["import { applyChunkToParts, type MessagePart } from \"./message-builder\";\nimport {\n AGENT_TOOL_MILESTONE_PART,\n AGENT_TOOL_PROGRESS_PART\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 this.hooks.broadcast(\n requestId,\n JSON.stringify({\n type: AGENT_TOOL_PROGRESS_PART,\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 const parts = [...seeded.parts];\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\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 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 /** Per-run forwarded-chunk counter; advanced even with no tailer attached. */\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 /** 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\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 */\nexport function interceptAgentToolBroadcast(\n msg: string | ArrayBuffer | ArrayBufferView,\n hooks: AgentToolBroadcastHooks\n): void {\n if (\n (hooks.forwarders.size > 0 || hooks.liveSequences.size > 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 } 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.\n const sequence = hooks.liveSequences.get(runId) ?? 0;\n hooks.liveSequences.set(runId, sequence + 1);\n const chunk: AgentToolStoredChunk = { sequence, body: parsed.body };\n const forwarders = hooks.forwarders.get(runId);\n if (forwarders) {\n for (const forward of forwarders) forward(chunk);\n }\n }\n }\n }\n } catch {\n // Non-chat frames pass through unchanged.\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
f as AgentToolProgress,
|
|
3
|
+
g as AgentToolRunPart,
|
|
4
|
+
o as AgentToolEventMessage,
|
|
5
|
+
s as AgentToolEventState,
|
|
6
|
+
y as AgentToolStoredChunk
|
|
7
|
+
} from "./agent-tool-types-Cd1TZPfB.js";
|
|
8
|
+
|
|
9
|
+
//#region src/chat/agent-tools.d.ts
|
|
10
|
+
type AgentToolProgressEmitResult = "emitted" | "coalesced" | "inactive";
|
|
11
|
+
/**
|
|
12
|
+
* Host-injected seams the shared progress emitter needs. Keeps the per-host
|
|
13
|
+
* `reportProgress` thin: Think / AIChatAgent supply how to resolve the active
|
|
14
|
+
* agent-tool run, how to broadcast a chat-response frame, and how to persist the
|
|
15
|
+
* latest snapshot on their own child-run table.
|
|
16
|
+
*/
|
|
17
|
+
type AgentToolProgressEmitHooks = {
|
|
18
|
+
/** The agent-tool run currently executing in this turn, or null. */ resolveActiveRun: () => {
|
|
19
|
+
runId: string;
|
|
20
|
+
requestId: string;
|
|
21
|
+
} | null /** Broadcast a chat-response frame (id = requestId) to clients/tailers. */;
|
|
22
|
+
broadcast: (
|
|
23
|
+
requestId: string,
|
|
24
|
+
chunkBody: string
|
|
25
|
+
) => void /** Persist the latest snapshot + signal timestamp on the child run row. */;
|
|
26
|
+
persistSnapshot: (
|
|
27
|
+
runId: string,
|
|
28
|
+
snapshot: {
|
|
29
|
+
fraction?: number;
|
|
30
|
+
message?: string;
|
|
31
|
+
phase?: string;
|
|
32
|
+
data?: unknown;
|
|
33
|
+
},
|
|
34
|
+
at: number
|
|
35
|
+
) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Persist a durable milestone row, bump the run's signal timestamp, and return
|
|
38
|
+
* the assigned monotonic per-run `sequence` (used to dedupe replay/live races).
|
|
39
|
+
*/
|
|
40
|
+
persistMilestone: (
|
|
41
|
+
runId: string,
|
|
42
|
+
name: string,
|
|
43
|
+
data: unknown,
|
|
44
|
+
at: number
|
|
45
|
+
) => number;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Shared implementation of `reportProgress` for chat hosts. Builds the reserved
|
|
49
|
+
* transient `data-agent-progress` wire frame, coalesces bursts to a bounded
|
|
50
|
+
* cadence (latest-wins; a `fraction >= 1` "done" frame always flushes), and
|
|
51
|
+
* persists a latest snapshot. `data` rides the live frame but is only persisted
|
|
52
|
+
* when the caller opts in via `{ persist: true }`.
|
|
53
|
+
*/
|
|
54
|
+
declare class AgentToolProgressEmitter {
|
|
55
|
+
private readonly hooks;
|
|
56
|
+
private readonly _lastEmitAt;
|
|
57
|
+
constructor(hooks: AgentToolProgressEmitHooks);
|
|
58
|
+
report(
|
|
59
|
+
progress: AgentToolProgress,
|
|
60
|
+
options?: {
|
|
61
|
+
persist?: boolean;
|
|
62
|
+
}
|
|
63
|
+
): AgentToolProgressEmitResult;
|
|
64
|
+
/** Drop coalescing state for a settled run (called on terminal). */
|
|
65
|
+
forget(runId: string): void;
|
|
66
|
+
}
|
|
67
|
+
declare function createAgentToolEventState<
|
|
68
|
+
Part extends AgentToolRunPart = AgentToolRunPart
|
|
69
|
+
>(): AgentToolEventState<Part>;
|
|
70
|
+
declare function applyAgentToolEvent<
|
|
71
|
+
Part extends AgentToolRunPart = AgentToolRunPart
|
|
72
|
+
>(
|
|
73
|
+
state: AgentToolEventState<Part>,
|
|
74
|
+
message: AgentToolEventMessage
|
|
75
|
+
): AgentToolEventState<Part>;
|
|
76
|
+
/**
|
|
77
|
+
* @internal Host substrate the {@link interceptAgentToolBroadcast} snoop reads,
|
|
78
|
+
* abstracting the divergent per-host run-lookup and response-frame constant.
|
|
79
|
+
*/
|
|
80
|
+
interface AgentToolBroadcastHooks {
|
|
81
|
+
/** Live tailers per run; iterated to forward each progress chunk. */
|
|
82
|
+
forwarders: Map<string, Set<(chunk: AgentToolStoredChunk) => void>>;
|
|
83
|
+
/** Per-run forwarded-chunk counter; advanced even with no tailer attached. */
|
|
84
|
+
liveSequences: Map<string, number>;
|
|
85
|
+
/** Per-run last error body, captured for replay to a late-attaching tailer. */
|
|
86
|
+
lastErrors: Map<string, string>;
|
|
87
|
+
/** The host's use-chat-response wire type (`CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE`). */
|
|
88
|
+
responseType: string;
|
|
89
|
+
/** Resolve the agent-tool run that owns a turn request id, or null. */
|
|
90
|
+
runForRequest: (requestId: string) => string | null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Snoop a host's outgoing chat frames while any agent-tool run is in flight and
|
|
94
|
+
* forward the owning run's streamed body to its live tailers (or capture its
|
|
95
|
+
* error), without altering the frame — the caller still broadcasts it (#1575).
|
|
96
|
+
*
|
|
97
|
+
* Shared verbatim by `@cloudflare/ai-chat` and `@cloudflare/think`; the only
|
|
98
|
+
* per-host variance (the response-frame type constant and the run-lookup, whose
|
|
99
|
+
* SQL differs) is supplied via {@link AgentToolBroadcastHooks}. Inspection runs
|
|
100
|
+
* for a run's whole lifecycle (live sequences exist even with no tailer), so
|
|
101
|
+
* error capture never depends on tailer timing. A frame belongs to a run iff it
|
|
102
|
+
* carries that run's turn request id, so concurrent runs can't cross-contaminate
|
|
103
|
+
* each other's progress or error state.
|
|
104
|
+
*/
|
|
105
|
+
declare function interceptAgentToolBroadcast(
|
|
106
|
+
msg: string | ArrayBuffer | ArrayBufferView,
|
|
107
|
+
hooks: AgentToolBroadcastHooks
|
|
108
|
+
): void;
|
|
109
|
+
//#endregion
|
|
110
|
+
export {
|
|
111
|
+
applyAgentToolEvent as a,
|
|
112
|
+
AgentToolProgressEmitter as i,
|
|
113
|
+
AgentToolProgressEmitHooks as n,
|
|
114
|
+
createAgentToolEventState as o,
|
|
115
|
+
AgentToolProgressEmitResult as r,
|
|
116
|
+
interceptAgentToolBroadcast as s,
|
|
117
|
+
AgentToolBroadcastHooks as t
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=agent-tools-_E8wxUIK.d.ts.map
|