agents 0.3.8 → 0.3.9
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/dist/{client-DGpERepg.d.ts → client-Ba-xntmv.d.ts} +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/workflows.d.ts +6 -1
- package/dist/workflows.js +25 -9
- package/dist/workflows.js.map +1 -1
- package/package.json +1 -1
|
@@ -327,7 +327,7 @@ declare class MCPClientConnection {
|
|
|
327
327
|
*/
|
|
328
328
|
getTransport(
|
|
329
329
|
transportType: BaseTransportType
|
|
330
|
-
):
|
|
330
|
+
): SSEClientTransport | StreamableHTTPClientTransport;
|
|
331
331
|
private tryConnect;
|
|
332
332
|
private _capabilityErrorHandler;
|
|
333
333
|
}
|
|
@@ -960,4 +960,4 @@ export {
|
|
|
960
960
|
MCPClientManager as t,
|
|
961
961
|
MCPConnectionState as u
|
|
962
962
|
};
|
|
963
|
-
//# sourceMappingURL=client-
|
|
963
|
+
//# sourceMappingURL=client-Ba-xntmv.d.ts.map
|
package/dist/index.d.ts
CHANGED
package/dist/mcp/client.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MCPConnectionResult, c as RegisterServerOptions, i as MCPClientOAuthResult, l as getNamespacedData, n as MCPClientManagerOptions, o as MCPDiscoverResult, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions, t as MCPClientManager } from "../client-
|
|
1
|
+
import { a as MCPConnectionResult, c as RegisterServerOptions, i as MCPClientOAuthResult, l as getNamespacedData, n as MCPClientManagerOptions, o as MCPDiscoverResult, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions, t as MCPClientManager } from "../client-Ba-xntmv.js";
|
|
2
2
|
export { MCPClientManager, MCPClientManagerOptions, MCPClientOAuthCallbackConfig, MCPClientOAuthResult, MCPConnectionResult, MCPDiscoverResult, MCPServerOptions, RegisterServerOptions, getNamespacedData };
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../internal_context-CEu5ji80.js";
|
|
2
2
|
import "../email-8ljcpvwV.js";
|
|
3
|
-
import { a as MCPConnectionResult, d as BaseTransportType, f as CORSOptions, i as MCPClientOAuthResult, m as ServeOptions, o as MCPDiscoverResult, p as MaybePromise, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions } from "../client-
|
|
3
|
+
import { a as MCPConnectionResult, d as BaseTransportType, f as CORSOptions, i as MCPClientOAuthResult, m as ServeOptions, o as MCPDiscoverResult, p as MaybePromise, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions } from "../client-Ba-xntmv.js";
|
|
4
4
|
import "../workflow-types-Z_Oem1FJ.js";
|
|
5
5
|
import { Agent, Connection, ConnectionContext } from "../index.js";
|
|
6
6
|
import { SSEClientTransport, SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
|
package/dist/react.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Method, RPCMethod } from "./serializable.js";
|
|
|
2
2
|
import { StreamOptions } from "./client.js";
|
|
3
3
|
import "./internal_context-CEu5ji80.js";
|
|
4
4
|
import "./email-8ljcpvwV.js";
|
|
5
|
-
import "./client-
|
|
5
|
+
import "./client-Ba-xntmv.js";
|
|
6
6
|
import "./workflow-types-Z_Oem1FJ.js";
|
|
7
7
|
import { Agent, MCPServersState } from "./index.js";
|
|
8
8
|
import { PartySocket } from "partysocket";
|
package/dist/workflows.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./internal_context-CEu5ji80.js";
|
|
2
2
|
import "./email-8ljcpvwV.js";
|
|
3
|
-
import "./client-
|
|
3
|
+
import "./client-Ba-xntmv.js";
|
|
4
4
|
import {
|
|
5
5
|
S as WorkflowTrackingRow,
|
|
6
6
|
_ as WorkflowPage,
|
|
@@ -54,6 +54,11 @@ declare class AgentWorkflow<
|
|
|
54
54
|
* Workflow binding name (for callbacks)
|
|
55
55
|
*/
|
|
56
56
|
private _workflowName;
|
|
57
|
+
/**
|
|
58
|
+
* Instance-level guard to prevent double initialization.
|
|
59
|
+
* Used when a subclass calls super.run() after its own run() was wrapped.
|
|
60
|
+
*/
|
|
61
|
+
private __agentInitCalled;
|
|
57
62
|
constructor(ctx: ExecutionContext, env: Env);
|
|
58
63
|
/**
|
|
59
64
|
* Initialize the Agent stub from workflow params.
|
package/dist/workflows.js
CHANGED
|
@@ -42,6 +42,11 @@ import { WorkflowEntrypoint } from "cloudflare:workers";
|
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
/**
|
|
45
|
+
* WeakSet to track which prototypes have been wrapped.
|
|
46
|
+
* This prevents re-wrapping on subsequent instantiations of the same class.
|
|
47
|
+
*/
|
|
48
|
+
const wrappedPrototypes = /* @__PURE__ */ new WeakSet();
|
|
49
|
+
/**
|
|
45
50
|
* Base class for Workflows that need access to their originating Agent.
|
|
46
51
|
*
|
|
47
52
|
* @template AgentType - The Agent class type (for typed RPC access)
|
|
@@ -52,15 +57,26 @@ import { WorkflowEntrypoint } from "cloudflare:workers";
|
|
|
52
57
|
var AgentWorkflow = class extends WorkflowEntrypoint {
|
|
53
58
|
constructor(ctx, env) {
|
|
54
59
|
super(ctx, env);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
this.__agentInitCalled = false;
|
|
61
|
+
const proto = Object.getPrototypeOf(this);
|
|
62
|
+
if (Object.hasOwn(proto, "run") && !wrappedPrototypes.has(proto)) {
|
|
63
|
+
const originalRun = proto.run;
|
|
64
|
+
proto.run = async function(event, step) {
|
|
65
|
+
if (!this.__agentInitCalled) {
|
|
66
|
+
const { __agentName, __agentBinding, __workflowName, ...userParams } = event.payload;
|
|
67
|
+
await this._initAgent(__agentName, __agentBinding, __workflowName, event.instanceId);
|
|
68
|
+
this.__agentInitCalled = true;
|
|
69
|
+
const cleanedEvent = {
|
|
70
|
+
...event,
|
|
71
|
+
payload: userParams
|
|
72
|
+
};
|
|
73
|
+
const wrappedStep = this._wrapStep(step);
|
|
74
|
+
return originalRun.call(this, cleanedEvent, wrappedStep);
|
|
75
|
+
}
|
|
76
|
+
return originalRun.call(this, event, step);
|
|
77
|
+
};
|
|
78
|
+
wrappedPrototypes.add(proto);
|
|
79
|
+
}
|
|
64
80
|
}
|
|
65
81
|
/**
|
|
66
82
|
* Initialize the Agent stub from workflow params.
|
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 * 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 constructor(ctx: ExecutionContext, env: Env) {\n super(ctx, env);\n\n // Store original run method - cast to accept clean event type and wrapped step\n // (user's implementation expects WorkflowEvent<Params> and AgentWorkflowStep)\n const originalRun = this.run.bind(this) as (\n event: WorkflowEvent<Params>,\n step: AgentWorkflowStep\n ) => Promise<unknown>;\n\n // Override run to initialize agent before user code executes\n this.run = async (\n event: WorkflowEvent<AgentWorkflowParams<Params>>,\n step: WorkflowStep\n ) => {\n // Extract internal params\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\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 return originalRun(cleanedEvent, wrappedStep);\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 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 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 this.agent._workflow_updateState(\"merge\", partialState);\n });\n };\n\n wrappedStep.resetAgentState = async (): Promise<void> => {\n await step.do(`__agent_resetState_${stepCounter++}`, async () => {\n 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 * 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 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 return originalRun.call(this, cleanedEvent, wrappedStep);\n }\n\n // If already initialized (e.g., called via super.run()),\n // just call the original with the event as-is\n return originalRun.call(\n this,\n event as WorkflowEvent<Params>,\n step as AgentWorkflowStep\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 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 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 this.agent._workflow_updateState(\"merge\", partialState);\n });\n };\n\n wrappedStep.resetAgentState = async (): Promise<void> => {\n await step.do(`__agent_resetState_${stepCounter++}`, async () => {\n 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 * 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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"}
|