agents 0.10.2 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/browser/ai.d.ts +31 -0
  2. package/dist/browser/ai.js +54 -0
  3. package/dist/browser/ai.js.map +1 -0
  4. package/dist/browser/index.d.ts +51 -0
  5. package/dist/browser/index.js +2 -0
  6. package/dist/browser/tanstack-ai.d.ts +31 -0
  7. package/dist/browser/tanstack-ai.js +51 -0
  8. package/dist/browser/tanstack-ai.js.map +1 -0
  9. package/dist/classPrivateFieldGet2-BVdP0e3Z.js +27 -0
  10. package/dist/client.d.ts +2 -2
  11. package/dist/{compaction-helpers-BPE1_ziA.js → compaction-helpers-C_cN3z55.js} +1 -1
  12. package/dist/{compaction-helpers-BPE1_ziA.js.map → compaction-helpers-C_cN3z55.js.map} +1 -1
  13. package/dist/{compaction-helpers-BdQbZiML.d.ts → compaction-helpers-YzCLvunJ.d.ts} +1 -1
  14. package/dist/{do-oauth-client-provider-31gqR33H.d.ts → do-oauth-client-provider-C38aWbFV.d.ts} +1 -1
  15. package/dist/{email-Cql45SKP.d.ts → email-X72-zjuq.d.ts} +1 -1
  16. package/dist/email.d.ts +2 -2
  17. package/dist/experimental/memory/session/index.d.ts +1 -1
  18. package/dist/experimental/memory/session/index.js +1 -1
  19. package/dist/experimental/memory/utils/index.d.ts +1 -1
  20. package/dist/experimental/memory/utils/index.js +1 -1
  21. package/dist/{index-DDSX-g7W.d.ts → index-Biv6K70p.d.ts} +9 -1
  22. package/dist/{index-D2lfljd3.d.ts → index-C_XD19E3.d.ts} +144 -62
  23. package/dist/index.d.ts +32 -28
  24. package/dist/index.js +3245 -2
  25. package/dist/index.js.map +1 -0
  26. package/dist/{internal_context-DuQZFvWI.d.ts → internal_context-BvuGZieY.d.ts} +1 -1
  27. package/dist/internal_context.d.ts +1 -1
  28. package/dist/mcp/client.d.ts +1 -1
  29. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  30. package/dist/mcp/index.d.ts +1 -1
  31. package/dist/mcp/index.js +1 -1
  32. package/dist/observability/index.d.ts +1 -1
  33. package/dist/react.d.ts +1 -1
  34. package/dist/{retries-B_CN5KM9.d.ts → retries-JlwH9mnV.d.ts} +1 -1
  35. package/dist/retries.d.ts +1 -1
  36. package/dist/{serializable-DGdO8CDh.d.ts → serializable-Bg8ARWlN.d.ts} +1 -1
  37. package/dist/serializable.d.ts +1 -1
  38. package/dist/shared-BUHZFGTk.d.ts +34 -0
  39. package/dist/shared-BtPEbm_U.js +437 -0
  40. package/dist/shared-BtPEbm_U.js.map +1 -0
  41. package/dist/{types-B9A8AU7B.d.ts → types-DAHCZC_W.d.ts} +1 -1
  42. package/dist/types.d.ts +1 -1
  43. package/dist/{workflow-types-XmOkuI7A.d.ts → workflow-types-DHs0L0KP.d.ts} +1 -1
  44. package/dist/workflow-types.d.ts +1 -1
  45. package/dist/workflows.d.ts +2 -2
  46. package/dist/workflows.js +1 -1
  47. package/package.json +30 -13
  48. package/dist/src-f7-4oW_C.js +0 -3217
  49. package/dist/src-f7-4oW_C.js.map +0 -1
@@ -0,0 +1,31 @@
1
+ import { t as BrowserToolsOptions } from "../shared-BUHZFGTk.js";
2
+ import { ToolSet } from "ai";
3
+
4
+ //#region src/browser/ai.d.ts
5
+ /**
6
+ * Create AI SDK tools for browser automation via CDP code mode.
7
+ *
8
+ * Returns a `ToolSet` with `search` (query the CDP spec) and
9
+ * `execute` (run CDP commands against a live browser).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { createBrowserTools } from "agents/browser/ai";
14
+ * import { generateText } from "ai";
15
+ *
16
+ * const browserTools = createBrowserTools({
17
+ * browser: env.BROWSER,
18
+ * loader: env.LOADER,
19
+ * });
20
+ *
21
+ * const result = await generateText({
22
+ * model,
23
+ * tools: { ...browserTools, ...otherTools },
24
+ * messages,
25
+ * });
26
+ * ```
27
+ */
28
+ declare function createBrowserTools(options: BrowserToolsOptions): ToolSet;
29
+ //#endregion
30
+ export { type BrowserToolsOptions, createBrowserTools };
31
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { n as SEARCH_DESCRIPTION, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-BtPEbm_U.js";
2
+ import { z } from "zod";
3
+ import { tool } from "ai";
4
+ //#region src/browser/ai.ts
5
+ /**
6
+ * Create AI SDK tools for browser automation via CDP code mode.
7
+ *
8
+ * Returns a `ToolSet` with `search` (query the CDP spec) and
9
+ * `execute` (run CDP commands against a live browser).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { createBrowserTools } from "agents/browser/ai";
14
+ * import { generateText } from "ai";
15
+ *
16
+ * const browserTools = createBrowserTools({
17
+ * browser: env.BROWSER,
18
+ * loader: env.LOADER,
19
+ * });
20
+ *
21
+ * const result = await generateText({
22
+ * model,
23
+ * tools: { ...browserTools, ...otherTools },
24
+ * messages,
25
+ * });
26
+ * ```
27
+ */
28
+ function createBrowserTools(options) {
29
+ const handlers = createBrowserToolHandlers(options);
30
+ return {
31
+ browser_search: tool({
32
+ description: SEARCH_DESCRIPTION,
33
+ inputSchema: z.object({ code: z.string().describe("JavaScript async arrow function that queries the CDP spec") }),
34
+ execute: async ({ code }) => {
35
+ const result = await handlers.search(code);
36
+ if (result.isError) throw new Error(result.text);
37
+ return result.text;
38
+ }
39
+ }),
40
+ browser_execute: tool({
41
+ description: EXECUTE_DESCRIPTION,
42
+ inputSchema: z.object({ code: z.string().describe("JavaScript async arrow function that uses the cdp helper") }),
43
+ execute: async ({ code }) => {
44
+ const result = await handlers.execute(code);
45
+ if (result.isError) throw new Error(result.text);
46
+ return result.text;
47
+ }
48
+ })
49
+ };
50
+ }
51
+ //#endregion
52
+ export { createBrowserTools };
53
+
54
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","names":[],"sources":["../../src/browser/ai.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport { z } from \"zod\";\nimport {\n createBrowserToolHandlers,\n SEARCH_DESCRIPTION,\n EXECUTE_DESCRIPTION,\n type BrowserToolsOptions\n} from \"./shared\";\n\nexport type { BrowserToolsOptions } from \"./shared\";\n\n/**\n * Create AI SDK tools for browser automation via CDP code mode.\n *\n * Returns a `ToolSet` with `search` (query the CDP spec) and\n * `execute` (run CDP commands against a live browser).\n *\n * @example\n * ```ts\n * import { createBrowserTools } from \"agents/browser/ai\";\n * import { generateText } from \"ai\";\n *\n * const browserTools = createBrowserTools({\n * browser: env.BROWSER,\n * loader: env.LOADER,\n * });\n *\n * const result = await generateText({\n * model,\n * tools: { ...browserTools, ...otherTools },\n * messages,\n * });\n * ```\n */\nexport function createBrowserTools(options: BrowserToolsOptions): ToolSet {\n const handlers = createBrowserToolHandlers(options);\n\n return {\n browser_search: tool({\n description: SEARCH_DESCRIPTION,\n inputSchema: z.object({\n code: z\n .string()\n .describe(\"JavaScript async arrow function that queries the CDP spec\")\n }),\n execute: async ({ code }) => {\n const result = await handlers.search(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return result.text;\n }\n }),\n\n browser_execute: tool({\n description: EXECUTE_DESCRIPTION,\n inputSchema: z.object({\n code: z\n .string()\n .describe(\"JavaScript async arrow function that uses the cdp helper\")\n }),\n execute: async ({ code }) => {\n const result = await handlers.execute(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return result.text;\n }\n })\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,mBAAmB,SAAuC;CACxE,MAAM,WAAW,0BAA0B,QAAQ;AAEnD,QAAO;EACL,gBAAgB,KAAK;GACnB,aAAa;GACb,aAAa,EAAE,OAAO,EACpB,MAAM,EACH,QAAQ,CACR,SAAS,4DAA4D,EACzE,CAAC;GACF,SAAS,OAAO,EAAE,WAAW;IAC3B,MAAM,SAAS,MAAM,SAAS,OAAO,KAAK;AAC1C,QAAI,OAAO,QACT,OAAM,IAAI,MAAM,OAAO,KAAK;AAE9B,WAAO,OAAO;;GAEjB,CAAC;EAEF,iBAAiB,KAAK;GACpB,aAAa;GACb,aAAa,EAAE,OAAO,EACpB,MAAM,EACH,QAAQ,CACR,SAAS,2DAA2D,EACxE,CAAC;GACF,SAAS,OAAO,EAAE,WAAW;IAC3B,MAAM,SAAS,MAAM,SAAS,QAAQ,KAAK;AAC3C,QAAI,OAAO,QACT,OAAM,IAAI,MAAM,OAAO,KAAK;AAE9B,WAAO,OAAO;;GAEjB,CAAC;EACH"}
@@ -0,0 +1,51 @@
1
+ import { a as createBrowserToolHandlers, i as ToolResult, n as EXECUTE_DESCRIPTION, r as SEARCH_DESCRIPTION, t as BrowserToolsOptions } from "../shared-BUHZFGTk.js";
2
+
3
+ //#region src/browser/cdp-session.d.ts
4
+ interface DebugEntry {
5
+ at: string;
6
+ type: string;
7
+ [key: string]: unknown;
8
+ }
9
+ interface CdpSendOptions {
10
+ timeoutMs?: number;
11
+ sessionId?: string;
12
+ }
13
+ interface CdpAttachOptions {
14
+ timeoutMs?: number;
15
+ }
16
+ /**
17
+ * A CDP session over an open WebSocket. Manages command correlation,
18
+ * timeouts, target sessions, and a debug event ring buffer.
19
+ *
20
+ * Used host-side (not in the sandbox) — the sandbox calls into this
21
+ * via DynamicWorkerExecutor's ToolDispatcher RPC.
22
+ */
23
+ declare class CdpSession {
24
+ #private;
25
+ constructor(socket: WebSocket, defaultTimeoutMs?: number, dispose?: () => void);
26
+ send(method: string, params?: unknown, options?: CdpSendOptions): Promise<unknown>;
27
+ attachToTarget(targetId: string, options?: CdpAttachOptions): Promise<string>;
28
+ getDebugLog(limit?: number): DebugEntry[];
29
+ clearDebugLog(): void;
30
+ close(): void;
31
+ }
32
+ /**
33
+ * Connect to a browser via the Browser Rendering binding (Fetcher).
34
+ * Establishes a CDP WebSocket through the binding's fetch interface.
35
+ */
36
+ declare function connectBrowser(browser: Fetcher, timeoutMs?: number): Promise<CdpSession>;
37
+ /**
38
+ * Connect to a browser via a CDP base URL (e.g. http://localhost:9222).
39
+ * Discovers the WebSocket debugger URL via /json/version,
40
+ * rewrites localhost URLs to the base URL host, and opens the WebSocket.
41
+ *
42
+ * Useful for local development with `chrome --remote-debugging-port=9222`
43
+ * or when connecting through a tunnel.
44
+ */
45
+ declare function connectUrl(baseUrl: string, options?: {
46
+ timeoutMs?: number;
47
+ headers?: Record<string, string>;
48
+ }): Promise<CdpSession>;
49
+ //#endregion
50
+ export { type BrowserToolsOptions, type CdpAttachOptions, type CdpSendOptions, CdpSession, EXECUTE_DESCRIPTION, SEARCH_DESCRIPTION, type ToolResult, connectBrowser, connectUrl, createBrowserToolHandlers };
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { a as connectBrowser, i as CdpSession, n as SEARCH_DESCRIPTION, o as connectUrl, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-BtPEbm_U.js";
2
+ export { CdpSession, EXECUTE_DESCRIPTION, SEARCH_DESCRIPTION, connectBrowser, connectUrl, createBrowserToolHandlers };
@@ -0,0 +1,31 @@
1
+ import { t as BrowserToolsOptions } from "../shared-BUHZFGTk.js";
2
+ import { ServerTool } from "@tanstack/ai";
3
+
4
+ //#region src/browser/tanstack-ai.d.ts
5
+ /**
6
+ * Create TanStack AI tools for browser automation via CDP code mode.
7
+ *
8
+ * Returns an array of `ServerTool`s: `browser_search` (query the CDP spec)
9
+ * and `browser_execute` (run CDP commands against a live browser).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { createBrowserTools } from "agents/browser/tanstack-ai";
14
+ * import { chat } from "@tanstack/ai";
15
+ *
16
+ * const browserTools = createBrowserTools({
17
+ * browser: env.BROWSER,
18
+ * loader: env.LOADER,
19
+ * });
20
+ *
21
+ * const stream = chat({
22
+ * adapter: openaiText("gpt-4o"),
23
+ * tools: [...browserTools, ...otherTools],
24
+ * messages,
25
+ * });
26
+ * ```
27
+ */
28
+ declare function createBrowserTools(options: BrowserToolsOptions): ServerTool[];
29
+ //#endregion
30
+ export { type BrowserToolsOptions, createBrowserTools };
31
+ //# sourceMappingURL=tanstack-ai.d.ts.map
@@ -0,0 +1,51 @@
1
+ import { n as SEARCH_DESCRIPTION, r as createBrowserToolHandlers, t as EXECUTE_DESCRIPTION } from "../shared-BtPEbm_U.js";
2
+ import { z } from "zod";
3
+ import { toolDefinition } from "@tanstack/ai";
4
+ //#region src/browser/tanstack-ai.ts
5
+ /**
6
+ * Create TanStack AI tools for browser automation via CDP code mode.
7
+ *
8
+ * Returns an array of `ServerTool`s: `browser_search` (query the CDP spec)
9
+ * and `browser_execute` (run CDP commands against a live browser).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { createBrowserTools } from "agents/browser/tanstack-ai";
14
+ * import { chat } from "@tanstack/ai";
15
+ *
16
+ * const browserTools = createBrowserTools({
17
+ * browser: env.BROWSER,
18
+ * loader: env.LOADER,
19
+ * });
20
+ *
21
+ * const stream = chat({
22
+ * adapter: openaiText("gpt-4o"),
23
+ * tools: [...browserTools, ...otherTools],
24
+ * messages,
25
+ * });
26
+ * ```
27
+ */
28
+ function createBrowserTools(options) {
29
+ const handlers = createBrowserToolHandlers(options);
30
+ return [toolDefinition({
31
+ name: "browser_search",
32
+ description: SEARCH_DESCRIPTION,
33
+ inputSchema: z.object({ code: z.string().meta({ description: "JavaScript async arrow function that queries the CDP spec" }) })
34
+ }).server(async ({ code }) => {
35
+ const result = await handlers.search(code);
36
+ if (result.isError) throw new Error(result.text);
37
+ return { text: result.text };
38
+ }), toolDefinition({
39
+ name: "browser_execute",
40
+ description: EXECUTE_DESCRIPTION,
41
+ inputSchema: z.object({ code: z.string().meta({ description: "JavaScript async arrow function that uses the cdp helper" }) })
42
+ }).server(async ({ code }) => {
43
+ const result = await handlers.execute(code);
44
+ if (result.isError) throw new Error(result.text);
45
+ return { text: result.text };
46
+ })];
47
+ }
48
+ //#endregion
49
+ export { createBrowserTools };
50
+
51
+ //# sourceMappingURL=tanstack-ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tanstack-ai.js","names":[],"sources":["../../src/browser/tanstack-ai.ts"],"sourcesContent":["import { toolDefinition } from \"@tanstack/ai\";\nimport type { ServerTool } from \"@tanstack/ai\";\nimport { z } from \"zod\";\nimport {\n createBrowserToolHandlers,\n SEARCH_DESCRIPTION,\n EXECUTE_DESCRIPTION,\n type BrowserToolsOptions\n} from \"./shared\";\n\nexport type { BrowserToolsOptions } from \"./shared\";\n\n/**\n * Create TanStack AI tools for browser automation via CDP code mode.\n *\n * Returns an array of `ServerTool`s: `browser_search` (query the CDP spec)\n * and `browser_execute` (run CDP commands against a live browser).\n *\n * @example\n * ```ts\n * import { createBrowserTools } from \"agents/browser/tanstack-ai\";\n * import { chat } from \"@tanstack/ai\";\n *\n * const browserTools = createBrowserTools({\n * browser: env.BROWSER,\n * loader: env.LOADER,\n * });\n *\n * const stream = chat({\n * adapter: openaiText(\"gpt-4o\"),\n * tools: [...browserTools, ...otherTools],\n * messages,\n * });\n * ```\n */\nexport function createBrowserTools(options: BrowserToolsOptions): ServerTool[] {\n const handlers = createBrowserToolHandlers(options);\n\n const search = toolDefinition({\n name: \"browser_search\" as const,\n description: SEARCH_DESCRIPTION,\n inputSchema: z.object({\n code: z.string().meta({\n description: \"JavaScript async arrow function that queries the CDP spec\"\n })\n })\n }).server(async ({ code }) => {\n const result = await handlers.search(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return { text: result.text };\n });\n\n const execute = toolDefinition({\n name: \"browser_execute\" as const,\n description: EXECUTE_DESCRIPTION,\n inputSchema: z.object({\n code: z.string().meta({\n description: \"JavaScript async arrow function that uses the cdp helper\"\n })\n })\n }).server(async ({ code }) => {\n const result = await handlers.execute(code);\n if (result.isError) {\n throw new Error(result.text);\n }\n return { text: result.text };\n });\n\n return [search, execute];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,mBAAmB,SAA4C;CAC7E,MAAM,WAAW,0BAA0B,QAAQ;AAkCnD,QAAO,CAhCQ,eAAe;EAC5B,MAAM;EACN,aAAa;EACb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,QAAQ,CAAC,KAAK,EACpB,aAAa,6DACd,CAAC,EACH,CAAC;EACH,CAAC,CAAC,OAAO,OAAO,EAAE,WAAW;EAC5B,MAAM,SAAS,MAAM,SAAS,OAAO,KAAK;AAC1C,MAAI,OAAO,QACT,OAAM,IAAI,MAAM,OAAO,KAAK;AAE9B,SAAO,EAAE,MAAM,OAAO,MAAM;GAC5B,EAEc,eAAe;EAC7B,MAAM;EACN,aAAa;EACb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,QAAQ,CAAC,KAAK,EACpB,aAAa,4DACd,CAAC,EACH,CAAC;EACH,CAAC,CAAC,OAAO,OAAO,EAAE,WAAW;EAC5B,MAAM,SAAS,MAAM,SAAS,QAAQ,KAAK;AAC3C,MAAI,OAAO,QACT,OAAM,IAAI,MAAM,OAAO,KAAK;AAE9B,SAAO,EAAE,MAAM,OAAO,MAAM;GAC5B,CAEsB"}
@@ -0,0 +1,27 @@
1
+ //#region \0@oxc-project+runtime@0.124.0/helpers/checkPrivateRedeclaration.js
2
+ function _checkPrivateRedeclaration(e, t) {
3
+ if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
4
+ }
5
+ //#endregion
6
+ //#region \0@oxc-project+runtime@0.124.0/helpers/classPrivateFieldInitSpec.js
7
+ function _classPrivateFieldInitSpec(e, t, a) {
8
+ _checkPrivateRedeclaration(e, t), t.set(e, a);
9
+ }
10
+ //#endregion
11
+ //#region \0@oxc-project+runtime@0.124.0/helpers/assertClassBrand.js
12
+ function _assertClassBrand(e, t, n) {
13
+ if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
14
+ throw new TypeError("Private element is not present on this object");
15
+ }
16
+ //#endregion
17
+ //#region \0@oxc-project+runtime@0.124.0/helpers/classPrivateFieldSet2.js
18
+ function _classPrivateFieldSet2(s, a, r) {
19
+ return s.set(_assertClassBrand(s, a), r), r;
20
+ }
21
+ //#endregion
22
+ //#region \0@oxc-project+runtime@0.124.0/helpers/classPrivateFieldGet2.js
23
+ function _classPrivateFieldGet2(s, a) {
24
+ return s.get(_assertClassBrand(s, a));
25
+ }
26
+ //#endregion
27
+ export { _checkPrivateRedeclaration as a, _classPrivateFieldInitSpec as i, _classPrivateFieldSet2 as n, _assertClassBrand as r, _classPrivateFieldGet2 as t };
package/dist/client.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { r as Agent } from "./index-D2lfljd3.js";
1
+ import { r as Agent } from "./index-C_XD19E3.js";
2
2
  import {
3
3
  i as SerializableValue,
4
4
  n as RPCMethod,
5
5
  r as SerializableReturnValue,
6
6
  t as Method
7
- } from "./serializable-DGdO8CDh.js";
7
+ } from "./serializable-Bg8ARWlN.js";
8
8
  import {
9
9
  PartyFetchOptions,
10
10
  PartySocket,
@@ -309,4 +309,4 @@ function createCompactFunction(opts) {
309
309
  //#endregion
310
310
  export { computeSummaryBudget as a, isCompactionMessage as c, TOKENS_PER_MESSAGE as d, WORDS_TOKEN_MULTIPLIER as f, buildSummaryPrompt as i, sanitizeToolPairs as l, estimateStringTokens as m, alignBoundaryBackward as n, createCompactFunction as o, estimateMessageTokens as p, alignBoundaryForward as r, findTailCutByTokens as s, COMPACTION_PREFIX as t, CHARS_PER_TOKEN as u };
311
311
 
312
- //# sourceMappingURL=compaction-helpers-BPE1_ziA.js.map
312
+ //# sourceMappingURL=compaction-helpers-C_cN3z55.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compaction-helpers-BPE1_ziA.js","names":[],"sources":["../src/experimental/memory/utils/tokens.ts","../src/experimental/memory/utils/compaction-helpers.ts"],"sourcesContent":["/**\n * Token Estimation Utilities\n *\n * IMPORTANT: These are heuristic estimates, not actual tokenizer counts.\n *\n * We intentionally avoid real tokenizers (e.g. tiktoken, sentencepiece) because:\n * - A single tiktoken instance costs ~80-120MB of heap\n * - Cloudflare Workers have tight memory limits (128MB)\n * - For compaction thresholds, a conservative estimate is sufficient\n *\n * The hybrid approach (max of character-based and word-based estimates) handles\n * both dense token content (JSON, code) and natural language reasonably well.\n *\n * Calibration notes:\n * - Character-based: ~4 chars per token (conservative, from OpenAI guidance)\n * - Word-based: ~1.3 tokens per word (empirical, from Mastra's memory system)\n * - Per-message overhead: ~4 tokens for role/framing (empirical)\n *\n * These ratios are tuned for English. CJK, emoji-heavy, or highly technical\n * content may have different ratios. The conservative estimates help ensure\n * compaction triggers before context windows are actually exceeded.\n */\n\nimport type { SessionMessage } from \"../session/types\";\n\n/** Approximate characters per token for English text */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Approximate token multiplier per whitespace-separated word */\nexport const WORDS_TOKEN_MULTIPLIER = 1.3;\n\n/** Approximate overhead tokens per message (role, framing) */\nexport const TOKENS_PER_MESSAGE = 4;\n\n/**\n * Estimate token count for a string using a hybrid heuristic.\n *\n * Takes the max of two estimates:\n * - Character-based: `length / 4` — better for dense content (JSON, code, URLs)\n * - Word-based: `words * 1.3` — better for natural language prose\n *\n * This is a heuristic. Do not use where exact counts are required.\n */\nexport function estimateStringTokens(text: string): number {\n if (!text) return 0;\n const charEstimate = text.length / CHARS_PER_TOKEN;\n const wordEstimate =\n text.split(/\\s+/).filter(Boolean).length * WORDS_TOKEN_MULTIPLIER;\n return Math.ceil(Math.max(charEstimate, wordEstimate));\n}\n\n/**\n * Estimate total token count for an array of UIMessages.\n *\n * Walks each message's parts (text, tool invocations, tool results)\n * and applies per-message overhead.\n *\n * This is a heuristic. Do not use where exact counts are required.\n */\nexport function estimateMessageTokens(messages: SessionMessage[]): number {\n let tokens = 0;\n for (const msg of messages) {\n tokens += TOKENS_PER_MESSAGE;\n for (const part of msg.parts) {\n if (part.type === \"text\") {\n tokens += estimateStringTokens(\n (part as { type: \"text\"; text: string }).text\n );\n } else if (\n part.type.startsWith(\"tool-\") ||\n part.type === \"dynamic-tool\"\n ) {\n const toolPart = part as { input?: unknown; output?: unknown };\n if (toolPart.input) {\n tokens += estimateStringTokens(JSON.stringify(toolPart.input));\n }\n if (toolPart.output) {\n tokens += estimateStringTokens(JSON.stringify(toolPart.output));\n }\n }\n }\n }\n return tokens;\n}\n","/**\n * Compaction Helpers\n *\n * Utilities for full compaction (LLM-based summarization).\n * Used by the reference compaction implementation and available\n * for custom CompactFunction implementations.\n */\n\nimport type { SessionMessage } from \"../session/types\";\nimport { estimateMessageTokens } from \"./tokens\";\n\n// ── Compaction ID constants ─────────────────────────────────────────\n\n/** Prefix for all compaction messages (overlays and summaries) */\nexport const COMPACTION_PREFIX = \"compaction_\";\n\n/** Check if a message is a compaction message */\nexport function isCompactionMessage(msg: SessionMessage): boolean {\n return msg.id.startsWith(COMPACTION_PREFIX);\n}\n\n// ── Tool Pair Alignment ──────────────────────────────────────────────\n\n/**\n * Check if a message contains tool invocations.\n */\nfunction hasToolCalls(msg: SessionMessage): boolean {\n return msg.parts.some(\n (p) => p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\"\n );\n}\n\n/**\n * Get tool call IDs from a message's parts.\n */\nfunction getToolCallIds(msg: SessionMessage): Set<string> {\n const ids = new Set<string>();\n for (const part of msg.parts) {\n if (\n (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") &&\n \"toolCallId\" in part\n ) {\n ids.add((part as { toolCallId: string }).toolCallId);\n }\n }\n return ids;\n}\n\n/**\n * Check if a message is a tool result referencing a specific call ID.\n */\nfunction isToolResultFor(msg: SessionMessage, callIds: Set<string>): boolean {\n return msg.parts.some(\n (p) =>\n (p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\") &&\n \"toolCallId\" in p &&\n callIds.has((p as { toolCallId: string }).toolCallId)\n );\n}\n\n/**\n * Align a boundary index forward to avoid splitting tool call/result groups.\n * If the boundary falls between an assistant message with tool calls and its\n * tool results, move it forward past the results.\n */\nexport function alignBoundaryForward(\n messages: SessionMessage[],\n idx: number\n): number {\n if (idx <= 0 || idx >= messages.length) return idx;\n\n // Check if the message before the boundary has tool calls\n const prev = messages[idx - 1];\n if (prev.role === \"assistant\" && hasToolCalls(prev)) {\n const callIds = getToolCallIds(prev);\n // Skip forward past any tool results for these calls\n while (idx < messages.length && isToolResultFor(messages[idx], callIds)) {\n idx++;\n }\n }\n\n return idx;\n}\n\n/**\n * Align a boundary index backward to avoid splitting tool call/result groups.\n * If the boundary falls in the middle of tool results, move it backward to\n * include the assistant message that made the calls.\n */\nexport function alignBoundaryBackward(\n messages: SessionMessage[],\n idx: number\n): number {\n if (idx <= 0 || idx >= messages.length) return idx;\n\n // If the message at idx is a tool result, walk backward to find the call\n while (idx > 0) {\n const msg = messages[idx];\n if (msg.role === \"assistant\" && hasToolCalls(msg)) {\n break; // This is a tool call message — include it\n }\n // Check if this looks like a tool result (assistant message following another)\n const prev = messages[idx - 1];\n if (prev.role === \"assistant\" && hasToolCalls(prev)) {\n const callIds = getToolCallIds(prev);\n if (isToolResultFor(msg, callIds)) {\n idx--; // Move back to include the call\n continue;\n }\n }\n break;\n }\n\n return idx;\n}\n\n// ── Token-Budget Tail Protection ─────────────────────────────────────\n\n/**\n * Find the compression end boundary using a token budget for the tail.\n * Walks backward from the end, accumulating tokens until budget is reached.\n * Returns the index where compression should stop (everything from this\n * index onward is protected).\n *\n * @param messages All messages\n * @param headEnd Index where the protected head ends (compression starts here)\n * @param tailTokenBudget Maximum tokens to keep in the tail\n * @param minTailMessages Minimum messages to protect in the tail (fallback)\n */\nexport function findTailCutByTokens(\n messages: SessionMessage[],\n headEnd: number,\n tailTokenBudget = 20000,\n minTailMessages = 2\n): number {\n const n = messages.length;\n let accumulated = 0;\n let tokenCut = n;\n\n for (let i = n - 1; i >= headEnd; i--) {\n const msgTokens = estimateMessageTokens([messages[i]]);\n\n if (accumulated + msgTokens > tailTokenBudget && tokenCut < n) {\n // Budget exceeded and we already have at least one tail message\n break;\n }\n accumulated += msgTokens;\n tokenCut = i;\n }\n\n // Protect whichever is larger: token-based tail or minTailMessages\n const minCut = n - minTailMessages;\n const cutIdx = minCut >= headEnd ? Math.min(tokenCut, minCut) : tokenCut;\n\n // Align to avoid splitting tool groups\n return alignBoundaryBackward(messages, cutIdx);\n}\n\n// ── Tool Pair Sanitization ───────────────────────────────────────────\n\n/**\n * Fix orphaned tool call/result pairs after compaction.\n *\n * Two failure modes:\n * 1. Tool result references a call_id whose assistant tool_call was removed\n * → Remove the orphaned result\n * 2. Assistant has tool_calls whose results were dropped\n * → Add stub results so the API doesn't error\n *\n * @param messages Messages after compaction\n * @returns Sanitized messages with no orphaned pairs\n */\nexport function sanitizeToolPairs(\n messages: SessionMessage[]\n): SessionMessage[] {\n // Build set of surviving tool call IDs (from assistant messages)\n const survivingCallIds = new Set<string>();\n for (const msg of messages) {\n if (msg.role === \"assistant\") {\n for (const id of getToolCallIds(msg)) {\n survivingCallIds.add(id);\n }\n }\n }\n\n // Build set of tool result IDs\n const resultCallIds = new Set<string>();\n for (const msg of messages) {\n for (const part of msg.parts) {\n if (\n (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") &&\n \"toolCallId\" in part &&\n \"output\" in part\n ) {\n resultCallIds.add((part as { toolCallId: string }).toolCallId);\n }\n }\n }\n\n // Remove orphaned results (results whose calls were dropped)\n const orphanedResults = new Set<string>();\n for (const id of resultCallIds) {\n if (!survivingCallIds.has(id)) {\n orphanedResults.add(id);\n }\n }\n\n let result = messages;\n if (orphanedResults.size > 0) {\n result = result.map((msg) => {\n const filteredParts = msg.parts.filter((part) => {\n if (\n (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") &&\n \"toolCallId\" in part &&\n \"output\" in part\n ) {\n return !orphanedResults.has(\n (part as { toolCallId: string }).toolCallId\n );\n }\n return true;\n });\n if (filteredParts.length !== msg.parts.length) {\n return { ...msg, parts: filteredParts } as SessionMessage;\n }\n return msg;\n });\n }\n\n // Add stub results for calls whose results were dropped\n const missingResults = new Set<string>();\n for (const id of survivingCallIds) {\n if (!resultCallIds.has(id) && !orphanedResults.has(id)) {\n missingResults.add(id);\n }\n }\n\n if (missingResults.size > 0) {\n const patched: SessionMessage[] = [];\n for (const msg of result) {\n patched.push(msg);\n if (msg.role === \"assistant\") {\n for (const id of getToolCallIds(msg)) {\n if (missingResults.has(id)) {\n // Find the tool name from the call\n const callPart = msg.parts.find(\n (p) =>\n \"toolCallId\" in p &&\n (p as { toolCallId: string }).toolCallId === id\n ) as { toolName?: string } | undefined;\n\n patched.push({\n id: `stub-${id}`,\n role: \"assistant\",\n parts: [\n {\n type: \"tool-result\" as const,\n toolCallId: id,\n toolName: callPart?.toolName ?? \"unknown\",\n result:\n \"[Result from earlier conversation — see context summary above]\"\n } as unknown as SessionMessage[\"parts\"][number]\n ],\n createdAt: new Date()\n } as SessionMessage);\n }\n }\n }\n }\n result = patched;\n }\n\n // Remove empty messages (all parts filtered out)\n return result.filter((msg) => msg.parts.length > 0);\n}\n\n// ── Summary Budget ───────────────────────────────────────────────────\n\n/**\n * Compute a summary token budget based on the content being compressed.\n * 20% of the compressed content, clamped to 2K-8K tokens.\n */\nexport function computeSummaryBudget(messages: SessionMessage[]): number {\n const contentTokens = estimateMessageTokens(messages);\n // Summary is ~20% of the content being compressed.\n // The summary replaces the compressed middle, so it's sized relative\n // to what it's replacing — not the tail budget (they occupy different\n // slots in the context window).\n const budget = Math.floor(contentTokens * 0.2);\n return Math.max(100, budget);\n}\n\n// ── Structured Summary Prompt ────────────────────────────────────────\n\n/**\n * Build a prompt for LLM summarization of compressed messages.\n *\n * @param messages Messages to summarize\n * @param previousSummary Previous summary for iterative updates (or null for first compaction)\n * @param budget Target token count for the summary\n */\nexport function buildSummaryPrompt(\n messages: SessionMessage[],\n previousSummary: string | null,\n budget: number\n): string {\n const content = messages\n .map((msg) => {\n const textParts = msg.parts\n .filter((p) => p.type === \"text\")\n .map((p) => (p as { text: string }).text)\n .join(\"\\n\");\n\n const toolParts = msg.parts\n .filter((p) => p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\")\n .map((p) => {\n const tp = p as {\n toolName?: string;\n input?: unknown;\n output?: unknown;\n };\n const parts = [`[Tool: ${tp.toolName ?? \"unknown\"}]`];\n if (tp.input)\n parts.push(`Input: ${JSON.stringify(tp.input).slice(0, 500)}`);\n if (tp.output)\n parts.push(`Output: ${String(tp.output).slice(0, 500)}`);\n return parts.join(\"\\n\");\n })\n .join(\"\\n\");\n\n return `[${msg.role}]\\n${textParts}${toolParts ? \"\\n\" + toolParts : \"\"}`;\n })\n .join(\"\\n\\n---\\n\\n\");\n\n if (previousSummary) {\n return `You are updating a conversation summary. A previous summary exists below. New conversation turns have occurred since then and need to be incorporated.\n\nPREVIOUS SUMMARY:\n${previousSummary}\n\nNEW TURNS TO INCORPORATE:\n${content}\n\nUpdate the summary. PRESERVE existing information that is still relevant. ADD new information. Remove information only if it is clearly obsolete.\n\n## Topic\n[What the conversation is about]\n\n## Key Points\n[Important information, decisions, and conclusions from the conversation]\n\n## Current State\n[Where things stand now — what has been done, what is in progress]\n\n## Open Items\n[Unresolved questions, pending tasks, or next steps discussed]\n\nTarget ~${budget} tokens. Be factual — only include information that was explicitly discussed in the conversation. Do NOT invent file paths, commands, or details that were not mentioned. Write only the summary body.`;\n }\n\n return `Create a concise summary of this conversation that preserves the important information for future context.\n\nCONVERSATION TO SUMMARIZE:\n${content}\n\nUse this structure:\n\n## Topic\n[What the conversation is about]\n\n## Key Points\n[Important information, decisions, and conclusions from the conversation]\n\n## Current State\n[Where things stand now — what has been done, what is in progress]\n\n## Open Items\n[Unresolved questions, pending tasks, or next steps discussed]\n\nTarget ~${budget} tokens. Be factual — only include information that was explicitly discussed in the conversation. Do NOT invent file paths, commands, or details that were not mentioned. Write only the summary body.`;\n}\n\n// ── Reference Compaction Implementation ──────────────────────────────\n\n/**\n * Result of a compaction function — describes the overlay to store.\n */\nexport interface CompactResult {\n /** First message ID in the compacted range */\n fromMessageId: string;\n /** Last message ID in the compacted range */\n toMessageId: string;\n /** Summary text to store as the overlay */\n summary: string;\n}\n\nexport interface CompactOptions {\n /**\n * Function to call the LLM for summarization.\n * Takes a user prompt string, returns the LLM's text response.\n */\n summarize: (prompt: string) => Promise<string>;\n\n /** Number of head messages to protect (default: 2) */\n protectHead?: number;\n\n /** Token budget for tail protection (default: 20000) */\n tailTokenBudget?: number;\n\n /** Minimum tail messages to protect (default: 2) */\n minTailMessages?: number;\n}\n\n/**\n * Reference compaction implementation.\n *\n * Implements the full hermes-style compaction algorithm:\n * 1. Protect head messages (first N)\n * 2. Protect tail by token budget (walk backward)\n * 3. Align boundaries to tool call groups\n * 4. Summarize middle section with LLM (structured format)\n * 5. Sanitize orphaned tool pairs\n * 6. Iterative summary updates on subsequent compactions\n *\n * @example\n * ```typescript\n * import { createCompactFunction } from \"agents/experimental/memory/utils\";\n *\n * const session = new Session(provider, {\n * compaction: {\n * tokenThreshold: 100000,\n * fn: createCompactFunction({\n * summarize: (prompt) => generateText({ model, prompt }).then(r => r.text)\n * })\n * }\n * });\n * ```\n */\nexport function createCompactFunction(opts: CompactOptions) {\n const protectHead = opts.protectHead ?? 3;\n const tailTokenBudget = opts.tailTokenBudget ?? 20000;\n const minTailMessages = opts.minTailMessages ?? 2;\n\n return async (messages: SessionMessage[]): Promise<CompactResult | null> => {\n if (messages.length <= protectHead + minTailMessages) {\n return null;\n }\n\n // 1. Find compression boundaries\n let compressStart = protectHead;\n compressStart = alignBoundaryForward(messages, compressStart);\n\n let compressEnd = findTailCutByTokens(\n messages,\n compressStart,\n tailTokenBudget,\n minTailMessages\n );\n\n if (compressEnd <= compressStart) {\n return null;\n }\n\n // Filter out compaction overlay messages — they have virtual IDs\n // and should not be included in the summary prompt or used as range IDs\n const middleMessages = messages\n .slice(compressStart, compressEnd)\n .filter((m) => !isCompactionMessage(m));\n\n if (middleMessages.length === 0) return null;\n\n // 2. Generate summary — extract previous summary from compaction overlays\n const existingCompaction = messages.find(isCompactionMessage);\n const previousSummary = existingCompaction\n ? existingCompaction.parts\n .filter((p) => p.type === \"text\")\n .map((p) => (p as { text: string }).text)\n .join(\"\\n\")\n : null;\n\n const budget = computeSummaryBudget(middleMessages);\n const prompt = buildSummaryPrompt(middleMessages, previousSummary, budget);\n const summary = await opts.summarize(prompt);\n\n if (!summary.trim()) return null;\n\n return {\n fromMessageId: middleMessages[0].id,\n toMessageId: middleMessages[middleMessages.length - 1].id,\n summary\n };\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"compaction-helpers-C_cN3z55.js","names":[],"sources":["../src/experimental/memory/utils/tokens.ts","../src/experimental/memory/utils/compaction-helpers.ts"],"sourcesContent":["/**\n * Token Estimation Utilities\n *\n * IMPORTANT: These are heuristic estimates, not actual tokenizer counts.\n *\n * We intentionally avoid real tokenizers (e.g. tiktoken, sentencepiece) because:\n * - A single tiktoken instance costs ~80-120MB of heap\n * - Cloudflare Workers have tight memory limits (128MB)\n * - For compaction thresholds, a conservative estimate is sufficient\n *\n * The hybrid approach (max of character-based and word-based estimates) handles\n * both dense token content (JSON, code) and natural language reasonably well.\n *\n * Calibration notes:\n * - Character-based: ~4 chars per token (conservative, from OpenAI guidance)\n * - Word-based: ~1.3 tokens per word (empirical, from Mastra's memory system)\n * - Per-message overhead: ~4 tokens for role/framing (empirical)\n *\n * These ratios are tuned for English. CJK, emoji-heavy, or highly technical\n * content may have different ratios. The conservative estimates help ensure\n * compaction triggers before context windows are actually exceeded.\n */\n\nimport type { SessionMessage } from \"../session/types\";\n\n/** Approximate characters per token for English text */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Approximate token multiplier per whitespace-separated word */\nexport const WORDS_TOKEN_MULTIPLIER = 1.3;\n\n/** Approximate overhead tokens per message (role, framing) */\nexport const TOKENS_PER_MESSAGE = 4;\n\n/**\n * Estimate token count for a string using a hybrid heuristic.\n *\n * Takes the max of two estimates:\n * - Character-based: `length / 4` — better for dense content (JSON, code, URLs)\n * - Word-based: `words * 1.3` — better for natural language prose\n *\n * This is a heuristic. Do not use where exact counts are required.\n */\nexport function estimateStringTokens(text: string): number {\n if (!text) return 0;\n const charEstimate = text.length / CHARS_PER_TOKEN;\n const wordEstimate =\n text.split(/\\s+/).filter(Boolean).length * WORDS_TOKEN_MULTIPLIER;\n return Math.ceil(Math.max(charEstimate, wordEstimate));\n}\n\n/**\n * Estimate total token count for an array of UIMessages.\n *\n * Walks each message's parts (text, tool invocations, tool results)\n * and applies per-message overhead.\n *\n * This is a heuristic. Do not use where exact counts are required.\n */\nexport function estimateMessageTokens(messages: SessionMessage[]): number {\n let tokens = 0;\n for (const msg of messages) {\n tokens += TOKENS_PER_MESSAGE;\n for (const part of msg.parts) {\n if (part.type === \"text\") {\n tokens += estimateStringTokens(\n (part as { type: \"text\"; text: string }).text\n );\n } else if (\n part.type.startsWith(\"tool-\") ||\n part.type === \"dynamic-tool\"\n ) {\n const toolPart = part as { input?: unknown; output?: unknown };\n if (toolPart.input) {\n tokens += estimateStringTokens(JSON.stringify(toolPart.input));\n }\n if (toolPart.output) {\n tokens += estimateStringTokens(JSON.stringify(toolPart.output));\n }\n }\n }\n }\n return tokens;\n}\n","/**\n * Compaction Helpers\n *\n * Utilities for full compaction (LLM-based summarization).\n * Used by the reference compaction implementation and available\n * for custom CompactFunction implementations.\n */\n\nimport type { SessionMessage } from \"../session/types\";\nimport { estimateMessageTokens } from \"./tokens\";\n\n// ── Compaction ID constants ─────────────────────────────────────────\n\n/** Prefix for all compaction messages (overlays and summaries) */\nexport const COMPACTION_PREFIX = \"compaction_\";\n\n/** Check if a message is a compaction message */\nexport function isCompactionMessage(msg: SessionMessage): boolean {\n return msg.id.startsWith(COMPACTION_PREFIX);\n}\n\n// ── Tool Pair Alignment ──────────────────────────────────────────────\n\n/**\n * Check if a message contains tool invocations.\n */\nfunction hasToolCalls(msg: SessionMessage): boolean {\n return msg.parts.some(\n (p) => p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\"\n );\n}\n\n/**\n * Get tool call IDs from a message's parts.\n */\nfunction getToolCallIds(msg: SessionMessage): Set<string> {\n const ids = new Set<string>();\n for (const part of msg.parts) {\n if (\n (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") &&\n \"toolCallId\" in part\n ) {\n ids.add((part as { toolCallId: string }).toolCallId);\n }\n }\n return ids;\n}\n\n/**\n * Check if a message is a tool result referencing a specific call ID.\n */\nfunction isToolResultFor(msg: SessionMessage, callIds: Set<string>): boolean {\n return msg.parts.some(\n (p) =>\n (p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\") &&\n \"toolCallId\" in p &&\n callIds.has((p as { toolCallId: string }).toolCallId)\n );\n}\n\n/**\n * Align a boundary index forward to avoid splitting tool call/result groups.\n * If the boundary falls between an assistant message with tool calls and its\n * tool results, move it forward past the results.\n */\nexport function alignBoundaryForward(\n messages: SessionMessage[],\n idx: number\n): number {\n if (idx <= 0 || idx >= messages.length) return idx;\n\n // Check if the message before the boundary has tool calls\n const prev = messages[idx - 1];\n if (prev.role === \"assistant\" && hasToolCalls(prev)) {\n const callIds = getToolCallIds(prev);\n // Skip forward past any tool results for these calls\n while (idx < messages.length && isToolResultFor(messages[idx], callIds)) {\n idx++;\n }\n }\n\n return idx;\n}\n\n/**\n * Align a boundary index backward to avoid splitting tool call/result groups.\n * If the boundary falls in the middle of tool results, move it backward to\n * include the assistant message that made the calls.\n */\nexport function alignBoundaryBackward(\n messages: SessionMessage[],\n idx: number\n): number {\n if (idx <= 0 || idx >= messages.length) return idx;\n\n // If the message at idx is a tool result, walk backward to find the call\n while (idx > 0) {\n const msg = messages[idx];\n if (msg.role === \"assistant\" && hasToolCalls(msg)) {\n break; // This is a tool call message — include it\n }\n // Check if this looks like a tool result (assistant message following another)\n const prev = messages[idx - 1];\n if (prev.role === \"assistant\" && hasToolCalls(prev)) {\n const callIds = getToolCallIds(prev);\n if (isToolResultFor(msg, callIds)) {\n idx--; // Move back to include the call\n continue;\n }\n }\n break;\n }\n\n return idx;\n}\n\n// ── Token-Budget Tail Protection ─────────────────────────────────────\n\n/**\n * Find the compression end boundary using a token budget for the tail.\n * Walks backward from the end, accumulating tokens until budget is reached.\n * Returns the index where compression should stop (everything from this\n * index onward is protected).\n *\n * @param messages All messages\n * @param headEnd Index where the protected head ends (compression starts here)\n * @param tailTokenBudget Maximum tokens to keep in the tail\n * @param minTailMessages Minimum messages to protect in the tail (fallback)\n */\nexport function findTailCutByTokens(\n messages: SessionMessage[],\n headEnd: number,\n tailTokenBudget = 20000,\n minTailMessages = 2\n): number {\n const n = messages.length;\n let accumulated = 0;\n let tokenCut = n;\n\n for (let i = n - 1; i >= headEnd; i--) {\n const msgTokens = estimateMessageTokens([messages[i]]);\n\n if (accumulated + msgTokens > tailTokenBudget && tokenCut < n) {\n // Budget exceeded and we already have at least one tail message\n break;\n }\n accumulated += msgTokens;\n tokenCut = i;\n }\n\n // Protect whichever is larger: token-based tail or minTailMessages\n const minCut = n - minTailMessages;\n const cutIdx = minCut >= headEnd ? Math.min(tokenCut, minCut) : tokenCut;\n\n // Align to avoid splitting tool groups\n return alignBoundaryBackward(messages, cutIdx);\n}\n\n// ── Tool Pair Sanitization ───────────────────────────────────────────\n\n/**\n * Fix orphaned tool call/result pairs after compaction.\n *\n * Two failure modes:\n * 1. Tool result references a call_id whose assistant tool_call was removed\n * → Remove the orphaned result\n * 2. Assistant has tool_calls whose results were dropped\n * → Add stub results so the API doesn't error\n *\n * @param messages Messages after compaction\n * @returns Sanitized messages with no orphaned pairs\n */\nexport function sanitizeToolPairs(\n messages: SessionMessage[]\n): SessionMessage[] {\n // Build set of surviving tool call IDs (from assistant messages)\n const survivingCallIds = new Set<string>();\n for (const msg of messages) {\n if (msg.role === \"assistant\") {\n for (const id of getToolCallIds(msg)) {\n survivingCallIds.add(id);\n }\n }\n }\n\n // Build set of tool result IDs\n const resultCallIds = new Set<string>();\n for (const msg of messages) {\n for (const part of msg.parts) {\n if (\n (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") &&\n \"toolCallId\" in part &&\n \"output\" in part\n ) {\n resultCallIds.add((part as { toolCallId: string }).toolCallId);\n }\n }\n }\n\n // Remove orphaned results (results whose calls were dropped)\n const orphanedResults = new Set<string>();\n for (const id of resultCallIds) {\n if (!survivingCallIds.has(id)) {\n orphanedResults.add(id);\n }\n }\n\n let result = messages;\n if (orphanedResults.size > 0) {\n result = result.map((msg) => {\n const filteredParts = msg.parts.filter((part) => {\n if (\n (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") &&\n \"toolCallId\" in part &&\n \"output\" in part\n ) {\n return !orphanedResults.has(\n (part as { toolCallId: string }).toolCallId\n );\n }\n return true;\n });\n if (filteredParts.length !== msg.parts.length) {\n return { ...msg, parts: filteredParts } as SessionMessage;\n }\n return msg;\n });\n }\n\n // Add stub results for calls whose results were dropped\n const missingResults = new Set<string>();\n for (const id of survivingCallIds) {\n if (!resultCallIds.has(id) && !orphanedResults.has(id)) {\n missingResults.add(id);\n }\n }\n\n if (missingResults.size > 0) {\n const patched: SessionMessage[] = [];\n for (const msg of result) {\n patched.push(msg);\n if (msg.role === \"assistant\") {\n for (const id of getToolCallIds(msg)) {\n if (missingResults.has(id)) {\n // Find the tool name from the call\n const callPart = msg.parts.find(\n (p) =>\n \"toolCallId\" in p &&\n (p as { toolCallId: string }).toolCallId === id\n ) as { toolName?: string } | undefined;\n\n patched.push({\n id: `stub-${id}`,\n role: \"assistant\",\n parts: [\n {\n type: \"tool-result\" as const,\n toolCallId: id,\n toolName: callPart?.toolName ?? \"unknown\",\n result:\n \"[Result from earlier conversation — see context summary above]\"\n } as unknown as SessionMessage[\"parts\"][number]\n ],\n createdAt: new Date()\n } as SessionMessage);\n }\n }\n }\n }\n result = patched;\n }\n\n // Remove empty messages (all parts filtered out)\n return result.filter((msg) => msg.parts.length > 0);\n}\n\n// ── Summary Budget ───────────────────────────────────────────────────\n\n/**\n * Compute a summary token budget based on the content being compressed.\n * 20% of the compressed content, clamped to 2K-8K tokens.\n */\nexport function computeSummaryBudget(messages: SessionMessage[]): number {\n const contentTokens = estimateMessageTokens(messages);\n // Summary is ~20% of the content being compressed.\n // The summary replaces the compressed middle, so it's sized relative\n // to what it's replacing — not the tail budget (they occupy different\n // slots in the context window).\n const budget = Math.floor(contentTokens * 0.2);\n return Math.max(100, budget);\n}\n\n// ── Structured Summary Prompt ────────────────────────────────────────\n\n/**\n * Build a prompt for LLM summarization of compressed messages.\n *\n * @param messages Messages to summarize\n * @param previousSummary Previous summary for iterative updates (or null for first compaction)\n * @param budget Target token count for the summary\n */\nexport function buildSummaryPrompt(\n messages: SessionMessage[],\n previousSummary: string | null,\n budget: number\n): string {\n const content = messages\n .map((msg) => {\n const textParts = msg.parts\n .filter((p) => p.type === \"text\")\n .map((p) => (p as { text: string }).text)\n .join(\"\\n\");\n\n const toolParts = msg.parts\n .filter((p) => p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\")\n .map((p) => {\n const tp = p as {\n toolName?: string;\n input?: unknown;\n output?: unknown;\n };\n const parts = [`[Tool: ${tp.toolName ?? \"unknown\"}]`];\n if (tp.input)\n parts.push(`Input: ${JSON.stringify(tp.input).slice(0, 500)}`);\n if (tp.output)\n parts.push(`Output: ${String(tp.output).slice(0, 500)}`);\n return parts.join(\"\\n\");\n })\n .join(\"\\n\");\n\n return `[${msg.role}]\\n${textParts}${toolParts ? \"\\n\" + toolParts : \"\"}`;\n })\n .join(\"\\n\\n---\\n\\n\");\n\n if (previousSummary) {\n return `You are updating a conversation summary. A previous summary exists below. New conversation turns have occurred since then and need to be incorporated.\n\nPREVIOUS SUMMARY:\n${previousSummary}\n\nNEW TURNS TO INCORPORATE:\n${content}\n\nUpdate the summary. PRESERVE existing information that is still relevant. ADD new information. Remove information only if it is clearly obsolete.\n\n## Topic\n[What the conversation is about]\n\n## Key Points\n[Important information, decisions, and conclusions from the conversation]\n\n## Current State\n[Where things stand now — what has been done, what is in progress]\n\n## Open Items\n[Unresolved questions, pending tasks, or next steps discussed]\n\nTarget ~${budget} tokens. Be factual — only include information that was explicitly discussed in the conversation. Do NOT invent file paths, commands, or details that were not mentioned. Write only the summary body.`;\n }\n\n return `Create a concise summary of this conversation that preserves the important information for future context.\n\nCONVERSATION TO SUMMARIZE:\n${content}\n\nUse this structure:\n\n## Topic\n[What the conversation is about]\n\n## Key Points\n[Important information, decisions, and conclusions from the conversation]\n\n## Current State\n[Where things stand now — what has been done, what is in progress]\n\n## Open Items\n[Unresolved questions, pending tasks, or next steps discussed]\n\nTarget ~${budget} tokens. Be factual — only include information that was explicitly discussed in the conversation. Do NOT invent file paths, commands, or details that were not mentioned. Write only the summary body.`;\n}\n\n// ── Reference Compaction Implementation ──────────────────────────────\n\n/**\n * Result of a compaction function — describes the overlay to store.\n */\nexport interface CompactResult {\n /** First message ID in the compacted range */\n fromMessageId: string;\n /** Last message ID in the compacted range */\n toMessageId: string;\n /** Summary text to store as the overlay */\n summary: string;\n}\n\nexport interface CompactOptions {\n /**\n * Function to call the LLM for summarization.\n * Takes a user prompt string, returns the LLM's text response.\n */\n summarize: (prompt: string) => Promise<string>;\n\n /** Number of head messages to protect (default: 2) */\n protectHead?: number;\n\n /** Token budget for tail protection (default: 20000) */\n tailTokenBudget?: number;\n\n /** Minimum tail messages to protect (default: 2) */\n minTailMessages?: number;\n}\n\n/**\n * Reference compaction implementation.\n *\n * Implements the full hermes-style compaction algorithm:\n * 1. Protect head messages (first N)\n * 2. Protect tail by token budget (walk backward)\n * 3. Align boundaries to tool call groups\n * 4. Summarize middle section with LLM (structured format)\n * 5. Sanitize orphaned tool pairs\n * 6. Iterative summary updates on subsequent compactions\n *\n * @example\n * ```typescript\n * import { createCompactFunction } from \"agents/experimental/memory/utils\";\n *\n * const session = new Session(provider, {\n * compaction: {\n * tokenThreshold: 100000,\n * fn: createCompactFunction({\n * summarize: (prompt) => generateText({ model, prompt }).then(r => r.text)\n * })\n * }\n * });\n * ```\n */\nexport function createCompactFunction(opts: CompactOptions) {\n const protectHead = opts.protectHead ?? 3;\n const tailTokenBudget = opts.tailTokenBudget ?? 20000;\n const minTailMessages = opts.minTailMessages ?? 2;\n\n return async (messages: SessionMessage[]): Promise<CompactResult | null> => {\n if (messages.length <= protectHead + minTailMessages) {\n return null;\n }\n\n // 1. Find compression boundaries\n let compressStart = protectHead;\n compressStart = alignBoundaryForward(messages, compressStart);\n\n let compressEnd = findTailCutByTokens(\n messages,\n compressStart,\n tailTokenBudget,\n minTailMessages\n );\n\n if (compressEnd <= compressStart) {\n return null;\n }\n\n // Filter out compaction overlay messages — they have virtual IDs\n // and should not be included in the summary prompt or used as range IDs\n const middleMessages = messages\n .slice(compressStart, compressEnd)\n .filter((m) => !isCompactionMessage(m));\n\n if (middleMessages.length === 0) return null;\n\n // 2. Generate summary — extract previous summary from compaction overlays\n const existingCompaction = messages.find(isCompactionMessage);\n const previousSummary = existingCompaction\n ? existingCompaction.parts\n .filter((p) => p.type === \"text\")\n .map((p) => (p as { text: string }).text)\n .join(\"\\n\")\n : null;\n\n const budget = computeSummaryBudget(middleMessages);\n const prompt = buildSummaryPrompt(middleMessages, previousSummary, budget);\n const summary = await opts.summarize(prompt);\n\n if (!summary.trim()) return null;\n\n return {\n fromMessageId: middleMessages[0].id,\n toMessageId: middleMessages[middleMessages.length - 1].id,\n summary\n };\n };\n}\n"],"mappings":"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"}
@@ -438,4 +438,4 @@ export {
438
438
  SearchProvider as x,
439
439
  isSkillProvider as y
440
440
  };
441
- //# sourceMappingURL=compaction-helpers-BdQbZiML.d.ts.map
441
+ //# sourceMappingURL=compaction-helpers-YzCLvunJ.d.ts.map
@@ -75,4 +75,4 @@ export {
75
75
  DurableObjectOAuthClientProvider as r,
76
76
  AgentMcpOAuthProvider as t
77
77
  };
78
- //# sourceMappingURL=do-oauth-client-provider-31gqR33H.d.ts.map
78
+ //# sourceMappingURL=do-oauth-client-provider-C38aWbFV.d.ts.map
@@ -154,4 +154,4 @@ export {
154
154
  DEFAULT_MAX_AGE_SECONDS as t,
155
155
  createSecureReplyEmailResolver as u
156
156
  };
157
- //# sourceMappingURL=email-Cql45SKP.d.ts.map
157
+ //# sourceMappingURL=email-X72-zjuq.d.ts.map
package/dist/email.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as AgentEmail } from "./internal_context-DuQZFvWI.js";
1
+ import { n as AgentEmail } from "./internal_context-BvuGZieY.js";
2
2
  import {
3
3
  a as SecureReplyResolverOptions,
4
4
  c as createCatchAllEmailResolver,
@@ -12,7 +12,7 @@ import {
12
12
  s as createAddressBasedEmailResolver,
13
13
  t as DEFAULT_MAX_AGE_SECONDS,
14
14
  u as createSecureReplyEmailResolver
15
- } from "./email-Cql45SKP.js";
15
+ } from "./email-X72-zjuq.js";
16
16
  export {
17
17
  AgentEmail,
18
18
  DEFAULT_MAX_AGE_SECONDS,
@@ -1,4 +1,4 @@
1
- import { A as SessionOptions, C as AgentSessionProvider, D as StoredCompaction, E as SessionProvider, O as SessionMessage, S as isSearchProvider, T as SearchResult, _ as R2SkillProvider, b as AgentSearchProvider, f as ContextBlock, g as isWritableProvider, h as WritableContextProvider, k as SessionMessagePart, m as ContextProvider, p as ContextConfig, r as CompactResult, v as SkillProvider, w as SqlProvider, x as SearchProvider, y as isSkillProvider } from "../../../compaction-helpers-BdQbZiML.js";
1
+ import { A as SessionOptions, C as AgentSessionProvider, D as StoredCompaction, E as SessionProvider, O as SessionMessage, S as isSearchProvider, T as SearchResult, _ as R2SkillProvider, b as AgentSearchProvider, f as ContextBlock, g as isWritableProvider, h as WritableContextProvider, k as SessionMessagePart, m as ContextProvider, p as ContextConfig, r as CompactResult, v as SkillProvider, w as SqlProvider, x as SearchProvider, y as isSkillProvider } from "../../../compaction-helpers-YzCLvunJ.js";
2
2
  import { ToolSet } from "ai";
3
3
 
4
4
  //#region src/experimental/memory/session/session.d.ts
@@ -1,5 +1,5 @@
1
1
  import { MessageType } from "../../../types.js";
2
- import { m as estimateStringTokens, p as estimateMessageTokens, t as COMPACTION_PREFIX } from "../../../compaction-helpers-BPE1_ziA.js";
2
+ import { m as estimateStringTokens, p as estimateMessageTokens, t as COMPACTION_PREFIX } from "../../../compaction-helpers-C_cN3z55.js";
3
3
  import { z } from "zod";
4
4
  //#region src/experimental/memory/session/search.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { O as SessionMessage, a as alignBoundaryForward, c as createCompactFunction, d as sanitizeToolPairs, i as alignBoundaryBackward, l as findTailCutByTokens, n as CompactOptions, o as buildSummaryPrompt, r as CompactResult, s as computeSummaryBudget, t as COMPACTION_PREFIX, u as isCompactionMessage } from "../../../compaction-helpers-BdQbZiML.js";
1
+ import { O as SessionMessage, a as alignBoundaryForward, c as createCompactFunction, d as sanitizeToolPairs, i as alignBoundaryBackward, l as findTailCutByTokens, n as CompactOptions, o as buildSummaryPrompt, r as CompactResult, s as computeSummaryBudget, t as COMPACTION_PREFIX, u as isCompactionMessage } from "../../../compaction-helpers-YzCLvunJ.js";
2
2
 
3
3
  //#region src/experimental/memory/utils/tokens.d.ts
4
4
  /** Approximate characters per token for English text */
@@ -1,4 +1,4 @@
1
- import { a as computeSummaryBudget, c as isCompactionMessage, d as TOKENS_PER_MESSAGE, f as WORDS_TOKEN_MULTIPLIER, i as buildSummaryPrompt, l as sanitizeToolPairs, m as estimateStringTokens, n as alignBoundaryBackward, o as createCompactFunction, p as estimateMessageTokens, r as alignBoundaryForward, s as findTailCutByTokens, t as COMPACTION_PREFIX, u as CHARS_PER_TOKEN } from "../../../compaction-helpers-BPE1_ziA.js";
1
+ import { a as computeSummaryBudget, c as isCompactionMessage, d as TOKENS_PER_MESSAGE, f as WORDS_TOKEN_MULTIPLIER, i as buildSummaryPrompt, l as sanitizeToolPairs, m as estimateStringTokens, n as alignBoundaryBackward, o as createCompactFunction, p as estimateMessageTokens, r as alignBoundaryForward, s as findTailCutByTokens, t as COMPACTION_PREFIX, u as CHARS_PER_TOKEN } from "../../../compaction-helpers-C_cN3z55.js";
2
2
  //#region src/experimental/memory/utils/compaction.ts
3
3
  /**
4
4
  * Truncate tool outputs and long text in older messages.
@@ -232,6 +232,14 @@ type AgentObservabilityEvent =
232
232
  subject?: string;
233
233
  }
234
234
  >
235
+ | BaseEvent<
236
+ "email:send",
237
+ {
238
+ from: string;
239
+ to: string | string[];
240
+ subject: string;
241
+ }
242
+ >
235
243
  | BaseEvent<
236
244
  "workflow:start",
237
245
  {
@@ -413,4 +421,4 @@ export {
413
421
  MCPObservabilityEvent as s,
414
422
  ChannelEventMap as t
415
423
  };
416
- //# sourceMappingURL=index-DDSX-g7W.d.ts.map
424
+ //# sourceMappingURL=index-Biv6K70p.d.ts.map