agents 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-routing-B2XLNMxq.d.ts → agent-routing-0DR0Tk2v.d.ts} +205 -132
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-routing.js.map +1 -1
- package/dist/agent-tool-types.d.ts +28 -22
- package/dist/agent-tool-types.js +23 -1
- package/dist/agent-tool-types.js.map +1 -1
- package/dist/{agent-tools-y7zLfw4Q.js → agent-tools-CdJC-8Dc.js} +72 -9
- package/dist/agent-tools-CdJC-8Dc.js.map +1 -0
- package/dist/{agent-tools-Dj5Mzlw7.d.ts → agent-tools-YrATZJu2.d.ts} +34 -20
- package/dist/agent-tools.d.ts +20 -18
- package/dist/agent-tools.js.map +1 -1
- package/dist/ai-fm7xx1BK.js +312 -0
- package/dist/ai-fm7xx1BK.js.map +1 -0
- package/dist/base64-redaction-C1Uu29t5.js +59 -0
- package/dist/base64-redaction-C1Uu29t5.js.map +1 -0
- package/dist/browser/ai-sdk.d.ts +90 -0
- package/dist/browser/ai-sdk.js +51 -0
- package/dist/browser/ai-sdk.js.map +1 -0
- package/dist/browser/ai.d.ts +4 -4
- package/dist/browser/ai.js +1 -347
- package/dist/browser/index.d.ts +81 -79
- package/dist/browser/index.js +361 -2
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/tanstack-ai.d.ts +96 -1
- package/dist/browser/tanstack-ai.js +62 -2
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/browser-DE3d-RLk.d.ts +275 -0
- package/dist/browser-tool-CQ10e6Kj.js +480 -0
- package/dist/browser-tool-CQ10e6Kj.js.map +1 -0
- package/dist/browser-tool-DuNdlwZ9.d.ts +73 -0
- package/dist/capability-B4WbF81e.js.map +1 -1
- package/dist/{capability-runner-BUBa6Ake.d.ts → capability-runner-DBAnGr6L.d.ts} +7 -2
- package/dist/chat/index.d.ts +340 -234
- package/dist/chat/index.js +592 -66
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +42 -2
- package/dist/chat/react.js +191 -35
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/transport.d.ts +1 -1
- package/dist/chat/transport.js +1 -1
- package/dist/chat-sdk/index.d.ts +17 -3
- package/dist/chat-sdk/index.js +28 -2
- package/dist/chat-sdk/index.js.map +1 -1
- package/dist/{client-C9DAjZIY.js → client-4OlMIJx-.js} +102 -29
- package/dist/client-4OlMIJx-.js.map +1 -0
- package/dist/{client-BxdkCuVy.d.ts → client-je3koD9Z.d.ts} +45 -10
- package/dist/client.d.ts +7 -5
- package/dist/client.js +2 -2
- package/dist/{connector-CptFKzRh.js → connector-58XDGvc3.js} +251 -120
- package/dist/connector-58XDGvc3.js.map +1 -0
- package/dist/{connector-CkQD4MK3.d.ts → connector-Cl-VqPmA.d.ts} +244 -146
- package/dist/context/index.d.ts +29 -0
- package/dist/context/index.js +64 -17
- package/dist/context/index.js.map +1 -1
- package/dist/current-agent-DhoDkSnH.js.map +1 -1
- package/dist/{current-agent-C4w86kcN.d.ts → current-agent-vAk_5JMt.d.ts} +4 -4
- package/dist/{durable-object-lifecycle-ei7M7lqB.d.ts → durable-object-lifecycle-HhgOMWq9.d.ts} +15 -7
- package/dist/harness/pi/index.d.ts +344 -0
- package/dist/harness/pi/index.js +873 -0
- package/dist/harness/pi/index.js.map +1 -0
- package/dist/images-iiTDSyRu.js +1631 -0
- package/dist/images-iiTDSyRu.js.map +1 -0
- package/dist/{index-Dlgtd3Mj.d.ts → index-BreL0YrQ.d.ts} +2 -2
- package/dist/index-kbSUIer3.d.ts +343 -0
- package/dist/index.d.ts +46 -44
- package/dist/index.js +1 -1
- package/dist/internal_context.d.ts +1 -1
- package/dist/lifecycle/index.d.ts +3 -3
- package/dist/lifecycle/index.js +1 -1
- package/dist/{lifecycle-Mm_jQh7r.js → lifecycle-CFu6OV03.js} +39 -10
- package/dist/{lifecycle-Mm_jQh7r.js.map → lifecycle-CFu6OV03.js.map} +1 -1
- package/dist/mcp/client/index.d.ts +20 -20
- package/dist/mcp/client/x402.js +21 -19
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +35 -35
- package/dist/mcp/index.js +1 -1
- package/dist/{message-builder-BymO4N_D.js → message-builder-DAl9AhHH.js} +89 -4
- package/dist/message-builder-DAl9AhHH.js.map +1 -0
- package/dist/models/ai-sdk/index.d.ts +353 -0
- package/dist/models/ai-sdk/index.js +2443 -0
- package/dist/models/ai-sdk/index.js.map +1 -0
- package/dist/models/pi-ai/index.d.ts +313 -0
- package/dist/models/pi-ai/index.js +1795 -0
- package/dist/models/pi-ai/index.js.map +1 -0
- package/dist/observability/ai/index.js +20 -4
- package/dist/observability/ai/index.js.map +1 -1
- package/dist/{protocol-B0nh6KNf.js → protocol-kHsr-f0X.js} +26 -12
- package/dist/{protocol-B0nh6KNf.js.map → protocol-kHsr-f0X.js.map} +1 -1
- package/dist/queue/index.d.ts +3 -3
- package/dist/queue/index.js +1 -1
- package/dist/{queue-BC9F5cUo.js → queue-BB-zfIYF.js} +2 -2
- package/dist/{queue-BC9F5cUo.js.map → queue-BB-zfIYF.js.map} +1 -1
- package/dist/react.d.ts +6 -6
- package/dist/react.js +160 -64
- package/dist/react.js.map +1 -1
- package/dist/{retries-D9B2UCq3.d.ts → retries-CV6AkXmQ.d.ts} +18 -9
- package/dist/retries.d.ts +11 -9
- package/dist/retries.js +11 -1
- package/dist/retries.js.map +1 -1
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.js +1 -1
- package/dist/{scheduler-D_KHqxBa.js → scheduler-DZ3xQfeK.js} +2 -2
- package/dist/{scheduler-D_KHqxBa.js.map → scheduler-DZ3xQfeK.js.map} +1 -1
- package/dist/{scheduler-BGq6M5Kd.d.ts → scheduler-RdACNXDP.d.ts} +3 -3
- package/dist/schedules/index.d.ts +1 -1
- package/dist/schedules/index.js +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sessions/index.d.ts +70 -3
- package/dist/sessions/index.js +276 -67
- package/dist/sessions/index.js.map +1 -1
- package/dist/skills/index.d.ts +29 -314
- package/dist/socket-address.d.ts +16 -0
- package/dist/socket-address.js +19 -0
- package/dist/socket-address.js.map +1 -0
- package/dist/{src-BNU3ZiJM.js → src-BZeu-SCD.js} +423 -115
- package/dist/src-BZeu-SCD.js.map +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.js +1 -1
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/{streams-BcE8JP2X.d.ts → streams-Cmkj9QfW.d.ts} +4 -2
- package/dist/{streams-CCPRV6dt.js → streams-DW-UCOUc.js} +9 -2
- package/dist/streams-DW-UCOUc.js.map +1 -0
- package/dist/sub-routing.d.ts +12 -12
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/{tasks-D4nLqVSI.js → tasks-68DESxf0.js} +2 -2
- package/dist/{tasks-D4nLqVSI.js.map → tasks-68DESxf0.js.map} +1 -1
- package/dist/{tasks-V2lCT8ZV.d.ts → tasks-9YxYtByh.d.ts} +2 -2
- package/dist/transport-PfFnt-Ld.d.ts +525 -0
- package/dist/{types-DCD6BNZH.d.ts → types-BA4anrjI.d.ts} +2 -2
- package/dist/voice/index.d.ts +2 -2
- package/dist/websockets/index.d.ts +23 -6
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-D7IzWbZb.js → websockets-Ci-LZFHH.js} +45 -20
- package/dist/{websockets-D7IzWbZb.js.map → websockets-Ci-LZFHH.js.map} +1 -1
- package/dist/wire-types-CnMt6_HR.js.map +1 -1
- package/dist/wire-types-CrjKvDyi.d.ts +300 -0
- package/dist/workflow-types.d.ts +25 -25
- package/dist/workflows.d.ts +21 -21
- package/dist/workflows.js +1 -1
- package/dist/{ws-chat-transport-UNRIS2xl.d.ts → ws-chat-transport-BbT1A5Lc.d.ts} +51 -2
- package/dist/{ws-chat-transport-rWwta645.js → ws-chat-transport-cqMKq3IY.js} +143 -16
- package/dist/ws-chat-transport-cqMKq3IY.js.map +1 -0
- package/docs/agent-tools.md +29 -4
- package/docs/browse-the-web.md +87 -5
- package/docs/chat-agents.md +124 -16
- package/docs/context.md +27 -0
- package/docs/durable-execution.md +2 -0
- package/docs/harnesses/pi.md +173 -0
- package/docs/human-in-the-loop.md +4 -0
- package/docs/index.md +3 -0
- package/docs/lifecycle.md +20 -4
- package/docs/models-pi-ai.md +325 -0
- package/docs/models.md +504 -0
- package/docs/resumable-streaming.md +2 -0
- package/docs/routing.md +13 -13
- package/docs/sessions.md +36 -1
- package/docs/state.md +1 -0
- package/docs/sub-agents.md +9 -0
- package/package.json +40 -2
- package/dist/agent-tools-y7zLfw4Q.js.map +0 -1
- package/dist/browser/ai.js.map +0 -1
- package/dist/client-C9DAjZIY.js.map +0 -1
- package/dist/client-tools-aIBO0Fk7.d.ts +0 -53
- package/dist/connector-CptFKzRh.js.map +0 -1
- package/dist/message-builder-BymO4N_D.js.map +0 -1
- package/dist/src-BNU3ZiJM.js.map +0 -1
- package/dist/streams-CCPRV6dt.js.map +0 -1
- package/dist/ws-chat-transport-rWwta645.js.map +0 -1
package/dist/react.js
CHANGED
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
import { camelCaseToKebabCase } from "./utils.js";
|
|
2
2
|
import "./types.js";
|
|
3
3
|
import { r as CAPNWEB_TRANSPORT_VALUE, t as CAPNWEB_TRANSPORT_QUERY } from "./transport-protocol-BxyngQ_R.js";
|
|
4
|
-
import {
|
|
4
|
+
import { d as boundCapnWebSocket, i as NativeCallQueue, l as nativeCall, n as AgentConnectionError, o as createCloseClassifier, s as createStubProxy, u as splitCallOptions } from "./client-4OlMIJx-.js";
|
|
5
5
|
import { buildSubAgentPathUnchecked } from "./sub-routing.js";
|
|
6
|
-
import {
|
|
6
|
+
import { SOCKET_ADDRESS_PENDING } from "./socket-address.js";
|
|
7
|
+
import { i as createAgentToolEventState, n as agentToolEventDedupeKey, r as applyAgentToolEvent } from "./agent-tools-CdJC-8Dc.js";
|
|
7
8
|
import { usePartySocket } from "partysocket/react";
|
|
8
9
|
import { use, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
9
10
|
//#region src/react.tsx
|
|
10
11
|
const queryCache = /* @__PURE__ */ new Map();
|
|
12
|
+
function socketDestinationKey(options) {
|
|
13
|
+
return JSON.stringify([
|
|
14
|
+
options.host ?? null,
|
|
15
|
+
options.basePath ?? null,
|
|
16
|
+
options.party ?? null,
|
|
17
|
+
options.prefix ?? null,
|
|
18
|
+
options.room ?? null,
|
|
19
|
+
options.path ?? null,
|
|
20
|
+
options.protocol ?? null,
|
|
21
|
+
options.protocols ?? null
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
|
+
function createReadyEntry() {
|
|
25
|
+
let resolvePromise;
|
|
26
|
+
const entry = {
|
|
27
|
+
promise: new Promise((r) => {
|
|
28
|
+
resolvePromise = r;
|
|
29
|
+
}),
|
|
30
|
+
resolved: false,
|
|
31
|
+
resolve: () => {
|
|
32
|
+
entry.resolved = true;
|
|
33
|
+
resolvePromise();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return entry;
|
|
37
|
+
}
|
|
38
|
+
/** The host `usePartySocket` connects to when none is given. */
|
|
39
|
+
function defaultSocketHost() {
|
|
40
|
+
return typeof window !== "undefined" ? window.location.host : "dummy-domain.com";
|
|
41
|
+
}
|
|
11
42
|
function createCacheKey(agentNamespace, name, subChainOrDeps, deps) {
|
|
12
43
|
if (deps === void 0) return JSON.stringify([
|
|
13
44
|
agentNamespace,
|
|
@@ -185,27 +216,36 @@ function useAgent(options) {
|
|
|
185
216
|
const connectionErrorAddressKeyRef = useRef(null);
|
|
186
217
|
const shouldReconnectOnCloseRef = useRef(shouldReconnectOnClose);
|
|
187
218
|
shouldReconnectOnCloseRef.current = shouldReconnectOnClose;
|
|
188
|
-
const
|
|
189
|
-
|
|
219
|
+
const maxRetriesRef = useRef(restOptions.maxRetries);
|
|
220
|
+
maxRetriesRef.current = restOptions.maxRetries;
|
|
221
|
+
const [closeClassifier] = useState(() => createCloseClassifier({
|
|
222
|
+
socket: () => socketRef.current,
|
|
223
|
+
shouldReconnectOnClose: () => shouldReconnectOnCloseRef.current,
|
|
224
|
+
maxRetries: () => maxRetriesRef.current
|
|
225
|
+
}));
|
|
226
|
+
const classifyReconnect = closeClassifier.shouldReconnectOnClose;
|
|
227
|
+
const [identity, setIdentity] = useState(() => ({
|
|
190
228
|
name: leafName,
|
|
191
229
|
agent: camelCaseToKebabCase(leafAgent),
|
|
192
|
-
identified: false
|
|
193
|
-
|
|
230
|
+
identified: false,
|
|
231
|
+
destination: null
|
|
232
|
+
}));
|
|
194
233
|
const previousIdentityRef = useRef({
|
|
195
234
|
name: null,
|
|
196
235
|
agent: null
|
|
197
236
|
});
|
|
198
|
-
const readyRef = useRef(
|
|
199
|
-
const
|
|
200
|
-
let
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
237
|
+
const readyRef = useRef(/* @__PURE__ */ new Map());
|
|
238
|
+
const readyFor = (destination) => {
|
|
239
|
+
let entry = readyRef.current.get(destination);
|
|
240
|
+
if (!entry) {
|
|
241
|
+
entry = createReadyEntry();
|
|
242
|
+
readyRef.current.set(destination, entry);
|
|
243
|
+
}
|
|
244
|
+
return entry;
|
|
245
|
+
};
|
|
246
|
+
const resetReady = (destination) => {
|
|
247
|
+
if (readyRef.current.get(destination)?.resolved !== false) readyRef.current.set(destination, createReadyEntry());
|
|
207
248
|
};
|
|
208
|
-
if (!readyRef.current) resetReady();
|
|
209
249
|
const mutableAgentRef = useRef(null);
|
|
210
250
|
const combinedPath = useMemo(() => buildSubPath(subChain, userPath), [subChain, userPath]);
|
|
211
251
|
const socketQuery = transport === "capnweb" ? {
|
|
@@ -238,8 +278,62 @@ function useAgent(options) {
|
|
|
238
278
|
combinedPath || null,
|
|
239
279
|
transport
|
|
240
280
|
]);
|
|
281
|
+
const destination = socketDestinationKey({
|
|
282
|
+
...socketOptions,
|
|
283
|
+
host: socketOptions.host || defaultSocketHost()
|
|
284
|
+
});
|
|
285
|
+
const seedDestinationRef = useRef(destination);
|
|
241
286
|
const visibleConnectionError = connectionErrorAddressKeyRef.current === addressKey ? connectionError : null;
|
|
242
287
|
connectionErrorRef.current = visibleConnectionError;
|
|
288
|
+
const connectProgressRef = useRef(/* @__PURE__ */ new WeakMap());
|
|
289
|
+
const connectProgress = (socket) => {
|
|
290
|
+
if (!socket) return {
|
|
291
|
+
stateSeen: false,
|
|
292
|
+
pendingIdentity: null
|
|
293
|
+
};
|
|
294
|
+
let progress = connectProgressRef.current.get(socket);
|
|
295
|
+
if (!progress) {
|
|
296
|
+
progress = {
|
|
297
|
+
stateSeen: false,
|
|
298
|
+
pendingIdentity: null
|
|
299
|
+
};
|
|
300
|
+
connectProgressRef.current.set(socket, progress);
|
|
301
|
+
}
|
|
302
|
+
return progress;
|
|
303
|
+
};
|
|
304
|
+
const applyIdentity = (newName, newAgent, identifiedSocket) => {
|
|
305
|
+
const oldName = previousIdentityRef.current.name;
|
|
306
|
+
const oldAgent = previousIdentityRef.current.agent;
|
|
307
|
+
const currentAgent = mutableAgentRef.current;
|
|
308
|
+
if (currentAgent) {
|
|
309
|
+
currentAgent.name = newName;
|
|
310
|
+
currentAgent.agent = newAgent;
|
|
311
|
+
currentAgent.identified = true;
|
|
312
|
+
}
|
|
313
|
+
const identifiedDestination = identifiedSocket ? socketDestinationKey(identifiedSocket.partySocketOptions) : null;
|
|
314
|
+
setIdentity({
|
|
315
|
+
name: newName,
|
|
316
|
+
agent: newAgent,
|
|
317
|
+
identified: true,
|
|
318
|
+
destination: identifiedDestination
|
|
319
|
+
});
|
|
320
|
+
if (identifiedDestination !== null) readyFor(identifiedDestination).resolve();
|
|
321
|
+
if (oldName !== null && oldAgent !== null && (oldName !== newName || oldAgent !== newAgent)) if (options.onIdentityChange) options.onIdentityChange(oldName, newName, oldAgent, newAgent);
|
|
322
|
+
else {
|
|
323
|
+
const agentChanged = oldAgent !== newAgent;
|
|
324
|
+
const nameChanged = oldName !== newName;
|
|
325
|
+
let changeDescription = "";
|
|
326
|
+
if (agentChanged && nameChanged) changeDescription = `agent "${oldAgent}" → "${newAgent}", instance "${oldName}" → "${newName}"`;
|
|
327
|
+
else if (agentChanged) changeDescription = `agent "${oldAgent}" → "${newAgent}"`;
|
|
328
|
+
else changeDescription = `instance "${oldName}" → "${newName}"`;
|
|
329
|
+
console.warn(`[agents] Identity changed on reconnect: ${changeDescription}. This can happen with server-side routing (e.g., basePath with getAgentByName) where the instance is determined by auth/session. Provide onIdentityChange callback to handle this explicitly, or ignore if this is expected for your routing pattern.`);
|
|
330
|
+
}
|
|
331
|
+
previousIdentityRef.current = {
|
|
332
|
+
name: newName,
|
|
333
|
+
agent: newAgent
|
|
334
|
+
};
|
|
335
|
+
options.onIdentity?.(newName, newAgent);
|
|
336
|
+
};
|
|
243
337
|
const agent = usePartySocket({
|
|
244
338
|
...socketOptions,
|
|
245
339
|
enabled: socketEnabled,
|
|
@@ -258,42 +352,32 @@ function useAgent(options) {
|
|
|
258
352
|
return options.onMessage?.(message);
|
|
259
353
|
}
|
|
260
354
|
if (parsedMessage.type === "cf_agent_identity") {
|
|
261
|
-
const
|
|
262
|
-
const oldAgent = previousIdentityRef.current.agent;
|
|
355
|
+
const identifiedSocket = message.target ?? socketRef.current;
|
|
263
356
|
const newName = parsedMessage.name;
|
|
264
357
|
const newAgent = parsedMessage.agent;
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
currentAgent.identified = true;
|
|
270
|
-
}
|
|
271
|
-
setIdentity({
|
|
272
|
-
name: newName,
|
|
273
|
-
agent: newAgent,
|
|
274
|
-
identified: true
|
|
275
|
-
});
|
|
276
|
-
readyRef.current?.resolve();
|
|
277
|
-
if (oldName !== null && oldAgent !== null && (oldName !== newName || oldAgent !== newAgent)) if (options.onIdentityChange) options.onIdentityChange(oldName, newName, oldAgent, newAgent);
|
|
278
|
-
else {
|
|
279
|
-
const agentChanged = oldAgent !== newAgent;
|
|
280
|
-
const nameChanged = oldName !== newName;
|
|
281
|
-
let changeDescription = "";
|
|
282
|
-
if (agentChanged && nameChanged) changeDescription = `agent "${oldAgent}" → "${newAgent}", instance "${oldName}" → "${newName}"`;
|
|
283
|
-
else if (agentChanged) changeDescription = `agent "${oldAgent}" → "${newAgent}"`;
|
|
284
|
-
else changeDescription = `instance "${oldName}" → "${newName}"`;
|
|
285
|
-
console.warn(`[agents] Identity changed on reconnect: ${changeDescription}. This can happen with server-side routing (e.g., basePath with getAgentByName) where the instance is determined by auth/session. Provide onIdentityChange callback to handle this explicitly, or ignore if this is expected for your routing pattern.`);
|
|
358
|
+
const progress = connectProgress(identifiedSocket);
|
|
359
|
+
if (parsedMessage.stateFollows === true && !progress.stateSeen) {
|
|
360
|
+
progress.pendingIdentity = [newName, newAgent];
|
|
361
|
+
return;
|
|
286
362
|
}
|
|
287
|
-
|
|
288
|
-
name: newName,
|
|
289
|
-
agent: newAgent
|
|
290
|
-
};
|
|
291
|
-
options.onIdentity?.(newName, newAgent);
|
|
363
|
+
applyIdentity(newName, newAgent, identifiedSocket);
|
|
292
364
|
return;
|
|
293
365
|
}
|
|
294
366
|
if (parsedMessage.type === "cf_agent_state") {
|
|
295
367
|
setAgentState(parsedMessage.state);
|
|
296
|
-
|
|
368
|
+
if (mutableAgentRef.current) mutableAgentRef.current.state = parsedMessage.state;
|
|
369
|
+
const stateSocket = message.target ?? socketRef.current;
|
|
370
|
+
try {
|
|
371
|
+
options.onStateUpdate?.(parsedMessage.state, "server");
|
|
372
|
+
} finally {
|
|
373
|
+
const progress = connectProgress(stateSocket);
|
|
374
|
+
progress.stateSeen = true;
|
|
375
|
+
const pending = progress.pendingIdentity;
|
|
376
|
+
if (pending) {
|
|
377
|
+
progress.pendingIdentity = null;
|
|
378
|
+
applyIdentity(pending[0], pending[1], stateSocket);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
297
381
|
return;
|
|
298
382
|
}
|
|
299
383
|
if (parsedMessage.type === "cf_agent_state_error") {
|
|
@@ -337,24 +421,26 @@ function useAgent(options) {
|
|
|
337
421
|
onClose: (event) => {
|
|
338
422
|
const closedSocket = event.target ?? socketRef.current;
|
|
339
423
|
const isCurrentSocket = closedSocket === socketRef.current;
|
|
340
|
-
const
|
|
424
|
+
const finalClose = closeClassifier.takeFinalClose();
|
|
425
|
+
if (closedSocket) connectProgressRef.current.delete(closedSocket);
|
|
426
|
+
const reconnecting = !!closedSocket?.shouldReconnect && !finalClose;
|
|
341
427
|
if (closedSocket) {
|
|
342
428
|
rejectCallsSentOn(closedSocket, "Connection closed");
|
|
343
|
-
if (isCurrentSocket && !
|
|
429
|
+
if (isCurrentSocket && !reconnecting) rejectQueuedCalls("Connection closed");
|
|
344
430
|
}
|
|
345
431
|
if (isCurrentSocket) {
|
|
346
|
-
resetReady();
|
|
432
|
+
if (closedSocket) resetReady(socketDestinationKey(closedSocket.partySocketOptions));
|
|
347
433
|
if (mutableAgentRef.current) mutableAgentRef.current.identified = false;
|
|
348
434
|
setIdentity((prev) => ({
|
|
349
435
|
...prev,
|
|
350
436
|
identified: false
|
|
351
437
|
}));
|
|
352
|
-
if (
|
|
438
|
+
if (reconnecting) {
|
|
353
439
|
if (isAsyncQuery) setAwaitingQueryRefresh(true);
|
|
354
440
|
deleteCacheEntry(cacheKeyRef.current);
|
|
355
441
|
setCacheInvalidatedAt(Date.now());
|
|
356
442
|
}
|
|
357
|
-
if (
|
|
443
|
+
if (finalClose) {
|
|
358
444
|
const error = new AgentConnectionError(event);
|
|
359
445
|
connectionErrorAddressKeyRef.current = addressKey;
|
|
360
446
|
setConnectionError(error);
|
|
@@ -365,28 +451,41 @@ function useAgent(options) {
|
|
|
365
451
|
}
|
|
366
452
|
});
|
|
367
453
|
socketRef.current = agent;
|
|
454
|
+
const socketAddressPending = socketDestinationKey(agent.partySocketOptions) !== destination;
|
|
368
455
|
const prevSocketRef = useRef(null);
|
|
369
456
|
const prevAddressKeyRef = useRef(addressKey);
|
|
457
|
+
const prevDestinationRef = useRef(destination);
|
|
370
458
|
useEffect(() => {
|
|
371
459
|
const prev = prevSocketRef.current;
|
|
372
460
|
prevSocketRef.current = agent;
|
|
373
461
|
const prevAddress = prevAddressKeyRef.current;
|
|
374
462
|
prevAddressKeyRef.current = addressKey;
|
|
463
|
+
const prevDestination = prevDestinationRef.current;
|
|
464
|
+
prevDestinationRef.current = destination;
|
|
465
|
+
if (prevDestination !== destination) previousIdentityRef.current = {
|
|
466
|
+
name: null,
|
|
467
|
+
agent: null
|
|
468
|
+
};
|
|
375
469
|
if (prevAddress !== addressKey) {
|
|
376
470
|
connectionErrorAddressKeyRef.current = null;
|
|
377
471
|
setConnectionError(null);
|
|
378
472
|
rejectQueuedCalls("Call discarded: the agent address changed before the request could be sent");
|
|
379
473
|
}
|
|
474
|
+
for (const [key, entry] of readyRef.current) if (key !== destination && entry.resolved) readyRef.current.delete(key);
|
|
380
475
|
if (prev && prev !== agent) {
|
|
381
476
|
rejectCallsSentOn(prev, "Connection closed");
|
|
382
|
-
resetReady();
|
|
477
|
+
resetReady(socketDestinationKey(agent.partySocketOptions));
|
|
383
478
|
if (mutableAgentRef.current) mutableAgentRef.current.identified = false;
|
|
384
479
|
setIdentity((current) => current.identified ? {
|
|
385
480
|
...current,
|
|
386
481
|
identified: false
|
|
387
482
|
} : current);
|
|
388
483
|
}
|
|
389
|
-
}, [
|
|
484
|
+
}, [
|
|
485
|
+
agent,
|
|
486
|
+
addressKey,
|
|
487
|
+
destination
|
|
488
|
+
]);
|
|
390
489
|
const call = useCallback((method, args = [], options) => {
|
|
391
490
|
if (transportRef.current === "capnweb") {
|
|
392
491
|
const native = capnWebRef.current;
|
|
@@ -438,32 +537,29 @@ function useAgent(options) {
|
|
|
438
537
|
state: newState,
|
|
439
538
|
type: "cf_agent_state"
|
|
440
539
|
}));
|
|
540
|
+
if (mutableAgentRef.current) mutableAgentRef.current.state = newState;
|
|
441
541
|
setAgentState(newState);
|
|
442
542
|
options.onStateUpdate?.(newState, "client");
|
|
443
543
|
};
|
|
444
544
|
agent.call = call;
|
|
445
|
-
|
|
446
|
-
agent.
|
|
545
|
+
const identityIsCurrent = !!options.basePath || (identity.destination ?? seedDestinationRef.current) === destination;
|
|
546
|
+
agent.agent = identityIsCurrent ? identity.agent : camelCaseToKebabCase(leafAgent);
|
|
547
|
+
agent.name = identityIsCurrent ? identity.name : leafName;
|
|
447
548
|
agent.path = fullPath;
|
|
448
|
-
agent.identified = identity.identified;
|
|
449
|
-
agent.ready =
|
|
549
|
+
agent.identified = identityIsCurrent && identity.identified;
|
|
550
|
+
agent.ready = readyFor(destination).promise;
|
|
450
551
|
agent.state = agentState;
|
|
451
552
|
agent.connectionError = visibleConnectionError;
|
|
452
553
|
mutableAgentRef.current = agent;
|
|
453
554
|
agent.stub = useMemo(() => createStubProxy(call), [call]);
|
|
555
|
+
agent[SOCKET_ADDRESS_PENDING] = socketAddressPending;
|
|
454
556
|
agent.getHttpUrl = () => {
|
|
557
|
+
if (socketAddressPending) return "";
|
|
455
558
|
return (agent._url || agent._pkurl || "").replace("ws://", "http://").replace("wss://", "https://");
|
|
456
559
|
};
|
|
457
560
|
if (identity.agent !== identity.agent.toLowerCase()) console.warn("Agent name: " + identity.agent + " should probably be in lowercase. Received: " + identity.agent);
|
|
458
561
|
return agent;
|
|
459
562
|
}
|
|
460
|
-
function agentToolDedupeKey(message) {
|
|
461
|
-
return [
|
|
462
|
-
message.parentToolCallId ?? "",
|
|
463
|
-
message.event.runId,
|
|
464
|
-
String(message.sequence)
|
|
465
|
-
].join("\0");
|
|
466
|
-
}
|
|
467
563
|
function useAgentToolEvents(options) {
|
|
468
564
|
const { agent } = options;
|
|
469
565
|
const [state, setState] = useState(() => createAgentToolEventState());
|
|
@@ -478,7 +574,7 @@ function useAgentToolEvents(options) {
|
|
|
478
574
|
return;
|
|
479
575
|
}
|
|
480
576
|
if (message.type !== "agent-tool-event") return;
|
|
481
|
-
const key =
|
|
577
|
+
const key = agentToolEventDedupeKey(message);
|
|
482
578
|
if (seenRef.current.has(key)) return;
|
|
483
579
|
seenRef.current.add(key);
|
|
484
580
|
setState((prev) => applyAgentToolEvent(prev, message));
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["AgentConnectionErrorCtor"],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useState, useEffect } from \"react\";\nimport type { MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type {\n AgentConnectionError,\n AgentPromiseReturnType,\n AgentStub,\n CallOptions,\n OptionalAgentMethods,\n RequiredAgentMethods,\n StreamOptions,\n UntypedAgentStub\n} from \"./client\";\nimport type { ClientParameters } from \"./serializable\";\nimport {\n createStubProxy,\n DEFAULT_CALL_TIMEOUT_MS,\n AgentConnectionError as AgentConnectionErrorCtor,\n isTerminalCloseEvent,\n nativeCall,\n NativeCallQueue,\n splitCallOptions\n} from \"./client\";\nimport {\n boundCapnWebSocket,\n type CapnWebSocket\n} from \"./websockets/capnweb-socket\";\nimport {\n CAPNWEB_TRANSPORT_QUERY,\n CAPNWEB_TRANSPORT_VALUE,\n type AgentTransport\n} from \"./websockets/transport-protocol\";\nimport { buildSubAgentPathUnchecked } from \"./sub-routing\";\nimport { camelCaseToKebabCase } from \"./utils\";\nimport { MessageType } from \"./types\";\n\nexport type { AgentTransport } from \"./websockets/transport-protocol\";\nimport {\n applyAgentToolEvent,\n createAgentToolEventState,\n type AgentToolEventMessage,\n type AgentToolEventState,\n type AgentToolRunPart,\n type AgentToolRunState\n} from \"./chat/agent-tools\";\n\ntype QueryObject = Record<string, string | null>;\ntype TerminalReconnectOptions = {\n shouldReconnectOnClose?: (event: CloseEvent) => boolean;\n};\n\ninterface CacheEntry {\n promise: Promise<QueryObject>;\n expiresAt: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n subChainOrDeps: ReadonlyArray<{ agent: string; name: string }> | unknown[],\n deps?: unknown[]\n): string {\n // Backwards-compatible overload: if called with 3 args, the third\n // argument is `deps` and `subChain` defaults to empty. With 4 args,\n // the third is the sub-chain. This keeps existing callers (and\n // the `_testUtils` surface) working while letting new callers\n // include the nested chain in the cache key.\n //\n // Empty sub-chain must produce the same key as the old 3-arg\n // form, so nested-addressing code can opt-in without invalidating\n // existing caches.\n if (deps === undefined) {\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n ...(subChainOrDeps as unknown[])\n ]);\n }\n const subChain = subChainOrDeps as ReadonlyArray<{\n agent: string;\n name: string;\n }>;\n if (subChain.length === 0) {\n return JSON.stringify([agentNamespace, name || \"default\", ...deps]);\n }\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n subChain.map((s) => [s.agent, s.name]),\n ...deps\n ]);\n}\n\n/** Build a URL path tail `/sub/{agent-kebab}/{name}/...` from a sub chain. */\nfunction buildSubPath(\n subChain: ReadonlyArray<{ agent: string; name: string }>,\n extraPath?: string\n): string {\n return buildSubAgentPathUnchecked(\n subChain.map((step) => ({ className: step.agent, name: step.name })),\n extraPath\n );\n}\n\nfunction getCacheEntry(key: string): CacheEntry | undefined {\n const entry = queryCache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() >= entry.expiresAt) {\n queryCache.delete(key);\n return undefined;\n }\n\n return entry;\n}\n\nfunction setCacheEntry(\n key: string,\n promise: Promise<QueryObject>,\n cacheTtl: number\n): CacheEntry {\n const entry: CacheEntry = {\n promise,\n expiresAt: Date.now() + cacheTtl\n };\n queryCache.set(key, entry);\n return entry;\n}\n\nfunction deleteCacheEntry(key: string): void {\n queryCache.delete(key);\n}\n\n// Export for testing purposes\nexport const _testUtils = {\n queryCache,\n setCacheEntry,\n getCacheEntry,\n deleteCacheEntry,\n clearCache: () => queryCache.clear(),\n createStubProxy,\n createCacheKey\n};\n\n/**\n * Options for the useAgent hook\n * @template State Type of the Agent's state\n */\nexport type UseAgentOptions<State = unknown> = Omit<\n Parameters<typeof usePartySocket>[0],\n \"party\" | \"room\" | \"query\"\n> &\n TerminalReconnectOptions & {\n /** Name of the agent to connect to (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the client connects to this path directly.\n * Server must handle routing manually (e.g., with getAgentByName + fetch).\n * @example\n * // Client connects to /user, server routes based on session\n * useAgent({ agent: \"UserAgent\", basePath: \"user\" })\n */\n basePath?: string;\n /**\n * Wire the connection travels on. `\"cf-websocket\"` (default) is a\n * hibernating WebSocket where `call()` sends JSON `rpc` frames.\n * `\"capnweb\"` carries protocol frames over a Cap'n Web session whose\n * root also serves the host's `callables` natively, so `call()` and\n * `stub` invoke them directly and an `RpcTarget` result is a live stub.\n * The Durable Object stays in memory while a capnweb connection is open.\n * Identity, state, and reconnection behave the same on both.\n * @experimental The `\"capnweb\"` transport is experimental.\n */\n transport?: AgentTransport;\n /** Query parameters - can be static object or async function */\n query?: QueryObject | (() => Promise<QueryObject>);\n /** Dependencies for async query caching */\n queryDeps?: unknown[];\n /** Cache TTL in milliseconds for auth tokens/time-sensitive data */\n cacheTtl?: number;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when a state update fails (e.g., connection is readonly) */\n onStateUpdateError?: (error: string) => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n /**\n * Called when the server sends the agent's identity on connect.\n * Useful when using basePath, as the actual instance name is determined server-side.\n * @param name The actual agent instance name\n * @param agent The agent class name (kebab-case)\n */\n onIdentity?: (name: string, agent: string) => void;\n /**\n * Called when identity changes on reconnect (different instance than before).\n * If not provided and identity changes, a warning will be logged.\n * @param oldName Previous instance name\n * @param newName New instance name\n * @param oldAgent Previous agent class name\n * @param newAgent New agent class name\n */\n onIdentityChange?: (\n oldName: string,\n newName: string,\n oldAgent: string,\n newAgent: string\n ) => void;\n /**\n * Additional path to append to the URL.\n * Works with both standard routing and basePath.\n * @example\n * // With basePath: /user/settings\n * { basePath: \"user\", path: \"settings\" }\n * // Standard: /agents/my-agent/room/settings\n * { agent: \"MyAgent\", name: \"room\", path: \"settings\" }\n */\n path?: string;\n /**\n * Connect to a sub-agent (facet) via its parent. Flat array,\n * root-first. Each step addresses one parent↔child hop.\n *\n * The hook's returned `.agent` / `.name` report the **leaf**\n * identity (the deepest entry in `sub`), so downstream hooks\n * like `useAgentChat` see the child they actually talk to.\n * `.path` exposes the full chain for observability, deep links,\n * and reconnect keying.\n *\n * @example\n * ```ts\n * // Two-level nesting: Inbox (Alice) → Chat (abc)\n * useAgent({\n * agent: \"inbox\", name: userId,\n * sub: [{ agent: \"chat\", name: chatId }]\n * });\n *\n * // Three-level: tenant → inbox → chat\n * useAgent({\n * agent: \"tenant\", name: tenantId,\n * sub: [\n * { agent: \"inbox\", name: userId },\n * { agent: \"chat\", name: chatId }\n * ]\n * });\n * ```\n *\n * @experimental The API surface may change before stabilizing.\n */\n sub?: ReadonlyArray<{ agent: string; name: string }>;\n /**\n * Default timeout (in milliseconds) applied to non-streaming `call()`s\n * that don't pass an explicit `timeout`. Acts as a backstop so calls\n * whose response is lost (e.g. the connection is replaced mid-flight)\n * reject instead of hanging forever.\n *\n * Defaults to 30 000 ms. Set to `0` to disable the default timeout.\n * Streaming calls never get a default timeout (long-lived streams are\n * legitimate); pass an explicit `timeout` to bound them.\n */\n defaultCallTimeout?: number;\n /** Called when the connection closes with a terminal code and will not reconnect. */\n onConnectionError?: (error: AgentConnectionError) => void;\n };\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: ClientParameters<OptionalAgentMethods<AgentT>[K]>,\n options?: CallOptions | StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: ClientParameters<RequiredAgentMethods<AgentT>[K]>,\n options?: CallOptions | StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype AgentMethodCall<AgentT> = OptionalArgsAgentMethodCall<AgentT> &\n RequiredArgsAgentMethodCall<AgentT>;\n\ntype UntypedAgentMethodCall = <T = unknown>(\n method: string,\n args?: unknown[],\n options?: CallOptions | StreamOptions\n) => Promise<T>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n /** Full root-first address chain, including leaf. Single entry when `sub` isn't set. */\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n getHttpUrl: () => string;\n};\nexport function useAgent<State>(options: UseAgentOptions<unknown>): Omit<\n PartySocket,\n \"path\"\n> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n // NOTE: `path` is destructured out (as `userPath`) so it does NOT\n // end up in `restOptions`. Spreading `restOptions` after the\n // computed `path: combinedPath` would otherwise let the user's raw\n // `path` overwrite the combined sub-agent URL, dropping every\n // `/sub/{child}/{name}` segment on the way to the socket.\n const {\n query,\n queryDeps,\n cacheTtl,\n sub: subOption,\n path: userPath,\n defaultCallTimeout,\n onConnectionError,\n shouldReconnectOnClose,\n transport = \"cf-websocket\",\n ...restOptions\n } = options;\n // PartySocket keeps reconnection, buffering, and backoff; the transport\n // only swaps the socket class it instantiates. The bound subclass hands\n // the hook each live Cap'n Web socket so `call()` can invoke natively.\n const capnWebRef = useRef<CapnWebSocket | null>(null);\n const transportRef = useRef(transport);\n transportRef.current = transport;\n // Native calls issued before the Cap'n Web socket is open wait here\n // instead of degrading to JSON frames; flushed on open, rejected on a\n // permanent close.\n const nativeQueueRef = useRef(new NativeCallQueue());\n const socketClass = useMemo(\n () =>\n transport === \"capnweb\"\n ? {\n WebSocket: boundCapnWebSocket((socket) => {\n capnWebRef.current = socket;\n })\n }\n : {},\n [transport]\n );\n\n const subChain = useMemo(\n () => (subOption ?? []).map((s) => ({ agent: s.agent, name: s.name })),\n // Stable serialization — deep changes re-memoize.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(subOption ?? [])]\n );\n\n // The \"leaf\" is the deepest entry in the chain; it's what\n // downstream code (useAgentChat etc.) should see as the\n // authoritative identity.\n const leafAgent =\n subChain.length > 0 ? subChain[subChain.length - 1].agent : options.agent;\n const leafName =\n subChain.length > 0\n ? subChain[subChain.length - 1].name\n : options.name || \"default\";\n\n // Full root-first chain, including the leaf. Exposed as `.path`\n // and used for cache keying so nested sessions with the same leaf\n // name don't collide.\n const fullPath = useMemo(\n () => [\n { agent: options.agent, name: options.name || \"default\" },\n ...subChain\n ],\n [options.agent, options.name, subChain]\n );\n\n // Keep track of pending RPC calls.\n //\n // Each entry is tagged with the socket the request was transmitted on\n // (`sentOn`). Requests are only handed to a socket once it's OPEN —\n // until then they stay queued here (`sentOn: null`). This matters\n // because `usePartySocket` *replaces* the socket object whenever\n // connection options change (async query refresh, path change, etc.):\n // anything buffered inside a replaced socket is lost forever, and a\n // call transmitted on a replaced socket can never receive its\n // response. Tagging lets us:\n // - flush still-queued requests on whichever socket connects next\n // (safe: they were never transmitted, so no double-execution risk)\n // - reject calls transmitted on a socket that closed or was replaced\n // (their response can never arrive)\n // - avoid rejecting calls in flight on the *new* socket when a stale\n // close event from an old socket trickles in\n const pendingCallsRef = useRef(\n new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n timeoutId?: ReturnType<typeof setTimeout>;\n /** Serialized RPC request, kept so it can be (re)transmitted */\n request: string;\n /** Socket the request was transmitted on; null while queued */\n sentOn: PartySocket | null;\n }\n >()\n );\n\n // Always points at the socket from the latest render. `call`,\n // `setState`, and the queue-flushing logic go through this ref so\n // that stale `agent` references held by old effect closures still\n // route their traffic to the live socket instead of a dead one.\n const socketRef = useRef<PartySocket | null>(null);\n\n const defaultCallTimeoutRef = useRef(\n defaultCallTimeout ?? DEFAULT_CALL_TIMEOUT_MS\n );\n defaultCallTimeoutRef.current = defaultCallTimeout ?? DEFAULT_CALL_TIMEOUT_MS;\n\n /** Reject (and remove) every pending call transmitted on `socket`. */\n const rejectCallsSentOn = (socket: PartySocket, reason: string) => {\n const error = new Error(reason);\n for (const [id, pending] of pendingCallsRef.current) {\n if (pending.sentOn === socket) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pendingCallsRef.current.delete(id);\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n }\n };\n\n /** Transmit queued (never-sent) calls if the live socket is open. */\n const flushQueuedCalls = () => {\n const socket = socketRef.current;\n if (!socket || socket.readyState !== socket.OPEN) return;\n for (const pending of pendingCallsRef.current.values()) {\n if (pending.sentOn === null) {\n socket.send(pending.request);\n pending.sentOn = socket;\n }\n }\n const native =\n transportRef.current === \"capnweb\" ? capnWebRef.current : null;\n if (native) nativeQueueRef.current.flush(native);\n };\n\n /** Reject (and remove) every still-queued (never transmitted) call. */\n const rejectQueuedCalls = (reason: string) => {\n nativeQueueRef.current.rejectAll(reason);\n const error = new Error(reason);\n for (const [id, pending] of pendingCallsRef.current) {\n if (pending.sentOn === null) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pendingCallsRef.current.delete(id);\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n }\n };\n\n const cacheKey = useMemo(\n () =>\n createCacheKey(agentNamespace, options.name, subChain, queryDeps || []),\n [agentNamespace, options.name, subChain, queryDeps]\n );\n\n // Track current cache key in a ref for use in onClose handler.\n // This ensures we invalidate the correct cache entry when the connection closes,\n // even if the component re-renders with different props before onClose fires.\n // We update synchronously during render (not in useEffect) to avoid race\n // conditions where onClose could fire before the effect runs.\n const cacheKeyRef = useRef(cacheKey);\n cacheKeyRef.current = cacheKey;\n\n const ttl = cacheTtl ?? 5 * 60 * 1000;\n\n // Track cache invalidation to force re-render when TTL expires\n const [cacheInvalidatedAt, setCacheInvalidatedAt] = useState<number>(0);\n\n // Disable socket while waiting for async query to refresh after disconnect\n const isAsyncQuery = query && typeof query === \"function\";\n const [awaitingQueryRefresh, setAwaitingQueryRefresh] = useState(false);\n\n // Get or create the query promise\n const queryPromise = useMemo(() => {\n // Re-run when cache is invalidated after TTL expiry\n void cacheInvalidatedAt;\n\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n // Always check cache first to deduplicate concurrent requests\n const cached = getCacheEntry(cacheKey);\n if (cached) {\n return cached.promise;\n }\n\n // Create new promise\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n deleteCacheEntry(cacheKey);\n throw error;\n });\n\n // Always cache to deduplicate concurrent requests\n setCacheEntry(cacheKey, promise, ttl);\n\n return promise;\n }, [cacheKey, query, options.agent, ttl, cacheInvalidatedAt]);\n\n // Schedule cache invalidation when TTL expires\n useEffect(() => {\n if (!queryPromise || ttl <= 0) return;\n\n const entry = getCacheEntry(cacheKey);\n if (!entry) return;\n\n const timeUntilExpiry = entry.expiresAt - Date.now();\n\n // Always set a timer (with min 0ms) to ensure cleanup function is returned\n const timer = setTimeout(\n () => {\n deleteCacheEntry(cacheKey);\n setCacheInvalidatedAt(Date.now());\n },\n Math.max(0, timeUntilExpiry)\n );\n\n return () => clearTimeout(timer);\n }, [cacheKey, queryPromise, ttl]);\n\n let resolvedQuery: QueryObject | undefined;\n\n if (query) {\n if (typeof query === \"function\") {\n // Use React's use() to resolve the promise\n const queryResult = use(queryPromise!);\n\n // Check for non-primitive values and warn\n if (queryResult) {\n for (const [key, value] of Object.entries(queryResult)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n console.warn(\n `[useAgent] Query parameter \"${key}\" is an object and will be converted to \"[object Object]\". ` +\n \"Query parameters should be string, number, boolean, or null.\"\n );\n }\n }\n resolvedQuery = queryResult;\n }\n } else {\n // Sync query - use directly\n resolvedQuery = query;\n }\n }\n\n // Re-enable socket after async query resolves\n useEffect(() => {\n if (awaitingQueryRefresh && resolvedQuery !== undefined) {\n setAwaitingQueryRefresh(false);\n }\n }, [awaitingQueryRefresh, resolvedQuery]);\n\n // Track agent state for reactivity — updated on server broadcasts and client setState\n const [agentState, setAgentState] = useState<State | undefined>(undefined);\n const [connectionError, setConnectionError] =\n useState<AgentConnectionError | null>(null);\n const connectionErrorRef = useRef<AgentConnectionError | null>(null);\n const connectionErrorAddressKeyRef = useRef<string | null>(null);\n const shouldReconnectOnCloseRef = useRef(shouldReconnectOnClose);\n shouldReconnectOnCloseRef.current = shouldReconnectOnClose;\n const classifyReconnect = useCallback(\n (event: CloseEvent) =>\n (shouldReconnectOnCloseRef.current?.(event) ?? true) &&\n !isTerminalCloseEvent(event),\n []\n );\n\n // Store identity in React state for reactivity. Seed with the\n // leaf's address — what the server will echo back in\n // `cf_agent_identity`.\n const [identity, setIdentity] = useState({\n name: leafName,\n agent: camelCaseToKebabCase(leafAgent),\n identified: false\n });\n\n // Track previous identity for change detection\n const previousIdentityRef = useRef<{\n name: string | null;\n agent: string | null;\n }>({ name: null, agent: null });\n\n // Ready promise - resolves when identity is received, resets on close\n const readyRef = useRef<\n { promise: Promise<void>; resolve: () => void } | undefined\n >(undefined);\n\n const resetReady = () => {\n let resolve: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n readyRef.current = { promise, resolve: resolve! };\n };\n\n if (!readyRef.current) {\n resetReady();\n }\n\n const mutableAgentRef = useRef<{\n agent: string;\n name: string;\n identified: boolean;\n } | null>(null);\n\n // Combine the sub-agent chain with the user-provided `path`.\n // Order matters: `/sub/{child}/{name}/...` comes before `path` so\n // the server sees the hierarchy it expects.\n const combinedPath = useMemo(\n () => buildSubPath(subChain, userPath),\n [subChain, userPath]\n );\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n // The transport rides in the query too, so it is part of PartySocket's\n // socket key: changing `transport` reconnects on the new wire.\n const socketQuery =\n transport === \"capnweb\"\n ? { ...resolvedQuery, [CAPNWEB_TRANSPORT_QUERY]: CAPNWEB_TRANSPORT_VALUE }\n : resolvedQuery;\n\n const socketOptions = options.basePath\n ? {\n basePath: options.basePath,\n path: combinedPath || undefined,\n query: socketQuery,\n ...restOptions,\n ...socketClass,\n shouldReconnectOnClose: classifyReconnect\n }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: combinedPath || undefined,\n query: socketQuery,\n ...restOptions,\n ...socketClass,\n shouldReconnectOnClose: classifyReconnect\n };\n\n const socketEnabled = !awaitingQueryRefresh && (restOptions.enabled ?? true);\n\n // Identifies *which agent instance* this hook is addressing. Queued\n // (never-transmitted) RPC calls are only safe to flush onto a later\n // socket if it still points at the same instance — a call composed for\n // agent \"alpha\" must not execute on agent \"beta\" just because the\n // `name` prop changed while the call was waiting for a connection.\n // Credentials (query params) are deliberately excluded: a token\n // refresh doesn't change where calls go.\n // The wire is part of the address: queued calls belong to a transport as\n // much as to an instance, so switching `transport` rejects them rather\n // than flushing a native call onto a JSON socket or vice versa.\n const addressKey = JSON.stringify([\n options.host ?? null,\n options.basePath ?? null,\n agentNamespace,\n options.name || \"default\",\n combinedPath || null,\n transport\n ]);\n const visibleConnectionError =\n connectionErrorAddressKeyRef.current === addressKey\n ? connectionError\n : null;\n connectionErrorRef.current = visibleConnectionError;\n\n const agent = usePartySocket({\n ...socketOptions,\n enabled: socketEnabled,\n onOpen: (event: Event) => {\n connectionErrorAddressKeyRef.current = null;\n setConnectionError(null);\n // The socket is open: transmit any RPC requests that were issued\n // while disconnected (or while a previous socket was being\n // replaced). They were never handed to a socket before, so this\n // cannot double-execute anything server-side.\n flushQueuedCalls();\n options.onOpen?.(event);\n },\n onMessage: (message) => {\n if (typeof message.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(message.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return options.onMessage?.(message);\n }\n if (parsedMessage.type === MessageType.CF_AGENT_IDENTITY) {\n const oldName = previousIdentityRef.current.name;\n const oldAgent = previousIdentityRef.current.agent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n const currentAgent = mutableAgentRef.current;\n if (currentAgent) {\n currentAgent.name = newName;\n currentAgent.agent = newAgent;\n currentAgent.identified = true;\n }\n\n // Update reactive state (triggers re-render)\n setIdentity({ name: newName, agent: newAgent, identified: true });\n\n // Resolve ready promise\n readyRef.current?.resolve();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (options.onIdentityChange) {\n options.onIdentityChange(oldName, newName, oldAgent, newAgent);\n } else {\n const agentChanged = oldAgent !== newAgent;\n const nameChanged = oldName !== newName;\n let changeDescription = \"\";\n if (agentChanged && nameChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\", instance \"${oldName}\" → \"${newName}\"`;\n } else if (agentChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\"`;\n } else {\n changeDescription = `instance \"${oldName}\" → \"${newName}\"`;\n }\n console.warn(\n `[agents] Identity changed on reconnect: ${changeDescription}. ` +\n \"This can happen with server-side routing (e.g., basePath with getAgentByName) \" +\n \"where the instance is determined by auth/session. \" +\n \"Provide onIdentityChange callback to handle this explicitly, \" +\n \"or ignore if this is expected for your routing pattern.\"\n );\n }\n }\n\n // Track for next change detection\n previousIdentityRef.current = { name: newName, agent: newAgent };\n\n // Call onIdentity callback\n options.onIdentity?.(newName, newAgent);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n setAgentState(parsedMessage.state as State);\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {\n options.onStateUpdateError?.(parsedMessage.error as string);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_MCP_SERVERS) {\n options.onMcpUpdate?.(parsedMessage.mcp as MCPServersState);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = pendingCallsRef.current.get(response.id);\n if (!pending) {\n console.warn(\n `[useAgent] Discarded an RPC response with no matching pending call (id \"${response.id}\"). ` +\n \"The call likely timed out or was rejected when its connection closed before the response arrived.\"\n );\n return;\n }\n\n if (!response.success) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.reject(new Error(response.error));\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onError?.(response.error);\n return;\n }\n\n // Handle streaming responses\n if (\"done\" in response) {\n if (response.done) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onDone?.(response.result);\n } else {\n pending.stream?.onChunk?.(response.result);\n }\n } else {\n // Non-streaming response\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n },\n onClose: (event: CloseEvent) => {\n // Identify which socket actually closed. Close events are\n // dispatched asynchronously, so a close from an old socket that\n // was just replaced can arrive while a new socket is already\n // connecting (or connected). `event.target` is the PartySocket\n // that dispatched the event; fall back to the live socket if the\n // environment doesn't populate it.\n const closedSocket =\n (event.target as PartySocket | null) ?? socketRef.current;\n const isCurrentSocket = closedSocket === socketRef.current;\n const terminalClose = isTerminalCloseEvent(event);\n\n // Calls transmitted on the closed socket can never receive their\n // response — reject them. Calls still queued (never transmitted)\n // stay pending and are flushed when a socket next opens; calls\n // in flight on a *different* (newer) socket are untouched.\n if (closedSocket) {\n rejectCallsSentOn(closedSocket, \"Connection closed\");\n if (isCurrentSocket && !closedSocket.shouldReconnect) {\n rejectQueuedCalls(\"Connection closed\");\n }\n }\n\n if (isCurrentSocket) {\n // Reset ready state for next connection\n resetReady();\n if (mutableAgentRef.current) {\n mutableAgentRef.current.identified = false;\n }\n setIdentity((prev) => ({ ...prev, identified: false }));\n\n if (closedSocket?.shouldReconnect) {\n // Pause reconnection for async queries until fresh query params are ready.\n if (isAsyncQuery) {\n setAwaitingQueryRefresh(true);\n }\n\n // Invalidate cache and trigger re-render to fetch fresh query params.\n deleteCacheEntry(cacheKeyRef.current);\n setCacheInvalidatedAt(Date.now());\n }\n\n if (!closedSocket?.shouldReconnect && terminalClose) {\n const error = new AgentConnectionErrorCtor(event);\n connectionErrorAddressKeyRef.current = addressKey;\n setConnectionError(error);\n onConnectionError?.(error);\n }\n }\n\n // Call user's onClose if provided\n options.onClose?.(event);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n };\n // Update the live-socket ref before anything below can use it.\n socketRef.current = agent;\n\n // When `usePartySocket` replaces the socket object (connection options\n // changed — async query refresh, path change, enabled toggle, ...) the\n // old socket's event listeners are detached at the same commit, so its\n // final close event may never be observed by our onClose handler.\n // Sweep here instead: anything transmitted on the old socket can never\n // get a response, and the identity it established no longer applies.\n // Queued (never-transmitted) calls survive and flush when the new\n // socket opens.\n const prevSocketRef = useRef<PartySocket | null>(null);\n const prevAddressKeyRef = useRef(addressKey);\n useEffect(() => {\n const prev = prevSocketRef.current;\n prevSocketRef.current = agent;\n const prevAddress = prevAddressKeyRef.current;\n prevAddressKeyRef.current = addressKey;\n\n // Destination guard: if the agent address changed (different agent,\n // name, or path — not just refreshed credentials), calls that are\n // still queued were composed for the *old* instance. Reject them\n // before anything can flush them onto the new instance.\n if (prevAddress !== addressKey) {\n connectionErrorAddressKeyRef.current = null;\n setConnectionError(null);\n rejectQueuedCalls(\n \"Call discarded: the agent address changed before the request could be sent\"\n );\n }\n\n if (prev && prev !== agent) {\n rejectCallsSentOn(prev, \"Connection closed\");\n resetReady();\n if (mutableAgentRef.current) {\n mutableAgentRef.current.identified = false;\n }\n setIdentity((current) =>\n current.identified ? { ...current, identified: false } : current\n );\n }\n // The helpers only touch refs; re-running on socket/address change is all we need.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agent, addressKey]);\n\n // Create the call method. Deliberately dependency-free: it routes\n // through refs, so even a stale `agent` reference captured by an old\n // effect closure issues calls against the live socket.\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<T> => {\n // On the Cap'n Web transport, callables are native methods on the\n // session root: invoke them directly so an RpcTarget result arrives\n // as a live stub and chained calls pipeline. The JSON `rpc` frame\n // below is the WebSocket wire's protocol.\n if (transportRef.current === \"capnweb\") {\n const native = capnWebRef.current;\n const socket = socketRef.current;\n if (native && socket?.readyState === WebSocket.OPEN) {\n return nativeCall<T>(\n native,\n method,\n args,\n options,\n defaultCallTimeoutRef.current\n );\n }\n if (\n socket &&\n connectionErrorRef.current &&\n socket.readyState === socket.CLOSED\n ) {\n return Promise.reject(new Error(\"Connection closed\"));\n }\n // Connecting or between reconnects: hold the call as a native call\n // rather than queueing a JSON frame that would change its meaning.\n return nativeQueueRef.current.enqueue<T>(\n method,\n args,\n options,\n defaultCallTimeoutRef.current\n );\n }\n return new Promise((resolve, reject) => {\n const socket = socketRef.current;\n if (\n socket &&\n connectionErrorRef.current &&\n socket.readyState === socket.CLOSED\n ) {\n reject(new Error(\"Connection closed\"));\n return;\n }\n\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const { stream: streamOptions, timeout } = splitCallOptions(options);\n\n // Apply the default timeout as a backstop for non-streaming\n // calls so a lost response rejects instead of hanging forever.\n // An explicit `timeout` (including 0 = disabled) always wins.\n const effectiveTimeout =\n timeout !== undefined\n ? timeout\n : streamOptions\n ? undefined\n : defaultCallTimeoutRef.current;\n\n if (effectiveTimeout) {\n timeoutId = setTimeout(() => {\n const pending = pendingCallsRef.current.get(id);\n pendingCallsRef.current.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${effectiveTimeout}ms`;\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, effectiveTimeout);\n }\n\n const rpcRequest: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n const request = JSON.stringify(rpcRequest);\n\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions,\n timeoutId,\n request,\n sentOn: null\n });\n\n // Transmit immediately if the live socket is open; otherwise the\n // request stays queued and is flushed on the next open event.\n // We never hand requests to a non-open socket: its internal\n // buffer is lost forever if the socket gets replaced.\n if (socket && socket.readyState === socket.OPEN) {\n socket.send(request);\n const pending = pendingCallsRef.current.get(id);\n if (pending) pending.sentOn = socket;\n }\n });\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n agent.setState = (newState: State) => {\n // Route through the live socket so stale `agent` references don't\n // write into a replaced socket's dead buffer.\n (socketRef.current ?? agent).send(\n JSON.stringify({ state: newState, type: MessageType.CF_AGENT_STATE })\n );\n setAgentState(newState);\n options.onStateUpdate?.(newState, \"client\");\n };\n\n agent.call = call;\n // Use reactive identity state (updates on identity message)\n agent.agent = identity.agent;\n agent.name = identity.name;\n // Full root-first chain including the leaf. Computed from the\n // user-provided options — the server doesn't need to echo it\n // back because the client already knows. Write past the\n // PartySocket `.path: string` shape via an unknown cast — the\n // overload signatures expose this as `ReadonlyArray<...>`.\n (\n agent as unknown as { path: ReadonlyArray<{ agent: string; name: string }> }\n ).path = fullPath;\n agent.identified = identity.identified;\n agent.ready = readyRef.current!.promise;\n agent.state = agentState;\n agent.connectionError = visibleConnectionError;\n mutableAgentRef.current = agent;\n // Memoize stub so it's referentially stable across renders\n // (call is already stable via useCallback)\n const stub = useMemo(() => createStubProxy(call), [call]);\n agent.stub = stub;\n agent.getHttpUrl = () => {\n // TODO: upstream to partysocket — expose an HTTP URL property\n // @ts-expect-error accessing protected PartySocket internals\n const wsUrl: string = (agent._url as string | null) || agent._pkurl || \"\";\n return wsUrl.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\");\n };\n\n // warn if agent isn't in lowercase\n if (identity.agent !== identity.agent.toLowerCase()) {\n console.warn(\n \"Agent name: \" +\n identity.agent +\n \" should probably be in lowercase. Received: \" +\n identity.agent\n );\n }\n\n // The overload signatures return `Omit<PartySocket, \"path\"> & { path: ... }`,\n // but `agent` is inferred as the raw PartySocket. Cast to satisfy\n // the overload contract — the runtime override of `agent.path`\n // above ensures the shape matches.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return agent as any;\n}\n\ntype AgentToolEventAgent = Pick<\n PartySocket,\n \"addEventListener\" | \"removeEventListener\"\n>;\n\nfunction agentToolDedupeKey(message: AgentToolEventMessage): string {\n return [\n message.parentToolCallId ?? \"\",\n message.event.runId,\n String(message.sequence)\n ].join(\"\\0\");\n}\n\nexport function useAgentToolEvents<\n Part extends AgentToolRunPart = AgentToolRunPart\n>(options: {\n agent: AgentToolEventAgent;\n}): {\n runsById: Record<string, AgentToolRunState<Part>>;\n runsByToolCallId: Record<string, AgentToolRunState<Part>[]>;\n unboundRuns: AgentToolRunState<Part>[];\n getRunsForToolCall(toolCallId: string): AgentToolRunState<Part>[];\n resetLocalState(): void;\n} {\n const { agent } = options;\n const [state, setState] = useState<AgentToolEventState<Part>>(() =>\n createAgentToolEventState<Part>()\n );\n const seenRef = useRef(new Set<string>());\n\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n if (typeof event.data !== \"string\") return;\n let message: AgentToolEventMessage;\n try {\n message = JSON.parse(event.data) as AgentToolEventMessage;\n } catch {\n return;\n }\n if (message.type !== \"agent-tool-event\") return;\n const key = agentToolDedupeKey(message);\n if (seenRef.current.has(key)) return;\n seenRef.current.add(key);\n setState((prev) => applyAgentToolEvent<Part>(prev, message));\n };\n\n agent.addEventListener(\"message\", onMessage);\n return () => agent.removeEventListener(\"message\", onMessage);\n }, [agent]);\n\n const resetLocalState = useCallback(() => {\n seenRef.current.clear();\n setState(createAgentToolEventState<Part>());\n }, []);\n\n const getRunsForToolCall = useCallback(\n (toolCallId: string) => state.runsByToolCallId[toolCallId] ?? [],\n [state.runsByToolCallId]\n );\n\n return {\n ...state,\n getRunsForToolCall,\n resetLocalState\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.js","names":["AgentConnectionErrorCtor"],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useState, useEffect } from \"react\";\nimport type { MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type {\n AgentConnectionError,\n AgentPromiseReturnType,\n AgentStub,\n CallOptions,\n OptionalAgentMethods,\n RequiredAgentMethods,\n StreamOptions,\n UntypedAgentStub\n} from \"./client\";\nimport type { ClientParameters } from \"./serializable\";\nimport {\n createStubProxy,\n DEFAULT_CALL_TIMEOUT_MS,\n AgentConnectionError as AgentConnectionErrorCtor,\n createCloseClassifier,\n nativeCall,\n NativeCallQueue,\n splitCallOptions\n} from \"./client\";\nimport {\n boundCapnWebSocket,\n type CapnWebSocket\n} from \"./websockets/capnweb-socket\";\nimport {\n CAPNWEB_TRANSPORT_QUERY,\n CAPNWEB_TRANSPORT_VALUE,\n type AgentTransport\n} from \"./websockets/transport-protocol\";\nimport { buildSubAgentPathUnchecked } from \"./sub-routing\";\nimport { SOCKET_ADDRESS_PENDING } from \"./socket-address\";\nimport { camelCaseToKebabCase } from \"./utils\";\nimport { MessageType } from \"./types\";\n\nexport type { AgentTransport } from \"./websockets/transport-protocol\";\nimport {\n agentToolEventDedupeKey,\n applyAgentToolEvent,\n createAgentToolEventState,\n type AgentToolEventMessage,\n type AgentToolEventState,\n type AgentToolRunPart,\n type AgentToolRunState\n} from \"./chat/agent-tools\";\n\ntype QueryObject = Record<string, string | null>;\ntype TerminalReconnectOptions = {\n shouldReconnectOnClose?: (event: CloseEvent) => boolean;\n};\n\ninterface CacheEntry {\n promise: Promise<QueryObject>;\n expiresAt: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\n\ntype SocketDestination = {\n host?: string;\n basePath?: string;\n party?: string;\n prefix?: string;\n room?: string;\n path?: string;\n protocol?: string;\n protocols?: unknown;\n};\n\nfunction socketDestinationKey(options: SocketDestination): string {\n return JSON.stringify([\n options.host ?? null,\n options.basePath ?? null,\n options.party ?? null,\n options.prefix ?? null,\n options.room ?? null,\n options.path ?? null,\n options.protocol ?? null,\n options.protocols ?? null\n ]);\n}\n\ntype ReadyEntry = {\n promise: Promise<void>;\n resolve: () => void;\n resolved: boolean;\n};\n\nfunction createReadyEntry(): ReadyEntry {\n let resolvePromise!: () => void;\n const entry: ReadyEntry = {\n promise: new Promise<void>((r) => {\n resolvePromise = r;\n }),\n resolved: false,\n resolve: () => {\n entry.resolved = true;\n resolvePromise();\n }\n };\n return entry;\n}\n\n/** The host `usePartySocket` connects to when none is given. */\nfunction defaultSocketHost(): string {\n return typeof window !== \"undefined\"\n ? window.location.host\n : \"dummy-domain.com\";\n}\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n subChainOrDeps: ReadonlyArray<{ agent: string; name: string }> | unknown[],\n deps?: unknown[]\n): string {\n // Backwards-compatible overload: if called with 3 args, the third\n // argument is `deps` and `subChain` defaults to empty. With 4 args,\n // the third is the sub-chain. This keeps existing callers (and\n // the `_testUtils` surface) working while letting new callers\n // include the nested chain in the cache key.\n //\n // Empty sub-chain must produce the same key as the old 3-arg\n // form, so nested-addressing code can opt-in without invalidating\n // existing caches.\n if (deps === undefined) {\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n ...(subChainOrDeps as unknown[])\n ]);\n }\n const subChain = subChainOrDeps as ReadonlyArray<{\n agent: string;\n name: string;\n }>;\n if (subChain.length === 0) {\n return JSON.stringify([agentNamespace, name || \"default\", ...deps]);\n }\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n subChain.map((s) => [s.agent, s.name]),\n ...deps\n ]);\n}\n\n/** Build a URL path tail `/sub/{agent-kebab}/{name}/...` from a sub chain. */\nfunction buildSubPath(\n subChain: ReadonlyArray<{ agent: string; name: string }>,\n extraPath?: string\n): string {\n return buildSubAgentPathUnchecked(\n subChain.map((step) => ({ className: step.agent, name: step.name })),\n extraPath\n );\n}\n\nfunction getCacheEntry(key: string): CacheEntry | undefined {\n const entry = queryCache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() >= entry.expiresAt) {\n queryCache.delete(key);\n return undefined;\n }\n\n return entry;\n}\n\nfunction setCacheEntry(\n key: string,\n promise: Promise<QueryObject>,\n cacheTtl: number\n): CacheEntry {\n const entry: CacheEntry = {\n promise,\n expiresAt: Date.now() + cacheTtl\n };\n queryCache.set(key, entry);\n return entry;\n}\n\nfunction deleteCacheEntry(key: string): void {\n queryCache.delete(key);\n}\n\n// Export for testing purposes\nexport const _testUtils = {\n queryCache,\n setCacheEntry,\n getCacheEntry,\n deleteCacheEntry,\n clearCache: () => queryCache.clear(),\n createStubProxy,\n createCacheKey\n};\n\n/**\n * Options for the useAgent hook\n * @template State Type of the Agent's state\n */\nexport type UseAgentOptions<State = unknown> = Omit<\n Parameters<typeof usePartySocket>[0],\n \"party\" | \"room\" | \"query\"\n> &\n TerminalReconnectOptions & {\n /** Name of the agent to connect to (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the client connects to this path directly.\n * Server must handle routing manually (e.g., with getAgentByName + fetch).\n * @example\n * // Client connects to /user, server routes based on session\n * useAgent({ agent: \"UserAgent\", basePath: \"user\" })\n */\n basePath?: string;\n /**\n * Wire the connection travels on. `\"cf-websocket\"` (default) is a\n * hibernating WebSocket where `call()` sends JSON `rpc` frames.\n * `\"capnweb\"` carries protocol frames over a Cap'n Web session whose\n * root also serves the host's `callables` natively, so `call()` and\n * `stub` invoke them directly and an `RpcTarget` result is a live stub.\n * The Durable Object stays in memory while a capnweb connection is open.\n * Identity, state, and reconnection behave the same on both.\n * @experimental The `\"capnweb\"` transport is experimental.\n */\n transport?: AgentTransport;\n /** Query parameters - can be static object or async function */\n query?: QueryObject | (() => Promise<QueryObject>);\n /** Dependencies for async query caching */\n queryDeps?: unknown[];\n /** Cache TTL in milliseconds for auth tokens/time-sensitive data */\n cacheTtl?: number;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when a state update fails (e.g., connection is readonly) */\n onStateUpdateError?: (error: string) => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n /**\n * Called when the server sends the agent's identity on connect.\n * Useful when using basePath, as the actual instance name is determined server-side.\n * @param name The actual agent instance name\n * @param agent The agent class name (kebab-case)\n */\n onIdentity?: (name: string, agent: string) => void;\n /**\n * Called when identity changes on reconnect (different instance than before).\n * If not provided and identity changes, a warning will be logged.\n * @param oldName Previous instance name\n * @param newName New instance name\n * @param oldAgent Previous agent class name\n * @param newAgent New agent class name\n */\n onIdentityChange?: (\n oldName: string,\n newName: string,\n oldAgent: string,\n newAgent: string\n ) => void;\n /**\n * Additional path to append to the URL.\n * Works with both standard routing and basePath.\n * @example\n * // With basePath: /user/settings\n * { basePath: \"user\", path: \"settings\" }\n * // Standard: /agents/my-agent/room/settings\n * { agent: \"MyAgent\", name: \"room\", path: \"settings\" }\n */\n path?: string;\n /**\n * Connect to a sub-agent (facet) via its parent. Flat array,\n * root-first. Each step addresses one parent↔child hop.\n *\n * The hook's returned `.agent` / `.name` report the **leaf**\n * identity (the deepest entry in `sub`), so downstream hooks\n * like `useAgentChat` see the child they actually talk to.\n * `.path` exposes the full chain for observability, deep links,\n * and reconnect keying.\n *\n * @example\n * ```ts\n * // Two-level nesting: Inbox (Alice) → Chat (abc)\n * useAgent({\n * agent: \"inbox\", name: userId,\n * sub: [{ agent: \"chat\", name: chatId }]\n * });\n *\n * // Three-level: tenant → inbox → chat\n * useAgent({\n * agent: \"tenant\", name: tenantId,\n * sub: [\n * { agent: \"inbox\", name: userId },\n * { agent: \"chat\", name: chatId }\n * ]\n * });\n * ```\n *\n * @experimental The API surface may change before stabilizing.\n */\n sub?: ReadonlyArray<{ agent: string; name: string }>;\n /**\n * Default timeout (in milliseconds) applied to non-streaming `call()`s\n * that don't pass an explicit `timeout`. Acts as a backstop so calls\n * whose response is lost (e.g. the connection is replaced mid-flight)\n * reject instead of hanging forever.\n *\n * Defaults to 30 000 ms. Set to `0` to disable the default timeout.\n * Streaming calls never get a default timeout (long-lived streams are\n * legitimate); pass an explicit `timeout` to bound them.\n */\n defaultCallTimeout?: number;\n /** Called when the connection closes with a terminal code and will not reconnect. */\n onConnectionError?: (error: AgentConnectionError) => void;\n };\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: ClientParameters<OptionalAgentMethods<AgentT>[K]>,\n options?: CallOptions | StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: ClientParameters<RequiredAgentMethods<AgentT>[K]>,\n options?: CallOptions | StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype AgentMethodCall<AgentT> = OptionalArgsAgentMethodCall<AgentT> &\n RequiredArgsAgentMethodCall<AgentT>;\n\ntype UntypedAgentMethodCall = <T = unknown>(\n method: string,\n args?: unknown[],\n options?: CallOptions | StreamOptions\n) => Promise<T>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n /** Full root-first address chain, including leaf. Single entry when `sub` isn't set. */\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n getHttpUrl: () => string;\n};\nexport function useAgent<State>(options: UseAgentOptions<unknown>): Omit<\n PartySocket,\n \"path\"\n> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n // NOTE: `path` is destructured out (as `userPath`) so it does NOT\n // end up in `restOptions`. Spreading `restOptions` after the\n // computed `path: combinedPath` would otherwise let the user's raw\n // `path` overwrite the combined sub-agent URL, dropping every\n // `/sub/{child}/{name}` segment on the way to the socket.\n const {\n query,\n queryDeps,\n cacheTtl,\n sub: subOption,\n path: userPath,\n defaultCallTimeout,\n onConnectionError,\n shouldReconnectOnClose,\n transport = \"cf-websocket\",\n ...restOptions\n } = options;\n // PartySocket keeps reconnection, buffering, and backoff; the transport\n // only swaps the socket class it instantiates. The bound subclass hands\n // the hook each live Cap'n Web socket so `call()` can invoke natively.\n const capnWebRef = useRef<CapnWebSocket | null>(null);\n const transportRef = useRef(transport);\n transportRef.current = transport;\n // Native calls issued before the Cap'n Web socket is open wait here\n // instead of degrading to JSON frames; flushed on open, rejected on a\n // permanent close.\n const nativeQueueRef = useRef(new NativeCallQueue());\n const socketClass = useMemo(\n () =>\n transport === \"capnweb\"\n ? {\n WebSocket: boundCapnWebSocket((socket) => {\n capnWebRef.current = socket;\n })\n }\n : {},\n [transport]\n );\n\n const subChain = useMemo(\n () => (subOption ?? []).map((s) => ({ agent: s.agent, name: s.name })),\n // Stable serialization — deep changes re-memoize.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(subOption ?? [])]\n );\n\n // The \"leaf\" is the deepest entry in the chain; it's what\n // downstream code (useAgentChat etc.) should see as the\n // authoritative identity.\n const leafAgent =\n subChain.length > 0 ? subChain[subChain.length - 1].agent : options.agent;\n const leafName =\n subChain.length > 0\n ? subChain[subChain.length - 1].name\n : options.name || \"default\";\n\n // Full root-first chain, including the leaf. Exposed as `.path`\n // and used for cache keying so nested sessions with the same leaf\n // name don't collide.\n const fullPath = useMemo(\n () => [\n { agent: options.agent, name: options.name || \"default\" },\n ...subChain\n ],\n [options.agent, options.name, subChain]\n );\n\n // Keep track of pending RPC calls.\n //\n // Each entry is tagged with the socket the request was transmitted on\n // (`sentOn`). Requests are only handed to a socket once it's OPEN —\n // until then they stay queued here (`sentOn: null`). This matters\n // because `usePartySocket` *replaces* the socket object whenever\n // connection options change (async query refresh, path change, etc.):\n // anything buffered inside a replaced socket is lost forever, and a\n // call transmitted on a replaced socket can never receive its\n // response. Tagging lets us:\n // - flush still-queued requests on whichever socket connects next\n // (safe: they were never transmitted, so no double-execution risk)\n // - reject calls transmitted on a socket that closed or was replaced\n // (their response can never arrive)\n // - avoid rejecting calls in flight on the *new* socket when a stale\n // close event from an old socket trickles in\n const pendingCallsRef = useRef(\n new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n timeoutId?: ReturnType<typeof setTimeout>;\n /** Serialized RPC request, kept so it can be (re)transmitted */\n request: string;\n /** Socket the request was transmitted on; null while queued */\n sentOn: PartySocket | null;\n }\n >()\n );\n\n // Always points at the socket from the latest render. `call`,\n // `setState`, and the queue-flushing logic go through this ref so\n // that stale `agent` references held by old effect closures still\n // route their traffic to the live socket instead of a dead one.\n const socketRef = useRef<PartySocket | null>(null);\n\n const defaultCallTimeoutRef = useRef(\n defaultCallTimeout ?? DEFAULT_CALL_TIMEOUT_MS\n );\n defaultCallTimeoutRef.current = defaultCallTimeout ?? DEFAULT_CALL_TIMEOUT_MS;\n\n /** Reject (and remove) every pending call transmitted on `socket`. */\n const rejectCallsSentOn = (socket: PartySocket, reason: string) => {\n const error = new Error(reason);\n for (const [id, pending] of pendingCallsRef.current) {\n if (pending.sentOn === socket) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pendingCallsRef.current.delete(id);\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n }\n };\n\n /** Transmit queued (never-sent) calls if the live socket is open. */\n const flushQueuedCalls = () => {\n const socket = socketRef.current;\n if (!socket || socket.readyState !== socket.OPEN) return;\n for (const pending of pendingCallsRef.current.values()) {\n if (pending.sentOn === null) {\n socket.send(pending.request);\n pending.sentOn = socket;\n }\n }\n const native =\n transportRef.current === \"capnweb\" ? capnWebRef.current : null;\n if (native) nativeQueueRef.current.flush(native);\n };\n\n /** Reject (and remove) every still-queued (never transmitted) call. */\n const rejectQueuedCalls = (reason: string) => {\n nativeQueueRef.current.rejectAll(reason);\n const error = new Error(reason);\n for (const [id, pending] of pendingCallsRef.current) {\n if (pending.sentOn === null) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pendingCallsRef.current.delete(id);\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n }\n };\n\n const cacheKey = useMemo(\n () =>\n createCacheKey(agentNamespace, options.name, subChain, queryDeps || []),\n [agentNamespace, options.name, subChain, queryDeps]\n );\n\n // Track current cache key in a ref for use in onClose handler.\n // This ensures we invalidate the correct cache entry when the connection closes,\n // even if the component re-renders with different props before onClose fires.\n // We update synchronously during render (not in useEffect) to avoid race\n // conditions where onClose could fire before the effect runs.\n const cacheKeyRef = useRef(cacheKey);\n cacheKeyRef.current = cacheKey;\n\n const ttl = cacheTtl ?? 5 * 60 * 1000;\n\n // Track cache invalidation to force re-render when TTL expires\n const [cacheInvalidatedAt, setCacheInvalidatedAt] = useState<number>(0);\n\n // Disable socket while waiting for async query to refresh after disconnect\n const isAsyncQuery = query && typeof query === \"function\";\n const [awaitingQueryRefresh, setAwaitingQueryRefresh] = useState(false);\n\n // Get or create the query promise\n const queryPromise = useMemo(() => {\n // Re-run when cache is invalidated after TTL expiry\n void cacheInvalidatedAt;\n\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n // Always check cache first to deduplicate concurrent requests\n const cached = getCacheEntry(cacheKey);\n if (cached) {\n return cached.promise;\n }\n\n // Create new promise\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n deleteCacheEntry(cacheKey);\n throw error;\n });\n\n // Always cache to deduplicate concurrent requests\n setCacheEntry(cacheKey, promise, ttl);\n\n return promise;\n }, [cacheKey, query, options.agent, ttl, cacheInvalidatedAt]);\n\n // Schedule cache invalidation when TTL expires\n useEffect(() => {\n if (!queryPromise || ttl <= 0) return;\n\n const entry = getCacheEntry(cacheKey);\n if (!entry) return;\n\n const timeUntilExpiry = entry.expiresAt - Date.now();\n\n // Always set a timer (with min 0ms) to ensure cleanup function is returned\n const timer = setTimeout(\n () => {\n deleteCacheEntry(cacheKey);\n setCacheInvalidatedAt(Date.now());\n },\n Math.max(0, timeUntilExpiry)\n );\n\n return () => clearTimeout(timer);\n }, [cacheKey, queryPromise, ttl]);\n\n let resolvedQuery: QueryObject | undefined;\n\n if (query) {\n if (typeof query === \"function\") {\n // Use React's use() to resolve the promise\n const queryResult = use(queryPromise!);\n\n // Check for non-primitive values and warn\n if (queryResult) {\n for (const [key, value] of Object.entries(queryResult)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n console.warn(\n `[useAgent] Query parameter \"${key}\" is an object and will be converted to \"[object Object]\". ` +\n \"Query parameters should be string, number, boolean, or null.\"\n );\n }\n }\n resolvedQuery = queryResult;\n }\n } else {\n // Sync query - use directly\n resolvedQuery = query;\n }\n }\n\n // Re-enable socket after async query resolves\n useEffect(() => {\n if (awaitingQueryRefresh && resolvedQuery !== undefined) {\n setAwaitingQueryRefresh(false);\n }\n }, [awaitingQueryRefresh, resolvedQuery]);\n\n // Track agent state for reactivity — updated on server broadcasts and client setState\n const [agentState, setAgentState] = useState<State | undefined>(undefined);\n const [connectionError, setConnectionError] =\n useState<AgentConnectionError | null>(null);\n const connectionErrorRef = useRef<AgentConnectionError | null>(null);\n const connectionErrorAddressKeyRef = useRef<string | null>(null);\n const shouldReconnectOnCloseRef = useRef(shouldReconnectOnClose);\n shouldReconnectOnCloseRef.current = shouldReconnectOnClose;\n const maxRetriesRef = useRef(restOptions.maxRetries);\n maxRetriesRef.current = restOptions.maxRetries;\n const [closeClassifier] = useState(() =>\n createCloseClassifier({\n socket: () => socketRef.current,\n shouldReconnectOnClose: () => shouldReconnectOnCloseRef.current,\n maxRetries: () => maxRetriesRef.current\n })\n );\n const classifyReconnect = closeClassifier.shouldReconnectOnClose;\n\n // Store identity in React state for reactivity. Seed with the\n // leaf's address — what the server will echo back in\n // `cf_agent_identity`.\n // `destination` records which socket destination the identity came from,\n // so an address change can stop exposing the previous agent's identity\n // before the new socket reports its own.\n const [identity, setIdentity] = useState(() => ({\n name: leafName,\n agent: camelCaseToKebabCase(leafAgent),\n identified: false,\n destination: null as string | null\n }));\n\n // Track previous identity for change detection\n const previousIdentityRef = useRef<{\n name: string | null;\n agent: string | null;\n }>({ name: null, agent: null });\n\n // Ready promise - resolves when identity is received, resets on close\n // One entry per socket destination, so `ready` for a newly requested\n // agent is not the previous agent's resolved promise.\n const readyRef = useRef(new Map<string, ReadyEntry>());\n const readyFor = (destination: string): ReadyEntry => {\n let entry = readyRef.current.get(destination);\n if (!entry) {\n entry = createReadyEntry();\n readyRef.current.set(destination, entry);\n }\n return entry;\n };\n // A still-pending promise is kept, so a caller already awaiting it is\n // resolved by the next identity rather than left on a replaced promise.\n const resetReady = (destination: string) => {\n if (readyRef.current.get(destination)?.resolved !== false) {\n readyRef.current.set(destination, createReadyEntry());\n }\n };\n\n const mutableAgentRef = useRef<{\n agent: string;\n name: string;\n identified: boolean;\n state: State | undefined;\n } | null>(null);\n\n // Combine the sub-agent chain with the user-provided `path`.\n // Order matters: `/sub/{child}/{name}/...` comes before `path` so\n // the server sees the hierarchy it expects.\n const combinedPath = useMemo(\n () => buildSubPath(subChain, userPath),\n [subChain, userPath]\n );\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n // The transport rides in the query too, so it is part of PartySocket's\n // socket key: changing `transport` reconnects on the new wire.\n const socketQuery =\n transport === \"capnweb\"\n ? { ...resolvedQuery, [CAPNWEB_TRANSPORT_QUERY]: CAPNWEB_TRANSPORT_VALUE }\n : resolvedQuery;\n\n const socketOptions = options.basePath\n ? {\n basePath: options.basePath,\n path: combinedPath || undefined,\n query: socketQuery,\n ...restOptions,\n ...socketClass,\n shouldReconnectOnClose: classifyReconnect\n }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: combinedPath || undefined,\n query: socketQuery,\n ...restOptions,\n ...socketClass,\n shouldReconnectOnClose: classifyReconnect\n };\n\n const socketEnabled = !awaitingQueryRefresh && (restOptions.enabled ?? true);\n\n // Identifies *which agent instance* this hook is addressing. Queued\n // (never-transmitted) RPC calls are only safe to flush onto a later\n // socket if it still points at the same instance — a call composed for\n // agent \"alpha\" must not execute on agent \"beta\" just because the\n // `name` prop changed while the call was waiting for a connection.\n // Credentials (query params) are deliberately excluded: a token\n // refresh doesn't change where calls go.\n // The wire is part of the address: queued calls belong to a transport as\n // much as to an instance, so switching `transport` rejects them rather\n // than flushing a native call onto a JSON socket or vice versa.\n const addressKey = JSON.stringify([\n options.host ?? null,\n options.basePath ?? null,\n agentNamespace,\n options.name || \"default\",\n combinedPath || null,\n transport\n ]);\n const destination = socketDestinationKey({\n ...socketOptions,\n host: socketOptions.host || defaultSocketHost()\n });\n // The seeded identity (before any identity message) belongs to the\n // destination of the first render.\n const seedDestinationRef = useRef(destination);\n const visibleConnectionError =\n connectionErrorAddressKeyRef.current === addressKey\n ? connectionError\n : null;\n connectionErrorRef.current = visibleConnectionError;\n\n // Connect-sequence progress per socket: whether the state frame has\n // landed, and an identity held back until it does.\n const connectProgressRef = useRef(\n new WeakMap<\n PartySocket,\n { stateSeen: boolean; pendingIdentity: [string, string] | null }\n >()\n );\n const connectProgress = (socket: PartySocket | null) => {\n if (!socket) return { stateSeen: false, pendingIdentity: null };\n let progress = connectProgressRef.current.get(socket);\n if (!progress) {\n progress = { stateSeen: false, pendingIdentity: null };\n connectProgressRef.current.set(socket, progress);\n }\n return progress;\n };\n\n const applyIdentity = (\n newName: string,\n newAgent: string,\n identifiedSocket: PartySocket | null\n ) => {\n const oldName = previousIdentityRef.current.name;\n const oldAgent = previousIdentityRef.current.agent;\n\n const currentAgent = mutableAgentRef.current;\n if (currentAgent) {\n currentAgent.name = newName;\n currentAgent.agent = newAgent;\n currentAgent.identified = true;\n }\n\n // Update reactive state (triggers re-render)\n const identifiedDestination = identifiedSocket\n ? socketDestinationKey(identifiedSocket.partySocketOptions)\n : null;\n setIdentity({\n name: newName,\n agent: newAgent,\n identified: true,\n destination: identifiedDestination\n });\n\n // Resolve ready promise\n if (identifiedDestination !== null) {\n readyFor(identifiedDestination).resolve();\n }\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (options.onIdentityChange) {\n options.onIdentityChange(oldName, newName, oldAgent, newAgent);\n } else {\n const agentChanged = oldAgent !== newAgent;\n const nameChanged = oldName !== newName;\n let changeDescription = \"\";\n if (agentChanged && nameChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\", instance \"${oldName}\" → \"${newName}\"`;\n } else if (agentChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\"`;\n } else {\n changeDescription = `instance \"${oldName}\" → \"${newName}\"`;\n }\n console.warn(\n `[agents] Identity changed on reconnect: ${changeDescription}. ` +\n \"This can happen with server-side routing (e.g., basePath with getAgentByName) \" +\n \"where the instance is determined by auth/session. \" +\n \"Provide onIdentityChange callback to handle this explicitly, \" +\n \"or ignore if this is expected for your routing pattern.\"\n );\n }\n }\n\n // Track for next change detection\n previousIdentityRef.current = { name: newName, agent: newAgent };\n\n // Call onIdentity callback\n options.onIdentity?.(newName, newAgent);\n };\n\n const agent = usePartySocket({\n ...socketOptions,\n enabled: socketEnabled,\n onOpen: (event: Event) => {\n connectionErrorAddressKeyRef.current = null;\n setConnectionError(null);\n // The socket is open: transmit any RPC requests that were issued\n // while disconnected (or while a previous socket was being\n // replaced). They were never handed to a socket before, so this\n // cannot double-execute anything server-side.\n flushQueuedCalls();\n options.onOpen?.(event);\n },\n onMessage: (message) => {\n if (typeof message.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(message.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return options.onMessage?.(message);\n }\n if (parsedMessage.type === MessageType.CF_AGENT_IDENTITY) {\n const identifiedSocket =\n (message.target as PartySocket | null) ?? socketRef.current;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n const progress = connectProgress(identifiedSocket);\n // The server flags an identity whose state frame is next, so\n // `ready` never resolves with the stored state still missing.\n if (parsedMessage.stateFollows === true && !progress.stateSeen) {\n progress.pendingIdentity = [newName, newAgent];\n return;\n }\n applyIdentity(newName, newAgent, identifiedSocket);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n setAgentState(parsedMessage.state as State);\n // Before `ready` can resolve below: a caller awaiting it reads\n // the live object, not the next render.\n if (mutableAgentRef.current) {\n mutableAgentRef.current.state = parsedMessage.state as State;\n }\n const stateSocket =\n (message.target as PartySocket | null) ?? socketRef.current;\n try {\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n } finally {\n const progress = connectProgress(stateSocket);\n progress.stateSeen = true;\n const pending = progress.pendingIdentity;\n if (pending) {\n progress.pendingIdentity = null;\n applyIdentity(pending[0], pending[1], stateSocket);\n }\n }\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {\n options.onStateUpdateError?.(parsedMessage.error as string);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_MCP_SERVERS) {\n options.onMcpUpdate?.(parsedMessage.mcp as MCPServersState);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = pendingCallsRef.current.get(response.id);\n if (!pending) {\n console.warn(\n `[useAgent] Discarded an RPC response with no matching pending call (id \"${response.id}\"). ` +\n \"The call likely timed out or was rejected when its connection closed before the response arrived.\"\n );\n return;\n }\n\n if (!response.success) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.reject(new Error(response.error));\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onError?.(response.error);\n return;\n }\n\n // Handle streaming responses\n if (\"done\" in response) {\n if (response.done) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onDone?.(response.result);\n } else {\n pending.stream?.onChunk?.(response.result);\n }\n } else {\n // Non-streaming response\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n },\n onClose: (event: CloseEvent) => {\n // Identify which socket actually closed. Close events are\n // dispatched asynchronously, so a close from an old socket that\n // was just replaced can arrive while a new socket is already\n // connecting (or connected). `event.target` is the PartySocket\n // that dispatched the event; fall back to the live socket if the\n // environment doesn't populate it.\n const closedSocket =\n (event.target as PartySocket | null) ?? socketRef.current;\n const isCurrentSocket = closedSocket === socketRef.current;\n const finalClose = closeClassifier.takeFinalClose();\n if (closedSocket) connectProgressRef.current.delete(closedSocket);\n const reconnecting = !!closedSocket?.shouldReconnect && !finalClose;\n\n // Calls transmitted on the closed socket can never receive their\n // response — reject them. Calls still queued (never transmitted)\n // stay pending and are flushed when a socket next opens; calls\n // in flight on a *different* (newer) socket are untouched.\n if (closedSocket) {\n rejectCallsSentOn(closedSocket, \"Connection closed\");\n if (isCurrentSocket && !reconnecting) {\n rejectQueuedCalls(\"Connection closed\");\n }\n }\n\n if (isCurrentSocket) {\n // Reset ready state for next connection\n if (closedSocket) {\n resetReady(socketDestinationKey(closedSocket.partySocketOptions));\n }\n if (mutableAgentRef.current) {\n mutableAgentRef.current.identified = false;\n }\n setIdentity((prev) => ({ ...prev, identified: false }));\n\n if (reconnecting) {\n // Pause reconnection for async queries until fresh query params are ready.\n if (isAsyncQuery) {\n setAwaitingQueryRefresh(true);\n }\n\n // Invalidate cache and trigger re-render to fetch fresh query params.\n deleteCacheEntry(cacheKeyRef.current);\n setCacheInvalidatedAt(Date.now());\n }\n\n if (finalClose) {\n const error = new AgentConnectionErrorCtor(event);\n connectionErrorAddressKeyRef.current = addressKey;\n setConnectionError(error);\n onConnectionError?.(error);\n }\n }\n\n // Call user's onClose if provided\n options.onClose?.(event);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n connectionError: AgentConnectionError | null;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n };\n // Update the live-socket ref before anything below can use it.\n socketRef.current = agent;\n\n // `usePartySocket` swaps in a socket for new options in an effect, so for\n // at least one render after the destination changes (and for as long as\n // the socket is disabled) `agent` still points at the previous one. Query\n // params are not part of the destination: a token refresh reaches the\n // same agent.\n const socketAddressPending =\n socketDestinationKey(agent.partySocketOptions) !== destination;\n\n // When `usePartySocket` replaces the socket object (connection options\n // changed — async query refresh, path change, enabled toggle, ...) the\n // old socket's event listeners are detached at the same commit, so its\n // final close event may never be observed by our onClose handler.\n // Sweep here instead: anything transmitted on the old socket can never\n // get a response, and the identity it established no longer applies.\n // Queued (never-transmitted) calls survive and flush when the new\n // socket opens.\n const prevSocketRef = useRef<PartySocket | null>(null);\n const prevAddressKeyRef = useRef(addressKey);\n const prevDestinationRef = useRef(destination);\n useEffect(() => {\n const prev = prevSocketRef.current;\n prevSocketRef.current = agent;\n const prevAddress = prevAddressKeyRef.current;\n prevAddressKeyRef.current = addressKey;\n const prevDestination = prevDestinationRef.current;\n prevDestinationRef.current = destination;\n\n // The caller chose the new destination, so the identity the new socket\n // reports is not an identity change on reconnect. Options the\n // destination ignores (`name` under `basePath`) keep the comparison.\n if (prevDestination !== destination) {\n previousIdentityRef.current = { name: null, agent: null };\n }\n\n // Destination guard: if the agent address changed (different agent,\n // name, or path — not just refreshed credentials), calls that are\n // still queued were composed for the *old* instance. Reject them\n // before anything can flush them onto the new instance.\n if (prevAddress !== addressKey) {\n connectionErrorAddressKeyRef.current = null;\n setConnectionError(null);\n rejectQueuedCalls(\n \"Call discarded: the agent address changed before the request could be sent\"\n );\n }\n\n // Pending entries stay: a caller may still await one, and returning to\n // that destination must resolve the promise it already holds.\n for (const [key, entry] of readyRef.current) {\n if (key !== destination && entry.resolved) readyRef.current.delete(key);\n }\n\n if (prev && prev !== agent) {\n rejectCallsSentOn(prev, \"Connection closed\");\n resetReady(socketDestinationKey(agent.partySocketOptions));\n if (mutableAgentRef.current) {\n mutableAgentRef.current.identified = false;\n }\n setIdentity((current) =>\n current.identified ? { ...current, identified: false } : current\n );\n }\n // The helpers only touch refs; re-running on socket/address change is all we need.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agent, addressKey, destination]);\n\n // Create the call method. Deliberately dependency-free: it routes\n // through refs, so even a stale `agent` reference captured by an old\n // effect closure issues calls against the live socket.\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<T> => {\n // On the Cap'n Web transport, callables are native methods on the\n // session root: invoke them directly so an RpcTarget result arrives\n // as a live stub and chained calls pipeline. The JSON `rpc` frame\n // below is the WebSocket wire's protocol.\n if (transportRef.current === \"capnweb\") {\n const native = capnWebRef.current;\n const socket = socketRef.current;\n if (native && socket?.readyState === WebSocket.OPEN) {\n return nativeCall<T>(\n native,\n method,\n args,\n options,\n defaultCallTimeoutRef.current\n );\n }\n if (\n socket &&\n connectionErrorRef.current &&\n socket.readyState === socket.CLOSED\n ) {\n return Promise.reject(new Error(\"Connection closed\"));\n }\n // Connecting or between reconnects: hold the call as a native call\n // rather than queueing a JSON frame that would change its meaning.\n return nativeQueueRef.current.enqueue<T>(\n method,\n args,\n options,\n defaultCallTimeoutRef.current\n );\n }\n return new Promise((resolve, reject) => {\n const socket = socketRef.current;\n if (\n socket &&\n connectionErrorRef.current &&\n socket.readyState === socket.CLOSED\n ) {\n reject(new Error(\"Connection closed\"));\n return;\n }\n\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const { stream: streamOptions, timeout } = splitCallOptions(options);\n\n // Apply the default timeout as a backstop for non-streaming\n // calls so a lost response rejects instead of hanging forever.\n // An explicit `timeout` (including 0 = disabled) always wins.\n const effectiveTimeout =\n timeout !== undefined\n ? timeout\n : streamOptions\n ? undefined\n : defaultCallTimeoutRef.current;\n\n if (effectiveTimeout) {\n timeoutId = setTimeout(() => {\n const pending = pendingCallsRef.current.get(id);\n pendingCallsRef.current.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${effectiveTimeout}ms`;\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, effectiveTimeout);\n }\n\n const rpcRequest: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n const request = JSON.stringify(rpcRequest);\n\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions,\n timeoutId,\n request,\n sentOn: null\n });\n\n // Transmit immediately if the live socket is open; otherwise the\n // request stays queued and is flushed on the next open event.\n // We never hand requests to a non-open socket: its internal\n // buffer is lost forever if the socket gets replaced.\n if (socket && socket.readyState === socket.OPEN) {\n socket.send(request);\n const pending = pendingCallsRef.current.get(id);\n if (pending) pending.sentOn = socket;\n }\n });\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n agent.setState = (newState: State) => {\n // Route through the live socket so stale `agent` references don't\n // write into a replaced socket's dead buffer.\n (socketRef.current ?? agent).send(\n JSON.stringify({ state: newState, type: MessageType.CF_AGENT_STATE })\n );\n if (mutableAgentRef.current) mutableAgentRef.current.state = newState;\n setAgentState(newState);\n options.onStateUpdate?.(newState, \"client\");\n };\n\n agent.call = call;\n // Use reactive identity state (updates on identity message). Once the\n // address moves away from the one the identity came from, expose the new\n // leaf until the new socket identifies. A `basePath` connection keeps the\n // server-reported identity: the server owns its name.\n const identityIsCurrent =\n !!options.basePath ||\n (identity.destination ?? seedDestinationRef.current) === destination;\n agent.agent = identityIsCurrent\n ? identity.agent\n : camelCaseToKebabCase(leafAgent);\n agent.name = identityIsCurrent ? identity.name : leafName;\n // Full root-first chain including the leaf. Computed from the\n // user-provided options — the server doesn't need to echo it\n // back because the client already knows. Write past the\n // PartySocket `.path: string` shape via an unknown cast — the\n // overload signatures expose this as `ReadonlyArray<...>`.\n (\n agent as unknown as { path: ReadonlyArray<{ agent: string; name: string }> }\n ).path = fullPath;\n agent.identified = identityIsCurrent && identity.identified;\n agent.ready = readyFor(destination).promise;\n agent.state = agentState;\n agent.connectionError = visibleConnectionError;\n mutableAgentRef.current = agent;\n // Memoize stub so it's referentially stable across renders\n // (call is already stable via useCallback)\n const stub = useMemo(() => createStubProxy(call), [call]);\n agent.stub = stub;\n (agent as { [SOCKET_ADDRESS_PENDING]?: boolean })[SOCKET_ADDRESS_PENDING] =\n socketAddressPending;\n agent.getHttpUrl = () => {\n // The previous socket's URL names the previous agent and carries its\n // credentials.\n if (socketAddressPending) return \"\";\n // TODO: upstream to partysocket — expose an HTTP URL property\n // @ts-expect-error accessing protected PartySocket internals\n const wsUrl: string = (agent._url as string | null) || agent._pkurl || \"\";\n return wsUrl.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\");\n };\n\n // warn if agent isn't in lowercase\n if (identity.agent !== identity.agent.toLowerCase()) {\n console.warn(\n \"Agent name: \" +\n identity.agent +\n \" should probably be in lowercase. Received: \" +\n identity.agent\n );\n }\n\n // The overload signatures return `Omit<PartySocket, \"path\"> & { path: ... }`,\n // but `agent` is inferred as the raw PartySocket. Cast to satisfy\n // the overload contract — the runtime override of `agent.path`\n // above ensures the shape matches.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return agent as any;\n}\n\ntype AgentToolEventAgent = Pick<\n PartySocket,\n \"addEventListener\" | \"removeEventListener\"\n>;\n\nexport function useAgentToolEvents<\n Part extends AgentToolRunPart = AgentToolRunPart\n>(options: {\n agent: AgentToolEventAgent;\n}): {\n runsById: Record<string, AgentToolRunState<Part>>;\n runsByToolCallId: Record<string, AgentToolRunState<Part>[]>;\n unboundRuns: AgentToolRunState<Part>[];\n getRunsForToolCall(toolCallId: string): AgentToolRunState<Part>[];\n resetLocalState(): void;\n} {\n const { agent } = options;\n const [state, setState] = useState<AgentToolEventState<Part>>(() =>\n createAgentToolEventState<Part>()\n );\n const seenRef = useRef(new Set<string>());\n\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n if (typeof event.data !== \"string\") return;\n let message: AgentToolEventMessage;\n try {\n message = JSON.parse(event.data) as AgentToolEventMessage;\n } catch {\n return;\n }\n if (message.type !== \"agent-tool-event\") return;\n const key = agentToolEventDedupeKey(message);\n if (seenRef.current.has(key)) return;\n seenRef.current.add(key);\n setState((prev) => applyAgentToolEvent<Part>(prev, message));\n };\n\n agent.addEventListener(\"message\", onMessage);\n return () => agent.removeEventListener(\"message\", onMessage);\n }, [agent]);\n\n const resetLocalState = useCallback(() => {\n seenRef.current.clear();\n setState(createAgentToolEventState<Part>());\n }, []);\n\n const getRunsForToolCall = useCallback(\n (toolCallId: string) => state.runsByToolCallId[toolCallId] ?? [],\n [state.runsByToolCallId]\n );\n\n return {\n ...state,\n getRunsForToolCall,\n resetLocalState\n };\n}\n"],"mappings":"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"}
|