@trenchwork/coder 1.4.0 → 1.5.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 (95) hide show
  1. package/dist/contracts/v1/agent.d.ts +2 -0
  2. package/dist/contracts/v1/agent.d.ts.map +1 -1
  3. package/dist/core/agent.d.ts.map +1 -1
  4. package/dist/core/agent.js +77 -2
  5. package/dist/core/agent.js.map +1 -1
  6. package/dist/core/contextManager.d.ts +10 -137
  7. package/dist/core/contextManager.d.ts.map +1 -1
  8. package/dist/core/contextManager.js +74 -540
  9. package/dist/core/contextManager.js.map +1 -1
  10. package/dist/core/errorClassification.d.ts.map +1 -1
  11. package/dist/core/errorClassification.js +8 -0
  12. package/dist/core/errorClassification.js.map +1 -1
  13. package/dist/core/hooks.d.ts.map +1 -1
  14. package/dist/core/hooks.js +42 -19
  15. package/dist/core/hooks.js.map +1 -1
  16. package/dist/core/keyResolution.d.ts +30 -0
  17. package/dist/core/keyResolution.d.ts.map +1 -0
  18. package/dist/core/keyResolution.js +38 -0
  19. package/dist/core/keyResolution.js.map +1 -0
  20. package/dist/core/permissionMode.d.ts +17 -2
  21. package/dist/core/permissionMode.d.ts.map +1 -1
  22. package/dist/core/permissionMode.js +20 -7
  23. package/dist/core/permissionMode.js.map +1 -1
  24. package/dist/core/reasoningFallback.d.ts +22 -0
  25. package/dist/core/reasoningFallback.d.ts.map +1 -0
  26. package/dist/core/reasoningFallback.js +22 -0
  27. package/dist/core/reasoningFallback.js.map +1 -0
  28. package/dist/core/sessionStore.js +34 -8
  29. package/dist/core/sessionStore.js.map +1 -1
  30. package/dist/core/slashCommands.d.ts.map +1 -1
  31. package/dist/core/slashCommands.js +0 -3
  32. package/dist/core/slashCommands.js.map +1 -1
  33. package/dist/core/taskCompletionDetector.d.ts.map +1 -1
  34. package/dist/core/taskCompletionDetector.js +10 -3
  35. package/dist/core/taskCompletionDetector.js.map +1 -1
  36. package/dist/core/toolRuntime.d.ts +1 -0
  37. package/dist/core/toolRuntime.d.ts.map +1 -1
  38. package/dist/core/toolRuntime.js +21 -2
  39. package/dist/core/toolRuntime.js.map +1 -1
  40. package/dist/core/turnTokenMeter.d.ts +19 -0
  41. package/dist/core/turnTokenMeter.d.ts.map +1 -0
  42. package/dist/core/turnTokenMeter.js +36 -0
  43. package/dist/core/turnTokenMeter.js.map +1 -0
  44. package/dist/headless/interactiveShell.d.ts +3 -3
  45. package/dist/headless/interactiveShell.d.ts.map +1 -1
  46. package/dist/headless/interactiveShell.js +68 -115
  47. package/dist/headless/interactiveShell.js.map +1 -1
  48. package/dist/plugins/providers/deepseek/index.js +4 -6
  49. package/dist/plugins/providers/deepseek/index.js.map +1 -1
  50. package/dist/providers/openaiChatCompletionsProvider.d.ts.map +1 -1
  51. package/dist/providers/openaiChatCompletionsProvider.js +33 -26
  52. package/dist/providers/openaiChatCompletionsProvider.js.map +1 -1
  53. package/dist/runtime/agentController.d.ts.map +1 -1
  54. package/dist/runtime/agentController.js +16 -7
  55. package/dist/runtime/agentController.js.map +1 -1
  56. package/dist/runtime/agentSession.d.ts.map +1 -1
  57. package/dist/runtime/agentSession.js +10 -3
  58. package/dist/runtime/agentSession.js.map +1 -1
  59. package/dist/tools/bashTools.d.ts +63 -0
  60. package/dist/tools/bashTools.d.ts.map +1 -1
  61. package/dist/tools/bashTools.js +186 -77
  62. package/dist/tools/bashTools.js.map +1 -1
  63. package/dist/tools/grepTools.d.ts.map +1 -1
  64. package/dist/tools/grepTools.js +41 -23
  65. package/dist/tools/grepTools.js.map +1 -1
  66. package/dist/tools/searchTools.d.ts.map +1 -1
  67. package/dist/tools/searchTools.js +18 -8
  68. package/dist/tools/searchTools.js.map +1 -1
  69. package/dist/tools/webTools.d.ts.map +1 -1
  70. package/dist/tools/webTools.js +10 -2
  71. package/dist/tools/webTools.js.map +1 -1
  72. package/dist/ui/ink/App.d.ts +6 -1
  73. package/dist/ui/ink/App.d.ts.map +1 -1
  74. package/dist/ui/ink/App.js +20 -2
  75. package/dist/ui/ink/App.js.map +1 -1
  76. package/dist/ui/ink/ChatStatic.d.ts.map +1 -1
  77. package/dist/ui/ink/ChatStatic.js +9 -2
  78. package/dist/ui/ink/ChatStatic.js.map +1 -1
  79. package/dist/ui/ink/InkPromptController.d.ts +8 -8
  80. package/dist/ui/ink/InkPromptController.d.ts.map +1 -1
  81. package/dist/ui/ink/InkPromptController.js +19 -11
  82. package/dist/ui/ink/InkPromptController.js.map +1 -1
  83. package/dist/ui/ink/StatusLine.d.ts +6 -7
  84. package/dist/ui/ink/StatusLine.d.ts.map +1 -1
  85. package/dist/ui/ink/StatusLine.js +9 -9
  86. package/dist/ui/ink/StatusLine.js.map +1 -1
  87. package/dist/ui/ink/markdownRender.d.ts +2 -0
  88. package/dist/ui/ink/markdownRender.d.ts.map +1 -0
  89. package/dist/ui/ink/markdownRender.js +76 -0
  90. package/dist/ui/ink/markdownRender.js.map +1 -0
  91. package/package.json +2 -1
  92. package/dist/core/hostedAuth.d.ts +0 -88
  93. package/dist/core/hostedAuth.d.ts.map +0 -1
  94. package/dist/core/hostedAuth.js +0 -219
  95. package/dist/core/hostedAuth.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"contextManager.d.ts","sourceRoot":"","sources":["../../src/core/contextManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contextManager.d.ts","sourceRoot":"","sources":["../../src/core/contextManager.ts"],"names":[],"mappings":"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"}
@@ -29,59 +29,6 @@ Format:
29
29
 
30
30
  Conversation:
31
31
  {conversation}`;
32
- /**
33
- * Pre-defined AI Flow Patterns for intelligent context management
34
- */
35
- export const DEFAULT_AI_FLOW_PATTERNS = [
36
- {
37
- patternId: 'read_edit_workflow',
38
- description: 'Standard file modification workflow',
39
- toolSequence: ['read', 'edit'],
40
- contextImpact: 1500,
41
- compactionOpportunity: true,
42
- preservationPriority: 8,
43
- },
44
- {
45
- patternId: 'analysis_phase',
46
- description: 'Code analysis and exploration phase',
47
- toolSequence: ['read', 'grep', 'glob', 'search'],
48
- contextImpact: 3000,
49
- compactionOpportunity: true,
50
- preservationPriority: 6,
51
- },
52
- {
53
- patternId: 'implementation_phase',
54
- description: 'Active code implementation phase',
55
- toolSequence: ['edit', 'write'],
56
- contextImpact: 2000,
57
- compactionOpportunity: false, // Preserve implementation context
58
- preservationPriority: 9,
59
- },
60
- {
61
- patternId: 'validation_phase',
62
- description: 'Code validation and testing phase',
63
- toolSequence: ['run_tests', 'run_build', 'run_repo_checks'],
64
- contextImpact: 1000,
65
- compactionOpportunity: true,
66
- preservationPriority: 5,
67
- },
68
- {
69
- patternId: 'parallel_execution',
70
- description: 'Efficient parallel tool usage',
71
- toolSequence: ['read', 'read', 'read'], // Multiple parallel reads
72
- contextImpact: 2500,
73
- compactionOpportunity: true,
74
- preservationPriority: 7,
75
- },
76
- {
77
- patternId: 'git_workflow',
78
- description: 'Git operations workflow',
79
- toolSequence: ['git_smart_commit', 'git_sync', 'git_create_pr'],
80
- contextImpact: 1200,
81
- compactionOpportunity: true,
82
- preservationPriority: 6,
83
- },
84
- ];
85
32
  export class ContextManager {
86
33
  config;
87
34
  sessionStartTime = Date.now();
@@ -215,28 +162,54 @@ export class ContextManager {
215
162
  }
216
163
  return Math.ceil(charCount / this.config.estimatedCharsPerToken);
217
164
  }
218
- /**
219
- * Detect context overflow risk from recent tool usage patterns
220
- */
221
- detectContextOverflowRisk(toolCalls) {
222
- const recentTools = toolCalls.slice(-10); // Last 10 tools
223
- // Check for broad search patterns without limits
224
- const broadSearches = recentTools.filter(tool => tool.includes('Glob') && !tool.includes('head_limit'));
225
- // Check for multiple large file reads
226
- const fileReads = recentTools.filter(tool => tool.includes('Read') || tool.includes('read_file'));
227
- // Check for redundant context_snapshot calls
228
- const contextSnapshots = recentTools.filter(tool => tool.includes('context_snapshot'));
229
- // Risk threshold: 2+ broad searches OR 5+ file reads OR 1+ context_snapshot
230
- return broadSearches.length >= 2 ||
231
- fileReads.length >= 5 ||
232
- contextSnapshots.length >= 1;
233
- }
234
165
  /**
235
166
  * Estimate total tokens in conversation
236
167
  */
237
168
  estimateTotalTokens(messages) {
238
169
  return messages.reduce((sum, msg) => sum + this.estimateTokens(msg), 0);
239
170
  }
171
+ /**
172
+ * Intra-turn reduction for the tool-heavy single-turn case. Normal pruning
173
+ * keeps whole turns and counts only USER turns, so one request with many tool
174
+ * rounds (one user message, dozens of assistant+tool messages) prunes nothing
175
+ * and can overflow. This shrinks the OLDEST verbose tool-result bodies to a
176
+ * placeholder — never dropping a message (tool_call/result pairing stays
177
+ * intact), never touching the user task, assistant reasoning, or the most
178
+ * recent few messages. Returns the new list and how many bodies were truncated.
179
+ */
180
+ reduceOversizedHistory(messages) {
181
+ const KEEP_INTACT = 6; // leave the most recent messages untouched
182
+ const MIN_TRUNCATABLE = 400; // only shrink substantial bodies (chars)
183
+ const PLACEHOLDER = '[older tool output truncated to fit the context budget]';
184
+ const out = messages.map((m) => ({ ...m }));
185
+ let total = this.estimateTotalTokens(out);
186
+ let truncated = 0;
187
+ // Collapse an oversized tool RESULT at index i (they hold the bulk — file
188
+ // reads, command output — and are safe to drop; user/assistant text stays).
189
+ const tryTruncate = (i) => {
190
+ const m = out[i];
191
+ if (!m || m.role !== 'tool' || !m.content)
192
+ return;
193
+ if (m.content.length < MIN_TRUNCATABLE || m.content === PLACEHOLDER)
194
+ return;
195
+ const before = this.estimateTokens(m);
196
+ m.content = PLACEHOLDER;
197
+ total -= before - this.estimateTokens(m);
198
+ truncated++;
199
+ };
200
+ // Pass 1: oldest-first, leaving the most recent KEEP_INTACT messages intact.
201
+ const editableUpTo = Math.max(0, out.length - KEEP_INTACT);
202
+ for (let i = 0; i < editableUpTo && total >= this.config.targetTokens; i++) {
203
+ tryTruncate(i);
204
+ }
205
+ // Pass 2 (last resort): still over budget because a giant tool output sits
206
+ // inside the protected tail (e.g. a single `[user, assistant, tool(HUGE)]`
207
+ // turn). Collapse those too, oldest-first — but never the very last message.
208
+ for (let i = editableUpTo; i < out.length - 1 && total >= this.config.targetTokens; i++) {
209
+ tryTruncate(i);
210
+ }
211
+ return { messages: out, truncated };
212
+ }
240
213
  /**
241
214
  * Prune old messages when approaching limit
242
215
  *
@@ -274,6 +247,14 @@ export class ContextManager {
274
247
  // Tool results belong with the current assistant turn
275
248
  currentTurn.push(msg);
276
249
  }
250
+ else if (msg.role === 'system') {
251
+ // Mid-conversation system messages — a PRIOR compaction summary, a
252
+ // recovery note — must not be silently dropped (the grouping used to
253
+ // have no `system` branch). Attach to the current turn so they travel
254
+ // with it: kept if recent, folded into the next summary if old. The
255
+ // leading base system prompt is handled separately above.
256
+ currentTurn.push(msg);
257
+ }
277
258
  }
278
259
  if (currentTurn.length > 0) {
279
260
  turns.push(currentTurn);
@@ -344,6 +325,15 @@ export class ContextManager {
344
325
  });
345
326
  }
346
327
  pruned.push(...recentMessages);
328
+ // Tool-heavy single-turn fallback: if turn-level pruning removed nothing
329
+ // (only one user turn, so the whole conversation is "recent") but we're
330
+ // still over budget, shrink the oldest verbose tool outputs in place.
331
+ if (removedCount === 0 && this.estimateTotalTokens(pruned) >= this.config.targetTokens) {
332
+ const reduced = this.reduceOversizedHistory(pruned);
333
+ if (reduced.truncated > 0) {
334
+ return { pruned: reduced.messages, removed: reduced.truncated };
335
+ }
336
+ }
347
337
  return {
348
338
  pruned,
349
339
  removed: removedCount,
@@ -389,6 +379,12 @@ export class ContextManager {
389
379
  else if (msg.role === 'tool') {
390
380
  currentTurn.push(msg);
391
381
  }
382
+ else if (msg.role === 'system') {
383
+ // Carry mid-conversation system messages (a prior compaction summary)
384
+ // into a turn so they're folded into the next summary instead of being
385
+ // silently dropped by the grouping.
386
+ currentTurn.push(msg);
387
+ }
392
388
  }
393
389
  if (currentTurn.length > 0) {
394
390
  turns.push(currentTurn);
@@ -449,6 +445,15 @@ export class ContextManager {
449
445
  const toSummarize = summarizeTurns.flat();
450
446
  // If nothing to summarize, return as-is
451
447
  if (toSummarize.length === 0) {
448
+ // Nothing spans multiple turns to summarize (e.g. a single tool-heavy
449
+ // turn). If still over budget, shrink the oldest verbose tool outputs in
450
+ // place rather than no-op into an overflow.
451
+ if (this.estimateTotalTokens(messages) >= this.config.targetTokens) {
452
+ const reduced = this.reduceOversizedHistory(messages);
453
+ if (reduced.truncated > 0) {
454
+ return { pruned: reduced.messages, removed: reduced.truncated, summarized: false };
455
+ }
456
+ }
452
457
  return { pruned: messages, removed: 0, summarized: false };
453
458
  }
454
459
  try {
@@ -540,472 +545,6 @@ export class ContextManager {
540
545
  updateConfig(config) {
541
546
  this.config = { ...this.config, ...config };
542
547
  }
543
- // ============================================================================
544
- // INTELLIGENT COMPACTION SYSTEM
545
- // Automatically detects optimal points for conversation compaction
546
- // ============================================================================
547
- /**
548
- * Default patterns that indicate task boundaries
549
- */
550
- static DEFAULT_TASK_BOUNDARY_PATTERNS = [
551
- // Completion indicators
552
- /\b(done|completed|finished|fixed|resolved|implemented|added|created|updated)\b/i,
553
- /\b(all\s+(?:tests?\s+)?pass(?:ing|ed)?)\b/i,
554
- /\b(successfully|works?\s+(?:now|correctly))\b/i,
555
- // Transition indicators
556
- /\b(next|now\s+(?:let's|we\s+can)|moving\s+on)\b/i,
557
- /\b(that's\s+(?:it|all|done))\b/i,
558
- // Acknowledgment patterns
559
- /^(?:great|perfect|thanks|thank\s+you|got\s+it|understood)\b/i,
560
- ];
561
- /**
562
- * Patterns indicating topic/task shifts
563
- */
564
- static TOPIC_SHIFT_PATTERNS = [
565
- /\b(different|another|new|separate|unrelated)\s+(?:task|thing|topic|issue|question)\b/i,
566
- /\b(can\s+you|could\s+you|please|now|let's)\s+(?:also|help|do|make|create|fix|add)\b/i,
567
- /\b(switching|changing|moving)\s+to\b/i,
568
- /\b(forget|ignore|never\s*mind)\s+(?:that|the|about)\b/i,
569
- /^(?:ok|okay|alright|anyway|so)\s*[,.]?\s*(?:can|could|now|let|please)/i,
570
- ];
571
- /**
572
- * Patterns indicating user pivots (abandoning current direction)
573
- */
574
- static USER_PIVOT_PATTERNS = [
575
- /\b(actually|wait|hold\s+on|stop|cancel|scratch\s+that)\b/i,
576
- /\b(let's\s+(?:try|do)\s+(?:something|it)\s+(?:else|differently))\b/i,
577
- /\b(go\s+back|revert|undo|start\s+over)\b/i,
578
- /\b(wrong|not\s+(?:what|right)|that's\s+not)\b/i,
579
- ];
580
- /**
581
- * Analyze the conversation to detect intelligent compaction points
582
- */
583
- analyzeCompactionPoints(messages) {
584
- const signals = [];
585
- const totalTokens = this.estimateTotalTokens(messages);
586
- const tokenPercentage = totalTokens / this.config.maxTokens;
587
- const compactionThreshold = this.config.compactionThreshold ?? 0.5;
588
- const minConfidence = this.config.minSignalConfidence ?? 0.6;
589
- // Don't analyze if below threshold
590
- if (tokenPercentage < compactionThreshold) {
591
- return {
592
- shouldCompact: false,
593
- signals: [],
594
- recommendedCompactionPoint: null,
595
- urgency: 'none',
596
- preserveFromIndex: 0,
597
- };
598
- }
599
- // Analyze each message for compaction signals
600
- for (let i = 0; i < messages.length; i++) {
601
- const msg = messages[i];
602
- if (!msg)
603
- continue;
604
- // Detect task boundaries
605
- const taskBoundary = this.detectTaskBoundary(msg, i, messages);
606
- if (taskBoundary && taskBoundary.confidence >= minConfidence) {
607
- signals.push(taskBoundary);
608
- }
609
- // Detect topic shifts
610
- const topicShift = this.detectTopicShift(msg, i, messages);
611
- if (topicShift && topicShift.confidence >= minConfidence) {
612
- signals.push(topicShift);
613
- }
614
- // Detect user pivots
615
- const userPivot = this.detectUserPivot(msg, i);
616
- if (userPivot && userPivot.confidence >= minConfidence) {
617
- signals.push(userPivot);
618
- }
619
- // Detect context saturation (tool output heavy regions)
620
- const saturation = this.detectContextSaturation(msg, i, messages);
621
- if (saturation && saturation.confidence >= minConfidence) {
622
- signals.push(saturation);
623
- }
624
- // Detect milestones
625
- const milestone = this.detectMilestone(msg, i, messages);
626
- if (milestone && milestone.confidence >= minConfidence) {
627
- signals.push(milestone);
628
- }
629
- }
630
- // Determine urgency based on token percentage
631
- const urgency = this.calculateUrgency(tokenPercentage);
632
- // Find the best compaction point
633
- const recommendedPoint = this.findBestCompactionPoint(signals, messages, urgency);
634
- // Calculate preserve index (everything after this should be kept)
635
- const preserveFromIndex = recommendedPoint !== null
636
- ? this.findSafePreservePoint(recommendedPoint, messages)
637
- : messages.length;
638
- return {
639
- shouldCompact: signals.length > 0 && urgency !== 'none',
640
- signals,
641
- recommendedCompactionPoint: recommendedPoint,
642
- urgency,
643
- preserveFromIndex,
644
- };
645
- }
646
- /**
647
- * Detect task boundary signals
648
- */
649
- detectTaskBoundary(msg, index, messages) {
650
- if (msg.role !== 'user' && msg.role !== 'assistant')
651
- return null;
652
- const content = msg.content || '';
653
- const patterns = this.config.taskBoundaryPatterns
654
- ? this.config.taskBoundaryPatterns.map(p => new RegExp(p, 'i'))
655
- : ContextManager.DEFAULT_TASK_BOUNDARY_PATTERNS;
656
- let matchCount = 0;
657
- const reasons = [];
658
- for (const pattern of patterns) {
659
- if (pattern.test(content)) {
660
- matchCount++;
661
- reasons.push(pattern.source.slice(0, 30));
662
- }
663
- }
664
- if (matchCount === 0)
665
- return null;
666
- // Higher confidence if followed by a new user message with different intent
667
- let confidence = Math.min(0.4 + matchCount * 0.2, 0.9);
668
- // Boost confidence if this looks like a conclusion
669
- if (msg.role === 'assistant' && this.looksLikeConclusion(content)) {
670
- confidence = Math.min(confidence + 0.2, 0.95);
671
- }
672
- // Boost if next user message starts a new topic
673
- const nextUserMsg = messages.slice(index + 1).find(m => m.role === 'user');
674
- if (nextUserMsg && this.isNewTopic(content, nextUserMsg.content || '')) {
675
- confidence = Math.min(confidence + 0.15, 0.95);
676
- }
677
- return {
678
- type: 'task_boundary',
679
- confidence,
680
- messageIndex: index,
681
- reason: `Task completion detected: ${reasons.slice(0, 2).join(', ')}`,
682
- };
683
- }
684
- /**
685
- * Detect topic shift signals
686
- */
687
- detectTopicShift(msg, index, messages) {
688
- if (msg.role !== 'user')
689
- return null;
690
- const content = msg.content || '';
691
- const sensitivity = this.config.topicShiftSensitivity ?? 0.7;
692
- // Check explicit shift patterns
693
- for (const pattern of ContextManager.TOPIC_SHIFT_PATTERNS) {
694
- if (pattern.test(content)) {
695
- return {
696
- type: 'topic_shift',
697
- confidence: 0.7 + sensitivity * 0.2,
698
- messageIndex: index,
699
- reason: 'Explicit topic shift language detected',
700
- };
701
- }
702
- }
703
- // Check semantic shift from previous context
704
- const prevMessages = messages.slice(Math.max(0, index - 5), index);
705
- const prevContent = prevMessages
706
- .filter(m => m.role === 'user' || m.role === 'assistant')
707
- .map(m => m.content || '')
708
- .join(' ');
709
- if (prevContent && this.isNewTopic(prevContent, content)) {
710
- return {
711
- type: 'topic_shift',
712
- confidence: 0.6 + sensitivity * 0.2,
713
- messageIndex: index,
714
- reason: 'Semantic topic shift detected',
715
- };
716
- }
717
- return null;
718
- }
719
- /**
720
- * Detect user pivot signals (abandoning current direction)
721
- */
722
- detectUserPivot(msg, index) {
723
- if (msg.role !== 'user')
724
- return null;
725
- const content = msg.content || '';
726
- for (const pattern of ContextManager.USER_PIVOT_PATTERNS) {
727
- if (pattern.test(content)) {
728
- return {
729
- type: 'user_pivot',
730
- confidence: 0.85,
731
- messageIndex: index,
732
- reason: 'User pivot/direction change detected',
733
- };
734
- }
735
- }
736
- return null;
737
- }
738
- /**
739
- * Detect context saturation (heavy tool output regions)
740
- */
741
- detectContextSaturation(msg, index, messages) {
742
- if (msg.role !== 'tool')
743
- return null;
744
- // Look at the surrounding region
745
- const windowStart = Math.max(0, index - 10);
746
- const windowEnd = Math.min(messages.length, index + 5);
747
- const window = messages.slice(windowStart, windowEnd);
748
- // Count tool messages and their sizes
749
- let toolCount = 0;
750
- let totalToolSize = 0;
751
- for (const m of window) {
752
- if (m.role === 'tool') {
753
- toolCount++;
754
- totalToolSize += (m.content || '').length;
755
- }
756
- }
757
- // High saturation if many tool outputs with large content
758
- if (toolCount >= 5 && totalToolSize > 20000) {
759
- // Find the last tool message in this cluster as compaction point
760
- let lastToolIndex = index;
761
- for (let i = index + 1; i < windowEnd; i++) {
762
- if (messages[i]?.role === 'tool') {
763
- lastToolIndex = i;
764
- }
765
- else if (messages[i]?.role === 'user') {
766
- break; // Stop at next user message
767
- }
768
- }
769
- return {
770
- type: 'context_saturation',
771
- confidence: Math.min(0.5 + toolCount * 0.05, 0.85),
772
- messageIndex: lastToolIndex,
773
- reason: `Heavy tool output region (${toolCount} tools, ${Math.round(totalToolSize / 1000)}k chars)`,
774
- };
775
- }
776
- return null;
777
- }
778
- /**
779
- * Detect milestone signals (significant accomplishments)
780
- */
781
- detectMilestone(msg, index, _messages) {
782
- if (msg.role !== 'assistant')
783
- return null;
784
- const content = msg.content || '';
785
- // Look for milestone indicators
786
- const milestonePatterns = [
787
- /\b(commit(?:ted)?|pushed|deployed|merged|released)\b/i,
788
- /\b(all\s+tests?\s+pass(?:ing|ed)?)\b/i,
789
- /\b(build\s+(?:succeed|success|pass))\b/i,
790
- /\b(feature\s+(?:complete|done|ready))\b/i,
791
- /\b(pr\s+(?:created|opened|merged))\b/i,
792
- ];
793
- for (const pattern of milestonePatterns) {
794
- if (pattern.test(content)) {
795
- return {
796
- type: 'milestone',
797
- confidence: 0.9,
798
- messageIndex: index,
799
- reason: 'Significant milestone achieved',
800
- };
801
- }
802
- }
803
- return null;
804
- }
805
- /**
806
- * Check if content looks like a task conclusion
807
- */
808
- looksLikeConclusion(content) {
809
- const conclusionPatterns = [
810
- /\b(let\s+me\s+know|feel\s+free|if\s+you\s+(?:need|have|want))\b/i,
811
- /\b(anything\s+else|other\s+questions?)\b/i,
812
- /\b(should\s+be\s+(?:good|working|ready|done))\b/i,
813
- /\b(that\s+should|this\s+(?:should|will))\s+(?:fix|solve|work)/i,
814
- ];
815
- return conclusionPatterns.some(p => p.test(content));
816
- }
817
- /**
818
- * Check if two contents represent different topics (simple heuristic)
819
- */
820
- isNewTopic(prevContent, newContent) {
821
- // Extract key terms (simple tokenization)
822
- const extractTerms = (text) => {
823
- const words = text.toLowerCase()
824
- .replace(/[^a-z0-9\s]/g, ' ')
825
- .split(/\s+/)
826
- .filter(w => w.length > 3);
827
- return new Set(words);
828
- };
829
- const prevTerms = extractTerms(prevContent);
830
- const newTerms = extractTerms(newContent);
831
- if (prevTerms.size === 0 || newTerms.size === 0)
832
- return false;
833
- // Calculate overlap
834
- let overlap = 0;
835
- for (const term of newTerms) {
836
- if (prevTerms.has(term))
837
- overlap++;
838
- }
839
- const overlapRatio = overlap / Math.min(prevTerms.size, newTerms.size);
840
- // Low overlap suggests new topic
841
- return overlapRatio < 0.2;
842
- }
843
- /**
844
- * Calculate urgency level based on token percentage
845
- */
846
- calculateUrgency(tokenPercentage) {
847
- if (tokenPercentage >= 0.9)
848
- return 'critical';
849
- if (tokenPercentage >= 0.75)
850
- return 'high';
851
- if (tokenPercentage >= 0.6)
852
- return 'medium';
853
- if (tokenPercentage >= 0.5)
854
- return 'low';
855
- return 'none';
856
- }
857
- /**
858
- * Find the best compaction point from signals
859
- */
860
- findBestCompactionPoint(signals, messages, urgency) {
861
- if (signals.length === 0)
862
- return null;
863
- // Score each signal based on type priority and confidence
864
- const typePriority = {
865
- milestone: 1.0,
866
- task_boundary: 0.9,
867
- user_pivot: 0.85,
868
- ai_flow_pattern: 0.82, // AI flow patterns like thinking/tool use cycles
869
- topic_shift: 0.8,
870
- context_saturation: 0.7,
871
- };
872
- // Urgency affects how far back we're willing to compact
873
- const urgencyDepth = {
874
- none: 0,
875
- low: 0.3, // Compact only recent 30%
876
- medium: 0.5,
877
- high: 0.7,
878
- critical: 0.9,
879
- };
880
- const maxDepth = urgencyDepth[urgency] ?? 0.5;
881
- const minIndex = Math.floor(messages.length * (1 - maxDepth));
882
- // Find highest scoring signal within allowed depth
883
- let bestSignal = null;
884
- let bestScore = 0;
885
- for (const signal of signals) {
886
- if (signal.messageIndex < minIndex)
887
- continue;
888
- const score = signal.confidence * typePriority[signal.type];
889
- if (score > bestScore) {
890
- bestScore = score;
891
- bestSignal = signal;
892
- }
893
- }
894
- return bestSignal?.messageIndex ?? null;
895
- }
896
- /**
897
- * Find a safe preservation point that doesn't break tool call chains
898
- */
899
- findSafePreservePoint(compactionPoint, messages) {
900
- // Start from compaction point and move forward to find a safe break
901
- for (let i = compactionPoint + 1; i < messages.length; i++) {
902
- const msg = messages[i];
903
- if (!msg)
904
- continue;
905
- // Safe if it's a user message
906
- if (msg.role === 'user') {
907
- return i;
908
- }
909
- // Safe if it's an assistant without pending tool calls
910
- if (msg.role === 'assistant' && !msg.toolCalls?.length) {
911
- return i;
912
- }
913
- }
914
- // If no safe point found, keep more messages
915
- return Math.min(compactionPoint + 1, messages.length);
916
- }
917
- /**
918
- * Perform intelligent compaction based on analysis
919
- * This method analyzes the conversation and compacts at the optimal point
920
- */
921
- async intelligentCompact(messages) {
922
- // Analyze for compaction points
923
- const analysis = this.analyzeCompactionPoints(messages);
924
- // If no compaction needed or no good point found
925
- if (!analysis.shouldCompact || analysis.recommendedCompactionPoint === null) {
926
- return {
927
- compacted: messages,
928
- analysis,
929
- summarized: false,
930
- };
931
- }
932
- // Separate messages to summarize and preserve
933
- const firstMessage = messages[0];
934
- const systemMessage = firstMessage?.role === 'system' ? firstMessage : null;
935
- const startIndex = systemMessage ? 1 : 0;
936
- const toSummarize = messages.slice(startIndex, analysis.preserveFromIndex);
937
- const toPreserve = messages.slice(analysis.preserveFromIndex);
938
- // If nothing to summarize, return as-is
939
- if (toSummarize.length === 0) {
940
- return {
941
- compacted: messages,
942
- analysis,
943
- summarized: false,
944
- };
945
- }
946
- // Build result
947
- const compacted = [];
948
- if (systemMessage) {
949
- compacted.push(systemMessage);
950
- }
951
- // Try LLM summarization if available
952
- if (this.config.summarizationCallback && this.config.useLLMSummarization !== false) {
953
- try {
954
- const summary = await this.config.summarizationCallback(toSummarize);
955
- compacted.push({
956
- role: 'system',
957
- content: [
958
- '=== Intelligent Context Summary ===',
959
- `Compaction triggered: ${analysis.signals[0]?.reason || 'Context optimization'}`,
960
- '',
961
- summary.trim(),
962
- '',
963
- `[Summarized ${toSummarize.length} messages. ${toPreserve.length} recent messages preserved.]`,
964
- ].join('\n'),
965
- });
966
- compacted.push(...toPreserve);
967
- return {
968
- compacted,
969
- analysis,
970
- summarized: true,
971
- };
972
- }
973
- catch {
974
- // Fall through to simple compaction
975
- }
976
- }
977
- // Simple compaction without LLM
978
- compacted.push({
979
- role: 'system',
980
- content: `[Context Manager: Intelligently compacted ${toSummarize.length} messages at "${analysis.signals[0]?.reason || 'optimal point'}". ${toPreserve.length} recent messages preserved.]`,
981
- });
982
- compacted.push(...toPreserve);
983
- return {
984
- compacted,
985
- analysis,
986
- summarized: false,
987
- };
988
- }
989
- /**
990
- * Check if intelligent compaction should be triggered
991
- * Call this before generation to proactively manage context
992
- */
993
- shouldTriggerCompaction(messages) {
994
- if (this.config.enableIntelligentCompaction === false) {
995
- return { shouldCompact: false, urgency: 'none', reason: null };
996
- }
997
- const analysis = this.analyzeCompactionPoints(messages);
998
- if (!analysis.shouldCompact) {
999
- return { shouldCompact: false, urgency: analysis.urgency, reason: null };
1000
- }
1001
- const topSignal = analysis.signals
1002
- .sort((a, b) => b.confidence - a.confidence)[0];
1003
- return {
1004
- shouldCompact: true,
1005
- urgency: analysis.urgency,
1006
- reason: topSignal?.reason || 'Context optimization recommended',
1007
- };
1008
- }
1009
548
  }
1010
549
  /**
1011
550
  * Create a default context manager instance with model-aware limits
@@ -1022,11 +561,6 @@ export function createDefaultContextManager(overrides, model) {
1022
561
  preserveRecentMessages: 5, // Keep last 5 exchanges
1023
562
  estimatedCharsPerToken: 3.5, // More aggressive estimate (accounts for special tokens, JSON overhead)
1024
563
  useLLMSummarization: true, // Enable LLM summarization by default
1025
- // Intelligent compaction defaults
1026
- enableIntelligentCompaction: true,
1027
- compactionThreshold: 0.5, // Start analyzing at 50% context usage
1028
- minSignalConfidence: 0.6, // Require 60% confidence for compaction signals
1029
- topicShiftSensitivity: 0.7, // Moderately sensitive to topic changes
1030
564
  model,
1031
565
  ...overrides,
1032
566
  });