agents 0.13.2 → 0.14.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 (74) hide show
  1. package/README.md +6 -4
  2. package/dist/{agent-tool-types-Dn9n-3SI.d.ts → agent-tool-types-LInzZfLo.d.ts} +511 -124
  3. package/dist/agent-tool-types.d.ts +13 -11
  4. package/dist/{agent-tools-B1ttU-pq.d.ts → agent-tools-BE9xosUG.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +14 -20
  6. package/dist/agent-tools.js +10 -6
  7. package/dist/agent-tools.js.map +1 -1
  8. package/dist/browser/ai.d.ts +1 -1
  9. package/dist/browser/ai.js +1 -1
  10. package/dist/browser/index.d.ts +1 -1
  11. package/dist/browser/index.js +1 -1
  12. package/dist/browser/tanstack-ai.d.ts +1 -1
  13. package/dist/browser/tanstack-ai.js +1 -1
  14. package/dist/chat/index.d.ts +194 -22
  15. package/dist/chat/index.js +144 -11
  16. package/dist/chat/index.js.map +1 -1
  17. package/dist/chat-sdk/index.d.ts +4 -4
  18. package/dist/classPrivateMethodInitSpec-bG0tD96O.js +7 -0
  19. package/dist/{client-D1kFXo80.js → client-NradHZZz.js} +206 -75
  20. package/dist/client-NradHZZz.js.map +1 -0
  21. package/dist/client.d.ts +1 -1
  22. package/dist/{compaction-helpers-DvcZnvQ1.js → compaction-helpers-BjT2NKRZ.js} +37 -9
  23. package/dist/compaction-helpers-BjT2NKRZ.js.map +1 -0
  24. package/dist/{compaction-helpers-DAe-xiVY.d.ts → compaction-helpers-DpP_XP9J.d.ts} +86 -29
  25. package/dist/{do-oauth-client-provider-4OKQU9rT.d.ts → do-oauth-client-provider-CPm9rK5I.d.ts} +1 -1
  26. package/dist/{email-J0GGS3sa.d.ts → email-1fTSJwPm.d.ts} +1 -1
  27. package/dist/email.d.ts +2 -2
  28. package/dist/experimental/memory/session/index.d.ts +58 -23
  29. package/dist/experimental/memory/session/index.js +98 -9
  30. package/dist/experimental/memory/session/index.js.map +1 -1
  31. package/dist/experimental/memory/utils/index.d.ts +13 -11
  32. package/dist/experimental/memory/utils/index.js +2 -2
  33. package/dist/{index-DKey3P4s.d.ts → index-Brdu5nMI.d.ts} +270 -1
  34. package/dist/index.d.ts +74 -67
  35. package/dist/index.js +607 -97
  36. package/dist/index.js.map +1 -1
  37. package/dist/{internal_context-BZrMS0B5.d.ts → internal_context-CcZy2Em7.d.ts} +1 -1
  38. package/dist/internal_context.d.ts +1 -1
  39. package/dist/mcp/client.d.ts +17 -13
  40. package/dist/mcp/client.js +2 -2
  41. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  42. package/dist/mcp/index.d.ts +35 -27
  43. package/dist/mcp/index.js +402 -69
  44. package/dist/mcp/index.js.map +1 -1
  45. package/dist/observability/index.d.ts +1 -1
  46. package/dist/observability/index.js +15 -1
  47. package/dist/observability/index.js.map +1 -1
  48. package/dist/react.d.ts +3 -3
  49. package/dist/{retries-BVdRl5ZE.d.ts → retries-ClWwxADl.d.ts} +1 -1
  50. package/dist/retries.d.ts +1 -1
  51. package/dist/serializable.d.ts +1 -1
  52. package/dist/{shared-Cvj92byG.d.ts → shared-CpY1FLvm.d.ts} +1 -1
  53. package/dist/{shared-CiKaIK4h.js → shared-DdOn6sp4.js} +3 -7
  54. package/dist/{shared-CiKaIK4h.js.map → shared-DdOn6sp4.js.map} +1 -1
  55. package/dist/skills/index.d.ts +236 -0
  56. package/dist/skills/index.js +1326 -0
  57. package/dist/skills/index.js.map +1 -0
  58. package/dist/sub-routing.d.ts +6 -6
  59. package/dist/{tool-output-truncation-CH-khbZ3.js → tool-output-truncation-BF4AZQlw.js} +1 -1
  60. package/dist/{tool-output-truncation-CH-khbZ3.js.map → tool-output-truncation-BF4AZQlw.js.map} +1 -1
  61. package/dist/{types-_JjKmv-l.d.ts → types-B0GymtN_.d.ts} +1 -1
  62. package/dist/types.d.ts +1 -1
  63. package/dist/vite.d.ts +1 -1
  64. package/dist/vite.js +248 -2
  65. package/dist/vite.js.map +1 -1
  66. package/dist/{workflow-types-Dkzg4hAx.d.ts → workflow-types-DPkuBi--.d.ts} +1 -1
  67. package/dist/workflow-types.d.ts +1 -1
  68. package/dist/workflows.d.ts +13 -3
  69. package/dist/workflows.js +10 -1
  70. package/dist/workflows.js.map +1 -1
  71. package/package.json +21 -3
  72. package/skills-module.d.ts +22 -0
  73. package/dist/client-D1kFXo80.js.map +0 -1
  74. package/dist/compaction-helpers-DvcZnvQ1.js.map +0 -1
@@ -8,6 +8,7 @@ import { ToolSet } from "ai";
8
8
  interface SessionMessagePart {
9
9
  type: string;
10
10
  text?: string;
11
+ reasoning?: string;
11
12
  toolCallId?: string;
12
13
  toolName?: string;
13
14
  input?: unknown;
@@ -15,6 +16,40 @@ interface SessionMessagePart {
15
16
  state?: string;
16
17
  result?: unknown;
17
18
  }
19
+ interface SessionTokenCounterInput {
20
+ /** Messages returned by `session.getHistory()` for the active branch. */
21
+ messages: SessionMessage[];
22
+ /** Frozen system prompt managed by the Session context system. */
23
+ systemPrompt: string;
24
+ /** Loaded context blocks that were used to build `systemPrompt`. */
25
+ contextBlocks: ContextBlock[];
26
+ }
27
+ type SessionTokenCounter = (
28
+ input: SessionTokenCounterInput
29
+ ) => number | Promise<number>;
30
+ interface CompactAfterOptions {
31
+ /**
32
+ * Override the token estimate used by auto-compaction and status broadcasts.
33
+ *
34
+ * The default is a Workers-safe heuristic over message parts plus the
35
+ * Session-managed frozen system prompt. Callers that have model-reported
36
+ * usage or a tokenizer can provide a more precise counter here.
37
+ */
38
+ tokenCounter?: SessionTokenCounter;
39
+ }
40
+ /**
41
+ * Context the Session passes to the registered compaction function. Lets the
42
+ * same authoritative token accounting drive BOTH the "should we compact?"
43
+ * (`compactAfter`) and "what should we compact?" (boundary) decisions, so a
44
+ * consumer that wires a `tokenCounter` once doesn't hit the failure mode where
45
+ * compaction fires every turn but silently no-ops because the boundary logic
46
+ * used a different (under-counting) estimate.
47
+ */
48
+ interface CompactContext {
49
+ /** The Session's token counter (from `compactAfter`/options), if configured. */
50
+ tokenCounter?: SessionTokenCounter;
51
+ }
52
+ type CompactionErrorHandler = (error: unknown) => void | Promise<void>;
18
53
  /**
19
54
  * Minimal message shape used by Session internals.
20
55
  * Vercel AI SDK's `UIMessage` is structurally compatible — you can pass
@@ -34,6 +69,10 @@ interface SessionOptions {
34
69
  context?: ContextConfig[];
35
70
  /** Provider for persisting the frozen system prompt. */
36
71
  promptStore?: WritableContextProvider;
72
+ /** Custom token counter for auto-compaction/status estimates. */
73
+ tokenCounter?: SessionTokenCounter;
74
+ /** Called when automatic compaction fails after a threshold trigger. */
75
+ onCompactionError?: CompactionErrorHandler;
37
76
  }
38
77
  //#endregion
39
78
  //#region src/experimental/memory/session/provider.d.ts
@@ -307,6 +346,9 @@ interface ContextBlock {
307
346
  }
308
347
  //#endregion
309
348
  //#region src/experimental/memory/utils/compaction-helpers.d.ts
349
+ type CompactTokenCounter = (
350
+ messages: SessionMessage[]
351
+ ) => number | Promise<number>;
310
352
  /** Prefix for all compaction messages (overlays and summaries) */
311
353
  declare const COMPACTION_PREFIX = "compaction_";
312
354
  /** Check if a message is a compaction message */
@@ -401,6 +443,12 @@ interface CompactOptions {
401
443
  tailTokenBudget?: number;
402
444
  /** Minimum tail messages to protect (default: 2) */
403
445
  minTailMessages?: number;
446
+ /**
447
+ * Optional counter for tail-budget decisions. Use this when a tokenizer or
448
+ * model-reported accounting is available; otherwise the Workers-safe
449
+ * heuristic is used.
450
+ */
451
+ tokenCounter?: CompactTokenCounter;
404
452
  }
405
453
  /**
406
454
  * Reference compaction implementation.
@@ -429,38 +477,47 @@ interface CompactOptions {
429
477
  */
430
478
  declare function createCompactFunction(
431
479
  opts: CompactOptions
432
- ): (messages: SessionMessage[]) => Promise<CompactResult | null>;
480
+ ): (
481
+ messages: SessionMessage[],
482
+ context?: CompactContext
483
+ ) => Promise<CompactResult | null>;
433
484
  //#endregion
434
485
  export {
435
- SessionOptions as A,
436
- AgentSessionProvider as C,
437
- StoredCompaction as D,
438
- SessionProvider as E,
439
- SessionMessage as O,
440
- isSearchProvider as S,
441
- SearchResult as T,
442
- R2SkillProvider as _,
443
- alignBoundaryForward as a,
444
- AgentSearchProvider as b,
445
- createCompactFunction as c,
446
- sanitizeToolPairs as d,
447
- ContextBlock as f,
448
- isWritableProvider as g,
449
- WritableContextProvider as h,
450
- alignBoundaryBackward as i,
451
- SessionMessagePart as k,
452
- findTailCutByTokens as l,
453
- ContextProvider as m,
486
+ CompactContext as A,
487
+ 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,
496
+ SearchProvider as S,
497
+ SqlProvider as T,
498
+ isWritableProvider as _,
499
+ alignBoundaryBackward as a,
500
+ isSkillProvider as b,
501
+ computeSummaryBudget as c,
502
+ isCompactionMessage as d,
503
+ sanitizeToolPairs as f,
504
+ WritableContextProvider as g,
505
+ ContextProvider as h,
506
+ CompactTokenCounter as i,
507
+ CompactionErrorHandler as j,
508
+ CompactAfterOptions as k,
509
+ createCompactFunction as l,
510
+ ContextConfig as m,
454
511
  CompactOptions as n,
455
- buildSummaryPrompt as o,
456
- ContextConfig as p,
512
+ alignBoundaryForward as o,
513
+ ContextBlock as p,
457
514
  CompactResult as r,
458
- computeSummaryBudget as s,
515
+ buildSummaryPrompt as s,
459
516
  COMPACTION_PREFIX as t,
460
- isCompactionMessage as u,
461
- SkillProvider as v,
462
- SqlProvider as w,
463
- SearchProvider as x,
464
- isSkillProvider as y
517
+ findTailCutByTokens as u,
518
+ R2SkillProvider as v,
519
+ AgentSessionProvider as w,
520
+ AgentSearchProvider as x,
521
+ SkillProvider as y
465
522
  };
466
- //# sourceMappingURL=compaction-helpers-DAe-xiVY.d.ts.map
523
+ //# sourceMappingURL=compaction-helpers-DpP_XP9J.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-4OKQU9rT.d.ts.map
78
+ //# sourceMappingURL=do-oauth-client-provider-CPm9rK5I.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-J0GGS3sa.d.ts.map
157
+ //# sourceMappingURL=email-1fTSJwPm.d.ts.map
package/dist/email.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as AgentEmail } from "./internal_context-BZrMS0B5.js";
1
+ import { n as AgentEmail } from "./internal_context-CcZy2Em7.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-J0GGS3sa.js";
15
+ } from "./email-1fTSJwPm.js";
16
16
  export {
17
17
  type AgentEmail,
18
18
  DEFAULT_MAX_AGE_SECONDS,
@@ -1,25 +1,30 @@
1
1
  import {
2
- A as SessionOptions,
3
- C as AgentSessionProvider,
4
- D as StoredCompaction,
5
- E as SessionProvider,
6
- O as SessionMessage,
7
- S as isSearchProvider,
8
- T as SearchResult,
9
- _ as R2SkillProvider,
10
- b as AgentSearchProvider,
11
- f as ContextBlock,
12
- g as isWritableProvider,
13
- h as WritableContextProvider,
14
- k as SessionMessagePart,
15
- m as ContextProvider,
16
- p as ContextConfig,
2
+ A as CompactContext,
3
+ C as isSearchProvider,
4
+ D as SessionProvider,
5
+ E as SearchResult,
6
+ F as SessionTokenCounter,
7
+ I as SessionTokenCounterInput,
8
+ M as SessionMessage,
9
+ N as SessionMessagePart,
10
+ O as StoredCompaction,
11
+ P as SessionOptions,
12
+ S as SearchProvider,
13
+ T as SqlProvider,
14
+ _ as isWritableProvider,
15
+ b as isSkillProvider,
16
+ g as WritableContextProvider,
17
+ h as ContextProvider,
18
+ j as CompactionErrorHandler,
19
+ k as CompactAfterOptions,
20
+ m as ContextConfig,
21
+ p as ContextBlock,
17
22
  r as CompactResult,
18
- v as SkillProvider,
19
- w as SqlProvider,
20
- x as SearchProvider,
21
- y as isSkillProvider
22
- } from "../../../compaction-helpers-DAe-xiVY.js";
23
+ v as R2SkillProvider,
24
+ w as AgentSessionProvider,
25
+ x as AgentSearchProvider,
26
+ y as SkillProvider
27
+ } from "../../../compaction-helpers-DpP_XP9J.js";
23
28
  import { ToolSet } from "ai";
24
29
 
25
30
  //#region src/experimental/memory/session/session.d.ts
@@ -55,7 +60,10 @@ declare class Session {
55
60
  private _pending?;
56
61
  private _cachedPrompt?;
57
62
  private _compactionFn?;
63
+ private _warnedCompactionNoOp;
58
64
  private _tokenThreshold?;
65
+ private _tokenCounter?;
66
+ private _compactionErrorHandler?;
59
67
  private _ready;
60
68
  private _restorePromise?;
61
69
  private _messageChangeListener?;
@@ -99,13 +107,27 @@ declare class Session {
99
107
  * message history into a summary overlay.
100
108
  */
101
109
  onCompaction(
102
- fn: (messages: SessionMessage[]) => Promise<CompactResult | null>
110
+ fn: (
111
+ messages: SessionMessage[],
112
+ context?: CompactContext
113
+ ) => Promise<CompactResult | null>
103
114
  ): this;
104
115
  /**
105
116
  * Auto-compact when estimated token count exceeds the threshold.
106
117
  * Checked after each `appendMessage`. Requires `onCompaction()`.
118
+ *
119
+ * By default this uses a Workers-safe heuristic over stored messages plus
120
+ * the Session-managed frozen system prompt. Provide `tokenCounter` when you
121
+ * have model-reported usage or a tokenizer and need a stricter budget.
107
122
  */
108
- compactAfter(tokenThreshold: number): this;
123
+ compactAfter(tokenThreshold: number, options?: CompactAfterOptions): this;
124
+ /**
125
+ * Handle failures from the automatic `compactAfter()` trigger.
126
+ *
127
+ * Manual `compact()` still reports errors through the existing session error
128
+ * broadcast path.
129
+ */
130
+ onCompactionError(handler: CompactionErrorHandler): this;
109
131
  /**
110
132
  * @internal
111
133
  * Framework hook for cache-owning callers that need to mirror message
@@ -153,6 +175,9 @@ declare class Session {
153
175
  getBranches(messageId: string): Promise<SessionMessage[]>;
154
176
  getPathLength(leafId?: string | null): Promise<number>;
155
177
  private _broadcast;
178
+ private _shouldEstimateTokens;
179
+ private _estimateTokenCount;
180
+ private _handleAutoCompactionError;
156
181
  private _emitStatus;
157
182
  private _emitError;
158
183
  appendMessage(
@@ -263,6 +288,8 @@ declare class SessionManager {
263
288
  private _cachedPrompt?;
264
289
  private _compactionFn?;
265
290
  private _tokenThreshold?;
291
+ private _tokenCounter?;
292
+ private _compactionErrorHandler?;
266
293
  private _sessions;
267
294
  private _historyLabel?;
268
295
  private _tableReady;
@@ -299,7 +326,11 @@ declare class SessionManager {
299
326
  * Auto-compact when estimated token count exceeds the threshold.
300
327
  * Propagated to all sessions. Requires `onCompaction()`.
301
328
  */
302
- compactAfter(tokenThreshold: number): this;
329
+ compactAfter(tokenThreshold: number, options?: CompactAfterOptions): this;
330
+ /**
331
+ * Handle failures from automatic compaction in managed sessions.
332
+ */
333
+ onCompactionError(handler: CompactionErrorHandler): this;
303
334
  /**
304
335
  * Add a searchable context block that searches conversation history
305
336
  * across all sessions managed by this manager.
@@ -540,6 +571,8 @@ export {
540
571
  AgentContextProvider,
541
572
  AgentSearchProvider,
542
573
  AgentSessionProvider,
574
+ type CompactAfterOptions,
575
+ type CompactionErrorHandler,
543
576
  type ContextBlock,
544
577
  type ContextConfig,
545
578
  type ContextProvider,
@@ -561,6 +594,8 @@ export {
561
594
  type SessionMessagePart,
562
595
  type SessionOptions,
563
596
  type SessionProvider,
597
+ type SessionTokenCounter,
598
+ type SessionTokenCounterInput,
564
599
  type SkillProvider,
565
600
  type SqlProvider,
566
601
  type StoredCompaction,
@@ -1,5 +1,5 @@
1
1
  import "../../../types.js";
2
- import { m as estimateStringTokens, p as estimateMessageTokens, t as COMPACTION_PREFIX } from "../../../compaction-helpers-DvcZnvQ1.js";
2
+ import { m as estimateStringTokens, p as estimateMessageTokens, t as COMPACTION_PREFIX } from "../../../compaction-helpers-BjT2NKRZ.js";
3
3
  import { z } from "zod";
4
4
  //#region src/experimental/memory/session/search.ts
5
5
  /**
@@ -446,7 +446,7 @@ var ContextBlocks = class {
446
446
  refreshSnapshot() {
447
447
  return this.captureSnapshot();
448
448
  }
449
- captureSnapshot() {
449
+ renderPrompt() {
450
450
  const parts = [];
451
451
  const sep = "═".repeat(46);
452
452
  for (const block of this.blocks.values()) {
@@ -463,7 +463,10 @@ var ContextBlocks = class {
463
463
  else header += " [writable]";
464
464
  parts.push(`${sep}\n${header}\n${sep}\n${block.content}`);
465
465
  }
466
- this.snapshot = parts.join("\n\n");
466
+ return parts.join("\n\n");
467
+ }
468
+ captureSnapshot() {
469
+ this.snapshot = this.renderPrompt();
467
470
  return this.snapshot;
468
471
  }
469
472
  /**
@@ -512,6 +515,23 @@ var ContextBlocks = class {
512
515
  return prompt;
513
516
  }
514
517
  /**
518
+ * Return the prompt text used for token estimation without persisting a new
519
+ * frozen prompt to the prompt store.
520
+ *
521
+ * This still reads an existing cached prompt when present, so estimates match
522
+ * the prompt that inference would reuse. If no cached prompt exists, it loads
523
+ * providers and renders the current blocks without freezing the snapshot.
524
+ */
525
+ async getSystemPromptForEstimate() {
526
+ if (this.snapshot !== null) return this.snapshot;
527
+ if (this.promptStore) {
528
+ const stored = await this.promptStore.get();
529
+ if (stored !== null) return stored;
530
+ }
531
+ if (!this.loaded) await this.load();
532
+ return this.renderPrompt();
533
+ }
534
+ /**
515
535
  * Force reload blocks from providers, re-render the system prompt,
516
536
  * and persist to the store. Use this after block content has changed
517
537
  * or to invalidate the cached prompt.
@@ -1001,9 +1021,12 @@ function isSqlProvider(arg) {
1001
1021
  }
1002
1022
  var Session = class Session {
1003
1023
  constructor(storage, options) {
1024
+ this._warnedCompactionNoOp = false;
1004
1025
  this._ready = false;
1005
1026
  this.storage = storage;
1006
1027
  this.context = new ContextBlocks(options?.context ?? [], options?.promptStore);
1028
+ this._tokenCounter = options?.tokenCounter;
1029
+ this._compactionErrorHandler = options?.onCompactionError;
1007
1030
  this._ready = true;
1008
1031
  }
1009
1032
  /**
@@ -1072,9 +1095,24 @@ var Session = class Session {
1072
1095
  /**
1073
1096
  * Auto-compact when estimated token count exceeds the threshold.
1074
1097
  * Checked after each `appendMessage`. Requires `onCompaction()`.
1098
+ *
1099
+ * By default this uses a Workers-safe heuristic over stored messages plus
1100
+ * the Session-managed frozen system prompt. Provide `tokenCounter` when you
1101
+ * have model-reported usage or a tokenizer and need a stricter budget.
1075
1102
  */
1076
- compactAfter(tokenThreshold) {
1103
+ compactAfter(tokenThreshold, options) {
1077
1104
  this._tokenThreshold = tokenThreshold;
1105
+ if (options?.tokenCounter) this._tokenCounter = options.tokenCounter;
1106
+ return this;
1107
+ }
1108
+ /**
1109
+ * Handle failures from the automatic `compactAfter()` trigger.
1110
+ *
1111
+ * Manual `compact()` still reports errors through the existing session error
1112
+ * broadcast path.
1113
+ */
1114
+ onCompactionError(handler) {
1115
+ this._compactionErrorHandler = handler;
1078
1116
  return this;
1079
1117
  }
1080
1118
  /**
@@ -1223,8 +1261,42 @@ var Session = class Session {
1223
1261
  ...data
1224
1262
  }));
1225
1263
  }
1264
+ _shouldEstimateTokens() {
1265
+ return Boolean(this._broadcaster || this._tokenThreshold != null && this._compactionFn);
1266
+ }
1267
+ async _estimateTokenCount() {
1268
+ const messages = await this.getHistory();
1269
+ const systemPrompt = await this.context.getSystemPromptForEstimate();
1270
+ if (this._tokenCounter) {
1271
+ if (!this.context.isLoaded()) await this.context.load();
1272
+ const contextBlocks = this.context.getBlocks();
1273
+ const estimate = await this._tokenCounter({
1274
+ messages,
1275
+ systemPrompt,
1276
+ contextBlocks
1277
+ });
1278
+ return Number.isFinite(estimate) ? Math.max(0, Math.ceil(estimate)) : 0;
1279
+ }
1280
+ return estimateMessageTokens(messages) + estimateStringTokens(systemPrompt);
1281
+ }
1282
+ async _handleAutoCompactionError(error) {
1283
+ const message = error instanceof Error ? error.message : String(error);
1284
+ if (this._compactionErrorHandler) try {
1285
+ await this._compactionErrorHandler(error);
1286
+ } catch (handlerError) {
1287
+ const handlerMessage = handlerError instanceof Error ? handlerError.message : String(handlerError);
1288
+ console.warn(`Session auto-compaction error handler failed: ${handlerMessage}`);
1289
+ }
1290
+ else console.warn(`Session auto-compaction failed: ${message}`);
1291
+ this._emitError(message);
1292
+ }
1226
1293
  async _emitStatus(phase, extra) {
1227
- const tokenEstimate = estimateMessageTokens(await this.getHistory());
1294
+ let tokenEstimate = 0;
1295
+ if (this._shouldEstimateTokens()) try {
1296
+ tokenEstimate = await this._estimateTokenCount();
1297
+ } catch (err) {
1298
+ await this._handleAutoCompactionError(err);
1299
+ }
1228
1300
  this._broadcast("cf_agent_session", {
1229
1301
  phase,
1230
1302
  tokenEstimate,
@@ -1256,7 +1328,13 @@ var Session = class Session {
1256
1328
  let compacted = false;
1257
1329
  if (this._tokenThreshold != null && this._compactionFn && tokenEstimate > this._tokenThreshold) try {
1258
1330
  compacted = Boolean(await this.compact());
1259
- } catch {}
1331
+ if (!compacted && !this._warnedCompactionNoOp) {
1332
+ this._warnedCompactionNoOp = true;
1333
+ console.warn(`[Session] Auto-compaction fired (~${tokenEstimate} tokens > ${this._tokenThreshold}) but the compaction function returned null, so history was not shortened. ` + (this._tokenCounter ? `A tokenCounter is configured and now flows to the boundary logic, but it is invoked per-message there — a whole-prompt/usage counter (e.g. returning a fixed usage.inputTokens regardless of which messages are passed) degrades the tail budget to minTailMessages and can still no-op. Pass a per-message CompactOptions.tokenCounter for precise tail budgeting.` : `If your history is tool-heavy, configure a tokenCounter on compactAfter() — it flows to createCompactFunction's boundary logic automatically.`));
1334
+ } else if (compacted) this._warnedCompactionNoOp = false;
1335
+ } catch (err) {
1336
+ await this._handleAutoCompactionError(err);
1337
+ }
1260
1338
  if (!compacted) await this._notifyMessagesChanged({
1261
1339
  type: "append",
1262
1340
  message,
@@ -1308,7 +1386,7 @@ var Session = class Session {
1308
1386
  const tokensBefore = await this._emitStatus("compacting");
1309
1387
  let result;
1310
1388
  try {
1311
- result = await this._compactionFn(await this.getHistory());
1389
+ result = await this._compactionFn(await this.getHistory(), { tokenCounter: this._tokenCounter });
1312
1390
  } catch (err) {
1313
1391
  this._emitError(err instanceof Error ? err.message : String(err));
1314
1392
  return null;
@@ -1468,6 +1546,8 @@ var SessionManager = class SessionManager {
1468
1546
  mgr._pending = [];
1469
1547
  mgr._compactionFn = null;
1470
1548
  mgr._tokenThreshold = void 0;
1549
+ mgr._tokenCounter = void 0;
1550
+ mgr._compactionErrorHandler = void 0;
1471
1551
  mgr._sessions = /* @__PURE__ */ new Map();
1472
1552
  mgr._tableReady = false;
1473
1553
  mgr._ready = false;
@@ -1496,8 +1576,16 @@ var SessionManager = class SessionManager {
1496
1576
  * Auto-compact when estimated token count exceeds the threshold.
1497
1577
  * Propagated to all sessions. Requires `onCompaction()`.
1498
1578
  */
1499
- compactAfter(tokenThreshold) {
1579
+ compactAfter(tokenThreshold, options) {
1500
1580
  this._tokenThreshold = tokenThreshold;
1581
+ if (options?.tokenCounter) this._tokenCounter = options.tokenCounter;
1582
+ return this;
1583
+ }
1584
+ /**
1585
+ * Handle failures from automatic compaction in managed sessions.
1586
+ */
1587
+ onCompactionError(handler) {
1588
+ this._compactionErrorHandler = handler;
1501
1589
  return this;
1502
1590
  }
1503
1591
  /**
@@ -1576,7 +1664,8 @@ var SessionManager = class SessionManager {
1576
1664
  provider: this._createHistoryProvider()
1577
1665
  });
1578
1666
  if (this._compactionFn) s.onCompaction(this._compactionFn);
1579
- if (this._tokenThreshold != null) s.compactAfter(this._tokenThreshold);
1667
+ if (this._tokenThreshold != null) s.compactAfter(this._tokenThreshold, { tokenCounter: this._tokenCounter });
1668
+ if (this._compactionErrorHandler) s.onCompactionError(this._compactionErrorHandler);
1580
1669
  session = s;
1581
1670
  this._sessions.set(sessionId, session);
1582
1671
  }