agents 0.12.2 → 0.12.4
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/{agent-tool-types-DSteYkkS.d.ts → agent-tool-types-CM_50fcV.d.ts} +104 -87
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/agent-tools-BAdX1vdI.js.map +1 -1
- package/dist/{agent-tools-eGTCdVZX.d.ts → agent-tools-BylX6WXG.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/agent-tools.js.map +1 -1
- package/dist/browser/ai.d.ts +2 -2
- package/dist/browser/ai.js +1 -1
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +41 -10
- package/dist/browser/index.js +1 -1
- package/dist/browser/tanstack-ai.d.ts +2 -2
- package/dist/browser/tanstack-ai.js +1 -1
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/chat/index.d.ts +297 -148
- package/dist/chat/index.js +43 -14
- package/dist/chat/index.js.map +1 -1
- package/dist/{classPrivateFieldGet2-Bqby-AHD.js → classPrivateFieldGet2-CS51BNGR.js} +5 -5
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/client-D1kFXo80.js.map +1 -1
- package/dist/client.d.ts +11 -10
- package/dist/client.js.map +1 -1
- package/dist/codemode/ai.d.ts +1 -1
- package/dist/{compaction-helpers-CSaqCmdE.js → compaction-helpers-DvcZnvQ1.js} +1 -1
- package/dist/{compaction-helpers-CSaqCmdE.js.map → compaction-helpers-DvcZnvQ1.js.map} +1 -1
- package/dist/{compaction-helpers-D92Ipstp.d.ts → compaction-helpers-bYvP1o2S.d.ts} +10 -3
- package/dist/{do-oauth-client-provider-C38aWbFV.d.ts → do-oauth-client-provider-4OKQU9rT.d.ts} +1 -1
- package/dist/{email-X72-zjuq.d.ts → email-J0GGS3sa.d.ts} +1 -1
- package/dist/email.d.ts +2 -2
- package/dist/email.js.map +1 -1
- package/dist/experimental/memory/session/index.d.ts +126 -26
- package/dist/experimental/memory/session/index.js +13 -3
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +41 -5
- package/dist/experimental/memory/utils/index.js +15 -5
- package/dist/experimental/memory/utils/index.js.map +1 -1
- package/dist/experimental/webmcp.d.ts +9 -3
- package/dist/experimental/webmcp.js.map +1 -1
- package/dist/{index-Biv6K70p.d.ts → index-DKey3P4s.d.ts} +26 -2
- package/dist/index.d.ts +48 -44
- package/dist/index.js +122 -85
- package/dist/index.js.map +1 -1
- package/dist/{internal_context-BvuGZieY.d.ts → internal_context-BZrMS0B5.d.ts} +1 -1
- package/dist/internal_context.d.ts +1 -1
- package/dist/mcp/client.d.ts +26 -2
- package/dist/mcp/do-oauth-client-provider.d.ts +10 -2
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +54 -2
- package/dist/mcp/index.js +43 -19
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +74 -17
- package/dist/mcp/x402.js.map +1 -1
- package/dist/observability/index.d.ts +16 -2
- package/dist/observability/index.js +1 -1
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +9 -7
- package/dist/react.js +18 -2
- package/dist/react.js.map +1 -1
- package/dist/{retries-fLD8cGNf.d.ts → retries-BVdRl5ZE.d.ts} +1 -1
- package/dist/retries.d.ts +1 -1
- package/dist/retries.js.map +1 -1
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +141 -7
- package/dist/{shared-Ch9slKdI.d.ts → shared-Cvj92byG.d.ts} +1 -1
- package/dist/{shared-C6l4ZKRN.js → shared-DzJYHisH.js} +3 -3
- package/dist/{shared-C6l4ZKRN.js.map → shared-DzJYHisH.js.map} +1 -1
- package/dist/sub-routing.d.ts +6 -6
- package/dist/sub-routing.js.map +1 -1
- package/dist/tool-output-truncation-CH-khbZ3.js +98 -0
- package/dist/tool-output-truncation-CH-khbZ3.js.map +1 -0
- package/dist/{types-DAHCZC_W.d.ts → types-_JjKmv-l.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/vite.js.map +1 -1
- package/dist/{workflow-types-DHs0L0KP.d.ts → workflow-types-Dkzg4hAx.d.ts} +1 -1
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflow-types.js.map +1 -1
- package/dist/workflows.d.ts +2 -2
- package/dist/workflows.js.map +1 -1
- package/package.json +9 -9
- package/dist/serializable-Brg7fRds.d.ts +0 -131
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { n as AgentEmail } from "./internal_context-
|
|
2
|
-
import { t as RetryOptions } from "./retries-
|
|
1
|
+
import { n as AgentEmail } from "./internal_context-BZrMS0B5.js";
|
|
2
|
+
import { t as RetryOptions } from "./retries-BVdRl5ZE.js";
|
|
3
3
|
import {
|
|
4
4
|
n as Observability,
|
|
5
5
|
r as ObservabilityEvent,
|
|
6
6
|
s as MCPObservabilityEvent
|
|
7
|
-
} from "./index-
|
|
8
|
-
import { t as AgentMcpOAuthProvider } from "./do-oauth-client-provider-
|
|
7
|
+
} from "./index-DKey3P4s.js";
|
|
8
|
+
import { t as AgentMcpOAuthProvider } from "./do-oauth-client-provider-4OKQU9rT.js";
|
|
9
9
|
import {
|
|
10
10
|
_ as WorkflowPage,
|
|
11
11
|
g as WorkflowInfo,
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
l as WorkflowCallback,
|
|
14
14
|
s as RunWorkflowOptions,
|
|
15
15
|
y as WorkflowQueryCriteria
|
|
16
|
-
} from "./workflow-types-
|
|
17
|
-
import { t as MessageType } from "./types-
|
|
18
|
-
import { r as EmailResolver } from "./email-
|
|
16
|
+
} from "./workflow-types-Dkzg4hAx.js";
|
|
17
|
+
import { t as MessageType } from "./types-_JjKmv-l.js";
|
|
18
|
+
import { r as EmailResolver } from "./email-J0GGS3sa.js";
|
|
19
19
|
import { ToolSet, UIMessage } from "ai";
|
|
20
20
|
import { RpcTarget } from "cloudflare:workers";
|
|
21
21
|
import {
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
ConnectionContext,
|
|
25
25
|
ConnectionContext as ConnectionContext$1,
|
|
26
26
|
PartyServerOptions,
|
|
27
|
+
RoutingRetryOptions,
|
|
27
28
|
Server,
|
|
28
29
|
WSMessage,
|
|
29
30
|
WSMessage as WSMessage$1
|
|
@@ -846,7 +847,7 @@ declare class MCPClientConnection {
|
|
|
846
847
|
*/
|
|
847
848
|
getTransport(
|
|
848
849
|
transportType: BaseTransportType
|
|
849
|
-
):
|
|
850
|
+
): RPCClientTransport | SSEClientTransport | StreamableHTTPClientTransport;
|
|
850
851
|
private tryConnect;
|
|
851
852
|
private _capabilityErrorHandler;
|
|
852
853
|
}
|
|
@@ -1996,6 +1997,7 @@ declare class Agent<
|
|
|
1996
1997
|
* parent-owned WebSocket handles during this window.
|
|
1997
1998
|
*/
|
|
1998
1999
|
private _suppressProtocolBroadcasts;
|
|
2000
|
+
private _protocolBroadcastExcludeIds;
|
|
1999
2001
|
private _cf_currentSubAgentBridge?;
|
|
2000
2002
|
private _cf_virtualSubAgentConnections;
|
|
2001
2003
|
/**
|
|
@@ -2234,7 +2236,7 @@ declare class Agent<
|
|
|
2234
2236
|
*
|
|
2235
2237
|
* IMPORTANT: This hook must be synchronous.
|
|
2236
2238
|
*/
|
|
2237
|
-
validateStateChange(
|
|
2239
|
+
validateStateChange(_nextState: State, _source: Connection | "server"): void;
|
|
2238
2240
|
/**
|
|
2239
2241
|
* Called after the Agent's state has been persisted and broadcast to all clients.
|
|
2240
2242
|
* This is a notification hook — errors here are routed to onError and do not
|
|
@@ -2243,7 +2245,10 @@ declare class Agent<
|
|
|
2243
2245
|
* @param state Updated state
|
|
2244
2246
|
* @param source Source of the state update ("server" or a client connection)
|
|
2245
2247
|
*/
|
|
2246
|
-
onStateChanged(
|
|
2248
|
+
onStateChanged(
|
|
2249
|
+
_state: State | undefined,
|
|
2250
|
+
_source: Connection | "server"
|
|
2251
|
+
): void;
|
|
2247
2252
|
/**
|
|
2248
2253
|
* @deprecated Renamed to `onStateChanged` — the behavior is identical.
|
|
2249
2254
|
* `onStateUpdate` will be removed in the next major version.
|
|
@@ -2255,7 +2260,10 @@ declare class Agent<
|
|
|
2255
2260
|
* @param state Updated state
|
|
2256
2261
|
* @param source Source of the state update ("server" or a client connection)
|
|
2257
2262
|
*/
|
|
2258
|
-
onStateUpdate(
|
|
2263
|
+
onStateUpdate(
|
|
2264
|
+
_state: State | undefined,
|
|
2265
|
+
_source: Connection | "server"
|
|
2266
|
+
): void;
|
|
2259
2267
|
/**
|
|
2260
2268
|
* Dispatch to the appropriate persistence hook based on the mode
|
|
2261
2269
|
* cached in the constructor. No prototype walks at call time.
|
|
@@ -2777,7 +2785,7 @@ declare class Agent<
|
|
|
2777
2785
|
_cf_dispatchScheduledCallback(
|
|
2778
2786
|
ownerPath: ReadonlyArray<AgentPathStep>,
|
|
2779
2787
|
row: ScheduleStorageRow
|
|
2780
|
-
): Promise<
|
|
2788
|
+
): Promise<boolean>;
|
|
2781
2789
|
/**
|
|
2782
2790
|
* Recursively destroy a descendant facet identified by
|
|
2783
2791
|
* `targetPath`. Walks down from `selfPath` until reaching the
|
|
@@ -3129,13 +3137,17 @@ declare class Agent<
|
|
|
3129
3137
|
private _defaultAgentToolPreview;
|
|
3130
3138
|
private _readAgentToolRun;
|
|
3131
3139
|
private _resultFromAgentToolRow;
|
|
3140
|
+
private _agentToolRunInfoFromRow;
|
|
3132
3141
|
private _terminalResultFromInspection;
|
|
3142
|
+
private _finishAgentToolRun;
|
|
3143
|
+
private _runDeferredAgentToolFinishHooks;
|
|
3133
3144
|
private _updateAgentToolTerminal;
|
|
3134
3145
|
private _markAgentToolRunning;
|
|
3135
3146
|
private _parseAgentToolJson;
|
|
3136
3147
|
private _stringifyAgentToolOutput;
|
|
3137
3148
|
private _broadcastAgentToolEvent;
|
|
3138
3149
|
private _broadcastAgentToolChunks;
|
|
3150
|
+
private _broadcastAgentToolStoredChunks;
|
|
3139
3151
|
private _forwardAgentToolStream;
|
|
3140
3152
|
private _broadcastAgentToolTerminal;
|
|
3141
3153
|
private _asAgentToolChildAdapter;
|
|
@@ -3727,6 +3739,13 @@ type AgentContext = DurableObjectState;
|
|
|
3727
3739
|
* Configuration options for Agent routing
|
|
3728
3740
|
*/
|
|
3729
3741
|
type AgentOptions<Env> = PartyServerOptions<Env>;
|
|
3742
|
+
type AgentGetOptions<
|
|
3743
|
+
Env,
|
|
3744
|
+
Props extends Record<string, unknown> = Record<string, unknown>
|
|
3745
|
+
> = Pick<
|
|
3746
|
+
PartyServerOptions<Env, Props>,
|
|
3747
|
+
"jurisdiction" | "locationHint" | "props" | "routingRetry"
|
|
3748
|
+
>;
|
|
3730
3749
|
/**
|
|
3731
3750
|
* Route a request to the appropriate Agent
|
|
3732
3751
|
* @param request Request to route
|
|
@@ -3789,11 +3808,7 @@ declare function getAgentByName<
|
|
|
3789
3808
|
>(
|
|
3790
3809
|
namespace: DurableObjectNamespace<T>,
|
|
3791
3810
|
name: string,
|
|
3792
|
-
options?:
|
|
3793
|
-
jurisdiction?: DurableObjectJurisdiction;
|
|
3794
|
-
locationHint?: DurableObjectLocationHint;
|
|
3795
|
-
props?: Props;
|
|
3796
|
-
}
|
|
3811
|
+
options?: AgentGetOptions<Env, Props>
|
|
3797
3812
|
): Promise<DurableObjectStub<T>>;
|
|
3798
3813
|
/**
|
|
3799
3814
|
* A wrapper for streaming responses in callable methods
|
|
@@ -3982,93 +3997,95 @@ type AgentToolEventState = {
|
|
|
3982
3997
|
};
|
|
3983
3998
|
//#endregion
|
|
3984
3999
|
export {
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4000
|
+
unstable_callable as $,
|
|
4001
|
+
FiberContext as A,
|
|
4002
|
+
McpClientOptions as At,
|
|
4003
|
+
ScheduleCriteria as B,
|
|
4004
|
+
AgentStaticOptions as C,
|
|
4005
|
+
McpAuthContext as Ct,
|
|
4006
|
+
DEFAULT_AGENT_STATIC_OPTIONS as D,
|
|
4007
|
+
WorkerTransportOptions as Dt,
|
|
4008
|
+
ConnectionContext$1 as E,
|
|
4009
|
+
WorkerTransport as Et,
|
|
4010
|
+
QueueItem as F,
|
|
4011
|
+
parseSubAgentPath as Ft,
|
|
4012
|
+
SubAgentClass as G,
|
|
4013
|
+
SqlError as H,
|
|
4014
|
+
RPCRequest as I,
|
|
4015
|
+
routeSubAgentRequest as It,
|
|
4016
|
+
callable as J,
|
|
4017
|
+
SubAgentStub as K,
|
|
4018
|
+
RPCResponse as L,
|
|
4019
|
+
MCPServer as M,
|
|
4020
|
+
SUB_PREFIX as Mt,
|
|
4021
|
+
MCPServerMessage as N,
|
|
4022
|
+
SubAgentPathMatch as Nt,
|
|
4023
|
+
EmailRoutingOptions as O,
|
|
4024
|
+
SSEEdgeClientTransport as Ot,
|
|
4025
|
+
MCPServersState as P,
|
|
4026
|
+
getSubAgentByName as Pt,
|
|
4027
|
+
routeAgentRequest as Q,
|
|
4028
|
+
RoutingRetryOptions as R,
|
|
4029
|
+
AgentOptions as S,
|
|
4030
|
+
experimental_createMcpHandler as St,
|
|
4031
|
+
Connection$1 as T,
|
|
4032
|
+
TransportState as Tt,
|
|
4033
|
+
StateUpdateMessage as U,
|
|
4034
|
+
SendEmailOptions as V,
|
|
4035
|
+
StreamingResponse as W,
|
|
4036
|
+
getCurrentAgent as X,
|
|
4037
|
+
getAgentByName as Y,
|
|
4038
|
+
routeAgentEmail as Z,
|
|
4022
4039
|
AddRpcMcpServerOptions as _,
|
|
4023
|
-
|
|
4040
|
+
ElicitRequestSchema$1 as _t,
|
|
4024
4041
|
AgentToolEventState as a,
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4042
|
+
MCPDiscoverResult as at,
|
|
4043
|
+
AgentGetOptions as b,
|
|
4044
|
+
CreateMcpHandlerOptions as bt,
|
|
4028
4045
|
AgentToolRunInspection as c,
|
|
4029
|
-
|
|
4046
|
+
MCPServerOptions as ct,
|
|
4030
4047
|
AgentToolStoredChunk as d,
|
|
4031
|
-
|
|
4032
|
-
|
|
4048
|
+
RPCClientTransport as dt,
|
|
4049
|
+
MCPClientManager as et,
|
|
4033
4050
|
AgentToolTerminalStatus as f,
|
|
4034
|
-
|
|
4051
|
+
RPCClientTransportOptions as ft,
|
|
4035
4052
|
AddMcpServerOptions as g,
|
|
4036
|
-
|
|
4053
|
+
ElicitRequest$1 as gt,
|
|
4037
4054
|
RunAgentToolResult as h,
|
|
4038
|
-
|
|
4055
|
+
RPC_DO_PREFIX as ht,
|
|
4039
4056
|
AgentToolEventMessage as i,
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4057
|
+
MCPConnectionResult as it,
|
|
4058
|
+
FiberRecoveryContext as j,
|
|
4059
|
+
TransportType as jt,
|
|
4060
|
+
EmailSendBinding as k,
|
|
4061
|
+
StreamableHTTPEdgeClientTransport as kt,
|
|
4045
4062
|
AgentToolRunState as l,
|
|
4046
|
-
|
|
4063
|
+
RegisterServerOptions as lt,
|
|
4047
4064
|
RunAgentToolOptions as m,
|
|
4048
|
-
|
|
4065
|
+
RPCServerTransportOptions as mt,
|
|
4049
4066
|
AgentToolDisplayMetadata as n,
|
|
4050
|
-
|
|
4067
|
+
MCPClientOAuthCallbackConfig as nt,
|
|
4051
4068
|
AgentToolLifecycleResult as o,
|
|
4052
|
-
|
|
4069
|
+
MCPOAuthCallbackResult as ot,
|
|
4053
4070
|
ChatCapableAgentClass as p,
|
|
4054
|
-
|
|
4055
|
-
|
|
4071
|
+
RPCServerTransport as pt,
|
|
4072
|
+
WSMessage$1 as q,
|
|
4056
4073
|
AgentToolEvent as r,
|
|
4057
|
-
|
|
4074
|
+
MCPClientOAuthResult as rt,
|
|
4058
4075
|
AgentToolRunInfo as s,
|
|
4059
|
-
|
|
4076
|
+
MCPServerFilter as st,
|
|
4060
4077
|
AgentToolChildAdapter as t,
|
|
4061
|
-
|
|
4078
|
+
MCPClientManagerOptions as tt,
|
|
4062
4079
|
AgentToolRunStatus as u,
|
|
4063
|
-
|
|
4080
|
+
getNamespacedData as ut,
|
|
4064
4081
|
Agent as v,
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4082
|
+
ElicitResult$1 as vt,
|
|
4083
|
+
CallableMetadata as w,
|
|
4084
|
+
getMcpAuthContext as wt,
|
|
4085
|
+
AgentNamespace as x,
|
|
4086
|
+
createMcpHandler as xt,
|
|
4070
4087
|
AgentContext as y,
|
|
4071
|
-
|
|
4072
|
-
|
|
4088
|
+
McpAgent as yt,
|
|
4089
|
+
Schedule as z
|
|
4073
4090
|
};
|
|
4074
|
-
//# sourceMappingURL=agent-tool-types-
|
|
4091
|
+
//# sourceMappingURL=agent-tool-types-CM_50fcV.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
a as AgentToolEventState,
|
|
3
3
|
i as AgentToolEventMessage
|
|
4
|
-
} from "./agent-tool-types-
|
|
4
|
+
} from "./agent-tool-types-CM_50fcV.js";
|
|
5
5
|
|
|
6
6
|
//#region src/chat/agent-tools.d.ts
|
|
7
7
|
declare function createAgentToolEventState(): AgentToolEventState;
|
|
@@ -11,4 +11,4 @@ declare function applyAgentToolEvent(
|
|
|
11
11
|
): AgentToolEventState;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { createAgentToolEventState as n, applyAgentToolEvent as t };
|
|
14
|
-
//# sourceMappingURL=agent-tools-
|
|
14
|
+
//# sourceMappingURL=agent-tools-BylX6WXG.d.ts.map
|
package/dist/agent-tools.d.ts
CHANGED
package/dist/agent-tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-tools.js","names":["agentContext","createTool"],"sources":["../src/agent-tools.ts"],"sourcesContent":["import { tool, type Tool } from \"ai\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"./internal_context\";\nimport type {\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult,\n AgentToolDisplayMetadata\n} from \"./agent-tool-types\";\n\ntype SchemaLike<T = unknown> = {\n parse(value: unknown): T;\n};\n\ntype AgentToolFactoryOptions<Output = unknown> = {\n description: string;\n inputSchema: unknown;\n outputSchema?: SchemaLike<Output>;\n displayName?: string;\n icon?: string;\n display?: AgentToolDisplayMetadata;\n};\n\ntype ToolExecutionOptions = {\n toolCallId?: string;\n abortSignal?: AbortSignal;\n};\n\ntype AgentToolRunner = {\n runAgentTool<Input, Output>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>>;\n};\n\nfunction currentAgentToolRunner(): AgentToolRunner {\n const agent = agentContext.getStore()?.agent;\n if (\n agent === null ||\n typeof agent !== \"object\" ||\n typeof (agent as { runAgentTool?: unknown }).runAgentTool !== \"function\"\n ) {\n throw new Error(\n \"agentTool() can only run inside an Agent turn. Use it from getTools() on an Agent subclass.\"\n );\n }\n return agent as AgentToolRunner;\n}\n\nfunction failure(error: string): { ok: false; error: string } {\n return { ok: false, error };\n}\n\n/**\n * Create an AI SDK tool that dispatches a chat-capable sub-agent through\n * `Agent.runAgentTool`.\n */\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output>\n): Tool<Input, string | Output | { ok: false; error: string }> {\n const createTool = tool as unknown as <I, O>(config: {\n description: string;\n inputSchema: unknown;\n execute: (input: I, options?: ToolExecutionOptions) => Promise<O>;\n }) => Tool<I, O>;\n\n return createTool<Input, string | Output | { ok: false; error: string }>({\n description: options.description,\n inputSchema: options.inputSchema,\n execute: async (input: Input, executeOptions?: ToolExecutionOptions) => {\n const display: AgentToolDisplayMetadata | undefined =\n options.displayName || options.icon || options.display\n ? {\n ...options.display,\n ...(options.displayName ? { name: options.displayName } : {}),\n ...(options.icon ? { icon: options.icon } : {})\n }\n : undefined;\n\n const result = await currentAgentToolRunner().runAgentTool<Input, Output>(\n cls,\n {\n input,\n parentToolCallId: executeOptions?.toolCallId,\n signal: executeOptions?.abortSignal,\n display\n }\n );\n\n if (result.status === \"completed\") {\n if (options.outputSchema) {\n if (result.output === undefined) {\n return failure(\n \"agent tool completed without structured output required by outputSchema\"\n );\n }\n return options.outputSchema.parse(result.output);\n }\n return result.summary ?? \"\";\n }\n\n if (result.status === \"aborted\") {\n return failure(\"agent tool run was cancelled\");\n }\n if (result.status === \"interrupted\") {\n return failure(\"agent tool run was interrupted; no recoverable output\");\n }\n return failure(result.error ?? \"agent tool run failed\");\n }\n });\n}\n\nexport type { AgentToolFactoryOptions };\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n"],"mappings":";;;AAkCA,SAAS,yBAA0C;CACjD,MAAM,QAAQA,sCAAa,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"agent-tools.js","names":["agentContext","createTool"],"sources":["../src/agent-tools.ts"],"sourcesContent":["import { tool, type Tool } from \"ai\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"./internal_context\";\nimport type {\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult,\n AgentToolDisplayMetadata\n} from \"./agent-tool-types\";\n\ntype SchemaLike<T = unknown> = {\n parse(value: unknown): T;\n};\n\ntype AgentToolFactoryOptions<Output = unknown> = {\n description: string;\n inputSchema: unknown;\n outputSchema?: SchemaLike<Output>;\n displayName?: string;\n icon?: string;\n display?: AgentToolDisplayMetadata;\n};\n\ntype ToolExecutionOptions = {\n toolCallId?: string;\n abortSignal?: AbortSignal;\n};\n\ntype AgentToolRunner = {\n runAgentTool<Input, Output>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>>;\n};\n\nfunction currentAgentToolRunner(): AgentToolRunner {\n const agent = agentContext.getStore()?.agent;\n if (\n agent === null ||\n typeof agent !== \"object\" ||\n typeof (agent as { runAgentTool?: unknown }).runAgentTool !== \"function\"\n ) {\n throw new Error(\n \"agentTool() can only run inside an Agent turn. Use it from getTools() on an Agent subclass.\"\n );\n }\n return agent as AgentToolRunner;\n}\n\nfunction failure(error: string): { ok: false; error: string } {\n return { ok: false, error };\n}\n\n/**\n * Create an AI SDK tool that dispatches a chat-capable sub-agent through\n * `Agent.runAgentTool`.\n */\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output>\n): Tool<Input, string | Output | { ok: false; error: string }> {\n const createTool = tool as unknown as <I, O>(config: {\n description: string;\n inputSchema: unknown;\n execute: (input: I, options?: ToolExecutionOptions) => Promise<O>;\n }) => Tool<I, O>;\n\n return createTool<Input, string | Output | { ok: false; error: string }>({\n description: options.description,\n inputSchema: options.inputSchema,\n execute: async (input: Input, executeOptions?: ToolExecutionOptions) => {\n const display: AgentToolDisplayMetadata | undefined =\n options.displayName || options.icon || options.display\n ? {\n ...options.display,\n ...(options.displayName ? { name: options.displayName } : {}),\n ...(options.icon ? { icon: options.icon } : {})\n }\n : undefined;\n\n const result = await currentAgentToolRunner().runAgentTool<Input, Output>(\n cls,\n {\n input,\n parentToolCallId: executeOptions?.toolCallId,\n signal: executeOptions?.abortSignal,\n display\n }\n );\n\n if (result.status === \"completed\") {\n if (options.outputSchema) {\n if (result.output === undefined) {\n return failure(\n \"agent tool completed without structured output required by outputSchema\"\n );\n }\n return options.outputSchema.parse(result.output);\n }\n return result.summary ?? \"\";\n }\n\n if (result.status === \"aborted\") {\n return failure(\"agent tool run was cancelled\");\n }\n if (result.status === \"interrupted\") {\n return failure(\"agent tool run was interrupted; no recoverable output\");\n }\n return failure(result.error ?? \"agent tool run failed\");\n }\n });\n}\n\nexport type { AgentToolFactoryOptions };\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n"],"mappings":";;;AAkCA,SAAS,yBAA0C;CACjD,MAAM,QAAQA,sCAAa,UAAU,EAAE;CACvC,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAqC,iBAAiB,YAE9D,MAAM,IAAI,MACR,8FACD;CAEH,OAAO;;AAGT,SAAS,QAAQ,OAA6C;CAC5D,OAAO;EAAE,IAAI;EAAO;EAAO;;;;;;AAO7B,SAAgB,UACd,KACA,SAC6D;CAO7D,OAAOC,KAAkE;EACvE,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,SAAS,OAAO,OAAc,mBAA0C;GACtE,MAAM,UACJ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,UAC3C;IACE,GAAG,QAAQ;IACX,GAAI,QAAQ,cAAc,EAAE,MAAM,QAAQ,aAAa,GAAG,EAAE;IAC5D,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,EAAE;IAC/C,GACD,KAAA;GAEN,MAAM,SAAS,MAAM,wBAAwB,CAAC,aAC5C,KACA;IACE;IACA,kBAAkB,gBAAgB;IAClC,QAAQ,gBAAgB;IACxB;IACD,CACF;GAED,IAAI,OAAO,WAAW,aAAa;IACjC,IAAI,QAAQ,cAAc;KACxB,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,QACL,0EACD;KAEH,OAAO,QAAQ,aAAa,MAAM,OAAO,OAAO;;IAElD,OAAO,OAAO,WAAW;;GAG3B,IAAI,OAAO,WAAW,WACpB,OAAO,QAAQ,+BAA+B;GAEhD,IAAI,OAAO,WAAW,eACpB,OAAO,QAAQ,wDAAwD;GAEzE,OAAO,QAAQ,OAAO,SAAS,wBAAwB;;EAE1D,CAAC"}
|
package/dist/browser/ai.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as BrowserToolsOptions } from "../shared-
|
|
1
|
+
import { t as BrowserToolsOptions } from "../shared-Cvj92byG.js";
|
|
2
2
|
import { ToolSet } from "ai";
|
|
3
3
|
|
|
4
4
|
//#region src/browser/ai.d.ts
|
|
@@ -28,4 +28,4 @@ import { ToolSet } from "ai";
|
|
|
28
28
|
declare function createBrowserTools(options: BrowserToolsOptions): ToolSet;
|
|
29
29
|
//#endregion
|
|
30
30
|
export { type BrowserToolsOptions, createBrowserTools };
|
|
31
|
-
//# sourceMappingURL=ai.d.ts.map
|
|
31
|
+
//# sourceMappingURL=ai.d.ts.map
|
package/dist/browser/ai.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as SEARCH_DESCRIPTION, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-
|
|
1
|
+
import { n as SEARCH_DESCRIPTION, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-DzJYHisH.js";
|
|
2
2
|
import { tool } from "ai";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/browser/ai.ts
|
package/dist/browser/ai.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.js","names":[],"sources":["../../src/browser/ai.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport { z } from \"zod\";\nimport {\n createBrowserToolHandlers,\n SEARCH_DESCRIPTION,\n EXECUTE_DESCRIPTION,\n type BrowserToolsOptions\n} from \"./shared\";\n\nexport type { BrowserToolsOptions } from \"./shared\";\n\n/**\n * Create AI SDK tools for browser automation via CDP code mode.\n *\n * Returns a `ToolSet` with `search` (query the CDP spec) and\n * `execute` (run CDP commands against a live browser).\n *\n * @example\n * ```ts\n * import { createBrowserTools } from \"agents/browser/ai\";\n * import { generateText } from \"ai\";\n *\n * const browserTools = createBrowserTools({\n * browser: env.BROWSER,\n * loader: env.LOADER,\n * });\n *\n * const result = await generateText({\n * model,\n * tools: { ...browserTools, ...otherTools },\n * messages,\n * });\n * ```\n */\nexport function createBrowserTools(options: BrowserToolsOptions): ToolSet {\n const handlers = createBrowserToolHandlers(options);\n\n return {\n browser_search: tool({\n description: SEARCH_DESCRIPTION,\n inputSchema: z.object({\n code: z\n .string()\n .describe(\"JavaScript async arrow function that queries the CDP spec\")\n }),\n execute: async ({ code }) => {\n const result = await handlers.search(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return result.text;\n }\n }),\n\n browser_execute: tool({\n description: EXECUTE_DESCRIPTION,\n inputSchema: z.object({\n code: z\n .string()\n .describe(\"JavaScript async arrow function that uses the cdp helper\")\n }),\n execute: async ({ code }) => {\n const result = await handlers.execute(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return result.text;\n }\n })\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,mBAAmB,SAAuC;CACxE,MAAM,WAAW,0BAA0B,QAAQ;
|
|
1
|
+
{"version":3,"file":"ai.js","names":[],"sources":["../../src/browser/ai.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport { z } from \"zod\";\nimport {\n createBrowserToolHandlers,\n SEARCH_DESCRIPTION,\n EXECUTE_DESCRIPTION,\n type BrowserToolsOptions\n} from \"./shared\";\n\nexport type { BrowserToolsOptions } from \"./shared\";\n\n/**\n * Create AI SDK tools for browser automation via CDP code mode.\n *\n * Returns a `ToolSet` with `search` (query the CDP spec) and\n * `execute` (run CDP commands against a live browser).\n *\n * @example\n * ```ts\n * import { createBrowserTools } from \"agents/browser/ai\";\n * import { generateText } from \"ai\";\n *\n * const browserTools = createBrowserTools({\n * browser: env.BROWSER,\n * loader: env.LOADER,\n * });\n *\n * const result = await generateText({\n * model,\n * tools: { ...browserTools, ...otherTools },\n * messages,\n * });\n * ```\n */\nexport function createBrowserTools(options: BrowserToolsOptions): ToolSet {\n const handlers = createBrowserToolHandlers(options);\n\n return {\n browser_search: tool({\n description: SEARCH_DESCRIPTION,\n inputSchema: z.object({\n code: z\n .string()\n .describe(\"JavaScript async arrow function that queries the CDP spec\")\n }),\n execute: async ({ code }) => {\n const result = await handlers.search(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return result.text;\n }\n }),\n\n browser_execute: tool({\n description: EXECUTE_DESCRIPTION,\n inputSchema: z.object({\n code: z\n .string()\n .describe(\"JavaScript async arrow function that uses the cdp helper\")\n }),\n execute: async ({ code }) => {\n const result = await handlers.execute(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return result.text;\n }\n })\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,mBAAmB,SAAuC;CACxE,MAAM,WAAW,0BAA0B,QAAQ;CAEnD,OAAO;EACL,gBAAgB,KAAK;GACnB,aAAa;GACb,aAAa,EAAE,OAAO,EACpB,MAAM,EACH,QAAQ,CACR,SAAS,4DAA4D,EACzE,CAAC;GACF,SAAS,OAAO,EAAE,WAAW;IAC3B,MAAM,SAAS,MAAM,SAAS,OAAO,KAAK;IAC1C,IAAI,OAAO,SACT,MAAM,IAAI,MAAM,OAAO,KAAK;IAE9B,OAAO,OAAO;;GAEjB,CAAC;EAEF,iBAAiB,KAAK;GACpB,aAAa;GACb,aAAa,EAAE,OAAO,EACpB,MAAM,EACH,QAAQ,CACR,SAAS,2DAA2D,EACxE,CAAC;GACF,SAAS,OAAO,EAAE,WAAW;IAC3B,MAAM,SAAS,MAAM,SAAS,QAAQ,KAAK;IAC3C,IAAI,OAAO,SACT,MAAM,IAAI,MAAM,OAAO,KAAK;IAE9B,OAAO,OAAO;;GAEjB,CAAC;EACH"}
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
a as createBrowserToolHandlers,
|
|
3
|
+
i as ToolResult,
|
|
4
|
+
n as EXECUTE_DESCRIPTION,
|
|
5
|
+
r as SEARCH_DESCRIPTION,
|
|
6
|
+
t as BrowserToolsOptions
|
|
7
|
+
} from "../shared-Cvj92byG.js";
|
|
2
8
|
|
|
3
9
|
//#region src/browser/cdp-session.d.ts
|
|
4
10
|
interface DebugEntry {
|
|
@@ -22,8 +28,16 @@ interface CdpAttachOptions {
|
|
|
22
28
|
*/
|
|
23
29
|
declare class CdpSession {
|
|
24
30
|
#private;
|
|
25
|
-
constructor(
|
|
26
|
-
|
|
31
|
+
constructor(
|
|
32
|
+
socket: WebSocket,
|
|
33
|
+
defaultTimeoutMs?: number,
|
|
34
|
+
dispose?: () => void
|
|
35
|
+
);
|
|
36
|
+
send(
|
|
37
|
+
method: string,
|
|
38
|
+
params?: unknown,
|
|
39
|
+
options?: CdpSendOptions
|
|
40
|
+
): Promise<unknown>;
|
|
27
41
|
attachToTarget(targetId: string, options?: CdpAttachOptions): Promise<string>;
|
|
28
42
|
getDebugLog(limit?: number): DebugEntry[];
|
|
29
43
|
clearDebugLog(): void;
|
|
@@ -33,7 +47,10 @@ declare class CdpSession {
|
|
|
33
47
|
* Connect to a browser via the Browser Rendering binding (Fetcher).
|
|
34
48
|
* Establishes a CDP WebSocket through the binding's fetch interface.
|
|
35
49
|
*/
|
|
36
|
-
declare function connectBrowser(
|
|
50
|
+
declare function connectBrowser(
|
|
51
|
+
browser: Fetcher,
|
|
52
|
+
timeoutMs?: number
|
|
53
|
+
): Promise<CdpSession>;
|
|
37
54
|
/**
|
|
38
55
|
* Connect to a browser via a CDP base URL (e.g. http://localhost:9222).
|
|
39
56
|
* Discovers the WebSocket debugger URL via /json/version,
|
|
@@ -42,10 +59,24 @@ declare function connectBrowser(browser: Fetcher, timeoutMs?: number): Promise<C
|
|
|
42
59
|
* Useful for local development with `chrome --remote-debugging-port=9222`
|
|
43
60
|
* or when connecting through a tunnel.
|
|
44
61
|
*/
|
|
45
|
-
declare function connectUrl(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
declare function connectUrl(
|
|
63
|
+
baseUrl: string,
|
|
64
|
+
options?: {
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
headers?: Record<string, string>;
|
|
67
|
+
}
|
|
68
|
+
): Promise<CdpSession>;
|
|
49
69
|
//#endregion
|
|
50
|
-
export {
|
|
51
|
-
|
|
70
|
+
export {
|
|
71
|
+
type BrowserToolsOptions,
|
|
72
|
+
type CdpAttachOptions,
|
|
73
|
+
type CdpSendOptions,
|
|
74
|
+
CdpSession,
|
|
75
|
+
EXECUTE_DESCRIPTION,
|
|
76
|
+
SEARCH_DESCRIPTION,
|
|
77
|
+
type ToolResult,
|
|
78
|
+
connectBrowser,
|
|
79
|
+
connectUrl,
|
|
80
|
+
createBrowserToolHandlers
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/browser/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as connectBrowser, i as CdpSession, n as SEARCH_DESCRIPTION, o as connectUrl, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-
|
|
1
|
+
import { a as connectBrowser, i as CdpSession, n as SEARCH_DESCRIPTION, o as connectUrl, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-DzJYHisH.js";
|
|
2
2
|
export { CdpSession, EXECUTE_DESCRIPTION, SEARCH_DESCRIPTION, connectBrowser, connectUrl, createBrowserToolHandlers };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as BrowserToolsOptions } from "../shared-
|
|
1
|
+
import { t as BrowserToolsOptions } from "../shared-Cvj92byG.js";
|
|
2
2
|
import { ServerTool } from "@tanstack/ai";
|
|
3
3
|
|
|
4
4
|
//#region src/browser/tanstack-ai.d.ts
|
|
@@ -28,4 +28,4 @@ import { ServerTool } from "@tanstack/ai";
|
|
|
28
28
|
declare function createBrowserTools(options: BrowserToolsOptions): ServerTool[];
|
|
29
29
|
//#endregion
|
|
30
30
|
export { type BrowserToolsOptions, createBrowserTools };
|
|
31
|
-
//# sourceMappingURL=tanstack-ai.d.ts.map
|
|
31
|
+
//# sourceMappingURL=tanstack-ai.d.ts.map
|