@dexto/core 1.5.3 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/agent/DextoAgent.cjs +284 -1
  2. package/dist/agent/DextoAgent.d.ts +114 -0
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +275 -1
  5. package/dist/agent/schemas.d.ts +51 -21
  6. package/dist/agent/schemas.d.ts.map +1 -1
  7. package/dist/context/compaction/overflow.cjs +6 -10
  8. package/dist/context/compaction/overflow.d.ts +14 -11
  9. package/dist/context/compaction/overflow.d.ts.map +1 -1
  10. package/dist/context/compaction/overflow.js +6 -10
  11. package/dist/context/compaction/providers/reactive-overflow-provider.cjs +15 -0
  12. package/dist/context/compaction/providers/reactive-overflow-provider.d.ts +15 -0
  13. package/dist/context/compaction/providers/reactive-overflow-provider.d.ts.map +1 -1
  14. package/dist/context/compaction/providers/reactive-overflow-provider.js +15 -0
  15. package/dist/context/compaction/schemas.cjs +22 -2
  16. package/dist/context/compaction/schemas.d.ts +45 -0
  17. package/dist/context/compaction/schemas.d.ts.map +1 -1
  18. package/dist/context/compaction/schemas.js +22 -2
  19. package/dist/context/compaction/strategies/reactive-overflow.cjs +166 -26
  20. package/dist/context/compaction/strategies/reactive-overflow.d.ts +21 -0
  21. package/dist/context/compaction/strategies/reactive-overflow.d.ts.map +1 -1
  22. package/dist/context/compaction/strategies/reactive-overflow.js +166 -26
  23. package/dist/context/manager.cjs +278 -31
  24. package/dist/context/manager.d.ts +192 -5
  25. package/dist/context/manager.d.ts.map +1 -1
  26. package/dist/context/manager.js +285 -32
  27. package/dist/context/types.d.ts +6 -0
  28. package/dist/context/types.d.ts.map +1 -1
  29. package/dist/context/utils.cjs +77 -11
  30. package/dist/context/utils.d.ts +86 -8
  31. package/dist/context/utils.d.ts.map +1 -1
  32. package/dist/context/utils.js +71 -11
  33. package/dist/events/index.cjs +4 -0
  34. package/dist/events/index.d.ts +41 -7
  35. package/dist/events/index.d.ts.map +1 -1
  36. package/dist/events/index.js +4 -0
  37. package/dist/llm/executor/stream-processor.cjs +19 -1
  38. package/dist/llm/executor/stream-processor.d.ts +3 -0
  39. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  40. package/dist/llm/executor/stream-processor.js +19 -1
  41. package/dist/llm/executor/turn-executor.cjs +219 -30
  42. package/dist/llm/executor/turn-executor.d.ts +62 -10
  43. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  44. package/dist/llm/executor/turn-executor.js +219 -30
  45. package/dist/llm/executor/types.d.ts +28 -0
  46. package/dist/llm/executor/types.d.ts.map +1 -1
  47. package/dist/llm/formatters/vercel.cjs +36 -28
  48. package/dist/llm/formatters/vercel.d.ts.map +1 -1
  49. package/dist/llm/formatters/vercel.js +36 -28
  50. package/dist/llm/services/factory.cjs +3 -2
  51. package/dist/llm/services/factory.d.ts +3 -1
  52. package/dist/llm/services/factory.d.ts.map +1 -1
  53. package/dist/llm/services/factory.js +3 -2
  54. package/dist/llm/services/vercel.cjs +34 -6
  55. package/dist/llm/services/vercel.d.ts +23 -3
  56. package/dist/llm/services/vercel.d.ts.map +1 -1
  57. package/dist/llm/services/vercel.js +34 -6
  58. package/dist/session/chat-session.cjs +20 -11
  59. package/dist/session/chat-session.d.ts +9 -4
  60. package/dist/session/chat-session.d.ts.map +1 -1
  61. package/dist/session/chat-session.js +20 -11
  62. package/dist/session/compaction-service.cjs +139 -0
  63. package/dist/session/compaction-service.d.ts +81 -0
  64. package/dist/session/compaction-service.d.ts.map +1 -0
  65. package/dist/session/compaction-service.js +106 -0
  66. package/dist/session/session-manager.cjs +146 -0
  67. package/dist/session/session-manager.d.ts +50 -0
  68. package/dist/session/session-manager.d.ts.map +1 -1
  69. package/dist/session/session-manager.js +146 -0
  70. package/dist/session/title-generator.cjs +2 -2
  71. package/dist/session/title-generator.js +2 -2
  72. package/dist/systemPrompt/in-built-prompts.cjs +36 -0
  73. package/dist/systemPrompt/in-built-prompts.d.ts +18 -1
  74. package/dist/systemPrompt/in-built-prompts.d.ts.map +1 -1
  75. package/dist/systemPrompt/in-built-prompts.js +25 -0
  76. package/dist/systemPrompt/manager.cjs +22 -0
  77. package/dist/systemPrompt/manager.d.ts +10 -0
  78. package/dist/systemPrompt/manager.d.ts.map +1 -1
  79. package/dist/systemPrompt/manager.js +22 -0
  80. package/dist/systemPrompt/registry.cjs +2 -1
  81. package/dist/systemPrompt/registry.d.ts +1 -1
  82. package/dist/systemPrompt/registry.d.ts.map +1 -1
  83. package/dist/systemPrompt/registry.js +2 -1
  84. package/dist/systemPrompt/schemas.cjs +7 -0
  85. package/dist/systemPrompt/schemas.d.ts +13 -13
  86. package/dist/systemPrompt/schemas.d.ts.map +1 -1
  87. package/dist/systemPrompt/schemas.js +7 -0
  88. package/dist/utils/index.cjs +3 -1
  89. package/dist/utils/index.d.ts +1 -0
  90. package/dist/utils/index.d.ts.map +1 -1
  91. package/dist/utils/index.js +1 -0
  92. package/package.json +1 -1
@@ -92,13 +92,15 @@ class VercelLLMService {
92
92
  resourceManager;
93
93
  messageQueue;
94
94
  compactionStrategy;
95
+ modelLimits;
96
+ compactionThresholdPercent;
95
97
  /**
96
98
  * Helper to extract model ID from LanguageModel union type (string | LanguageModelV2)
97
99
  */
98
100
  getModelId() {
99
101
  return typeof this.model === "string" ? this.model : this.model.modelId;
100
102
  }
101
- constructor(toolManager, model, systemPromptManager, historyProvider, sessionEventBus, config, sessionId, resourceManager, logger, compactionStrategy) {
103
+ constructor(toolManager, model, systemPromptManager, historyProvider, sessionEventBus, config, sessionId, resourceManager, logger, compactionStrategy, compactionConfig) {
102
104
  this.logger = logger.createChild(import_types2.DextoLogComponent.LLM);
103
105
  this.model = model;
104
106
  this.config = config;
@@ -107,9 +109,20 @@ class VercelLLMService {
107
109
  this.sessionId = sessionId;
108
110
  this.resourceManager = resourceManager;
109
111
  this.compactionStrategy = compactionStrategy ?? null;
112
+ this.compactionThresholdPercent = compactionConfig?.thresholdPercent ?? 0.9;
110
113
  this.messageQueue = new import_message_queue.MessageQueueService(this.sessionEventBus, this.logger);
111
114
  const formatter = new import_vercel.VercelMessageFormatter(this.logger);
112
115
  const maxInputTokens = (0, import_registry.getEffectiveMaxInputTokens)(config, this.logger);
116
+ let effectiveContextWindow = maxInputTokens;
117
+ if (compactionConfig?.maxContextTokens !== void 0) {
118
+ effectiveContextWindow = Math.min(maxInputTokens, compactionConfig.maxContextTokens);
119
+ this.logger.debug(
120
+ `Compaction: Using maxContextTokens override: ${compactionConfig.maxContextTokens} (model max: ${maxInputTokens})`
121
+ );
122
+ }
123
+ this.modelLimits = {
124
+ contextWindow: effectiveContextWindow
125
+ };
113
126
  this.contextManager = new import_manager.ContextManager(
114
127
  config,
115
128
  formatter,
@@ -149,19 +162,23 @@ class VercelLLMService {
149
162
  { provider: this.config.provider, model: this.getModelId() },
150
163
  this.logger,
151
164
  this.messageQueue,
152
- void 0,
153
- // modelLimits - TurnExecutor will use defaults
165
+ this.modelLimits,
154
166
  externalSignal,
155
- this.compactionStrategy
167
+ this.compactionStrategy,
168
+ this.compactionThresholdPercent
156
169
  );
157
170
  }
171
+ /**
172
+ * Result from streaming a response.
173
+ */
174
+ static StreamResult;
158
175
  /**
159
176
  * Stream a response for the given content.
160
177
  * Primary method for running conversations with multi-image support.
161
178
  *
162
179
  * @param content - String or ContentPart[] (text, images, files)
163
180
  * @param options - { signal?: AbortSignal }
164
- * @returns The assistant's text response
181
+ * @returns Object with text response, whether compaction occurred, and compaction data if applicable
165
182
  */
166
183
  async stream(content, options) {
167
184
  const activeSpan = import_api.trace.getActiveSpan();
@@ -191,7 +208,12 @@ class VercelLLMService {
191
208
  const executor = this.createTurnExecutor(options?.signal);
192
209
  const contributorContext = { mcpManager: this.toolManager.getMcpManager() };
193
210
  const result = await executor.execute(contributorContext, true);
194
- return result.text ?? "";
211
+ return {
212
+ text: result.text ?? "",
213
+ didCompact: result.didCompact,
214
+ // Use spread to conditionally include compaction (exactOptionalPropertyTypes)
215
+ ...result.compaction && { compaction: result.compaction }
216
+ };
195
217
  });
196
218
  }
197
219
  /**
@@ -236,6 +258,12 @@ class VercelLLMService {
236
258
  getMessageQueue() {
237
259
  return this.messageQueue;
238
260
  }
261
+ /**
262
+ * Get the compaction strategy for external access (e.g., session-native compaction)
263
+ */
264
+ getCompactionStrategy() {
265
+ return this.compactionStrategy;
266
+ }
239
267
  }
240
268
  _init = __decoratorStart(null);
241
269
  VercelLLMService = __decorateElement(_init, 0, "VercelLLMService", _VercelLLMService_decorators, VercelLLMService);
@@ -4,10 +4,12 @@ import { LLMServiceConfig } from './types.js';
4
4
  import type { IDextoLogger } from '../../logger/v2/types.js';
5
5
  import { ToolSet } from '../../tools/types.js';
6
6
  import { ContextManager } from '../../context/manager.js';
7
+ import type { CompactionConfigInput } from '../../context/compaction/schemas.js';
7
8
  import type { SessionEventBus } from '../../events/index.js';
8
9
  import type { IConversationHistoryProvider } from '../../session/history/types.js';
9
10
  import type { SystemPromptManager } from '../../systemPrompt/manager.js';
10
11
  import type { ValidatedLLMConfig } from '../schemas.js';
12
+ import type { CompactionData } from '../executor/types.js';
11
13
  import { MessageQueueService } from '../../session/message-queue.js';
12
14
  import type { ResourceManager } from '../../resources/index.js';
13
15
  import type { ContentInput } from '../../agent/types.js';
@@ -36,27 +38,41 @@ export declare class VercelLLMService {
36
38
  private resourceManager;
37
39
  private messageQueue;
38
40
  private compactionStrategy;
41
+ private modelLimits;
42
+ private compactionThresholdPercent;
39
43
  /**
40
44
  * Helper to extract model ID from LanguageModel union type (string | LanguageModelV2)
41
45
  */
42
46
  private getModelId;
43
- constructor(toolManager: ToolManager, model: LanguageModel, systemPromptManager: SystemPromptManager, historyProvider: IConversationHistoryProvider, sessionEventBus: SessionEventBus, config: ValidatedLLMConfig, sessionId: string, resourceManager: ResourceManager, logger: IDextoLogger, compactionStrategy?: import('../../context/compaction/types.js').ICompactionStrategy | null);
47
+ constructor(toolManager: ToolManager, model: LanguageModel, systemPromptManager: SystemPromptManager, historyProvider: IConversationHistoryProvider, sessionEventBus: SessionEventBus, config: ValidatedLLMConfig, sessionId: string, resourceManager: ResourceManager, logger: IDextoLogger, compactionStrategy?: import('../../context/compaction/types.js').ICompactionStrategy | null, compactionConfig?: CompactionConfigInput);
44
48
  getAllTools(): Promise<ToolSet>;
45
49
  /**
46
50
  * Create a TurnExecutor instance for executing the agent loop.
47
51
  */
48
52
  private createTurnExecutor;
53
+ /**
54
+ * Result from streaming a response.
55
+ */
56
+ static StreamResult: {
57
+ text: string;
58
+ didCompact: boolean;
59
+ compaction?: CompactionData;
60
+ };
49
61
  /**
50
62
  * Stream a response for the given content.
51
63
  * Primary method for running conversations with multi-image support.
52
64
  *
53
65
  * @param content - String or ContentPart[] (text, images, files)
54
66
  * @param options - { signal?: AbortSignal }
55
- * @returns The assistant's text response
67
+ * @returns Object with text response, whether compaction occurred, and compaction data if applicable
56
68
  */
57
69
  stream(content: ContentInput, options?: {
58
70
  signal?: AbortSignal;
59
- }): Promise<string>;
71
+ }): Promise<{
72
+ text: string;
73
+ didCompact: boolean;
74
+ compaction?: CompactionData;
75
+ }>;
60
76
  /**
61
77
  * Get configuration information about the LLM service
62
78
  * @returns Configuration object with provider and model information
@@ -70,5 +86,9 @@ export declare class VercelLLMService {
70
86
  * Get the message queue for external access (e.g., queueing messages while busy)
71
87
  */
72
88
  getMessageQueue(): MessageQueueService;
89
+ /**
90
+ * Get the compaction strategy for external access (e.g., session-native compaction)
91
+ */
92
+ getCompactionStrategy(): import('../../context/compaction/types.js').ICompactionStrategy | null;
73
93
  }
74
94
  //# sourceMappingURL=vercel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vercel.d.ts","sourceRoot":"","sources":["../../../src/llm/services/vercel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAqB,MAAM,IAAI,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,qBAIa,gBAAgB;IACzB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,kBAAkB,CAEf;IAEX;;OAEG;IACH,OAAO,CAAC,UAAU;gBAKd,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,aAAa,EACpB,mBAAmB,EAAE,mBAAmB,EACxC,eAAe,EAAE,4BAA4B,EAC7C,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,YAAY,EACpB,kBAAkB,CAAC,EAAE,OAAO,mCAAmC,EAAE,mBAAmB,GAAG,IAAI;IAkC/F,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyB1B;;;;;;;OAOG;IACG,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAsDxF;;;OAGG;IACH,SAAS,IAAI,gBAAgB;IA+B7B;;OAEG;IACH,iBAAiB,IAAI,cAAc,CAAC,OAAO,CAAC;IAI5C;;OAEG;IACH,eAAe,IAAI,mBAAmB;CAGzC"}
1
+ {"version":3,"file":"vercel.d.ts","sourceRoot":"","sources":["../../../src/llm/services/vercel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAqB,MAAM,IAAI,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAEjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,qBAIa,gBAAgB;IACzB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,kBAAkB,CAEf;IACX,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,0BAA0B,CAAS;IAE3C;;OAEG;IACH,OAAO,CAAC,UAAU;gBAKd,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,aAAa,EACpB,mBAAmB,EAAE,mBAAmB,EACxC,eAAe,EAAE,4BAA4B,EAC7C,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,eAAe,EAChC,MAAM,EAAE,YAAY,EACpB,kBAAkB,CAAC,EAAE,OAAO,mCAAmC,EAAE,mBAAmB,GAAG,IAAI,EAC3F,gBAAgB,CAAC,EAAE,qBAAqB;IAuD5C,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0B1B;;OAEG;IACH,OAAc,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,cAAc,CAAA;KAAE,CAAC;IAE/F;;;;;;;OAOG;IACG,MAAM,CACR,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACnC,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,cAAc,CAAA;KAAE,CAAC;IA2D9E;;;OAGG;IACH,SAAS,IAAI,gBAAgB;IA+B7B;;OAEG;IACH,iBAAiB,IAAI,cAAc,CAAC,OAAO,CAAC;IAI5C;;OAEG;IACH,eAAe,IAAI,mBAAmB;IAItC;;OAEG;IACH,qBAAqB,IACf,OAAO,mCAAmC,EAAE,mBAAmB,GAC/D,IAAI;CAGb"}
@@ -29,13 +29,15 @@ class VercelLLMService {
29
29
  resourceManager;
30
30
  messageQueue;
31
31
  compactionStrategy;
32
+ modelLimits;
33
+ compactionThresholdPercent;
32
34
  /**
33
35
  * Helper to extract model ID from LanguageModel union type (string | LanguageModelV2)
34
36
  */
35
37
  getModelId() {
36
38
  return typeof this.model === "string" ? this.model : this.model.modelId;
37
39
  }
38
- constructor(toolManager, model, systemPromptManager, historyProvider, sessionEventBus, config, sessionId, resourceManager, logger, compactionStrategy) {
40
+ constructor(toolManager, model, systemPromptManager, historyProvider, sessionEventBus, config, sessionId, resourceManager, logger, compactionStrategy, compactionConfig) {
39
41
  this.logger = logger.createChild(DextoLogComponent.LLM);
40
42
  this.model = model;
41
43
  this.config = config;
@@ -44,9 +46,20 @@ class VercelLLMService {
44
46
  this.sessionId = sessionId;
45
47
  this.resourceManager = resourceManager;
46
48
  this.compactionStrategy = compactionStrategy ?? null;
49
+ this.compactionThresholdPercent = compactionConfig?.thresholdPercent ?? 0.9;
47
50
  this.messageQueue = new MessageQueueService(this.sessionEventBus, this.logger);
48
51
  const formatter = new VercelMessageFormatter(this.logger);
49
52
  const maxInputTokens = getEffectiveMaxInputTokens(config, this.logger);
53
+ let effectiveContextWindow = maxInputTokens;
54
+ if (compactionConfig?.maxContextTokens !== void 0) {
55
+ effectiveContextWindow = Math.min(maxInputTokens, compactionConfig.maxContextTokens);
56
+ this.logger.debug(
57
+ `Compaction: Using maxContextTokens override: ${compactionConfig.maxContextTokens} (model max: ${maxInputTokens})`
58
+ );
59
+ }
60
+ this.modelLimits = {
61
+ contextWindow: effectiveContextWindow
62
+ };
50
63
  this.contextManager = new ContextManager(
51
64
  config,
52
65
  formatter,
@@ -86,19 +99,23 @@ class VercelLLMService {
86
99
  { provider: this.config.provider, model: this.getModelId() },
87
100
  this.logger,
88
101
  this.messageQueue,
89
- void 0,
90
- // modelLimits - TurnExecutor will use defaults
102
+ this.modelLimits,
91
103
  externalSignal,
92
- this.compactionStrategy
104
+ this.compactionStrategy,
105
+ this.compactionThresholdPercent
93
106
  );
94
107
  }
108
+ /**
109
+ * Result from streaming a response.
110
+ */
111
+ static StreamResult;
95
112
  /**
96
113
  * Stream a response for the given content.
97
114
  * Primary method for running conversations with multi-image support.
98
115
  *
99
116
  * @param content - String or ContentPart[] (text, images, files)
100
117
  * @param options - { signal?: AbortSignal }
101
- * @returns The assistant's text response
118
+ * @returns Object with text response, whether compaction occurred, and compaction data if applicable
102
119
  */
103
120
  async stream(content, options) {
104
121
  const activeSpan = trace.getActiveSpan();
@@ -128,7 +145,12 @@ class VercelLLMService {
128
145
  const executor = this.createTurnExecutor(options?.signal);
129
146
  const contributorContext = { mcpManager: this.toolManager.getMcpManager() };
130
147
  const result = await executor.execute(contributorContext, true);
131
- return result.text ?? "";
148
+ return {
149
+ text: result.text ?? "",
150
+ didCompact: result.didCompact,
151
+ // Use spread to conditionally include compaction (exactOptionalPropertyTypes)
152
+ ...result.compaction && { compaction: result.compaction }
153
+ };
132
154
  });
133
155
  }
134
156
  /**
@@ -173,6 +195,12 @@ class VercelLLMService {
173
195
  getMessageQueue() {
174
196
  return this.messageQueue;
175
197
  }
198
+ /**
199
+ * Get the compaction strategy for external access (e.g., session-native compaction)
200
+ */
201
+ getCompactionStrategy() {
202
+ return this.compactionStrategy;
203
+ }
176
204
  }
177
205
  _init = __decoratorStart(null);
178
206
  VercelLLMService = __decorateElement(_init, 0, "VercelLLMService", _VercelLLMService_decorators, VercelLLMService);
@@ -169,8 +169,10 @@ class ChatSession {
169
169
  // Pass ResourceManager for blob storage
170
170
  this.logger,
171
171
  // Pass logger for dependency injection
172
- compactionStrategy
172
+ compactionStrategy,
173
173
  // Pass compaction strategy
174
+ runtimeConfig.compaction
175
+ // Pass compaction config for threshold settings
174
176
  );
175
177
  this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`);
176
178
  }
@@ -210,15 +212,15 @@ class ChatSession {
210
212
  *
211
213
  * @param content - String or ContentPart[] (text, images, files)
212
214
  * @param options - { signal?: AbortSignal }
213
- * @returns Promise that resolves to the AI's response text
215
+ * @returns Promise that resolves to object with text and compaction status
214
216
  *
215
217
  * @example
216
218
  * ```typescript
217
219
  * // Text only
218
- * const response = await session.stream('What is the weather?');
220
+ * const { text, didCompact } = await session.stream('What is the weather?');
219
221
  *
220
222
  * // Multiple images
221
- * const response = await session.stream([
223
+ * const { text, didCompact } = await session.stream([
222
224
  * { type: 'text', text: 'Compare these images' },
223
225
  * { type: 'image', image: base64Data1, mimeType: 'image/png' },
224
226
  * { type: 'image', image: base64Data2, mimeType: 'image/png' }
@@ -275,10 +277,10 @@ class ChatSession {
275
277
  modifiedParts = modifiedParts.filter((p) => p.type !== "text");
276
278
  modifiedParts.unshift({ type: "text", text: modifiedBeforePayload.text });
277
279
  }
278
- const response = await this.llmService.stream(modifiedParts, { signal });
280
+ const streamResult = await this.llmService.stream(modifiedParts, { signal });
279
281
  const llmConfig = this.services.stateManager.getLLMConfig(this.id);
280
282
  const beforeResponsePayload = {
281
- content: response,
283
+ content: streamResult.text,
282
284
  provider: llmConfig.provider,
283
285
  model: llmConfig.model,
284
286
  sessionId: this.id
@@ -295,7 +297,12 @@ class ChatSession {
295
297
  abortSignal: signal
296
298
  }
297
299
  );
298
- return modifiedResponsePayload.content;
300
+ return {
301
+ text: modifiedResponsePayload.content,
302
+ didCompact: streamResult.didCompact,
303
+ // Use spread to conditionally include compaction (exactOptionalPropertyTypes)
304
+ ...streamResult.compaction && { compaction: streamResult.compaction }
305
+ };
299
306
  } catch (error) {
300
307
  const aborted = error instanceof Error && error.name === "AbortError" || typeof error === "object" && error !== null && error.aborted === true;
301
308
  if (aborted) {
@@ -308,12 +315,12 @@ class ChatSession {
308
315
  const history = await this.getHistory();
309
316
  const lastAssistant = history.filter((m) => m.role === "assistant").pop();
310
317
  if (lastAssistant && typeof lastAssistant.content === "string") {
311
- return lastAssistant.content;
318
+ return { text: lastAssistant.content, didCompact: false };
312
319
  }
313
320
  } catch {
314
321
  this.logger.debug("Failed to retrieve partial response from history on cancel");
315
322
  }
316
- return "";
323
+ return { text: "", didCompact: false };
317
324
  }
318
325
  if (error instanceof import_errors.DextoRuntimeError && error.code === import_error_codes.PluginErrorCode.PLUGIN_BLOCKED_EXECUTION && error.scope === import_errors.ErrorScope.PLUGIN && error.type === import_errors.ErrorType.FORBIDDEN) {
319
326
  const textContent = parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
@@ -327,7 +334,7 @@ class ChatSession {
327
334
  `Failed to save blocked interaction to history: ${saveError instanceof Error ? saveError.message : String(saveError)}`
328
335
  );
329
336
  }
330
- return error.message;
337
+ return { text: error.message, didCompact: false };
331
338
  }
332
339
  this.logger.error(
333
340
  `Error in ChatSession.stream: ${error instanceof Error ? error.message : String(error)}`
@@ -455,8 +462,10 @@ class ChatSession {
455
462
  this.id,
456
463
  this.services.resourceManager,
457
464
  this.logger,
458
- compactionStrategy
465
+ compactionStrategy,
459
466
  // Pass compaction strategy
467
+ runtimeConfig.compaction
468
+ // Pass compaction config for threshold settings
460
469
  );
461
470
  this.llmService = newLLMService;
462
471
  this.logger.info(
@@ -12,6 +12,7 @@ import type { IDextoLogger } from '../logger/v2/types.js';
12
12
  import type { InternalMessage } from '../context/types.js';
13
13
  import type { UserMessageInput } from './message-queue.js';
14
14
  import type { ContentInput } from '../agent/types.js';
15
+ import type { CompactionData } from '../llm/executor/types.js';
15
16
  /**
16
17
  * Represents an isolated conversation session within a Dexto agent.
17
18
  *
@@ -162,15 +163,15 @@ export declare class ChatSession {
162
163
  *
163
164
  * @param content - String or ContentPart[] (text, images, files)
164
165
  * @param options - { signal?: AbortSignal }
165
- * @returns Promise that resolves to the AI's response text
166
+ * @returns Promise that resolves to object with text and compaction status
166
167
  *
167
168
  * @example
168
169
  * ```typescript
169
170
  * // Text only
170
- * const response = await session.stream('What is the weather?');
171
+ * const { text, didCompact } = await session.stream('What is the weather?');
171
172
  *
172
173
  * // Multiple images
173
- * const response = await session.stream([
174
+ * const { text, didCompact } = await session.stream([
174
175
  * { type: 'text', text: 'Compare these images' },
175
176
  * { type: 'image', image: base64Data1, mimeType: 'image/png' },
176
177
  * { type: 'image', image: base64Data2, mimeType: 'image/png' }
@@ -179,7 +180,11 @@ export declare class ChatSession {
179
180
  */
180
181
  stream(content: ContentInput, options?: {
181
182
  signal?: AbortSignal;
182
- }): Promise<string>;
183
+ }): Promise<{
184
+ text: string;
185
+ didCompact: boolean;
186
+ compaction?: CompactionData;
187
+ }>;
183
188
  /**
184
189
  * Combine multiple abort signals into one.
185
190
  */
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/session/chat-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/session/chat-session.ts"],"names":[],"mappings":"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"}
@@ -150,8 +150,10 @@ class ChatSession {
150
150
  // Pass ResourceManager for blob storage
151
151
  this.logger,
152
152
  // Pass logger for dependency injection
153
- compactionStrategy
153
+ compactionStrategy,
154
154
  // Pass compaction strategy
155
+ runtimeConfig.compaction
156
+ // Pass compaction config for threshold settings
155
157
  );
156
158
  this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`);
157
159
  }
@@ -191,15 +193,15 @@ class ChatSession {
191
193
  *
192
194
  * @param content - String or ContentPart[] (text, images, files)
193
195
  * @param options - { signal?: AbortSignal }
194
- * @returns Promise that resolves to the AI's response text
196
+ * @returns Promise that resolves to object with text and compaction status
195
197
  *
196
198
  * @example
197
199
  * ```typescript
198
200
  * // Text only
199
- * const response = await session.stream('What is the weather?');
201
+ * const { text, didCompact } = await session.stream('What is the weather?');
200
202
  *
201
203
  * // Multiple images
202
- * const response = await session.stream([
204
+ * const { text, didCompact } = await session.stream([
203
205
  * { type: 'text', text: 'Compare these images' },
204
206
  * { type: 'image', image: base64Data1, mimeType: 'image/png' },
205
207
  * { type: 'image', image: base64Data2, mimeType: 'image/png' }
@@ -256,10 +258,10 @@ class ChatSession {
256
258
  modifiedParts = modifiedParts.filter((p) => p.type !== "text");
257
259
  modifiedParts.unshift({ type: "text", text: modifiedBeforePayload.text });
258
260
  }
259
- const response = await this.llmService.stream(modifiedParts, { signal });
261
+ const streamResult = await this.llmService.stream(modifiedParts, { signal });
260
262
  const llmConfig = this.services.stateManager.getLLMConfig(this.id);
261
263
  const beforeResponsePayload = {
262
- content: response,
264
+ content: streamResult.text,
263
265
  provider: llmConfig.provider,
264
266
  model: llmConfig.model,
265
267
  sessionId: this.id
@@ -276,7 +278,12 @@ class ChatSession {
276
278
  abortSignal: signal
277
279
  }
278
280
  );
279
- return modifiedResponsePayload.content;
281
+ return {
282
+ text: modifiedResponsePayload.content,
283
+ didCompact: streamResult.didCompact,
284
+ // Use spread to conditionally include compaction (exactOptionalPropertyTypes)
285
+ ...streamResult.compaction && { compaction: streamResult.compaction }
286
+ };
280
287
  } catch (error) {
281
288
  const aborted = error instanceof Error && error.name === "AbortError" || typeof error === "object" && error !== null && error.aborted === true;
282
289
  if (aborted) {
@@ -289,12 +296,12 @@ class ChatSession {
289
296
  const history = await this.getHistory();
290
297
  const lastAssistant = history.filter((m) => m.role === "assistant").pop();
291
298
  if (lastAssistant && typeof lastAssistant.content === "string") {
292
- return lastAssistant.content;
299
+ return { text: lastAssistant.content, didCompact: false };
293
300
  }
294
301
  } catch {
295
302
  this.logger.debug("Failed to retrieve partial response from history on cancel");
296
303
  }
297
- return "";
304
+ return { text: "", didCompact: false };
298
305
  }
299
306
  if (error instanceof DextoRuntimeError && error.code === PluginErrorCode.PLUGIN_BLOCKED_EXECUTION && error.scope === ErrorScope.PLUGIN && error.type === ErrorType.FORBIDDEN) {
300
307
  const textContent = parts.filter((p) => p.type === "text").map((p) => p.text).join("\n");
@@ -308,7 +315,7 @@ class ChatSession {
308
315
  `Failed to save blocked interaction to history: ${saveError instanceof Error ? saveError.message : String(saveError)}`
309
316
  );
310
317
  }
311
- return error.message;
318
+ return { text: error.message, didCompact: false };
312
319
  }
313
320
  this.logger.error(
314
321
  `Error in ChatSession.stream: ${error instanceof Error ? error.message : String(error)}`
@@ -436,8 +443,10 @@ class ChatSession {
436
443
  this.id,
437
444
  this.services.resourceManager,
438
445
  this.logger,
439
- compactionStrategy
446
+ compactionStrategy,
440
447
  // Pass compaction strategy
448
+ runtimeConfig.compaction
449
+ // Pass compaction config for threshold settings
441
450
  );
442
451
  this.llmService = newLLMService;
443
452
  this.logger.info(
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var compaction_service_exports = {};
30
+ __export(compaction_service_exports, {
31
+ SessionCompactionService: () => SessionCompactionService
32
+ });
33
+ module.exports = __toCommonJS(compaction_service_exports);
34
+ var import_types = require("../logger/v2/types.js");
35
+ var import_utils = require("../context/utils.js");
36
+ class SessionCompactionService {
37
+ constructor(sessionManager, compactionStrategy, logger) {
38
+ this.sessionManager = sessionManager;
39
+ this.compactionStrategy = compactionStrategy;
40
+ this.logger = logger.createChild(import_types.DextoLogComponent.SESSION);
41
+ }
42
+ logger;
43
+ /**
44
+ * Perform session-native compaction.
45
+ *
46
+ * This creates a new continuation session with the summary as initial context,
47
+ * then marks the old session as compacted.
48
+ *
49
+ * @param currentSession The session to compact
50
+ * @param options Compaction options
51
+ * @returns CompactionResult with new session, or null if compaction not needed/possible
52
+ */
53
+ async compact(currentSession, options) {
54
+ const { reason, eventBus } = options;
55
+ const currentSessionId = currentSession.id;
56
+ this.logger.info(
57
+ `SessionCompactionService: Starting compaction for session ${currentSessionId} (reason: ${reason})`
58
+ );
59
+ const history = await currentSession.getHistory();
60
+ if (history.length <= 2) {
61
+ this.logger.debug("SessionCompactionService: History too short for compaction");
62
+ return null;
63
+ }
64
+ const summaryMessages = await this.compactionStrategy.compact(history);
65
+ if (summaryMessages.length === 0) {
66
+ this.logger.debug("SessionCompactionService: Strategy returned no summary");
67
+ return null;
68
+ }
69
+ const strategySummary = summaryMessages[0];
70
+ if (!strategySummary || !strategySummary.content) {
71
+ return null;
72
+ }
73
+ const summaryText = this.extractTextContent(strategySummary.content);
74
+ if (!summaryText.trim()) {
75
+ this.logger.debug("SessionCompactionService: Empty summary text; skipping compaction");
76
+ return null;
77
+ }
78
+ const summaryMessage = {
79
+ role: "assistant",
80
+ content: [{ type: "text", text: summaryText }],
81
+ timestamp: Date.now(),
82
+ metadata: {
83
+ isSessionSummary: true,
84
+ // New marker for session-native compaction
85
+ continuedFrom: currentSessionId,
86
+ summarizedAt: Date.now(),
87
+ originalMessageCount: history.length,
88
+ originalFirstTimestamp: history[0]?.timestamp,
89
+ originalLastTimestamp: history[history.length - 1]?.timestamp
90
+ }
91
+ };
92
+ const summaryTokens = (0, import_utils.estimateMessagesTokens)([summaryMessage]);
93
+ const { sessionId: newSessionId, session: newSession } = await this.sessionManager.createContinuationSession(currentSessionId);
94
+ const contextManager = newSession.getContextManager();
95
+ await contextManager.addMessage(summaryMessage);
96
+ await this.sessionManager.markSessionCompacted(currentSessionId, newSessionId);
97
+ this.logger.info(
98
+ `SessionCompactionService: Compaction complete. ${currentSessionId} \u2192 ${newSessionId}, ${history.length} messages \u2192 summary (~${summaryTokens} tokens)`
99
+ );
100
+ if (eventBus) {
101
+ const llmConfig = newSession.getLLMService().getConfig();
102
+ const modelId = typeof llmConfig.model === "string" ? llmConfig.model : llmConfig.model.modelId;
103
+ const { getModelDisplayName } = await import("../llm/registry.js");
104
+ const modelDisplayName = getModelDisplayName(modelId, llmConfig.provider);
105
+ eventBus.emit("session:continued", {
106
+ previousSessionId: currentSessionId,
107
+ newSessionId,
108
+ summaryTokens,
109
+ originalMessages: history.length,
110
+ reason,
111
+ sessionId: newSessionId,
112
+ // For consistency with other streaming events
113
+ model: modelId,
114
+ modelDisplayName
115
+ });
116
+ }
117
+ return {
118
+ previousSessionId: currentSessionId,
119
+ newSessionId,
120
+ newSession,
121
+ summary: summaryMessage,
122
+ summaryTokens,
123
+ originalMessages: history.length
124
+ };
125
+ }
126
+ /**
127
+ * Extract text content from message content.
128
+ */
129
+ extractTextContent(content) {
130
+ if (typeof content === "string") {
131
+ return content;
132
+ }
133
+ return content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
134
+ }
135
+ }
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {
138
+ SessionCompactionService
139
+ });