@dexto/core 1.9.2 → 1.9.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 (36) hide show
  1. package/dist/context/error-codes.cjs +1 -0
  2. package/dist/context/error-codes.d.ts +1 -0
  3. package/dist/context/error-codes.d.ts.map +1 -1
  4. package/dist/context/error-codes.js +1 -0
  5. package/dist/context/errors.cjs +10 -0
  6. package/dist/context/errors.d.ts +1 -0
  7. package/dist/context/errors.d.ts.map +1 -1
  8. package/dist/context/errors.js +10 -0
  9. package/dist/context/manager.cjs +66 -24
  10. package/dist/context/manager.d.ts +27 -17
  11. package/dist/context/manager.d.ts.map +1 -1
  12. package/dist/context/manager.js +66 -24
  13. package/dist/llm/executor/model-request-diagnostics.cjs +286 -0
  14. package/dist/llm/executor/model-request-diagnostics.d.ts +63 -0
  15. package/dist/llm/executor/model-request-diagnostics.d.ts.map +1 -0
  16. package/dist/llm/executor/model-request-diagnostics.js +262 -0
  17. package/dist/llm/executor/stream-processor.cjs +8 -13
  18. package/dist/llm/executor/stream-processor.d.ts +0 -1
  19. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  20. package/dist/llm/executor/stream-processor.js +8 -13
  21. package/dist/llm/executor/turn-executor.cjs +48 -12
  22. package/dist/llm/executor/turn-executor.d.ts +1 -1
  23. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  24. package/dist/llm/executor/turn-executor.js +51 -12
  25. package/dist/storage/conversation/database.cjs +15 -0
  26. package/dist/storage/conversation/database.d.ts +4 -1
  27. package/dist/storage/conversation/database.d.ts.map +1 -1
  28. package/dist/storage/conversation/database.js +15 -0
  29. package/dist/storage/conversation/types.d.ts +12 -0
  30. package/dist/storage/conversation/types.d.ts.map +1 -1
  31. package/dist/storage/index.d.ts +1 -1
  32. package/dist/storage/index.d.ts.map +1 -1
  33. package/dist/storage/stores/in-memory.cjs +15 -0
  34. package/dist/storage/stores/in-memory.d.ts.map +1 -1
  35. package/dist/storage/stores/in-memory.js +15 -0
  36. package/package.json +2 -2
@@ -27,6 +27,7 @@ var ContextErrorCode = /* @__PURE__ */ ((ContextErrorCode2) => {
27
27
  ContextErrorCode2["USER_MESSAGE_CONTENT_INVALID"] = "context_user_message_content_invalid";
28
28
  ContextErrorCode2["ASSISTANT_MESSAGE_CONTENT_OR_TOOLS_REQUIRED"] = "context_assistant_message_content_or_tools_required";
29
29
  ContextErrorCode2["ASSISTANT_MESSAGE_TOOL_CALLS_INVALID"] = "context_assistant_message_tool_calls_invalid";
30
+ ContextErrorCode2["ASSISTANT_MESSAGE_ID_MISSING"] = "context_assistant_message_id_missing";
30
31
  ContextErrorCode2["TOOL_MESSAGE_FIELDS_MISSING"] = "context_tool_message_fields_missing";
31
32
  ContextErrorCode2["TOOL_CALL_ID_NAME_REQUIRED"] = "context_tool_call_id_name_required";
32
33
  ContextErrorCode2["SYSTEM_MESSAGE_CONTENT_INVALID"] = "context_system_message_content_invalid";
@@ -8,6 +8,7 @@ export declare enum ContextErrorCode {
8
8
  USER_MESSAGE_CONTENT_INVALID = "context_user_message_content_invalid",
9
9
  ASSISTANT_MESSAGE_CONTENT_OR_TOOLS_REQUIRED = "context_assistant_message_content_or_tools_required",
10
10
  ASSISTANT_MESSAGE_TOOL_CALLS_INVALID = "context_assistant_message_tool_calls_invalid",
11
+ ASSISTANT_MESSAGE_ID_MISSING = "context_assistant_message_id_missing",
11
12
  TOOL_MESSAGE_FIELDS_MISSING = "context_tool_message_fields_missing",
12
13
  TOOL_CALL_ID_NAME_REQUIRED = "context_tool_call_id_name_required",
13
14
  SYSTEM_MESSAGE_CONTENT_INVALID = "context_system_message_content_invalid",
@@ -1 +1 @@
1
- {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/context/error-codes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,oBAAY,gBAAgB;IAExB,oBAAoB,iCAAiC;IACrD,qBAAqB,kCAAkC;IAGvD,4BAA4B,yCAAyC;IAGrE,2CAA2C,wDAAwD;IACnG,oCAAoC,iDAAiD;IAGrF,2BAA2B,wCAAwC;IACnE,0BAA0B,uCAAuC;IAGjE,8BAA8B,2CAA2C;IAEzE,kBAAkB,+BAA+B;IAMjD,wBAAwB,qCAAqC;IAC7D,qBAAqB,kCAAkC;IACvD,uBAAuB,oCAAoC;IAC3D,qBAAqB,kCAAkC;IACvD,sBAAsB,mCAAmC;IACzD,sCAAsC,mDAAmD;IAGzF,iBAAiB,8BAA8B;IAC/C,qBAAqB,kCAAkC;IACvD,4BAA4B,yCAAyC;CACxE"}
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/context/error-codes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,oBAAY,gBAAgB;IAExB,oBAAoB,iCAAiC;IACrD,qBAAqB,kCAAkC;IAGvD,4BAA4B,yCAAyC;IAGrE,2CAA2C,wDAAwD;IACnG,oCAAoC,iDAAiD;IACrF,4BAA4B,yCAAyC;IAGrE,2BAA2B,wCAAwC;IACnE,0BAA0B,uCAAuC;IAGjE,8BAA8B,2CAA2C;IAEzE,kBAAkB,+BAA+B;IAMjD,wBAAwB,qCAAqC;IAC7D,qBAAqB,kCAAkC;IACvD,uBAAuB,oCAAoC;IAC3D,qBAAqB,kCAAkC;IACvD,sBAAsB,mCAAmC;IACzD,sCAAsC,mDAAmD;IAGzF,iBAAiB,8BAA8B;IAC/C,qBAAqB,kCAAkC;IACvD,4BAA4B,yCAAyC;CACxE"}
@@ -5,6 +5,7 @@ var ContextErrorCode = /* @__PURE__ */ ((ContextErrorCode2) => {
5
5
  ContextErrorCode2["USER_MESSAGE_CONTENT_INVALID"] = "context_user_message_content_invalid";
6
6
  ContextErrorCode2["ASSISTANT_MESSAGE_CONTENT_OR_TOOLS_REQUIRED"] = "context_assistant_message_content_or_tools_required";
7
7
  ContextErrorCode2["ASSISTANT_MESSAGE_TOOL_CALLS_INVALID"] = "context_assistant_message_tool_calls_invalid";
8
+ ContextErrorCode2["ASSISTANT_MESSAGE_ID_MISSING"] = "context_assistant_message_id_missing";
8
9
  ContextErrorCode2["TOOL_MESSAGE_FIELDS_MISSING"] = "context_tool_message_fields_missing";
9
10
  ContextErrorCode2["TOOL_CALL_ID_NAME_REQUIRED"] = "context_tool_call_id_name_required";
10
11
  ContextErrorCode2["SYSTEM_MESSAGE_CONTENT_INVALID"] = "context_system_message_content_invalid";
@@ -66,6 +66,16 @@ class ContextError {
66
66
  "Ensure toolCalls have proper structure with function name and arguments"
67
67
  );
68
68
  }
69
+ static assistantMessageIdMissing() {
70
+ return new import_errors.DextoRuntimeError(
71
+ import_error_codes.ContextErrorCode.ASSISTANT_MESSAGE_ID_MISSING,
72
+ import_types.ErrorScope.CONTEXT,
73
+ import_types.ErrorType.SYSTEM,
74
+ "Expected assistant message id after saving message",
75
+ {},
76
+ "Check conversation store saveMessage behavior"
77
+ );
78
+ }
69
79
  static toolMessageFieldsMissing() {
70
80
  return new import_errors.DextoRuntimeError(
71
81
  import_error_codes.ContextErrorCode.TOOL_MESSAGE_FIELDS_MISSING,
@@ -8,6 +8,7 @@ export declare class ContextError {
8
8
  static userMessageContentInvalid(): DextoRuntimeError<{}>;
9
9
  static assistantMessageContentOrToolsRequired(): DextoRuntimeError<{}>;
10
10
  static assistantMessageToolCallsInvalid(): DextoRuntimeError<{}>;
11
+ static assistantMessageIdMissing(): DextoRuntimeError<{}>;
11
12
  static toolMessageFieldsMissing(): DextoRuntimeError<{}>;
12
13
  static systemMessageContentInvalid(): DextoRuntimeError<{}>;
13
14
  static userMessageContentEmpty(): DextoRuntimeError<{}>;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/context/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAIvD;;;GAGG;AACH,qBAAa,YAAY;IAErB,MAAM,CAAC,kBAAkB;IAWzB,MAAM,CAAC,yBAAyB;IAWhC,MAAM,CAAC,sCAAsC;IAW7C,MAAM,CAAC,gCAAgC;IAWvC,MAAM,CAAC,wBAAwB;IAW/B,MAAM,CAAC,2BAA2B;IAWlC,MAAM,CAAC,uBAAuB;IAW9B,MAAM,CAAC,sBAAsB;IAe7B,MAAM,CAAC,sBAAsB;IAW7B,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM;;;IAWrC,MAAM,CAAC,mBAAmB;IAW1B,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;;;;IAW9D,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;;;;IAWzD,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM;;;IAWxC,MAAM,CAAC,mCAAmC,CAAC,IAAI,EAAE,MAAM;;;IAYvD,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM;;;IAUxC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,MAAM;;;IAU5C,MAAM,CAAC,yBAAyB;CASnC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/context/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAIvD;;;GAGG;AACH,qBAAa,YAAY;IAErB,MAAM,CAAC,kBAAkB;IAWzB,MAAM,CAAC,yBAAyB;IAWhC,MAAM,CAAC,sCAAsC;IAW7C,MAAM,CAAC,gCAAgC;IAWvC,MAAM,CAAC,yBAAyB;IAWhC,MAAM,CAAC,wBAAwB;IAW/B,MAAM,CAAC,2BAA2B;IAWlC,MAAM,CAAC,uBAAuB;IAW9B,MAAM,CAAC,sBAAsB;IAe7B,MAAM,CAAC,sBAAsB;IAW7B,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM;;;IAWrC,MAAM,CAAC,mBAAmB;IAW1B,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;;;;IAW9D,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;;;;IAWzD,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM;;;IAWxC,MAAM,CAAC,mCAAmC,CAAC,IAAI,EAAE,MAAM;;;IAYvD,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM;;;IAUxC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,MAAM;;;IAU5C,MAAM,CAAC,yBAAyB;CASnC"}
@@ -44,6 +44,16 @@ class ContextError {
44
44
  "Ensure toolCalls have proper structure with function name and arguments"
45
45
  );
46
46
  }
47
+ static assistantMessageIdMissing() {
48
+ return new DextoRuntimeError(
49
+ ContextErrorCode.ASSISTANT_MESSAGE_ID_MISSING,
50
+ ErrorScope.CONTEXT,
51
+ ErrorType.SYSTEM,
52
+ "Expected assistant message id after saving message",
53
+ {},
54
+ "Check conversation store saveMessage behavior"
55
+ );
56
+ }
47
57
  static toolMessageFieldsMissing() {
48
58
  return new DextoRuntimeError(
49
59
  ContextErrorCode.TOOL_MESSAGE_FIELDS_MISSING,
@@ -74,7 +74,7 @@ class ContextManager {
74
74
  */
75
75
  lastActualOutputTokens = null;
76
76
  /**
77
- * Message count at the time of the last LLM call.
77
+ * Model-visible message count at the time of the last LLM call.
78
78
  * Used to identify which messages are "new" since the last call.
79
79
  * Messages after this index are estimated with length/4 heuristic.
80
80
  */
@@ -321,19 +321,21 @@ class ContextManager {
321
321
  this.logger.debug(`Updated lastActualOutputTokens: ${tokens}`);
322
322
  }
323
323
  /**
324
- * Returns the message count at the time of the last LLM call.
324
+ * Returns the model-visible message count at the time of the last LLM call.
325
325
  * Returns null if no LLM call has been made yet.
326
326
  */
327
327
  getLastCallMessageCount() {
328
328
  return this.lastCallMessageCount;
329
329
  }
330
330
  /**
331
- * Records the current message count after an LLM call completes.
331
+ * Records the current model-visible message count after an LLM call completes.
332
332
  * This marks the boundary for "new messages" calculation.
333
333
  */
334
334
  async recordLastCallMessageCount() {
335
- const history = await this.conversationStore.listMessages({ sessionId: this.sessionId });
336
- this.lastCallMessageCount = history.length;
335
+ const history = await this.conversationStore.loadModelHistory({
336
+ sessionId: this.sessionId
337
+ });
338
+ this.lastCallMessageCount = history.messages.length;
337
339
  this.logger.debug(`Recorded lastCallMessageCount: ${this.lastCallMessageCount}`);
338
340
  }
339
341
  /**
@@ -371,9 +373,36 @@ class ContextManager {
371
373
  const fullHistory = await this.conversationStore.listMessages({
372
374
  sessionId: this.sessionId
373
375
  });
374
- const originalCount = fullHistory.length;
376
+ return this.prepareVisibleHistory({
377
+ history: (0, import_utils.filterCompacted)(fullHistory),
378
+ originalCount: fullHistory.length,
379
+ source: "prepareHistory"
380
+ });
381
+ }
382
+ /**
383
+ * Prepares model-visible history without first materializing the whole durable session.
384
+ * This is the model execution boundary; Worker/Workflow model calls should use this
385
+ * method instead of prepareHistory().
386
+ */
387
+ async prepareModelHistory() {
388
+ const modelHistory = await this.conversationStore.loadModelHistory({
389
+ sessionId: this.sessionId
390
+ });
391
+ return this.prepareVisibleHistory({
392
+ history: modelHistory.messages,
393
+ originalCount: modelHistory.stats.returnedMessages + modelHistory.stats.skippedPreSummaryMessages,
394
+ source: "prepareModelHistory"
395
+ });
396
+ }
397
+ async getModelHistory() {
398
+ const modelHistory = await this.conversationStore.loadModelHistory({
399
+ sessionId: this.sessionId
400
+ });
401
+ return modelHistory.messages;
402
+ }
403
+ prepareVisibleHistory(input) {
375
404
  const visibleToolCallIds = /* @__PURE__ */ new Set();
376
- let history = (0, import_utils.filterCompacted)(fullHistory).filter((message) => {
405
+ let history = input.history.filter((message) => {
377
406
  const isVisible = isVisibleInPreparedHistory(message);
378
407
  if (isVisible && message.role === "assistant") {
379
408
  for (const toolCall of message.toolCalls ?? []) {
@@ -386,9 +415,9 @@ class ContextManager {
386
415
  return message.role !== "tool" || visibleToolCallIds.has(message.toolCallId);
387
416
  });
388
417
  const filteredCount = history.length;
389
- if (filteredCount < originalCount) {
418
+ if (filteredCount < input.originalCount) {
390
419
  this.logger.debug(
391
- `prepareHistory: reduced from ${originalCount} to ${filteredCount} model-visible messages`
420
+ `${input.source}: reduced from ${input.originalCount} to ${filteredCount} model-visible messages`
392
421
  );
393
422
  }
394
423
  let prunedToolCount = 0;
@@ -406,13 +435,13 @@ class ContextManager {
406
435
  });
407
436
  if (prunedToolCount > 0) {
408
437
  this.logger.debug(
409
- `prepareHistory: Transformed ${prunedToolCount} pruned tool messages to placeholders`
438
+ `${input.source}: Transformed ${prunedToolCount} pruned tool messages to placeholders`
410
439
  );
411
440
  }
412
441
  return {
413
442
  preparedHistory: history,
414
443
  stats: {
415
- originalCount,
444
+ originalCount: input.originalCount,
416
445
  filteredCount,
417
446
  prunedToolCount
418
447
  }
@@ -642,8 +671,11 @@ ${prompt}`);
642
671
  `ContextManager: Adding message to conversation store: ${JSON.stringify(message, null, 2)}`
643
672
  );
644
673
  await this.conversationStore.saveMessage({ sessionId: this.sessionId, message });
645
- const history = await this.conversationStore.listMessages({ sessionId: this.sessionId });
646
- this.logger.debug(`ContextManager: History now contains ${history.length} messages`);
674
+ this.logger.debug("ContextManager: Message saved to conversation store", {
675
+ messageId: message.id,
676
+ role: message.role
677
+ });
678
+ return message;
647
679
  }
648
680
  /**
649
681
  * Adds a user message to the conversation.
@@ -689,7 +721,7 @@ ${prompt}`);
689
721
  throw import_errors.ContextError.assistantMessageContentOrToolsRequired();
690
722
  }
691
723
  const contentArray = content !== null ? [{ type: "text", text: content }] : null;
692
- await this.addMessage({
724
+ const message = await this.addMessage({
693
725
  role: "assistant",
694
726
  content: contentArray,
695
727
  ...toolCalls && toolCalls.length > 0 && { toolCalls },
@@ -702,6 +734,10 @@ ${prompt}`);
702
734
  ...metadata?.usageScopeId && { usageScopeId: metadata.usageScopeId },
703
735
  assistantOutput: metadata?.assistantOutput ?? { status: "complete" }
704
736
  });
737
+ if (message.id === void 0) {
738
+ throw import_errors.ContextError.assistantMessageIdMissing();
739
+ }
740
+ return message.id;
705
741
  }
706
742
  /**
707
743
  * Adds a tool result message to the conversation.
@@ -853,7 +889,7 @@ ${prompt}`);
853
889
  */
854
890
  async getFormattedMessagesForLLM(contributorContext, llmContext) {
855
891
  const systemPrompt = await this.getSystemPrompt(contributorContext);
856
- const { preparedHistory } = await this.prepareHistory();
892
+ const { preparedHistory } = await this.prepareModelHistory();
857
893
  const formattedMessages = await this.getFormattedMessages(
858
894
  contributorContext,
859
895
  llmContext,
@@ -868,7 +904,8 @@ ${prompt}`);
868
904
  }
869
905
  /**
870
906
  * Estimates context token usage for the /context command and compaction decisions.
871
- * Uses the same prepareHistory() logic as getFormattedMessagesForLLM() to ensure consistency.
907
+ * Uses the same model-history preparation logic as getFormattedMessagesForLLM() to ensure
908
+ * consistency.
872
909
  *
873
910
  * When actuals are available from previous LLM calls:
874
911
  * estimatedNextInput = lastInputTokens + lastOutputTokens + newMessagesEstimate
@@ -886,13 +923,18 @@ ${prompt}`);
886
923
  */
887
924
  async getContextTokenEstimate(contributorContext, tools) {
888
925
  const systemPrompt = await this.getSystemPrompt(contributorContext);
889
- const { preparedHistory, stats } = await this.prepareHistory();
926
+ const modelHistory = await this.conversationStore.loadModelHistory({
927
+ sessionId: this.sessionId
928
+ });
929
+ const { preparedHistory, stats } = this.prepareVisibleHistory({
930
+ history: modelHistory.messages,
931
+ originalCount: modelHistory.stats.returnedMessages + modelHistory.stats.skippedPreSummaryMessages,
932
+ source: "getContextTokenEstimate"
933
+ });
890
934
  const lastInput = this.lastActualInputTokens;
891
935
  const lastOutput = this.lastActualOutputTokens;
892
936
  const lastMsgCount = this.lastCallMessageCount;
893
- const currentHistory = await this.conversationStore.listMessages({
894
- sessionId: this.sessionId
895
- });
937
+ const currentHistory = modelHistory.messages;
896
938
  const pureEstimate = (0, import_utils.estimateContextTokens)(systemPrompt, preparedHistory, tools);
897
939
  let total;
898
940
  let calculationBasis;
@@ -992,11 +1034,11 @@ ${prompt}`);
992
1034
  const lastInput = this.lastActualInputTokens;
993
1035
  const lastOutput = this.lastActualOutputTokens;
994
1036
  const lastMsgCount = this.lastCallMessageCount;
995
- const currentHistory = await this.conversationStore.listMessages({
996
- sessionId: this.sessionId
997
- });
998
1037
  if (lastInput !== null && lastOutput !== null && lastMsgCount !== null) {
999
- const newMessages = currentHistory.slice(lastMsgCount);
1038
+ const modelHistory = await this.conversationStore.loadModelHistory({
1039
+ sessionId: this.sessionId
1040
+ });
1041
+ const newMessages = modelHistory.messages.slice(lastMsgCount);
1000
1042
  const newMessagesEstimate = (0, import_utils.estimateMessagesTokens)(newMessages);
1001
1043
  const total = lastInput + lastOutput + newMessagesEstimate;
1002
1044
  this.logger.debug(
@@ -9,6 +9,17 @@ import type { ConversationStore } from '../storage/conversation/types.js';
9
9
  import { ValidatedLLMConfig } from '../llm/schemas.js';
10
10
  import type { ToolPresentationSnapshotV1 } from '../tools/types.js';
11
11
  import type { ToolCallMetadata } from '../tools/tool-call-metadata.js';
12
+ export type PreparedHistoryResult = {
13
+ preparedHistory: InternalMessage[];
14
+ stats: {
15
+ /** Total messages in raw or model-history source */
16
+ originalCount: number;
17
+ /** Messages after model-history filters */
18
+ filteredCount: number;
19
+ /** Messages with compactedAt that were transformed to placeholders */
20
+ prunedToolCount: number;
21
+ };
22
+ };
12
23
  /**
13
24
  * Manages conversation history and provides message formatting capabilities for the LLM context.
14
25
  * The ContextManager is responsible for:
@@ -53,7 +64,7 @@ export declare class ContextManager<TMessage = unknown> {
53
64
  */
54
65
  private lastActualOutputTokens;
55
66
  /**
56
- * Message count at the time of the last LLM call.
67
+ * Model-visible message count at the time of the last LLM call.
57
68
  * Used to identify which messages are "new" since the last call.
58
69
  * Messages after this index are estimated with length/4 heuristic.
59
70
  */
@@ -116,12 +127,12 @@ export declare class ContextManager<TMessage = unknown> {
116
127
  */
117
128
  setLastActualOutputTokens(tokens: number): void;
118
129
  /**
119
- * Returns the message count at the time of the last LLM call.
130
+ * Returns the model-visible message count at the time of the last LLM call.
120
131
  * Returns null if no LLM call has been made yet.
121
132
  */
122
133
  getLastCallMessageCount(): number | null;
123
134
  /**
124
- * Records the current message count after an LLM call completes.
135
+ * Records the current model-visible message count after an LLM call completes.
125
136
  * This marks the boundary for "new messages" calculation.
126
137
  */
127
138
  recordLastCallMessageCount(): Promise<void>;
@@ -150,17 +161,15 @@ export declare class ContextManager<TMessage = unknown> {
150
161
  *
151
162
  * @returns Prepared history and statistics about the transformations
152
163
  */
153
- prepareHistory(): Promise<{
154
- preparedHistory: InternalMessage[];
155
- stats: {
156
- /** Total messages in raw history */
157
- originalCount: number;
158
- /** Messages after model-history filters */
159
- filteredCount: number;
160
- /** Messages with compactedAt that were transformed to placeholders */
161
- prunedToolCount: number;
162
- };
163
- }>;
164
+ prepareHistory(): Promise<PreparedHistoryResult>;
165
+ /**
166
+ * Prepares model-visible history without first materializing the whole durable session.
167
+ * This is the model execution boundary; Worker/Workflow model calls should use this
168
+ * method instead of prepareHistory().
169
+ */
170
+ prepareModelHistory(): Promise<PreparedHistoryResult>;
171
+ getModelHistory(): Promise<Readonly<InternalMessage[]>>;
172
+ private prepareVisibleHistory;
164
173
  /**
165
174
  * Assembles and returns the current system prompt by invoking the SystemPromptManager.
166
175
  */
@@ -224,7 +233,7 @@ export declare class ContextManager<TMessage = unknown> {
224
233
  * @param message The message to add to the history
225
234
  * @throws Error if message validation fails
226
235
  */
227
- addMessage(message: InternalMessage): Promise<void>;
236
+ addMessage(message: InternalMessage): Promise<InternalMessage>;
228
237
  /**
229
238
  * Adds a user message to the conversation.
230
239
  * Supports multiple images and files via ContentPart[].
@@ -249,7 +258,7 @@ export declare class ContextManager<TMessage = unknown> {
249
258
  pricingStatus?: AssistantMessage['pricingStatus'];
250
259
  usageScopeId?: AssistantMessage['usageScopeId'];
251
260
  assistantOutput?: AssistantMessage['assistantOutput'];
252
- }): Promise<void>;
261
+ }): Promise<string>;
253
262
  /**
254
263
  * Adds a tool result message to the conversation.
255
264
  * The result must already be sanitized - this method only persists it.
@@ -299,7 +308,8 @@ export declare class ContextManager<TMessage = unknown> {
299
308
  }>;
300
309
  /**
301
310
  * Estimates context token usage for the /context command and compaction decisions.
302
- * Uses the same prepareHistory() logic as getFormattedMessagesForLLM() to ensure consistency.
311
+ * Uses the same model-history preparation logic as getFormattedMessagesForLLM() to ensure
312
+ * consistency.
303
313
  *
304
314
  * When actuals are available from previous LLM calls:
305
315
  * estimatedNextInput = lastInputTokens + lastOutputTokens + newMessagesEstimate
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/context/manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/context/manager.ts"],"names":[],"mappings":"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"}
@@ -49,7 +49,7 @@ class ContextManager {
49
49
  */
50
50
  lastActualOutputTokens = null;
51
51
  /**
52
- * Message count at the time of the last LLM call.
52
+ * Model-visible message count at the time of the last LLM call.
53
53
  * Used to identify which messages are "new" since the last call.
54
54
  * Messages after this index are estimated with length/4 heuristic.
55
55
  */
@@ -296,19 +296,21 @@ class ContextManager {
296
296
  this.logger.debug(`Updated lastActualOutputTokens: ${tokens}`);
297
297
  }
298
298
  /**
299
- * Returns the message count at the time of the last LLM call.
299
+ * Returns the model-visible message count at the time of the last LLM call.
300
300
  * Returns null if no LLM call has been made yet.
301
301
  */
302
302
  getLastCallMessageCount() {
303
303
  return this.lastCallMessageCount;
304
304
  }
305
305
  /**
306
- * Records the current message count after an LLM call completes.
306
+ * Records the current model-visible message count after an LLM call completes.
307
307
  * This marks the boundary for "new messages" calculation.
308
308
  */
309
309
  async recordLastCallMessageCount() {
310
- const history = await this.conversationStore.listMessages({ sessionId: this.sessionId });
311
- this.lastCallMessageCount = history.length;
310
+ const history = await this.conversationStore.loadModelHistory({
311
+ sessionId: this.sessionId
312
+ });
313
+ this.lastCallMessageCount = history.messages.length;
312
314
  this.logger.debug(`Recorded lastCallMessageCount: ${this.lastCallMessageCount}`);
313
315
  }
314
316
  /**
@@ -346,9 +348,36 @@ class ContextManager {
346
348
  const fullHistory = await this.conversationStore.listMessages({
347
349
  sessionId: this.sessionId
348
350
  });
349
- const originalCount = fullHistory.length;
351
+ return this.prepareVisibleHistory({
352
+ history: filterCompacted(fullHistory),
353
+ originalCount: fullHistory.length,
354
+ source: "prepareHistory"
355
+ });
356
+ }
357
+ /**
358
+ * Prepares model-visible history without first materializing the whole durable session.
359
+ * This is the model execution boundary; Worker/Workflow model calls should use this
360
+ * method instead of prepareHistory().
361
+ */
362
+ async prepareModelHistory() {
363
+ const modelHistory = await this.conversationStore.loadModelHistory({
364
+ sessionId: this.sessionId
365
+ });
366
+ return this.prepareVisibleHistory({
367
+ history: modelHistory.messages,
368
+ originalCount: modelHistory.stats.returnedMessages + modelHistory.stats.skippedPreSummaryMessages,
369
+ source: "prepareModelHistory"
370
+ });
371
+ }
372
+ async getModelHistory() {
373
+ const modelHistory = await this.conversationStore.loadModelHistory({
374
+ sessionId: this.sessionId
375
+ });
376
+ return modelHistory.messages;
377
+ }
378
+ prepareVisibleHistory(input) {
350
379
  const visibleToolCallIds = /* @__PURE__ */ new Set();
351
- let history = filterCompacted(fullHistory).filter((message) => {
380
+ let history = input.history.filter((message) => {
352
381
  const isVisible = isVisibleInPreparedHistory(message);
353
382
  if (isVisible && message.role === "assistant") {
354
383
  for (const toolCall of message.toolCalls ?? []) {
@@ -361,9 +390,9 @@ class ContextManager {
361
390
  return message.role !== "tool" || visibleToolCallIds.has(message.toolCallId);
362
391
  });
363
392
  const filteredCount = history.length;
364
- if (filteredCount < originalCount) {
393
+ if (filteredCount < input.originalCount) {
365
394
  this.logger.debug(
366
- `prepareHistory: reduced from ${originalCount} to ${filteredCount} model-visible messages`
395
+ `${input.source}: reduced from ${input.originalCount} to ${filteredCount} model-visible messages`
367
396
  );
368
397
  }
369
398
  let prunedToolCount = 0;
@@ -381,13 +410,13 @@ class ContextManager {
381
410
  });
382
411
  if (prunedToolCount > 0) {
383
412
  this.logger.debug(
384
- `prepareHistory: Transformed ${prunedToolCount} pruned tool messages to placeholders`
413
+ `${input.source}: Transformed ${prunedToolCount} pruned tool messages to placeholders`
385
414
  );
386
415
  }
387
416
  return {
388
417
  preparedHistory: history,
389
418
  stats: {
390
- originalCount,
419
+ originalCount: input.originalCount,
391
420
  filteredCount,
392
421
  prunedToolCount
393
422
  }
@@ -617,8 +646,11 @@ ${prompt}`);
617
646
  `ContextManager: Adding message to conversation store: ${JSON.stringify(message, null, 2)}`
618
647
  );
619
648
  await this.conversationStore.saveMessage({ sessionId: this.sessionId, message });
620
- const history = await this.conversationStore.listMessages({ sessionId: this.sessionId });
621
- this.logger.debug(`ContextManager: History now contains ${history.length} messages`);
649
+ this.logger.debug("ContextManager: Message saved to conversation store", {
650
+ messageId: message.id,
651
+ role: message.role
652
+ });
653
+ return message;
622
654
  }
623
655
  /**
624
656
  * Adds a user message to the conversation.
@@ -664,7 +696,7 @@ ${prompt}`);
664
696
  throw ContextError.assistantMessageContentOrToolsRequired();
665
697
  }
666
698
  const contentArray = content !== null ? [{ type: "text", text: content }] : null;
667
- await this.addMessage({
699
+ const message = await this.addMessage({
668
700
  role: "assistant",
669
701
  content: contentArray,
670
702
  ...toolCalls && toolCalls.length > 0 && { toolCalls },
@@ -677,6 +709,10 @@ ${prompt}`);
677
709
  ...metadata?.usageScopeId && { usageScopeId: metadata.usageScopeId },
678
710
  assistantOutput: metadata?.assistantOutput ?? { status: "complete" }
679
711
  });
712
+ if (message.id === void 0) {
713
+ throw ContextError.assistantMessageIdMissing();
714
+ }
715
+ return message.id;
680
716
  }
681
717
  /**
682
718
  * Adds a tool result message to the conversation.
@@ -828,7 +864,7 @@ ${prompt}`);
828
864
  */
829
865
  async getFormattedMessagesForLLM(contributorContext, llmContext) {
830
866
  const systemPrompt = await this.getSystemPrompt(contributorContext);
831
- const { preparedHistory } = await this.prepareHistory();
867
+ const { preparedHistory } = await this.prepareModelHistory();
832
868
  const formattedMessages = await this.getFormattedMessages(
833
869
  contributorContext,
834
870
  llmContext,
@@ -843,7 +879,8 @@ ${prompt}`);
843
879
  }
844
880
  /**
845
881
  * Estimates context token usage for the /context command and compaction decisions.
846
- * Uses the same prepareHistory() logic as getFormattedMessagesForLLM() to ensure consistency.
882
+ * Uses the same model-history preparation logic as getFormattedMessagesForLLM() to ensure
883
+ * consistency.
847
884
  *
848
885
  * When actuals are available from previous LLM calls:
849
886
  * estimatedNextInput = lastInputTokens + lastOutputTokens + newMessagesEstimate
@@ -861,13 +898,18 @@ ${prompt}`);
861
898
  */
862
899
  async getContextTokenEstimate(contributorContext, tools) {
863
900
  const systemPrompt = await this.getSystemPrompt(contributorContext);
864
- const { preparedHistory, stats } = await this.prepareHistory();
901
+ const modelHistory = await this.conversationStore.loadModelHistory({
902
+ sessionId: this.sessionId
903
+ });
904
+ const { preparedHistory, stats } = this.prepareVisibleHistory({
905
+ history: modelHistory.messages,
906
+ originalCount: modelHistory.stats.returnedMessages + modelHistory.stats.skippedPreSummaryMessages,
907
+ source: "getContextTokenEstimate"
908
+ });
865
909
  const lastInput = this.lastActualInputTokens;
866
910
  const lastOutput = this.lastActualOutputTokens;
867
911
  const lastMsgCount = this.lastCallMessageCount;
868
- const currentHistory = await this.conversationStore.listMessages({
869
- sessionId: this.sessionId
870
- });
912
+ const currentHistory = modelHistory.messages;
871
913
  const pureEstimate = estimateContextTokens(systemPrompt, preparedHistory, tools);
872
914
  let total;
873
915
  let calculationBasis;
@@ -967,11 +1009,11 @@ ${prompt}`);
967
1009
  const lastInput = this.lastActualInputTokens;
968
1010
  const lastOutput = this.lastActualOutputTokens;
969
1011
  const lastMsgCount = this.lastCallMessageCount;
970
- const currentHistory = await this.conversationStore.listMessages({
971
- sessionId: this.sessionId
972
- });
973
1012
  if (lastInput !== null && lastOutput !== null && lastMsgCount !== null) {
974
- const newMessages = currentHistory.slice(lastMsgCount);
1013
+ const modelHistory = await this.conversationStore.loadModelHistory({
1014
+ sessionId: this.sessionId
1015
+ });
1016
+ const newMessages = modelHistory.messages.slice(lastMsgCount);
975
1017
  const newMessagesEstimate = estimateMessagesTokens(newMessages);
976
1018
  const total = lastInput + lastOutput + newMessagesEstimate;
977
1019
  this.logger.debug(