agents 0.13.3 → 0.14.1
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 +6 -4
- package/dist/{agent-tool-types-l98LCbBl.d.ts → agent-tool-types-BAJWu8s4.d.ts} +474 -117
- package/dist/agent-tool-types.d.ts +13 -11
- package/dist/{agent-tools-Bg5ilERh.d.ts → agent-tools-0R6KEert.d.ts} +2 -2
- package/dist/{agent-tools-BAdX1vdI.js → agent-tools-DYrkT-Kx.js} +46 -6
- package/dist/agent-tools-DYrkT-Kx.js.map +1 -0
- package/dist/agent-tools.d.ts +14 -20
- package/dist/agent-tools.js +10 -6
- package/dist/agent-tools.js.map +1 -1
- package/dist/browser/ai.d.ts +1 -1
- package/dist/browser/ai.js +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/tanstack-ai.d.ts +1 -1
- package/dist/browser/tanstack-ai.js +1 -1
- package/dist/chat/index.d.ts +162 -19
- package/dist/chat/index.js +97 -13
- package/dist/chat/index.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +5 -5
- package/dist/chat-sdk/index.js +2 -2
- package/dist/chat-sdk/index.js.map +1 -1
- package/dist/{classPrivateFieldGet2-Evpt0SEr.js → classPrivateFieldGet2-D_obpP6O.js} +5 -5
- package/dist/classPrivateMethodInitSpec-10iTYB7F.js +7 -0
- package/dist/{client-D1kFXo80.js → client-FUizKzj2.js} +299 -95
- package/dist/client-FUizKzj2.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/{compaction-helpers-B-pG5J22.d.ts → compaction-helpers-BEUILPss.d.ts} +59 -33
- package/dist/{compaction-helpers-fJyf8j4m.js → compaction-helpers-iiKMr2TQ.js} +22 -3
- package/dist/compaction-helpers-iiKMr2TQ.js.map +1 -0
- package/dist/{do-oauth-client-provider-4OKQU9rT.d.ts → do-oauth-client-provider-D4ZwyBDu.d.ts} +21 -1
- package/dist/{email-J0GGS3sa.d.ts → email-CL27preh.d.ts} +1 -1
- package/dist/email.d.ts +2 -2
- package/dist/experimental/memory/session/index.d.ts +30 -25
- package/dist/experimental/memory/session/index.js +7 -2
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +12 -10
- package/dist/experimental/memory/utils/index.js +2 -2
- package/dist/{index-DKey3P4s.d.ts → index-RJ4OxMOe.d.ts} +270 -1
- package/dist/index.d.ts +74 -67
- package/dist/index.js +485 -64
- package/dist/index.js.map +1 -1
- package/dist/{internal_context-BZrMS0B5.d.ts → internal_context-Dg4Cgjcu.d.ts} +1 -1
- package/dist/internal_context.d.ts +1 -1
- package/dist/mcp/client.d.ts +17 -13
- package/dist/mcp/client.js +2 -2
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/do-oauth-client-provider.js +143 -17
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +35 -27
- package/dist/mcp/index.js +402 -69
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js +15 -1
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +3 -3
- package/dist/react.js +1 -1
- package/dist/{retries-BVdRl5ZE.d.ts → retries-CF_HKSlJ.d.ts} +1 -1
- package/dist/retries.d.ts +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{shared-Cvj92byG.d.ts → shared-4CAYLCTO.d.ts} +1 -1
- package/dist/{shared-CiKaIK4h.js → shared-BIpUk4G5.js} +3 -7
- package/dist/{shared-CiKaIK4h.js.map → shared-BIpUk4G5.js.map} +1 -1
- package/dist/skills/index.d.ts +236 -0
- package/dist/skills/index.js +1326 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/sub-routing.d.ts +6 -6
- package/dist/{tool-output-truncation-CH-khbZ3.js → tool-output-truncation-CNnnGZQ3.js} +1 -1
- package/dist/{tool-output-truncation-CH-khbZ3.js.map → tool-output-truncation-CNnnGZQ3.js.map} +1 -1
- package/dist/{types-_JjKmv-l.d.ts → types-6Zo2zfoO.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +248 -2
- package/dist/vite.js.map +1 -1
- package/dist/{workflow-types-Dkzg4hAx.d.ts → workflow-types-SrZK_o9p.d.ts} +1 -1
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +13 -3
- package/dist/workflows.js +10 -1
- package/dist/workflows.js.map +1 -1
- package/package.json +31 -13
- package/skills-module.d.ts +22 -0
- package/dist/agent-tools-BAdX1vdI.js.map +0 -1
- package/dist/client-D1kFXo80.js.map +0 -1
- package/dist/compaction-helpers-fJyf8j4m.js.map +0 -1
package/dist/workflow-types.d.ts
CHANGED
package/dist/workflows.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { y as Agent } from "./agent-tool-types-BAJWu8s4.js";
|
|
2
2
|
import {
|
|
3
3
|
S as WorkflowTrackingRow,
|
|
4
4
|
_ as WorkflowPage,
|
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
v as WorkflowProgressCallback,
|
|
21
21
|
x as WorkflowStatus,
|
|
22
22
|
y as WorkflowQueryCriteria
|
|
23
|
-
} from "./workflow-types-
|
|
24
|
-
import { WorkflowEntrypoint } from "cloudflare:workers";
|
|
23
|
+
} from "./workflow-types-SrZK_o9p.js";
|
|
24
|
+
import { WorkflowEntrypoint, WorkflowEvent } from "cloudflare:workers";
|
|
25
25
|
|
|
26
26
|
//#region src/workflows.d.ts
|
|
27
27
|
/**
|
|
@@ -76,6 +76,16 @@ declare class AgentWorkflow<
|
|
|
76
76
|
* that Cloudflare's runtime may perform on the WorkflowStep class.
|
|
77
77
|
*/
|
|
78
78
|
private _wrapStep;
|
|
79
|
+
/**
|
|
80
|
+
* Extend the Agent-aware workflow step before user code receives it.
|
|
81
|
+
*
|
|
82
|
+
* Subclasses can override this to add framework-specific step helpers while
|
|
83
|
+
* preserving the underlying WorkflowStep object identity.
|
|
84
|
+
*/
|
|
85
|
+
protected extendStep(
|
|
86
|
+
step: AgentWorkflowStep,
|
|
87
|
+
_event: WorkflowEvent<Params>
|
|
88
|
+
): AgentWorkflowStep;
|
|
79
89
|
/**
|
|
80
90
|
* Get the Agent stub for RPC calls.
|
|
81
91
|
* Provides typed access to the Agent's methods.
|
package/dist/workflows.js
CHANGED
|
@@ -66,7 +66,7 @@ var AgentWorkflow = class extends WorkflowEntrypoint {
|
|
|
66
66
|
...event,
|
|
67
67
|
payload: userParams
|
|
68
68
|
};
|
|
69
|
-
const wrappedStep = this._wrapStep(step);
|
|
69
|
+
const wrappedStep = this.extendStep(this._wrapStep(step), cleanedEvent);
|
|
70
70
|
try {
|
|
71
71
|
return await originalRun.call(this, cleanedEvent, wrappedStep);
|
|
72
72
|
} catch (err) {
|
|
@@ -159,6 +159,15 @@ var AgentWorkflow = class extends WorkflowEntrypoint {
|
|
|
159
159
|
return wrappedStep;
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
|
+
* Extend the Agent-aware workflow step before user code receives it.
|
|
163
|
+
*
|
|
164
|
+
* Subclasses can override this to add framework-specific step helpers while
|
|
165
|
+
* preserving the underlying WorkflowStep object identity.
|
|
166
|
+
*/
|
|
167
|
+
extendStep(step, _event) {
|
|
168
|
+
return step;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
162
171
|
* Get the Agent stub for RPC calls.
|
|
163
172
|
* Provides typed access to the Agent's methods.
|
|
164
173
|
*
|
package/dist/workflows.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.js","names":[],"sources":["../src/workflows.ts"],"sourcesContent":["/**\n * AgentWorkflow - Base class for Workflows that integrate with Agents\n *\n * Extends Cloudflare's WorkflowEntrypoint to provide seamless access to\n * the Agent that started the workflow, enabling bidirectional communication.\n *\n * @example\n * ```typescript\n * import { AgentWorkflow } from 'agents/workflows';\n * import type { MyAgent } from './agent';\n *\n * type TaskParams = { taskId: string; data: string };\n *\n * export class ProcessingWorkflow extends AgentWorkflow<MyAgent, TaskParams> {\n * async run(event: AgentWorkflowEvent<TaskParams>, step: WorkflowStep) {\n * // Access the originating Agent via typed RPC\n * await this.agent.updateTaskStatus(event.payload.taskId, 'processing');\n *\n * const result = await step.do('process', async () => {\n * // ... processing logic\n * return { processed: true };\n * });\n *\n * // Report progress to Agent (typed)\n * await this.reportProgress({ step: 'process', status: 'complete', percent: 0.5 });\n *\n * // Broadcast to connected clients\n * await this.broadcastToClients({ type: 'progress', data: result });\n *\n * return result;\n * }\n * }\n * ```\n */\n\nimport { WorkflowEntrypoint } from \"cloudflare:workers\";\nimport type { WorkflowEvent, WorkflowStep } from \"cloudflare:workers\";\nimport { getAgentByName, type Agent } from \"./index\";\nimport type {\n AgentWorkflowParams,\n AgentWorkflowStep,\n WorkflowCallback,\n DefaultProgress,\n WaitForApprovalOptions\n} from \"./workflow-types\";\nimport { WorkflowRejectedError } from \"./workflow-types\";\n\n/**\n * WeakSet to track which prototypes have been wrapped.\n * This prevents re-wrapping on subsequent instantiations of the same class.\n */\nconst wrappedPrototypes = new WeakSet<object>();\n\n/**\n * Base class for Workflows that need access to their originating Agent.\n *\n * @template AgentType - The Agent class type (for typed RPC access)\n * @template Params - User-defined params passed to the workflow (optional)\n * @template ProgressType - Type for progress reporting (defaults to DefaultProgress)\n * @template Env - Environment type (defaults to Cloudflare.Env)\n */\nexport class AgentWorkflow<\n AgentType extends Agent = Agent,\n Params = unknown,\n ProgressType = DefaultProgress,\n Env extends Cloudflare.Env = Cloudflare.Env\n> extends WorkflowEntrypoint<Env, AgentWorkflowParams<Params>> {\n /**\n * The Agent stub - initialized before run() is called.\n * Use this.agent to access the Agent's RPC methods.\n */\n private _agent!: DurableObjectStub<AgentType>;\n\n /**\n * Workflow instance ID\n */\n private _workflowId!: string;\n\n /**\n * Workflow binding name (for callbacks)\n */\n private _workflowName!: string;\n\n /**\n * Instance-level guard to prevent double initialization.\n * Used when a subclass calls super.run() after its own run() was wrapped.\n */\n private __agentInitCalled = false;\n\n /**\n * Guard to prevent double error notification.\n * Set to true when reportError() is called explicitly, so the automatic\n * error catch in the run() wrapper doesn't send a duplicate notification.\n */\n private _errorReported = false;\n\n constructor(ctx: ExecutionContext, env: Env) {\n super(ctx, env);\n\n const proto = Object.getPrototypeOf(this);\n\n // Only wrap if:\n // 1. This prototype defines its own run method (hasOwnProperty)\n // 2. It hasn't been wrapped yet (WeakSet check)\n // This prevents double-wrapping inherited methods and ensures each subclass\n // that defines run() gets wrapped exactly once.\n if (Object.hasOwn(proto, \"run\") && !wrappedPrototypes.has(proto)) {\n const originalRun = proto.run as (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>;\n\n // Replace the prototype's run method with a wrapper that initializes\n // the agent before calling the user's implementation\n proto.run = async function (\n this: AgentWorkflow<AgentType, Params, ProgressType, Env>,\n event: WorkflowEvent<AgentWorkflowParams<Params>>,\n step: WorkflowStep\n ) {\n // Instance-level guard: only init once per instance\n // (prevents double init if super.run() is called from a subclass)\n if (!this.__agentInitCalled) {\n const { __agentName, __agentBinding, __workflowName, ...userParams } =\n event.payload;\n\n // Initialize agent connection\n await this._initAgent(\n __agentName,\n __agentBinding,\n __workflowName,\n event.instanceId\n );\n this.__agentInitCalled = true;\n\n // Pass cleaned event and wrapped step to user's implementation\n const cleanedEvent = {\n ...event,\n payload: userParams as Params\n } as WorkflowEvent<Params>;\n\n const wrappedStep = this._wrapStep(step);\n\n try {\n return await originalRun.call(this, cleanedEvent, wrappedStep);\n } catch (err) {\n await this._autoReportError(err);\n throw err;\n }\n }\n\n // If already initialized (e.g., called via super.run()),\n // just call the original with the event as-is\n try {\n return await originalRun.call(\n this,\n event as WorkflowEvent<Params>,\n step as AgentWorkflowStep\n );\n } catch (err) {\n await this._autoReportError(err);\n throw err;\n }\n };\n\n wrappedPrototypes.add(proto);\n }\n }\n\n /**\n * Initialize the Agent stub from workflow params.\n * Called automatically before run() executes.\n */\n private async _initAgent(\n agentName: string | undefined,\n agentBinding: string | undefined,\n workflowName: string | undefined,\n instanceId: string\n ): Promise<void> {\n if (!agentName || !agentBinding || !workflowName) {\n throw new Error(\n \"AgentWorkflow requires __agentName, __agentBinding, and __workflowName in params. \" +\n \"Use agent.runWorkflow() to start workflows with proper agent context.\"\n );\n }\n\n this._workflowId = instanceId;\n this._workflowName = workflowName;\n\n // Get the Agent namespace from env\n const namespace = (this.env as Record<string, unknown>)[\n agentBinding\n ] as DurableObjectNamespace<AgentType>;\n\n if (!namespace) {\n throw new Error(\n `Agent binding '${agentBinding}' not found in environment`\n );\n }\n\n // Get the Agent stub by name\n this._agent = await getAgentByName<Cloudflare.Env, AgentType>(\n namespace,\n agentName\n );\n }\n\n /**\n * Wrap WorkflowStep with durable Agent communication methods.\n * Methods added to the wrapped step are idempotent and won't repeat on retry.\n *\n * Note: We add methods directly to the step object to preserve instanceof checks\n * that Cloudflare's runtime may perform on the WorkflowStep class.\n */\n private _wrapStep(step: WorkflowStep): AgentWorkflowStep {\n let stepCounter = 0;\n\n // Cast step to our extended type and add methods directly\n // This preserves the original object identity and instanceof relationship\n const wrappedStep = step as AgentWorkflowStep;\n\n // Add durable Agent methods directly to the step object\n wrappedStep.reportComplete = async <T>(result?: T): Promise<void> => {\n await step.do(`__agent_reportComplete_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"complete\",\n result,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.reportError = async (error: Error | string): Promise<void> => {\n const errorMessage = error instanceof Error ? error.message : error;\n this._errorReported = true;\n await step.do(`__agent_reportError_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.sendEvent = async <T>(event: T): Promise<void> => {\n await step.do(`__agent_sendEvent_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"event\",\n event,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.updateAgentState = async (state: unknown): Promise<void> => {\n await step.do(`__agent_updateState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"set\", state);\n });\n };\n\n wrappedStep.mergeAgentState = async (\n partialState: Record<string, unknown>\n ): Promise<void> => {\n await step.do(`__agent_mergeState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"merge\", partialState);\n });\n };\n\n wrappedStep.resetAgentState = async (): Promise<void> => {\n await step.do(`__agent_resetState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"reset\");\n });\n };\n\n return wrappedStep;\n }\n\n /**\n * Get the Agent stub for RPC calls.\n * Provides typed access to the Agent's methods.\n *\n * @example\n * ```typescript\n * // Call any public method on the Agent\n * await this.agent.updateStatus('processing');\n * const data = await this.agent.getData();\n * ```\n */\n get agent(): DurableObjectStub<AgentType> {\n if (!this._agent) {\n throw new Error(\n \"Agent not initialized. Ensure you're accessing this.agent inside run().\"\n );\n }\n return this._agent;\n }\n\n /**\n * Get the workflow instance ID\n */\n get workflowId(): string {\n return this._workflowId;\n }\n\n /**\n * Get the workflow binding name\n */\n get workflowName(): string {\n return this._workflowName;\n }\n\n /**\n * Automatically report an unhandled error to the Agent.\n * Skipped if reportError() was already called (prevents double notification).\n * Best-effort: notification failures are swallowed so the original error propagates.\n *\n * @param err - The caught error\n */\n private async _autoReportError(err: unknown): Promise<void> {\n if (this._errorReported) {\n return;\n }\n this._errorReported = true;\n const errorMessage = err instanceof Error ? err.message : String(err);\n try {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n } catch (_notifyErr) {\n // Best-effort: don't mask the original error\n }\n }\n\n /**\n * Send a notification to the Agent via RPC.\n *\n * @param callback - Callback payload to send\n */\n protected async notifyAgent(callback: WorkflowCallback): Promise<void> {\n await this.agent._workflow_handleCallback(callback);\n }\n\n /**\n * Report progress to the Agent with typed progress data.\n * Triggers onWorkflowProgress() on the Agent.\n *\n * @param progress - Typed progress data\n *\n * @example\n * ```typescript\n * // Using default progress type\n * await this.reportProgress({ step: 'fetch', status: 'running' });\n * await this.reportProgress({ step: 'fetch', status: 'complete', percent: 0.5 });\n *\n * // With custom progress type\n * await this.reportProgress({ stage: 'extract', recordsProcessed: 100 });\n * ```\n */\n protected async reportProgress(progress: ProgressType): Promise<void> {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"progress\",\n progress: progress as DefaultProgress,\n timestamp: Date.now()\n });\n }\n\n /**\n * Broadcast a message to all connected WebSocket clients via the Agent.\n * This is non-durable and may repeat on workflow retry.\n *\n * @param message - Message to broadcast (will be JSON-stringified)\n */\n protected broadcastToClients(message: unknown): void {\n this.agent._workflow_broadcast(message);\n }\n\n /**\n * Wait for approval from the Agent.\n * Handles rejection by reporting error (durably) and throwing WorkflowRejectedError.\n *\n * @param step - AgentWorkflowStep object\n * @param options - Wait options (timeout, eventType, stepName)\n * @returns Approval payload (throws WorkflowRejectedError if rejected)\n *\n * @example\n * ```typescript\n * const approval = await this.waitForApproval(step, { timeout: '7 days' });\n * // approval contains the payload from approveWorkflow()\n * ```\n */\n protected async waitForApproval<T = unknown>(\n step: AgentWorkflowStep,\n options?: WaitForApprovalOptions\n ): Promise<T> {\n const stepName = options?.stepName ?? \"wait-for-approval\";\n const eventType = options?.eventType ?? \"approval\";\n const timeout = options?.timeout;\n\n // Wait for the approval event\n // Note: Call reportProgress() before this method if you want to update progress\n const event = await step.waitForEvent(stepName, {\n type: eventType,\n timeout\n });\n\n // Cast the payload to our expected type\n const payload = event.payload as {\n approved: boolean;\n reason?: string;\n metadata?: T;\n };\n\n // Check if rejected\n if (!payload.approved) {\n const reason = payload.reason;\n await step.reportError(reason ?? \"Workflow rejected\");\n throw new WorkflowRejectedError(reason, this._workflowId);\n }\n\n // Return the approval metadata as the result\n return payload.metadata as T;\n }\n}\n\n// Re-export types for convenience\nexport type {\n AgentWorkflowEvent,\n AgentWorkflowStep,\n WorkflowCallback,\n WorkflowCallbackType,\n WorkflowProgressCallback,\n WorkflowCompleteCallback,\n WorkflowErrorCallback,\n WorkflowEventCallback,\n DefaultProgress,\n WaitForApprovalOptions,\n ApprovalEventPayload,\n WorkflowStatus,\n WorkflowTrackingRow,\n RunWorkflowOptions,\n WorkflowEventPayload,\n WorkflowInfo,\n WorkflowQueryCriteria,\n WorkflowPage\n} from \"./workflow-types\";\n\nexport { WorkflowRejectedError } from \"./workflow-types\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflows.js","names":[],"sources":["../src/workflows.ts"],"sourcesContent":["/**\n * AgentWorkflow - Base class for Workflows that integrate with Agents\n *\n * Extends Cloudflare's WorkflowEntrypoint to provide seamless access to\n * the Agent that started the workflow, enabling bidirectional communication.\n *\n * @example\n * ```typescript\n * import { AgentWorkflow } from 'agents/workflows';\n * import type { MyAgent } from './agent';\n *\n * type TaskParams = { taskId: string; data: string };\n *\n * export class ProcessingWorkflow extends AgentWorkflow<MyAgent, TaskParams> {\n * async run(event: AgentWorkflowEvent<TaskParams>, step: WorkflowStep) {\n * // Access the originating Agent via typed RPC\n * await this.agent.updateTaskStatus(event.payload.taskId, 'processing');\n *\n * const result = await step.do('process', async () => {\n * // ... processing logic\n * return { processed: true };\n * });\n *\n * // Report progress to Agent (typed)\n * await this.reportProgress({ step: 'process', status: 'complete', percent: 0.5 });\n *\n * // Broadcast to connected clients\n * await this.broadcastToClients({ type: 'progress', data: result });\n *\n * return result;\n * }\n * }\n * ```\n */\n\nimport { WorkflowEntrypoint } from \"cloudflare:workers\";\nimport type { WorkflowEvent, WorkflowStep } from \"cloudflare:workers\";\nimport { getAgentByName, type Agent } from \"./index\";\nimport type {\n AgentWorkflowParams,\n AgentWorkflowStep,\n WorkflowCallback,\n DefaultProgress,\n WaitForApprovalOptions\n} from \"./workflow-types\";\nimport { WorkflowRejectedError } from \"./workflow-types\";\n\n/**\n * WeakSet to track which prototypes have been wrapped.\n * This prevents re-wrapping on subsequent instantiations of the same class.\n */\nconst wrappedPrototypes = new WeakSet<object>();\n\n/**\n * Base class for Workflows that need access to their originating Agent.\n *\n * @template AgentType - The Agent class type (for typed RPC access)\n * @template Params - User-defined params passed to the workflow (optional)\n * @template ProgressType - Type for progress reporting (defaults to DefaultProgress)\n * @template Env - Environment type (defaults to Cloudflare.Env)\n */\nexport class AgentWorkflow<\n AgentType extends Agent = Agent,\n Params = unknown,\n ProgressType = DefaultProgress,\n Env extends Cloudflare.Env = Cloudflare.Env\n> extends WorkflowEntrypoint<Env, AgentWorkflowParams<Params>> {\n /**\n * The Agent stub - initialized before run() is called.\n * Use this.agent to access the Agent's RPC methods.\n */\n private _agent!: DurableObjectStub<AgentType>;\n\n /**\n * Workflow instance ID\n */\n private _workflowId!: string;\n\n /**\n * Workflow binding name (for callbacks)\n */\n private _workflowName!: string;\n\n /**\n * Instance-level guard to prevent double initialization.\n * Used when a subclass calls super.run() after its own run() was wrapped.\n */\n private __agentInitCalled = false;\n\n /**\n * Guard to prevent double error notification.\n * Set to true when reportError() is called explicitly, so the automatic\n * error catch in the run() wrapper doesn't send a duplicate notification.\n */\n private _errorReported = false;\n\n constructor(ctx: ExecutionContext, env: Env) {\n super(ctx, env);\n\n const proto = Object.getPrototypeOf(this);\n\n // Only wrap if:\n // 1. This prototype defines its own run method (hasOwnProperty)\n // 2. It hasn't been wrapped yet (WeakSet check)\n // This prevents double-wrapping inherited methods and ensures each subclass\n // that defines run() gets wrapped exactly once.\n if (Object.hasOwn(proto, \"run\") && !wrappedPrototypes.has(proto)) {\n const originalRun = proto.run as (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>;\n\n // Replace the prototype's run method with a wrapper that initializes\n // the agent before calling the user's implementation\n proto.run = async function (\n this: AgentWorkflow<AgentType, Params, ProgressType, Env>,\n event: WorkflowEvent<AgentWorkflowParams<Params>>,\n step: WorkflowStep\n ) {\n // Instance-level guard: only init once per instance\n // (prevents double init if super.run() is called from a subclass)\n if (!this.__agentInitCalled) {\n const { __agentName, __agentBinding, __workflowName, ...userParams } =\n event.payload;\n\n // Initialize agent connection\n await this._initAgent(\n __agentName,\n __agentBinding,\n __workflowName,\n event.instanceId\n );\n this.__agentInitCalled = true;\n\n // Pass cleaned event and wrapped step to user's implementation\n const cleanedEvent = {\n ...event,\n payload: userParams as Params\n } as WorkflowEvent<Params>;\n\n const wrappedStep = this.extendStep(\n this._wrapStep(step),\n cleanedEvent\n );\n\n try {\n return await originalRun.call(this, cleanedEvent, wrappedStep);\n } catch (err) {\n await this._autoReportError(err);\n throw err;\n }\n }\n\n // If already initialized (e.g., called via super.run()),\n // just call the original with the event as-is\n try {\n return await originalRun.call(\n this,\n event as WorkflowEvent<Params>,\n step as AgentWorkflowStep\n );\n } catch (err) {\n await this._autoReportError(err);\n throw err;\n }\n };\n\n wrappedPrototypes.add(proto);\n }\n }\n\n /**\n * Initialize the Agent stub from workflow params.\n * Called automatically before run() executes.\n */\n private async _initAgent(\n agentName: string | undefined,\n agentBinding: string | undefined,\n workflowName: string | undefined,\n instanceId: string\n ): Promise<void> {\n if (!agentName || !agentBinding || !workflowName) {\n throw new Error(\n \"AgentWorkflow requires __agentName, __agentBinding, and __workflowName in params. \" +\n \"Use agent.runWorkflow() to start workflows with proper agent context.\"\n );\n }\n\n this._workflowId = instanceId;\n this._workflowName = workflowName;\n\n // Get the Agent namespace from env\n const namespace = (this.env as Record<string, unknown>)[\n agentBinding\n ] as DurableObjectNamespace<AgentType>;\n\n if (!namespace) {\n throw new Error(\n `Agent binding '${agentBinding}' not found in environment`\n );\n }\n\n // Get the Agent stub by name\n this._agent = await getAgentByName<Cloudflare.Env, AgentType>(\n namespace,\n agentName\n );\n }\n\n /**\n * Wrap WorkflowStep with durable Agent communication methods.\n * Methods added to the wrapped step are idempotent and won't repeat on retry.\n *\n * Note: We add methods directly to the step object to preserve instanceof checks\n * that Cloudflare's runtime may perform on the WorkflowStep class.\n */\n private _wrapStep(step: WorkflowStep): AgentWorkflowStep {\n let stepCounter = 0;\n\n // Cast step to our extended type and add methods directly\n // This preserves the original object identity and instanceof relationship\n const wrappedStep = step as AgentWorkflowStep;\n\n // Add durable Agent methods directly to the step object\n wrappedStep.reportComplete = async <T>(result?: T): Promise<void> => {\n await step.do(`__agent_reportComplete_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"complete\",\n result,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.reportError = async (error: Error | string): Promise<void> => {\n const errorMessage = error instanceof Error ? error.message : error;\n this._errorReported = true;\n await step.do(`__agent_reportError_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.sendEvent = async <T>(event: T): Promise<void> => {\n await step.do(`__agent_sendEvent_${stepCounter++}`, async () => {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"event\",\n event,\n timestamp: Date.now()\n });\n });\n };\n\n wrappedStep.updateAgentState = async (state: unknown): Promise<void> => {\n await step.do(`__agent_updateState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"set\", state);\n });\n };\n\n wrappedStep.mergeAgentState = async (\n partialState: Record<string, unknown>\n ): Promise<void> => {\n await step.do(`__agent_mergeState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"merge\", partialState);\n });\n };\n\n wrappedStep.resetAgentState = async (): Promise<void> => {\n await step.do(`__agent_resetState_${stepCounter++}`, async () => {\n await this.agent._workflow_updateState(\"reset\");\n });\n };\n\n return wrappedStep;\n }\n\n /**\n * Extend the Agent-aware workflow step before user code receives it.\n *\n * Subclasses can override this to add framework-specific step helpers while\n * preserving the underlying WorkflowStep object identity.\n */\n protected extendStep(\n step: AgentWorkflowStep,\n _event: WorkflowEvent<Params>\n ): AgentWorkflowStep {\n return step;\n }\n\n /**\n * Get the Agent stub for RPC calls.\n * Provides typed access to the Agent's methods.\n *\n * @example\n * ```typescript\n * // Call any public method on the Agent\n * await this.agent.updateStatus('processing');\n * const data = await this.agent.getData();\n * ```\n */\n get agent(): DurableObjectStub<AgentType> {\n if (!this._agent) {\n throw new Error(\n \"Agent not initialized. Ensure you're accessing this.agent inside run().\"\n );\n }\n return this._agent;\n }\n\n /**\n * Get the workflow instance ID\n */\n get workflowId(): string {\n return this._workflowId;\n }\n\n /**\n * Get the workflow binding name\n */\n get workflowName(): string {\n return this._workflowName;\n }\n\n /**\n * Automatically report an unhandled error to the Agent.\n * Skipped if reportError() was already called (prevents double notification).\n * Best-effort: notification failures are swallowed so the original error propagates.\n *\n * @param err - The caught error\n */\n private async _autoReportError(err: unknown): Promise<void> {\n if (this._errorReported) {\n return;\n }\n this._errorReported = true;\n const errorMessage = err instanceof Error ? err.message : String(err);\n try {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"error\",\n error: errorMessage,\n timestamp: Date.now()\n });\n } catch (_notifyErr) {\n // Best-effort: don't mask the original error\n }\n }\n\n /**\n * Send a notification to the Agent via RPC.\n *\n * @param callback - Callback payload to send\n */\n protected async notifyAgent(callback: WorkflowCallback): Promise<void> {\n await this.agent._workflow_handleCallback(callback);\n }\n\n /**\n * Report progress to the Agent with typed progress data.\n * Triggers onWorkflowProgress() on the Agent.\n *\n * @param progress - Typed progress data\n *\n * @example\n * ```typescript\n * // Using default progress type\n * await this.reportProgress({ step: 'fetch', status: 'running' });\n * await this.reportProgress({ step: 'fetch', status: 'complete', percent: 0.5 });\n *\n * // With custom progress type\n * await this.reportProgress({ stage: 'extract', recordsProcessed: 100 });\n * ```\n */\n protected async reportProgress(progress: ProgressType): Promise<void> {\n await this.notifyAgent({\n workflowName: this._workflowName,\n workflowId: this._workflowId,\n type: \"progress\",\n progress: progress as DefaultProgress,\n timestamp: Date.now()\n });\n }\n\n /**\n * Broadcast a message to all connected WebSocket clients via the Agent.\n * This is non-durable and may repeat on workflow retry.\n *\n * @param message - Message to broadcast (will be JSON-stringified)\n */\n protected broadcastToClients(message: unknown): void {\n this.agent._workflow_broadcast(message);\n }\n\n /**\n * Wait for approval from the Agent.\n * Handles rejection by reporting error (durably) and throwing WorkflowRejectedError.\n *\n * @param step - AgentWorkflowStep object\n * @param options - Wait options (timeout, eventType, stepName)\n * @returns Approval payload (throws WorkflowRejectedError if rejected)\n *\n * @example\n * ```typescript\n * const approval = await this.waitForApproval(step, { timeout: '7 days' });\n * // approval contains the payload from approveWorkflow()\n * ```\n */\n protected async waitForApproval<T = unknown>(\n step: AgentWorkflowStep,\n options?: WaitForApprovalOptions\n ): Promise<T> {\n const stepName = options?.stepName ?? \"wait-for-approval\";\n const eventType = options?.eventType ?? \"approval\";\n const timeout = options?.timeout;\n\n // Wait for the approval event\n // Note: Call reportProgress() before this method if you want to update progress\n const event = await step.waitForEvent(stepName, {\n type: eventType,\n timeout\n });\n\n // Cast the payload to our expected type\n const payload = event.payload as {\n approved: boolean;\n reason?: string;\n metadata?: T;\n };\n\n // Check if rejected\n if (!payload.approved) {\n const reason = payload.reason;\n await step.reportError(reason ?? \"Workflow rejected\");\n throw new WorkflowRejectedError(reason, this._workflowId);\n }\n\n // Return the approval metadata as the result\n return payload.metadata as T;\n }\n}\n\n// Re-export types for convenience\nexport type {\n AgentWorkflowEvent,\n AgentWorkflowStep,\n WorkflowCallback,\n WorkflowCallbackType,\n WorkflowProgressCallback,\n WorkflowCompleteCallback,\n WorkflowErrorCallback,\n WorkflowEventCallback,\n DefaultProgress,\n WaitForApprovalOptions,\n ApprovalEventPayload,\n WorkflowStatus,\n WorkflowTrackingRow,\n RunWorkflowOptions,\n WorkflowEventPayload,\n WorkflowInfo,\n WorkflowQueryCriteria,\n WorkflowPage\n} from \"./workflow-types\";\n\nexport { WorkflowRejectedError } from \"./workflow-types\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"durable objects"
|
|
10
10
|
],
|
|
11
11
|
"type": "module",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.14.1",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
15
15
|
"directory": "packages/agents",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"url": "https://github.com/cloudflare/agents/issues"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@babel/plugin-proposal-decorators": "^7.29.
|
|
27
|
+
"@babel/plugin-proposal-decorators": "^7.29.7",
|
|
28
28
|
"@cfworker/json-schema": "^4.1.1",
|
|
29
29
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
30
30
|
"@rolldown/plugin-babel": "^0.2.3",
|
|
@@ -33,30 +33,36 @@
|
|
|
33
33
|
"nanoid": "^5.1.11",
|
|
34
34
|
"partyserver": "^0.5.6",
|
|
35
35
|
"partysocket": "1.1.19",
|
|
36
|
+
"yaml": "^2.9.0",
|
|
36
37
|
"yargs": "^18.0.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@ai-sdk/react": "^3.0.
|
|
40
|
-
"@
|
|
41
|
-
"@
|
|
40
|
+
"@ai-sdk/react": "^3.0.196",
|
|
41
|
+
"@cloudflare/codemode": "^0.3.8",
|
|
42
|
+
"@cloudflare/worker-bundler": "^0.2.0",
|
|
43
|
+
"@tanstack/ai": "^0.26.1",
|
|
44
|
+
"@types/react": "^19.2.16",
|
|
42
45
|
"@types/yargs": "^17.0.35",
|
|
43
|
-
"@vitest/browser-playwright": "^4.1.
|
|
44
|
-
"@x402/core": "^2.
|
|
45
|
-
"@x402/evm": "^2.
|
|
46
|
-
"ai": "^6.0.
|
|
47
|
-
"chat": "^4.
|
|
48
|
-
"
|
|
46
|
+
"@vitest/browser-playwright": "^4.1.8",
|
|
47
|
+
"@x402/core": "^2.14.0",
|
|
48
|
+
"@x402/evm": "^2.14.0",
|
|
49
|
+
"ai": "^6.0.194",
|
|
50
|
+
"chat": "^4.30.0",
|
|
51
|
+
"just-bash": "^3.0.1",
|
|
52
|
+
"react": "^19.2.7",
|
|
49
53
|
"vitest-browser-react": "^2.2.0",
|
|
50
54
|
"zod": "^4.4.3"
|
|
51
55
|
},
|
|
52
56
|
"peerDependencies": {
|
|
53
|
-
"@cloudflare/ai-chat": ">=0.
|
|
54
|
-
"@cloudflare/codemode": ">=0.3.
|
|
57
|
+
"@cloudflare/ai-chat": ">=0.8.0 <1.0.0",
|
|
58
|
+
"@cloudflare/codemode": ">=0.3.8 <1.0.0",
|
|
59
|
+
"@cloudflare/worker-bundler": ">=0.2.0 <1.0.0",
|
|
55
60
|
"@tanstack/ai": ">=0.10.2 <1.0.0",
|
|
56
61
|
"@x402/core": "^2.0.0",
|
|
57
62
|
"@x402/evm": "^2.0.0",
|
|
58
63
|
"ai": "^6.0.0",
|
|
59
64
|
"chat": "^4.29.0",
|
|
65
|
+
"just-bash": "^3.0.0",
|
|
60
66
|
"react": "^19.0.0",
|
|
61
67
|
"vite": ">=6.0.0 <9.0.0",
|
|
62
68
|
"zod": "^4.0.0"
|
|
@@ -68,6 +74,9 @@
|
|
|
68
74
|
"@cloudflare/codemode": {
|
|
69
75
|
"optional": true
|
|
70
76
|
},
|
|
77
|
+
"@cloudflare/worker-bundler": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
71
80
|
"@tanstack/ai": {
|
|
72
81
|
"optional": true
|
|
73
82
|
},
|
|
@@ -80,6 +89,9 @@
|
|
|
80
89
|
"chat": {
|
|
81
90
|
"optional": true
|
|
82
91
|
},
|
|
92
|
+
"just-bash": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
83
95
|
"vite": {
|
|
84
96
|
"optional": true
|
|
85
97
|
}
|
|
@@ -221,6 +233,11 @@
|
|
|
221
233
|
"types": "./dist/vite.d.ts",
|
|
222
234
|
"import": "./dist/vite.js",
|
|
223
235
|
"require": "./dist/vite.js"
|
|
236
|
+
},
|
|
237
|
+
"./skills": {
|
|
238
|
+
"types": "./dist/skills/index.d.ts",
|
|
239
|
+
"import": "./dist/skills/index.js",
|
|
240
|
+
"require": "./dist/skills/index.js"
|
|
224
241
|
}
|
|
225
242
|
},
|
|
226
243
|
"publishConfig": {
|
|
@@ -229,6 +246,7 @@
|
|
|
229
246
|
"files": [
|
|
230
247
|
"dist",
|
|
231
248
|
"agents.tsconfig.json",
|
|
249
|
+
"skills-module.d.ts",
|
|
232
250
|
"README.md"
|
|
233
251
|
],
|
|
234
252
|
"nx": {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Ambient types for the Agents Vite plugin's `agents:skills` virtual modules.
|
|
2
|
+
//
|
|
3
|
+
// `import skills from "agents:skills"` (or `"agents:skills/<dir>"`) is resolved
|
|
4
|
+
// at build time by the `agents()` Vite plugin to a bundled `SkillSource`. This
|
|
5
|
+
// declaration gives those imports a type.
|
|
6
|
+
//
|
|
7
|
+
// It is referenced from the package's main type entry, so importing anything
|
|
8
|
+
// from `agents` (directly, or transitively via `@cloudflare/think` /
|
|
9
|
+
// `@cloudflare/ai-chat`) brings it into scope. For a file that imports only the
|
|
10
|
+
// specifier, add:
|
|
11
|
+
//
|
|
12
|
+
// /// <reference types="agents/skills-module" />
|
|
13
|
+
|
|
14
|
+
declare module "agents:skills" {
|
|
15
|
+
const source: import("agents/skills").SkillSource;
|
|
16
|
+
export default source;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module "agents:skills/*" {
|
|
20
|
+
const source: import("agents/skills").SkillSource;
|
|
21
|
+
export default source;
|
|
22
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-tools-BAdX1vdI.js","names":[],"sources":["../src/chat/message-builder.ts","../src/chat/agent-tools.ts"],"sourcesContent":["/**\n * Shared message builder for reconstructing UIMessage parts from stream chunks.\n *\n * Used by both @cloudflare/ai-chat (server + client) and @cloudflare/think\n * to avoid duplicating the chunk-type switch/case logic.\n *\n * Operates on a mutable parts array for performance (avoids allocating new arrays\n * on every chunk during streaming).\n */\n\nimport type { UIMessage } from \"ai\";\n\n/** The parts array type from UIMessage */\nexport type MessageParts = UIMessage[\"parts\"];\n\n/** A single part from the UIMessage parts array */\nexport type MessagePart = MessageParts[number];\n\n/**\n * Parsed chunk data from an AI SDK stream event.\n * This is the JSON-parsed body of a CF_AGENT_USE_CHAT_RESPONSE message,\n * or the `data:` payload of an SSE line.\n */\nexport type StreamChunkData = {\n type: string;\n id?: string;\n delta?: string;\n text?: string;\n mediaType?: string;\n url?: string;\n sourceId?: string;\n title?: string;\n filename?: string;\n toolCallId?: string;\n toolName?: string;\n input?: unknown;\n inputTextDelta?: string;\n output?: unknown;\n state?: string;\n errorText?: string;\n /** When true, the output is preliminary (may be updated by a later chunk) */\n preliminary?: boolean;\n /** Approval ID for tools with needsApproval */\n approvalId?: string;\n providerMetadata?: Record<string, unknown>;\n /** Whether the tool was executed by the provider (e.g. Gemini code execution) */\n providerExecuted?: boolean;\n /** Payload for data-* parts (developer-defined typed JSON) */\n data?: unknown;\n /** When true, data parts are ephemeral and not persisted to message.parts */\n transient?: boolean;\n /** Message ID assigned by the server at stream start */\n messageId?: string;\n /** Per-message metadata attached by start/finish/message-metadata chunks */\n messageMetadata?: unknown;\n [key: string]: unknown;\n};\n\n/**\n * Applies a stream chunk to a mutable parts array, building up the message\n * incrementally. Returns true if the chunk was handled, false if it was\n * an unrecognized type (caller may handle it with additional logic).\n *\n * Handles all common chunk types that both server and client need:\n * - text-start / text-delta / text-end\n * - reasoning-start / reasoning-delta / reasoning-end\n * - file\n * - source-url / source-document\n * - tool-input-start / tool-input-delta / tool-input-available / tool-input-error\n * - tool-output-available / tool-output-error\n * - step-start (aliased from start-step)\n * - data-* (developer-defined typed JSON blobs)\n *\n * @param parts - The mutable parts array to update\n * @param chunk - The parsed stream chunk data\n * @returns true if handled, false if the chunk type is not recognized\n */\nexport function applyChunkToParts(\n parts: MessagePart[],\n chunk: StreamChunkData\n): boolean {\n switch (chunk.type) {\n case \"text-start\": {\n parts.push({\n type: \"text\",\n text: \"\",\n state: \"streaming\"\n } as MessagePart);\n return true;\n }\n\n case \"text-delta\": {\n const lastTextPart = findLastPartByType(parts, \"text\");\n if (lastTextPart && lastTextPart.type === \"text\") {\n (lastTextPart as { text: string }).text += chunk.delta ?? \"\";\n } else {\n // No text-start received — create a new text part (stream resumption fallback)\n parts.push({\n type: \"text\",\n text: chunk.delta ?? \"\",\n state: \"streaming\"\n } as MessagePart);\n }\n return true;\n }\n\n case \"text-end\": {\n const lastTextPart = findLastPartByType(parts, \"text\");\n if (lastTextPart && \"state\" in lastTextPart) {\n (lastTextPart as { state: string }).state = \"done\";\n }\n return true;\n }\n\n case \"reasoning-start\": {\n parts.push({\n type: \"reasoning\",\n text: \"\",\n state: \"streaming\"\n } as MessagePart);\n return true;\n }\n\n case \"reasoning-delta\": {\n const lastReasoningPart = findLastPartByType(parts, \"reasoning\");\n if (lastReasoningPart && lastReasoningPart.type === \"reasoning\") {\n (lastReasoningPart as { text: string }).text += chunk.delta ?? \"\";\n mergeProviderMetadata(lastReasoningPart, chunk.providerMetadata);\n } else {\n // No reasoning-start received — create a new reasoning part (stream resumption fallback)\n parts.push({\n type: \"reasoning\",\n text: chunk.delta ?? \"\",\n state: \"streaming\",\n ...(chunk.providerMetadata != null\n ? { providerMetadata: chunk.providerMetadata }\n : {})\n } as MessagePart);\n }\n return true;\n }\n\n case \"reasoning-end\": {\n const lastReasoningPart = findLastPartByType(parts, \"reasoning\");\n if (lastReasoningPart && \"state\" in lastReasoningPart) {\n (lastReasoningPart as { state: string }).state = \"done\";\n mergeProviderMetadata(lastReasoningPart, chunk.providerMetadata);\n }\n return true;\n }\n\n case \"file\": {\n parts.push({\n type: \"file\",\n mediaType: chunk.mediaType,\n url: chunk.url\n } as MessagePart);\n return true;\n }\n\n case \"source-url\": {\n parts.push({\n type: \"source-url\",\n sourceId: chunk.sourceId,\n url: chunk.url,\n title: chunk.title,\n providerMetadata: chunk.providerMetadata\n } as MessagePart);\n return true;\n }\n\n case \"source-document\": {\n parts.push({\n type: \"source-document\",\n sourceId: chunk.sourceId,\n mediaType: chunk.mediaType,\n title: chunk.title,\n filename: chunk.filename,\n providerMetadata: chunk.providerMetadata\n } as MessagePart);\n return true;\n }\n\n case \"tool-input-start\": {\n // Idempotent against an existing tool part with the same toolCallId.\n // Some providers (notably the OpenAI Responses API) replay prior\n // tool calls in continuation streams as a fresh `tool-input-start`\n // → `tool-input-delta` → `tool-input-available` →\n // `tool-output-available` sequence carrying the original toolCallId\n // and original output. Without this guard a replay would push a\n // duplicate part into the streaming message *and* clobber the\n // original part's state when the AI SDK's mutate-in-place\n // `updateToolPart` processes the replay on the client (issue #1404).\n // A model that genuinely wants a fresh tool call always emits a\n // new toolCallId, so an existing match is never a legitimate\n // \"start over\".\n const existing = findToolPartByCallId(parts, chunk.toolCallId);\n if (existing) {\n return true;\n }\n parts.push({\n type: `tool-${chunk.toolName}`,\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n state: \"input-streaming\",\n input: undefined,\n ...(chunk.providerExecuted != null\n ? { providerExecuted: chunk.providerExecuted }\n : {}),\n ...(chunk.providerMetadata != null\n ? { callProviderMetadata: chunk.providerMetadata }\n : {}),\n ...(chunk.title != null ? { title: chunk.title } : {})\n } as MessagePart);\n return true;\n }\n\n case \"tool-input-delta\": {\n // Only mutate input while the tool is still actively input-streaming.\n // Deltas arriving after the tool has already advanced (input-available\n // or any terminal state) are provider replay and must not regress\n // a fully-formed input back to a partial one.\n const toolPart = findToolPartByCallId(parts, chunk.toolCallId);\n if (\n toolPart &&\n (toolPart as Record<string, unknown>).state === \"input-streaming\"\n ) {\n (toolPart as Record<string, unknown>).input = chunk.input;\n }\n return true;\n }\n\n case \"tool-input-available\": {\n const existing = findToolPartByCallId(parts, chunk.toolCallId);\n if (existing) {\n const p = existing as Record<string, unknown>;\n // Only advance from the streaming-input phase. Once the tool is\n // already at input-available or any terminal state\n // (output-available, output-error, output-denied,\n // approval-requested, approval-responded), this chunk is a\n // provider replay and must not regress state or overwrite a\n // resolved input/output. See the comment on tool-input-start.\n if (p.state === \"input-streaming\") {\n p.state = \"input-available\";\n p.input = chunk.input;\n if (chunk.providerExecuted != null) {\n p.providerExecuted = chunk.providerExecuted;\n }\n if (chunk.providerMetadata != null) {\n p.callProviderMetadata = chunk.providerMetadata;\n }\n if (chunk.title != null) {\n p.title = chunk.title;\n }\n }\n return true;\n }\n parts.push({\n type: `tool-${chunk.toolName}`,\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n state: \"input-available\",\n input: chunk.input,\n ...(chunk.providerExecuted != null\n ? { providerExecuted: chunk.providerExecuted }\n : {}),\n ...(chunk.providerMetadata != null\n ? { callProviderMetadata: chunk.providerMetadata }\n : {}),\n ...(chunk.title != null ? { title: chunk.title } : {})\n } as MessagePart);\n return true;\n }\n\n case \"tool-input-error\": {\n const existing = findToolPartByCallId(parts, chunk.toolCallId);\n if (existing) {\n const p = existing as Record<string, unknown>;\n // First-write-wins: a tool that's already terminal must not be\n // regressed (or re-decided as an error) by a later chunk. A\n // tool-input-error here is either provider replay or a confused\n // upstream — preserve the existing terminal state.\n if (\n p.state === \"output-available\" ||\n p.state === \"output-error\" ||\n p.state === \"output-denied\"\n ) {\n return true;\n }\n p.state = \"output-error\";\n p.errorText = chunk.errorText;\n p.input = chunk.input;\n if (chunk.providerExecuted != null) {\n p.providerExecuted = chunk.providerExecuted;\n }\n if (chunk.providerMetadata != null) {\n p.callProviderMetadata = chunk.providerMetadata;\n }\n } else {\n parts.push({\n type: `tool-${chunk.toolName}`,\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n state: \"output-error\",\n input: chunk.input,\n errorText: chunk.errorText,\n ...(chunk.providerExecuted != null\n ? { providerExecuted: chunk.providerExecuted }\n : {}),\n ...(chunk.providerMetadata != null\n ? { callProviderMetadata: chunk.providerMetadata }\n : {})\n } as MessagePart);\n }\n return true;\n }\n\n case \"tool-approval-request\": {\n const toolPart = findToolPartByCallId(parts, chunk.toolCallId);\n if (toolPart) {\n const p = toolPart as Record<string, unknown>;\n p.state = \"approval-requested\";\n p.approval = { id: chunk.approvalId };\n }\n return true;\n }\n\n case \"tool-output-denied\": {\n const toolPart = findToolPartByCallId(parts, chunk.toolCallId);\n if (toolPart) {\n const p = toolPart as Record<string, unknown>;\n p.state = \"output-denied\";\n }\n return true;\n }\n\n case \"tool-output-available\": {\n const toolPart = findToolPartByCallId(parts, chunk.toolCallId);\n if (toolPart) {\n const p = toolPart as Record<string, unknown>;\n p.state = \"output-available\";\n p.output = chunk.output;\n if (chunk.preliminary !== undefined) {\n p.preliminary = chunk.preliminary;\n }\n }\n return true;\n }\n\n case \"tool-output-error\": {\n const toolPart = findToolPartByCallId(parts, chunk.toolCallId);\n if (toolPart) {\n const p = toolPart as Record<string, unknown>;\n p.state = \"output-error\";\n p.errorText = chunk.errorText;\n }\n return true;\n }\n\n // Both \"step-start\" (client convention) and \"start-step\" (server convention)\n case \"step-start\":\n case \"start-step\": {\n parts.push({ type: \"step-start\" } as MessagePart);\n return true;\n }\n\n default: {\n // https://ai-sdk.dev/docs/ai-sdk-ui/streaming-data\n if (chunk.type.startsWith(\"data-\")) {\n // Transient parts are ephemeral — the AI SDK client fires an onData\n // callback instead of adding them to message.parts. On the server we\n // still broadcast them (so connected clients see them in real time)\n // but skip persisting them into the stored message parts.\n if (chunk.transient) {\n return true;\n }\n\n // Reconciliation: if a part with the same type AND id already exists,\n // update its data in-place instead of appending a duplicate.\n if (chunk.id != null) {\n const existing = findDataPartByTypeAndId(parts, chunk.type, chunk.id);\n if (existing) {\n (existing as Record<string, unknown>).data = chunk.data;\n return true;\n }\n }\n\n // Append new data parts to the array directly.\n // Note: `chunk.data` should always be provided — if omitted, the\n // persisted part will have `data: undefined` which JSON.stringify\n // drops, so the part will have no `data` field on reload.\n // The cast is needed because UIMessage[\"parts\"] doesn't include\n // data-* types in its union because they're an open extension point.\n parts.push({\n type: chunk.type,\n ...(chunk.id != null && { id: chunk.id }),\n data: chunk.data\n } as MessagePart);\n return true;\n }\n\n return false;\n }\n }\n}\n\n/**\n * Returns true if `chunk` would be a no-op replay against the already-known\n * `parts` — i.e. some upstream is re-emitting events for a tool call that\n * the message has already advanced past.\n *\n * Used by stream broadcasters to suppress re-broadcasting these chunks to\n * connected clients. AI SDK v6's `updateToolPart` mutates an existing tool\n * part in place when a chunk arrives with a matching `toolCallId`, so a\n * replayed `tool-input-start` would clobber an `output-available` part back\n * to `input-streaming` on the client (issue #1404).\n *\n * Only returns true when re-broadcasting would *visibly regress* state on\n * a v6 client. Safe-by-construction chunk types (e.g. `tool-output-available`\n * carrying the same output the part already has) return false.\n *\n * Conditions:\n * - `tool-input-start` for a `toolCallId` that already exists in `parts`.\n * - `tool-input-delta` for a `toolCallId` whose existing part is no longer\n * `input-streaming`.\n * - `tool-input-available` for a `toolCallId` whose existing part is no\n * longer `input-streaming` (i.e. has already advanced to `input-available`\n * or any terminal state).\n */\nexport function isReplayChunk(\n parts: MessagePart[],\n chunk: StreamChunkData\n): boolean {\n if (\n chunk.type !== \"tool-input-start\" &&\n chunk.type !== \"tool-input-delta\" &&\n chunk.type !== \"tool-input-available\"\n ) {\n return false;\n }\n if (!chunk.toolCallId) return false;\n const existing = findToolPartByCallId(parts, chunk.toolCallId);\n if (!existing) return false;\n if (chunk.type === \"tool-input-start\") return true;\n const state = (existing as Record<string, unknown>).state;\n return state !== \"input-streaming\";\n}\n\n/**\n * Finds the last part in the array matching the given type.\n * Searches from the end for efficiency (the part we want is usually recent).\n */\nfunction findLastPartByType(\n parts: MessagePart[],\n type: string\n): MessagePart | undefined {\n for (let i = parts.length - 1; i >= 0; i--) {\n if (parts[i].type === type) {\n return parts[i];\n }\n }\n return undefined;\n}\n\n/**\n * Finds a tool part by its toolCallId.\n * Searches from the end since the tool part is usually recent.\n */\nfunction findToolPartByCallId(\n parts: MessagePart[],\n toolCallId: string | undefined\n): MessagePart | undefined {\n if (!toolCallId) return undefined;\n for (let i = parts.length - 1; i >= 0; i--) {\n const p = parts[i];\n if (\"toolCallId\" in p && p.toolCallId === toolCallId) {\n return p;\n }\n }\n return undefined;\n}\n\n/**\n * Shallow-merges providerMetadata from a chunk onto an existing part.\n * Preserves any metadata already on the part (e.g. from earlier deltas)\n * while adding new keys from the chunk. This is critical for providers\n * like Anthropic that emit the thinking block signature on reasoning-end.\n */\nfunction mergeProviderMetadata(\n part: MessagePart,\n metadata: Record<string, unknown> | undefined\n): void {\n if (metadata == null) return;\n const p = part as Record<string, unknown>;\n p.providerMetadata = {\n ...(p.providerMetadata as Record<string, unknown> | undefined),\n ...metadata\n };\n}\n\n/**\n * Finds a data part by its type and id for reconciliation.\n * Data parts use type+id as a composite key so when the same combination\n * is seen again, the existing part's data is updated in-place.\n */\nfunction findDataPartByTypeAndId(\n parts: MessagePart[],\n type: string,\n id: string\n): MessagePart | undefined {\n for (let i = parts.length - 1; i >= 0; i--) {\n const p = parts[i];\n if (p.type === type && \"id\" in p && (p as { id: string }).id === id) {\n return p;\n }\n }\n return undefined;\n}\n","import { applyChunkToParts } from \"./message-builder\";\nimport type {\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolRunState\n} from \"../agent-tool-types\";\n\nfunction sortRuns(runs: AgentToolRunState[]): AgentToolRunState[] {\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(\n runsById: Record<string, AgentToolRunState>\n): Pick<AgentToolEventState, \"runsByToolCallId\" | \"unboundRuns\"> {\n const grouped: Record<string, AgentToolRunState[]> = {};\n const unboundRuns: AgentToolRunState[] = [];\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(\n message: AgentToolEventMessage\n): AgentToolRunState | 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(\n prev: AgentToolRunState | undefined,\n message: AgentToolEventMessage\n): AgentToolRunState | 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 try {\n applyChunkToParts(parts, JSON.parse(event.body));\n } catch {\n return seeded;\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 { ...seeded, status: \"interrupted\", error: event.error };\n }\n}\n\nexport function createAgentToolEventState(): AgentToolEventState {\n return {\n runsById: {},\n runsByToolCallId: {},\n unboundRuns: []\n };\n}\n\nexport function applyAgentToolEvent(\n state: AgentToolEventState,\n message: AgentToolEventMessage\n): AgentToolEventState {\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 AgentToolRunState\n} from \"../agent-tool-types\";\n"],"mappings":"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"}
|