agents 0.14.5 → 0.16.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.
Files changed (53) hide show
  1. package/dist/{agent-tool-types-V25Z_HcX.d.ts → agent-tool-types-NofdbL9X.d.ts} +182 -112
  2. package/dist/agent-tool-types.d.ts +1 -1
  3. package/dist/{agent-tools-C-9s151X.d.ts → agent-tools-DLquv-dp.d.ts} +2 -2
  4. package/dist/agent-tools.d.ts +1 -1
  5. package/dist/browser/ai.d.ts +126 -7
  6. package/dist/browser/ai.js +73 -29
  7. package/dist/browser/ai.js.map +1 -1
  8. package/dist/browser/index.d.ts +81 -69
  9. package/dist/browser/index.js +3 -2
  10. package/dist/browser/tanstack-ai.d.ts +13 -7
  11. package/dist/browser/tanstack-ai.js +18 -19
  12. package/dist/browser/tanstack-ai.js.map +1 -1
  13. package/dist/chat/index.d.ts +111 -5
  14. package/dist/chat/index.js +207 -35
  15. package/dist/chat/index.js.map +1 -1
  16. package/dist/chat-sdk/index.d.ts +1 -1
  17. package/dist/{classPrivateFieldGet2-Beqsfu2Z.js → classPrivateFieldGet2-CZ7QjTXN.js} +5 -5
  18. package/dist/{classPrivateMethodInitSpec-B5ko1s2R.js → classPrivateMethodInitSpec-D-0__zd9.js} +2 -2
  19. package/dist/client.d.ts +19 -2
  20. package/dist/client.js +31 -11
  21. package/dist/client.js.map +1 -1
  22. package/dist/{compaction-helpers-BEUILPss.d.ts → compaction-helpers-DVcu5lPN.d.ts} +91 -12
  23. package/dist/connector-D6yYzYHg.js +1080 -0
  24. package/dist/connector-D6yYzYHg.js.map +1 -0
  25. package/dist/connector-DXursxV5.d.ts +340 -0
  26. package/dist/experimental/memory/session/index.d.ts +75 -12
  27. package/dist/experimental/memory/session/index.js +226 -21
  28. package/dist/experimental/memory/session/index.js.map +1 -1
  29. package/dist/experimental/memory/utils/index.d.ts +2 -2
  30. package/dist/{index-CPe1OtI0.d.ts → index-B7IbEeze.d.ts} +32 -1
  31. package/dist/index.d.ts +8 -2
  32. package/dist/index.js +116 -45
  33. package/dist/index.js.map +1 -1
  34. package/dist/mcp/client.d.ts +1 -1
  35. package/dist/mcp/index.d.ts +1 -1
  36. package/dist/mcp/index.js +262 -487
  37. package/dist/mcp/index.js.map +1 -1
  38. package/dist/observability/index.d.ts +1 -1
  39. package/dist/react.d.ts +12 -1
  40. package/dist/react.js +101 -30
  41. package/dist/react.js.map +1 -1
  42. package/dist/{retries-CF_HKSlJ.d.ts → retries-CwlpAGet.d.ts} +35 -5
  43. package/dist/retries.d.ts +9 -5
  44. package/dist/retries.js +87 -1
  45. package/dist/retries.js.map +1 -1
  46. package/dist/serializable.d.ts +1 -1
  47. package/dist/skills/index.js +2 -2
  48. package/dist/sub-routing.d.ts +1 -1
  49. package/dist/workflows.d.ts +1 -1
  50. package/package.json +10 -10
  51. package/dist/shared-4CAYLCTO.d.ts +0 -34
  52. package/dist/shared-wyII629d.js +0 -432
  53. package/dist/shared-wyII629d.js.map +0 -1
@@ -1,25 +1,25 @@
1
- //#region \0@oxc-project+runtime@0.134.0/helpers/esm/checkPrivateRedeclaration.js
1
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/checkPrivateRedeclaration.js
2
2
  function _checkPrivateRedeclaration(e, t) {
3
3
  if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
4
4
  }
5
5
  //#endregion
6
- //#region \0@oxc-project+runtime@0.134.0/helpers/esm/classPrivateFieldInitSpec.js
6
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/classPrivateFieldInitSpec.js
7
7
  function _classPrivateFieldInitSpec(e, t, a) {
8
8
  _checkPrivateRedeclaration(e, t), t.set(e, a);
9
9
  }
10
10
  //#endregion
11
- //#region \0@oxc-project+runtime@0.134.0/helpers/esm/assertClassBrand.js
11
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/assertClassBrand.js
12
12
  function _assertClassBrand(e, t, n) {
13
13
  if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
14
14
  throw new TypeError("Private element is not present on this object");
15
15
  }
16
16
  //#endregion
17
- //#region \0@oxc-project+runtime@0.134.0/helpers/esm/classPrivateFieldSet2.js
17
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/classPrivateFieldSet2.js
18
18
  function _classPrivateFieldSet2(s, a, r) {
19
19
  return s.set(_assertClassBrand(s, a), r), r;
20
20
  }
21
21
  //#endregion
22
- //#region \0@oxc-project+runtime@0.134.0/helpers/esm/classPrivateFieldGet2.js
22
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/classPrivateFieldGet2.js
23
23
  function _classPrivateFieldGet2(s, a) {
24
24
  return s.get(_assertClassBrand(s, a));
25
25
  }
@@ -1,5 +1,5 @@
1
- import { a as _checkPrivateRedeclaration } from "./classPrivateFieldGet2-Beqsfu2Z.js";
2
- //#region \0@oxc-project+runtime@0.134.0/helpers/esm/classPrivateMethodInitSpec.js
1
+ import { a as _checkPrivateRedeclaration } from "./classPrivateFieldGet2-CZ7QjTXN.js";
2
+ //#region \0@oxc-project+runtime@0.135.0/helpers/esm/classPrivateMethodInitSpec.js
3
3
  function _classPrivateMethodInitSpec(e, a) {
4
4
  _checkPrivateRedeclaration(e, a), a.add(e);
5
5
  }
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as Agent } from "./agent-tool-types-V25Z_HcX.js";
1
+ import { b as Agent } from "./agent-tool-types-NofdbL9X.js";
2
2
  import {
3
3
  ClientParameters,
4
4
  Method,
@@ -67,7 +67,21 @@ type AgentClientOptions<State = unknown> = Omit<
67
67
  * { agent: "MyAgent", name: "room", path: "settings" }
68
68
  */
69
69
  path?: string;
70
+ /**
71
+ * Default timeout (in milliseconds) applied to non-streaming `call()`s
72
+ * that don't pass an explicit `timeout`. Defaults to 30 000 ms.
73
+ * Set to `0` to disable. Streaming calls never get a default timeout.
74
+ */
75
+ defaultCallTimeout?: number;
70
76
  };
77
+ /**
78
+ * Default timeout (in milliseconds) applied to non-streaming RPC calls
79
+ * that don't pass an explicit `timeout`. Acts as a backstop so calls
80
+ * whose response is lost (e.g. the connection drops mid-flight) reject
81
+ * instead of hanging forever. Override per client via
82
+ * `defaultCallTimeout`, or per call via `timeout` (0 disables).
83
+ */
84
+ declare const DEFAULT_CALL_TIMEOUT_MS = 30000;
71
85
  /**
72
86
  * Options for streaming RPC calls
73
87
  */
@@ -216,7 +230,9 @@ declare class AgentClient<
216
230
  private _resetReady;
217
231
  constructor(options: AgentClientOptions<State>);
218
232
  /**
219
- * Reject all pending RPC calls with the given reason.
233
+ * Reject pending RPC calls with the given reason.
234
+ * With `onlyTransmitted`, calls still sitting in the send buffer are
235
+ * kept pending (they'll be flushed on reconnect).
220
236
  */
221
237
  private _rejectPendingCalls;
222
238
  setState(state: State): void;
@@ -255,6 +271,7 @@ export {
255
271
  AgentPromiseReturnType,
256
272
  AgentStub,
257
273
  CallOptions,
274
+ DEFAULT_CALL_TIMEOUT_MS,
258
275
  OptionalAgentMethods,
259
276
  RPCMethods,
260
277
  RequiredAgentMethods,
package/dist/client.js CHANGED
@@ -3,6 +3,14 @@ import { camelCaseToKebabCase, isInternalJsStubProp } from "./utils.js";
3
3
  import { PartySocket } from "partysocket";
4
4
  //#region src/client.ts
5
5
  /**
6
+ * Default timeout (in milliseconds) applied to non-streaming RPC calls
7
+ * that don't pass an explicit `timeout`. Acts as a backstop so calls
8
+ * whose response is lost (e.g. the connection drops mid-flight) reject
9
+ * instead of hanging forever. Override per client via
10
+ * `defaultCallTimeout`, or per call via `timeout` (0 disables).
11
+ */
12
+ const DEFAULT_CALL_TIMEOUT_MS = 3e4;
13
+ /**
6
14
  * Creates a proxy that wraps RPC method calls.
7
15
  * Internal JS methods (toJSON, then, etc.) return undefined to avoid
8
16
  * triggering RPC calls during serialization (e.g., console.log)
@@ -103,7 +111,10 @@ var AgentClient = class extends PartySocket {
103
111
  if (parsedMessage.type === "rpc") {
104
112
  const response = parsedMessage;
105
113
  const pending = this._pendingCalls.get(response.id);
106
- if (!pending) return;
114
+ if (!pending) {
115
+ console.warn(`[AgentClient] Discarded an RPC response with no matching pending call (id "${response.id}"). The call likely timed out or was rejected when its connection closed before the response arrived.`);
116
+ return;
117
+ }
107
118
  if (!response.success) {
108
119
  pending.reject(new Error(response.error));
109
120
  this._pendingCalls.delete(response.id);
@@ -122,24 +133,31 @@ var AgentClient = class extends PartySocket {
122
133
  }
123
134
  }
124
135
  });
136
+ this.addEventListener("open", () => {
137
+ for (const pending of this._pendingCalls.values()) pending.transmitted = true;
138
+ });
125
139
  this.addEventListener("close", () => {
126
140
  this.identified = false;
127
141
  this._resetReady();
128
- this._rejectPendingCalls("Connection closed");
142
+ if (this.shouldReconnect) this._rejectPendingCalls("Connection closed", { onlyTransmitted: true });
143
+ else this._rejectPendingCalls("Connection closed");
129
144
  });
130
145
  this.call = this._callImpl.bind(this);
131
146
  this.stub = createStubProxy((method, args) => this._callImpl(method, args));
132
147
  }
133
148
  /**
134
- * Reject all pending RPC calls with the given reason.
149
+ * Reject pending RPC calls with the given reason.
150
+ * With `onlyTransmitted`, calls still sitting in the send buffer are
151
+ * kept pending (they'll be flushed on reconnect).
135
152
  */
136
- _rejectPendingCalls(reason) {
153
+ _rejectPendingCalls(reason, { onlyTransmitted = false } = {}) {
137
154
  const error = new Error(reason);
138
- for (const pending of this._pendingCalls.values()) {
155
+ for (const [id, pending] of this._pendingCalls) {
156
+ if (onlyTransmitted && !pending.transmitted) continue;
157
+ this._pendingCalls.delete(id);
139
158
  pending.reject(error);
140
159
  pending.stream?.onError?.(reason);
141
160
  }
142
- this._pendingCalls.clear();
143
161
  }
144
162
  setState(state) {
145
163
  this.send(JSON.stringify({
@@ -173,13 +191,14 @@ var AgentClient = class extends PartySocket {
173
191
  const isLegacyFormat = options && ("onChunk" in options || "onDone" in options || "onError" in options);
174
192
  const streamOptions = isLegacyFormat ? options : options?.stream;
175
193
  const timeout = isLegacyFormat ? void 0 : options?.timeout;
176
- if (timeout) timeoutId = setTimeout(() => {
194
+ const effectiveTimeout = timeout !== void 0 ? timeout : streamOptions ? void 0 : this.options.defaultCallTimeout ?? 3e4;
195
+ if (effectiveTimeout) timeoutId = setTimeout(() => {
177
196
  const pending = this._pendingCalls.get(id);
178
197
  this._pendingCalls.delete(id);
179
- const errorMessage = `RPC call to ${method} timed out after ${timeout}ms`;
198
+ const errorMessage = `RPC call to ${method} timed out after ${effectiveTimeout}ms`;
180
199
  pending?.stream?.onError?.(errorMessage);
181
200
  reject(new Error(errorMessage));
182
- }, timeout);
201
+ }, effectiveTimeout);
183
202
  this._pendingCalls.set(id, {
184
203
  reject: (e) => {
185
204
  if (timeoutId) clearTimeout(timeoutId);
@@ -189,7 +208,8 @@ var AgentClient = class extends PartySocket {
189
208
  if (timeoutId) clearTimeout(timeoutId);
190
209
  resolve(value);
191
210
  },
192
- stream: streamOptions
211
+ stream: streamOptions,
212
+ transmitted: this.readyState === this.OPEN
193
213
  });
194
214
  const request = {
195
215
  args,
@@ -221,6 +241,6 @@ function agentFetch(opts, init) {
221
241
  }, init);
222
242
  }
223
243
  //#endregion
224
- export { AgentClient, agentFetch, createStubProxy };
244
+ export { AgentClient, DEFAULT_CALL_TIMEOUT_MS, agentFetch, createStubProxy };
225
245
 
226
246
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import {\n type PartyFetchOptions,\n PartySocket,\n type PartySocketOptions\n} from \"partysocket\";\nimport type { Agent, RPCRequest, RPCResponse } from \"./\";\nimport type {\n ClientParameters,\n Method,\n RPCMethod,\n SerializableReturnValue,\n SerializableValue\n} from \"./serializable\";\nimport { MessageType } from \"./types\";\nimport { camelCaseToKebabCase, isInternalJsStubProp } from \"./utils\";\n\n/**\n * Options for creating an AgentClient\n */\nexport type AgentClientOptions<State = unknown> = Omit<\n PartySocketOptions,\n \"party\" | \"room\"\n> & {\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 /** 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 /**\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\n/**\n * Options for streaming RPC calls\n */\nexport type StreamOptions = {\n /** Called when a chunk of data is received */\n onChunk?: (chunk: unknown) => void;\n /** Called when the stream ends */\n onDone?: (finalChunk: unknown) => void;\n /** Called when an error occurs */\n onError?: (error: string) => void;\n};\n\n/**\n * Options for RPC calls\n */\nexport type CallOptions = {\n /** Timeout in milliseconds. If the call doesn't complete within this time, it will be rejected. */\n timeout?: number;\n /** Streaming options for handling streaming responses */\n stream?: StreamOptions;\n};\n\n/**\n * Options for the agentFetch function\n */\nexport type AgentClientFetchOptions = Omit<\n PartyFetchOptions,\n \"party\" | \"room\"\n> & {\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 request is made to this path directly.\n */\n basePath?: string;\n};\n\n// ---- Shared RPC Type Utilities ----\n\ntype AllOptional<T> = T extends [infer A, ...infer R]\n ? undefined extends A\n ? AllOptional<R>\n : false\n : true;\n\nexport type RPCMethods<T> = {\n [K in keyof T as T[K] extends RPCMethod<T[K]> ? K : never]: RPCMethod<T[K]>;\n};\n\ntype OptionalParametersMethod<T extends RPCMethod> =\n AllOptional<ClientParameters<T>> extends true ? T : never;\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic agent type constraint\nexport type AgentMethods<T> = Omit<RPCMethods<T>, keyof Agent<any, any>>;\n\nexport type OptionalAgentMethods<T> = {\n [K in keyof AgentMethods<T> as AgentMethods<T>[K] extends OptionalParametersMethod<\n AgentMethods<T>[K]\n >\n ? K\n : never]: OptionalParametersMethod<AgentMethods<T>[K]>;\n};\n\nexport type RequiredAgentMethods<T> = Omit<\n AgentMethods<T>,\n keyof OptionalAgentMethods<T>\n>;\n\nexport type AgentPromiseReturnType<T, K extends keyof AgentMethods<T>> =\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic promise return type\n ReturnType<AgentMethods<T>[K]> extends Promise<any>\n ? ReturnType<AgentMethods<T>[K]>\n : Promise<ReturnType<AgentMethods<T>[K]>>;\n\nexport type AgentStub<T> = {\n [K in keyof AgentMethods<T>]: (\n ...args: ClientParameters<AgentMethods<T>[K]>\n ) => AgentPromiseReturnType<AgentMethods<T>, K>;\n};\n\nexport type UntypedAgentStub = Record<string, Method>;\n\ntype AgentClientStub<AgentT> = keyof AgentMethods<AgentT> extends never\n ? UntypedAgentStub\n : AgentStub<AgentT>;\n\ntype OptionalArgsAgentClientCall<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 RequiredArgsAgentClientCall<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 TypedAgentClientCall<AgentT> = OptionalArgsAgentClientCall<AgentT> &\n RequiredArgsAgentClientCall<AgentT>;\n\ntype UntypedAgentClientCall = {\n <T extends SerializableReturnValue>(\n method: string,\n args?: SerializableValue[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n <T = unknown>(\n method: string,\n args?: unknown[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n};\n\ntype AgentClientCall<AgentT> = keyof AgentMethods<AgentT> extends never\n ? UntypedAgentClientCall\n : TypedAgentClientCall<AgentT>;\n\n/**\n * Creates a proxy that wraps RPC method calls.\n * Internal JS methods (toJSON, then, etc.) return undefined to avoid\n * triggering RPC calls during serialization (e.g., console.log)\n */\nexport function createStubProxy<T = Record<string, Method>>(\n call: (method: string, args: unknown[]) => unknown\n): T {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- proxy needs any for dynamic method access\n return new Proxy<any>(\n {},\n {\n get: (_target, method) => {\n if (isInternalJsStubProp(method)) {\n return undefined;\n }\n return (...args: unknown[]) => call(method as string, args);\n }\n }\n );\n}\n\n/**\n * WebSocket client for connecting to an Agent\n */\nexport class AgentClient<\n AgentT = unknown,\n State = AgentT extends { get state(): infer S } ? S : AgentT\n> extends PartySocket {\n /**\n * @deprecated Use agentFetch instead\n */\n static fetch(_opts: PartyFetchOptions): Promise<Response> {\n throw new Error(\n \"AgentClient.fetch is not implemented, use agentFetch instead\"\n );\n }\n agent: string;\n name: string;\n call: AgentClientCall<AgentT>;\n stub: AgentClientStub<AgentT>;\n\n /**\n * The current agent state, updated on server broadcasts and client setState calls.\n * Starts as undefined until the first state message is received from the server.\n */\n state: State | undefined = undefined;\n\n /**\n * Whether the client has received identity from the server.\n * Becomes true after the first identity message is received.\n * Resets to false on connection close.\n */\n identified = false;\n\n /**\n * Promise that resolves when identity has been received from the server.\n * Useful for waiting before making calls that depend on knowing the instance.\n * Resets on connection close so it can be awaited again after reconnect.\n */\n get ready(): Promise<void> {\n return this._readyPromise;\n }\n\n private options: AgentClientOptions<State>;\n private _pendingCalls = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n }\n >();\n private _readyPromise!: Promise<void>;\n private _resolveReady!: () => void;\n private _previousName: string | null = null;\n private _previousAgent: string | null = null;\n\n private _resetReady() {\n this._readyPromise = new Promise((resolve) => {\n this._resolveReady = resolve;\n });\n }\n\n constructor(options: AgentClientOptions<State>) {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n const socketOptions = options.basePath\n ? { basePath: options.basePath, path: options.path, ...options }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: options.path,\n ...options\n };\n\n super(socketOptions);\n this.agent = agentNamespace;\n this.name = options.name || \"default\";\n this.options = options;\n\n // Initialize ready promise\n this._resetReady();\n\n this.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(event.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_IDENTITY) {\n const oldName = this._previousName;\n const oldAgent = this._previousAgent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n // Resolve ready/identified\n this.identified = true;\n this._resolveReady();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (this.options.onIdentityChange) {\n this.options.onIdentityChange(\n oldName,\n newName,\n oldAgent,\n newAgent\n );\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 // Always update from server identity (server is authoritative)\n this._previousName = newName;\n this._previousAgent = newAgent;\n this.name = newName;\n this.agent = newAgent;\n\n // Call onIdentity callback\n this.options.onIdentity?.(newName, newAgent);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n this.state = parsedMessage.state as State;\n this.options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {\n this.options.onStateUpdateError?.(parsedMessage.error as string);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = this._pendingCalls.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n this._pendingCalls.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 pending.resolve(response.result);\n this._pendingCalls.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 pending.resolve(response.result);\n this._pendingCalls.delete(response.id);\n }\n }\n }\n });\n\n // Clean up pending calls and reset ready state when connection closes\n this.addEventListener(\"close\", () => {\n // Reset ready state for next connection\n this.identified = false;\n this._resetReady();\n\n // Reject any remaining pending calls (e.g., from unexpected disconnect)\n this._rejectPendingCalls(\"Connection closed\");\n });\n\n this.call = this._callImpl.bind(this) as AgentClientCall<AgentT>;\n this.stub = createStubProxy((method, args) =>\n this._callImpl(method, args)\n ) as AgentClientStub<AgentT>;\n }\n\n /**\n * Reject all pending RPC calls with the given reason.\n */\n private _rejectPendingCalls(reason: string) {\n const error = new Error(reason);\n for (const pending of this._pendingCalls.values()) {\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n this._pendingCalls.clear();\n }\n\n setState(state: State) {\n this.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n this.state = state;\n this.options.onStateUpdate?.(state, \"client\");\n }\n\n /**\n * Close the connection and immediately reject all pending RPC calls.\n * This provides immediate feedback on intentional close rather than\n * waiting for the WebSocket close handshake to complete.\n *\n * Note: Any calls made after `close()` will be rejected when the\n * underlying WebSocket close event fires.\n */\n close(code?: number, reason?: string) {\n // Immediately reject all pending calls on intentional close\n this._rejectPendingCalls(\"Connection closed\");\n\n // Then close the underlying socket\n super.close(code, reason);\n }\n\n /**\n * Call a method on the Agent.\n * When AgentT is provided, method names are inferred from the agent's methods.\n * Falls back to untyped string-based calls when AgentT is not provided.\n */\n private async _callImpl(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Detect legacy format: { onChunk?, onDone?, onError? } vs new format: { timeout?, stream? }\n const isLegacyFormat =\n options &&\n (\"onChunk\" in options || \"onDone\" in options || \"onError\" in options);\n const streamOptions = isLegacyFormat\n ? (options as StreamOptions)\n : (options as CallOptions | undefined)?.stream;\n const timeout = isLegacyFormat\n ? undefined\n : (options as CallOptions | undefined)?.timeout;\n\n // Set up timeout if specified\n if (timeout) {\n timeoutId = setTimeout(() => {\n const pending = this._pendingCalls.get(id);\n this._pendingCalls.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${timeout}ms`;\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, timeout);\n }\n\n this._pendingCalls.set(id, {\n reject: (e: Error) => {\n if (timeoutId) clearTimeout(timeoutId);\n reject(e);\n },\n resolve: (value: unknown) => {\n if (timeoutId) clearTimeout(timeoutId);\n resolve(value);\n },\n stream: streamOptions\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n this.send(JSON.stringify(request));\n });\n }\n}\n\n/**\n * Make an HTTP request to an Agent\n * @param opts Connection options\n * @param init Request initialization options\n * @returns Promise resolving to a Response\n */\nexport function agentFetch(opts: AgentClientFetchOptions, init?: RequestInit) {\n const agentNamespace = camelCaseToKebabCase(opts.agent);\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n // When basePath is set, room/party aren't used by PartySocket (basePath replaces the URL)\n if (opts.basePath) {\n return PartySocket.fetch(\n { basePath: opts.basePath, ...opts } as unknown as PartyFetchOptions,\n init\n );\n }\n\n return PartySocket.fetch(\n {\n party: agentNamespace,\n prefix: \"agents\",\n room: opts.name || \"default\",\n ...opts\n },\n init\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import {\n type PartyFetchOptions,\n PartySocket,\n type PartySocketOptions\n} from \"partysocket\";\nimport type { Agent, RPCRequest, RPCResponse } from \"./\";\nimport type {\n ClientParameters,\n Method,\n RPCMethod,\n SerializableReturnValue,\n SerializableValue\n} from \"./serializable\";\nimport { MessageType } from \"./types\";\nimport { camelCaseToKebabCase, isInternalJsStubProp } from \"./utils\";\n\n/**\n * Options for creating an AgentClient\n */\nexport type AgentClientOptions<State = unknown> = Omit<\n PartySocketOptions,\n \"party\" | \"room\"\n> & {\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 /** 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 /**\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 * Default timeout (in milliseconds) applied to non-streaming `call()`s\n * that don't pass an explicit `timeout`. Defaults to 30 000 ms.\n * Set to `0` to disable. Streaming calls never get a default timeout.\n */\n defaultCallTimeout?: number;\n};\n\n/**\n * Default timeout (in milliseconds) applied to non-streaming RPC calls\n * that don't pass an explicit `timeout`. Acts as a backstop so calls\n * whose response is lost (e.g. the connection drops mid-flight) reject\n * instead of hanging forever. Override per client via\n * `defaultCallTimeout`, or per call via `timeout` (0 disables).\n */\nexport const DEFAULT_CALL_TIMEOUT_MS = 30_000;\n\n/**\n * Options for streaming RPC calls\n */\nexport type StreamOptions = {\n /** Called when a chunk of data is received */\n onChunk?: (chunk: unknown) => void;\n /** Called when the stream ends */\n onDone?: (finalChunk: unknown) => void;\n /** Called when an error occurs */\n onError?: (error: string) => void;\n};\n\n/**\n * Options for RPC calls\n */\nexport type CallOptions = {\n /** Timeout in milliseconds. If the call doesn't complete within this time, it will be rejected. */\n timeout?: number;\n /** Streaming options for handling streaming responses */\n stream?: StreamOptions;\n};\n\n/**\n * Options for the agentFetch function\n */\nexport type AgentClientFetchOptions = Omit<\n PartyFetchOptions,\n \"party\" | \"room\"\n> & {\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 request is made to this path directly.\n */\n basePath?: string;\n};\n\n// ---- Shared RPC Type Utilities ----\n\ntype AllOptional<T> = T extends [infer A, ...infer R]\n ? undefined extends A\n ? AllOptional<R>\n : false\n : true;\n\nexport type RPCMethods<T> = {\n [K in keyof T as T[K] extends RPCMethod<T[K]> ? K : never]: RPCMethod<T[K]>;\n};\n\ntype OptionalParametersMethod<T extends RPCMethod> =\n AllOptional<ClientParameters<T>> extends true ? T : never;\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic agent type constraint\nexport type AgentMethods<T> = Omit<RPCMethods<T>, keyof Agent<any, any>>;\n\nexport type OptionalAgentMethods<T> = {\n [K in keyof AgentMethods<T> as AgentMethods<T>[K] extends OptionalParametersMethod<\n AgentMethods<T>[K]\n >\n ? K\n : never]: OptionalParametersMethod<AgentMethods<T>[K]>;\n};\n\nexport type RequiredAgentMethods<T> = Omit<\n AgentMethods<T>,\n keyof OptionalAgentMethods<T>\n>;\n\nexport type AgentPromiseReturnType<T, K extends keyof AgentMethods<T>> =\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic promise return type\n ReturnType<AgentMethods<T>[K]> extends Promise<any>\n ? ReturnType<AgentMethods<T>[K]>\n : Promise<ReturnType<AgentMethods<T>[K]>>;\n\nexport type AgentStub<T> = {\n [K in keyof AgentMethods<T>]: (\n ...args: ClientParameters<AgentMethods<T>[K]>\n ) => AgentPromiseReturnType<AgentMethods<T>, K>;\n};\n\nexport type UntypedAgentStub = Record<string, Method>;\n\ntype AgentClientStub<AgentT> = keyof AgentMethods<AgentT> extends never\n ? UntypedAgentStub\n : AgentStub<AgentT>;\n\ntype OptionalArgsAgentClientCall<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 RequiredArgsAgentClientCall<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 TypedAgentClientCall<AgentT> = OptionalArgsAgentClientCall<AgentT> &\n RequiredArgsAgentClientCall<AgentT>;\n\ntype UntypedAgentClientCall = {\n <T extends SerializableReturnValue>(\n method: string,\n args?: SerializableValue[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n <T = unknown>(\n method: string,\n args?: unknown[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n};\n\ntype AgentClientCall<AgentT> = keyof AgentMethods<AgentT> extends never\n ? UntypedAgentClientCall\n : TypedAgentClientCall<AgentT>;\n\n/**\n * Creates a proxy that wraps RPC method calls.\n * Internal JS methods (toJSON, then, etc.) return undefined to avoid\n * triggering RPC calls during serialization (e.g., console.log)\n */\nexport function createStubProxy<T = Record<string, Method>>(\n call: (method: string, args: unknown[]) => unknown\n): T {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any -- proxy needs any for dynamic method access\n return new Proxy<any>(\n {},\n {\n get: (_target, method) => {\n if (isInternalJsStubProp(method)) {\n return undefined;\n }\n return (...args: unknown[]) => call(method as string, args);\n }\n }\n );\n}\n\n/**\n * WebSocket client for connecting to an Agent\n */\nexport class AgentClient<\n AgentT = unknown,\n State = AgentT extends { get state(): infer S } ? S : AgentT\n> extends PartySocket {\n /**\n * @deprecated Use agentFetch instead\n */\n static fetch(_opts: PartyFetchOptions): Promise<Response> {\n throw new Error(\n \"AgentClient.fetch is not implemented, use agentFetch instead\"\n );\n }\n agent: string;\n name: string;\n call: AgentClientCall<AgentT>;\n stub: AgentClientStub<AgentT>;\n\n /**\n * The current agent state, updated on server broadcasts and client setState calls.\n * Starts as undefined until the first state message is received from the server.\n */\n state: State | undefined = undefined;\n\n /**\n * Whether the client has received identity from the server.\n * Becomes true after the first identity message is received.\n * Resets to false on connection close.\n */\n identified = false;\n\n /**\n * Promise that resolves when identity has been received from the server.\n * Useful for waiting before making calls that depend on knowing the instance.\n * Resets on connection close so it can be awaited again after reconnect.\n */\n get ready(): Promise<void> {\n return this._readyPromise;\n }\n\n private options: AgentClientOptions<State>;\n private _pendingCalls = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n /**\n * Whether the request was actually transmitted to the server.\n * Requests issued while disconnected sit in PartySocket's internal\n * buffer (transmitted: false) and are flushed on the next open —\n * they survive a transient close instead of being rejected, since\n * the server never saw them and re-delivery can't double-execute.\n */\n transmitted: boolean;\n }\n >();\n private _readyPromise!: Promise<void>;\n private _resolveReady!: () => void;\n private _previousName: string | null = null;\n private _previousAgent: string | null = null;\n\n private _resetReady() {\n this._readyPromise = new Promise((resolve) => {\n this._resolveReady = resolve;\n });\n }\n\n constructor(options: AgentClientOptions<State>) {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n const socketOptions = options.basePath\n ? { basePath: options.basePath, path: options.path, ...options }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: options.path,\n ...options\n };\n\n super(socketOptions);\n this.agent = agentNamespace;\n this.name = options.name || \"default\";\n this.options = options;\n\n // Initialize ready promise\n this._resetReady();\n\n this.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(event.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_IDENTITY) {\n const oldName = this._previousName;\n const oldAgent = this._previousAgent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n // Resolve ready/identified\n this.identified = true;\n this._resolveReady();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (this.options.onIdentityChange) {\n this.options.onIdentityChange(\n oldName,\n newName,\n oldAgent,\n newAgent\n );\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 // Always update from server identity (server is authoritative)\n this._previousName = newName;\n this._previousAgent = newAgent;\n this.name = newName;\n this.agent = newAgent;\n\n // Call onIdentity callback\n this.options.onIdentity?.(newName, newAgent);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n this.state = parsedMessage.state as State;\n this.options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {\n this.options.onStateUpdateError?.(parsedMessage.error as string);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = this._pendingCalls.get(response.id);\n if (!pending) {\n console.warn(\n `[AgentClient] 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 pending.reject(new Error(response.error));\n this._pendingCalls.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 pending.resolve(response.result);\n this._pendingCalls.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 pending.resolve(response.result);\n this._pendingCalls.delete(response.id);\n }\n }\n }\n });\n\n // PartySocket flushes its internal message buffer right before\n // dispatching \"open\" — anything queued has now been transmitted.\n this.addEventListener(\"open\", () => {\n for (const pending of this._pendingCalls.values()) {\n pending.transmitted = true;\n }\n });\n\n // Clean up pending calls and reset ready state when connection closes\n this.addEventListener(\"close\", () => {\n // Reset ready state for next connection\n this.identified = false;\n this._resetReady();\n\n if (this.shouldReconnect) {\n // Transient disconnect: reject calls whose request was already\n // transmitted — their response can never arrive. Buffered calls\n // stay pending; PartySocket re-sends them on reconnect.\n this._rejectPendingCalls(\"Connection closed\", {\n onlyTransmitted: true\n });\n } else {\n // Permanent close (close() called or retries exhausted): nothing\n // will ever flush the buffer, so reject everything.\n this._rejectPendingCalls(\"Connection closed\");\n }\n });\n\n this.call = this._callImpl.bind(this) as AgentClientCall<AgentT>;\n this.stub = createStubProxy((method, args) =>\n this._callImpl(method, args)\n ) as AgentClientStub<AgentT>;\n }\n\n /**\n * Reject pending RPC calls with the given reason.\n * With `onlyTransmitted`, calls still sitting in the send buffer are\n * kept pending (they'll be flushed on reconnect).\n */\n private _rejectPendingCalls(\n reason: string,\n { onlyTransmitted = false }: { onlyTransmitted?: boolean } = {}\n ) {\n const error = new Error(reason);\n for (const [id, pending] of this._pendingCalls) {\n if (onlyTransmitted && !pending.transmitted) continue;\n this._pendingCalls.delete(id);\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n }\n\n setState(state: State) {\n this.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n this.state = state;\n this.options.onStateUpdate?.(state, \"client\");\n }\n\n /**\n * Close the connection and immediately reject all pending RPC calls.\n * This provides immediate feedback on intentional close rather than\n * waiting for the WebSocket close handshake to complete.\n *\n * Note: Any calls made after `close()` will be rejected when the\n * underlying WebSocket close event fires.\n */\n close(code?: number, reason?: string) {\n // Immediately reject all pending calls on intentional close\n this._rejectPendingCalls(\"Connection closed\");\n\n // Then close the underlying socket\n super.close(code, reason);\n }\n\n /**\n * Call a method on the Agent.\n * When AgentT is provided, method names are inferred from the agent's methods.\n * Falls back to untyped string-based calls when AgentT is not provided.\n */\n private async _callImpl(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Detect legacy format: { onChunk?, onDone?, onError? } vs new format: { timeout?, stream? }\n const isLegacyFormat =\n options &&\n (\"onChunk\" in options || \"onDone\" in options || \"onError\" in options);\n const streamOptions = isLegacyFormat\n ? (options as StreamOptions)\n : (options as CallOptions | undefined)?.stream;\n const timeout = isLegacyFormat\n ? undefined\n : (options as CallOptions | undefined)?.timeout;\n\n // Apply the default timeout as a backstop for non-streaming calls\n // so a lost response rejects instead of hanging forever. An\n // explicit `timeout` (including 0 = disabled) always wins.\n const effectiveTimeout =\n timeout !== undefined\n ? timeout\n : streamOptions\n ? undefined\n : (this.options.defaultCallTimeout ?? DEFAULT_CALL_TIMEOUT_MS);\n\n if (effectiveTimeout) {\n timeoutId = setTimeout(() => {\n const pending = this._pendingCalls.get(id);\n this._pendingCalls.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 this._pendingCalls.set(id, {\n reject: (e: Error) => {\n if (timeoutId) clearTimeout(timeoutId);\n reject(e);\n },\n resolve: (value: unknown) => {\n if (timeoutId) clearTimeout(timeoutId);\n resolve(value);\n },\n stream: streamOptions,\n // If the socket is open, send() below transmits synchronously;\n // otherwise the request is buffered until the next open event\n // (the \"open\" listener then marks it transmitted).\n transmitted: this.readyState === this.OPEN\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n this.send(JSON.stringify(request));\n });\n }\n}\n\n/**\n * Make an HTTP request to an Agent\n * @param opts Connection options\n * @param init Request initialization options\n * @returns Promise resolving to a Response\n */\nexport function agentFetch(opts: AgentClientFetchOptions, init?: RequestInit) {\n const agentNamespace = camelCaseToKebabCase(opts.agent);\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n // When basePath is set, room/party aren't used by PartySocket (basePath replaces the URL)\n if (opts.basePath) {\n return PartySocket.fetch(\n { basePath: opts.basePath, ...opts } as unknown as PartyFetchOptions,\n init\n );\n }\n\n return PartySocket.fetch(\n {\n party: agentNamespace,\n prefix: \"agents\",\n room: opts.name || \"default\",\n ...opts\n },\n init\n );\n}\n"],"mappings":"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"}
@@ -90,6 +90,30 @@ interface StoredCompaction {
90
90
  toMessageId: string;
91
91
  createdAt: string;
92
92
  }
93
+ /** Per-row info for the active branch path, root → leaf order. */
94
+ interface HistoryRowStat {
95
+ id: string;
96
+ /** Stored message role (e.g. "user" / "assistant"). */
97
+ role: string;
98
+ /** Serialized content size of the stored row in bytes. */
99
+ bytes: number;
100
+ }
101
+ /** Result of a byte-budgeted history read. */
102
+ interface RecentHistoryResult {
103
+ /**
104
+ * The most recent messages on the active branch path whose summed stored
105
+ * content size fits `maxContentBytes`, root → leaf order, with compaction
106
+ * overlays applied within the window. The window always covers at least
107
+ * the leaf row (and `minRecentMessages` rows when requested), but rows
108
+ * whose stored content fails to parse are skipped — so a corrupt leaf can
109
+ * yield fewer messages than the window covers.
110
+ */
111
+ messages: SessionMessage[];
112
+ /** True when older messages were left out to satisfy the byte budget. */
113
+ truncated: boolean;
114
+ /** Summed stored content size of the FULL path, in bytes. */
115
+ totalContentBytes: number;
116
+ }
93
117
  /**
94
118
  * Session storage provider.
95
119
  * Messages are tree-structured via parentId for branching.
@@ -108,6 +132,32 @@ interface SessionProvider {
108
132
  getLatestLeaf(): SessionMessage | null | Promise<SessionMessage | null>;
109
133
  getBranches(messageId: string): SessionMessage[] | Promise<SessionMessage[]>;
110
134
  getPathLength(leafId?: string | null): number | Promise<number>;
135
+ /**
136
+ * Optional: byte-budgeted read of the most recent messages on the active
137
+ * branch path. Lets hosts hydrate a bounded window instead of the full
138
+ * transcript, so wake-time memory scales with the budget rather than total
139
+ * session history (#1710). Providers that don't implement it fall back to
140
+ * a full `getHistory()` read in `Session.getRecentHistory()`.
141
+ *
142
+ * `minRecentMessages` (default 1) is a floor on the window size: the most
143
+ * recent N rows are always included even when they exceed the byte budget.
144
+ * Hosts use this to guarantee the window never shrinks below the recent
145
+ * span their model context assembly expects (rows are individually capped
146
+ * at write time, so the floor keeps memory bounded).
147
+ */
148
+ getRecentHistory?(
149
+ leafId: string | null | undefined,
150
+ maxContentBytes: number,
151
+ minRecentMessages?: number
152
+ ): RecentHistoryResult | Promise<RecentHistoryResult>;
153
+ /**
154
+ * Optional: per-row stored sizes for the active branch path (root → leaf),
155
+ * WITHOUT loading message content. Lets hosts find oversized rows (e.g.
156
+ * inline base64 media) and process them one at a time with bounded memory.
157
+ */
158
+ getHistoryRowStats?(
159
+ leafId?: string | null
160
+ ): HistoryRowStat[] | Promise<HistoryRowStat[]>;
111
161
  /**
112
162
  * Append a message.
113
163
  *
@@ -159,6 +209,12 @@ declare class AgentSessionProvider implements SessionProvider {
159
209
  private ensureTable;
160
210
  getMessage(id: string): SessionMessage | null;
161
211
  getHistory(leafId?: string | null): SessionMessage[];
212
+ getRecentHistory(
213
+ leafId: string | null | undefined,
214
+ maxContentBytes: number,
215
+ minRecentMessages?: number
216
+ ): RecentHistoryResult;
217
+ getHistoryRowStats(leafId?: string | null): HistoryRowStat[];
162
218
  getLatestLeaf(): SessionMessage | null;
163
219
  getBranches(messageId: string): SessionMessage[];
164
220
  getPathLength(leafId?: string | null): number;
@@ -174,6 +230,27 @@ declare class AgentSessionProvider implements SessionProvider {
174
230
  getCompactions(): StoredCompaction[];
175
231
  searchMessages(query: string, limit?: number): SearchResult[];
176
232
  private latestLeafRow;
233
+ private leafRowById;
234
+ /**
235
+ * The active branch path as (id, role, content size) rows, root → leaf.
236
+ *
237
+ * Recurses over (id, parent_id) only. Carrying `content` through the
238
+ * recursive queue AND the ORDER BY sorter materializes the entire
239
+ * transcript several times over inside SQLite's allocator, which in
240
+ * workerd shares the isolate's memory budget with the JS heap — large
241
+ * media-heavy sessions then fail with SQLITE_NOMEM on wake (#1710).
242
+ * Content is fetched separately in bounded chunks (`messagesByPathStats`).
243
+ */
244
+ private pathRowStats;
245
+ /**
246
+ * Fetch and parse message content for an ordered list of path rows.
247
+ *
248
+ * Content is read in chunks bounded by both row count and cumulative
249
+ * stored bytes (no ORDER BY — SQLite streams rows without materializing
250
+ * the result set) and reassembled in path order. Rows that fail to parse
251
+ * are skipped, matching previous behavior.
252
+ */
253
+ private messagesByPathStats;
177
254
  private indexFTS;
178
255
  private deleteFTS;
179
256
  private applyCompactions;
@@ -483,16 +560,18 @@ declare function createCompactFunction(
483
560
  ) => Promise<CompactResult | null>;
484
561
  //#endregion
485
562
  export {
486
- CompactContext as A,
563
+ StoredCompaction as A,
487
564
  isSearchProvider as C,
488
- SessionProvider as D,
489
- SearchResult as E,
490
- SessionTokenCounter as F,
491
- SessionTokenCounterInput as I,
492
- SessionMessage as M,
493
- SessionMessagePart as N,
494
- StoredCompaction as O,
495
- SessionOptions as P,
565
+ RecentHistoryResult as D,
566
+ HistoryRowStat as E,
567
+ SessionMessagePart as F,
568
+ SessionOptions as I,
569
+ SessionTokenCounter as L,
570
+ CompactContext as M,
571
+ CompactionErrorHandler as N,
572
+ SearchResult as O,
573
+ SessionMessage as P,
574
+ SessionTokenCounterInput as R,
496
575
  SearchProvider as S,
497
576
  SqlProvider as T,
498
577
  isWritableProvider as _,
@@ -504,8 +583,8 @@ export {
504
583
  WritableContextProvider as g,
505
584
  ContextProvider as h,
506
585
  CompactTokenCounter as i,
507
- CompactionErrorHandler as j,
508
- CompactAfterOptions as k,
586
+ CompactAfterOptions as j,
587
+ SessionProvider as k,
509
588
  createCompactFunction as l,
510
589
  ContextConfig as m,
511
590
  CompactOptions as n,
@@ -520,4 +599,4 @@ export {
520
599
  AgentSearchProvider as x,
521
600
  SkillProvider as y
522
601
  };
523
- //# sourceMappingURL=compaction-helpers-BEUILPss.d.ts.map
602
+ //# sourceMappingURL=compaction-helpers-DVcu5lPN.d.ts.map