@gotza02/sequential-thinking 2026.3.9 → 2026.3.11

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.
@@ -0,0 +1,9 @@
1
+ import { ThoughtData } from '../lib.js';
2
+ export declare class ContextManager {
3
+ private summaryCache;
4
+ constructor();
5
+ getOptimizedContext(history: ThoughtData[], currentBlockId: string | null): Promise<string>;
6
+ private compressOldBlocks;
7
+ private groupByBlock;
8
+ private generateSummary;
9
+ }
@@ -0,0 +1,62 @@
1
+ export class ContextManager {
2
+ summaryCache = new Map();
3
+ constructor() { }
4
+ async getOptimizedContext(history, currentBlockId) {
5
+ // If no current block, treat everything as old or just show all?
6
+ // If null, we might be in setup mode. Let's assume empty current block.
7
+ const safeCurrentBlockId = currentBlockId || '';
8
+ const oldBlocks = history.filter(t => t.blockId !== safeCurrentBlockId);
9
+ const activeBlock = history.filter(t => t.blockId === safeCurrentBlockId);
10
+ const summaries = await this.compressOldBlocks(oldBlocks);
11
+ // Format active block detailed
12
+ const activeContext = activeBlock.map(t => `[${t.thoughtType?.toUpperCase() || 'INFO'}] #${t.thoughtNumber}: ${t.thought}`).join('\n');
13
+ return `
14
+ === PROJECT HISTORY (SUMMARIZED) ===
15
+ ${summaries}
16
+
17
+ === CURRENT FOCUS (DETAILED: ${safeCurrentBlockId || 'GLOBAL'}) ===
18
+ ${activeContext}
19
+ `;
20
+ }
21
+ async compressOldBlocks(logs) {
22
+ const groups = this.groupByBlock(logs);
23
+ let result = '';
24
+ for (const [blockId, thoughts] of groups) {
25
+ // Skip blocks with undefined or empty blockId if they sneak in
26
+ if (!blockId)
27
+ continue;
28
+ const cached = this.summaryCache.get(blockId);
29
+ if (cached && cached.count === thoughts.length) {
30
+ result += `[Block: ${blockId}] Summary: ${cached.summary}\n`;
31
+ }
32
+ else {
33
+ if (thoughts.length > 2) {
34
+ const summary = await this.generateSummary(thoughts);
35
+ this.summaryCache.set(blockId, { summary, count: thoughts.length });
36
+ result += `[Block: ${blockId}] Summary: ${summary}\n`;
37
+ }
38
+ else {
39
+ result += `[Block: ${blockId}] ${thoughts.map(t => t.thought).join(' -> ')}\n`;
40
+ }
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+ groupByBlock(logs) {
46
+ const map = new Map();
47
+ logs.forEach(log => {
48
+ const bid = log.blockId || 'default';
49
+ const items = map.get(bid) || [];
50
+ items.push(log);
51
+ map.set(bid, items);
52
+ });
53
+ return map;
54
+ }
55
+ async generateSummary(thoughts) {
56
+ // Mock implementation
57
+ const decisions = thoughts.filter(t => t.thoughtType === 'planning' || t.thoughtType === 'selection').length;
58
+ const executions = thoughts.filter(t => t.thoughtType === 'execution').length;
59
+ const topic = thoughts[0]?.thought.substring(0, 30) || 'Unknown';
60
+ return `Topic: "${topic}...". Processed ${thoughts.length} steps (${decisions} plans, ${executions} actions). Outcome: Handed off or completed.`;
61
+ }
62
+ }
package/dist/lib.d.ts CHANGED
@@ -38,6 +38,7 @@ export declare class SequentialThinkingServer {
38
38
  private saveMutex;
39
39
  private consecutiveStallCount;
40
40
  private confidenceScore;
41
+ private contextManager;
41
42
  constructor(storagePath?: string, delayMs?: number);
42
43
  private loadHistory;
43
44
  private attemptRecovery;
package/dist/lib.js CHANGED
@@ -3,6 +3,7 @@ import * as fs from 'fs/promises';
3
3
  import { existsSync, readFileSync } from 'fs';
4
4
  import * as path from 'path';
5
5
  import { AsyncMutex } from './utils.js';
6
+ import { ContextManager } from './core/ContextManager.js';
6
7
  export class SequentialThinkingServer {
7
8
  thoughtHistory = [];
8
9
  blocks = [];
@@ -15,6 +16,7 @@ export class SequentialThinkingServer {
15
16
  saveMutex = new AsyncMutex();
16
17
  consecutiveStallCount = 0; // Track consecutive stalls/loops
17
18
  confidenceScore = 100; // Meta-Cognition Score (0-100)
19
+ contextManager = new ContextManager();
18
20
  constructor(storagePath = 'thoughts_history.json', delayMs = 0) {
19
21
  this.disableThoughtLogging = (process.env.DISABLE_THOUGHT_LOGGING || "").toLowerCase() === "true";
20
22
  this.storagePath = path.resolve(storagePath);
@@ -437,6 +439,13 @@ ${typeof wrappedThought === 'string' && wrappedThought.startsWith('│') ? wrapp
437
439
  const complexity = input.complexity || 'medium';
438
440
  const warnings = [];
439
441
  let feedbackExtension = "";
442
+ // --- šŸ”„ FEATURE 0: Smart Branching Reward (Reset Confidence on Pivot) ---
443
+ if (input.branchFromThought) {
444
+ if (this.confidenceScore < 75) {
445
+ this.confidenceScore = 75;
446
+ feedbackExtension += `\n🌿 BRANCH DETECTED: Confidence restored to 75. Good decision to pivot.`;
447
+ }
448
+ }
440
449
  // --- 🧠 FEATURE 1: Semantic Thought Recall ---
441
450
  if (input.thoughtType === 'analysis') {
442
451
  const previousSolution = await this.findSolution(input.thought);
@@ -444,14 +453,50 @@ ${typeof wrappedThought === 'string' && wrappedThought.startsWith('│') ? wrapp
444
453
  feedbackExtension += `\nšŸ’” RECALL: I found a similar past solution for '${previousSolution.topic}'.\nTry these steps: ${previousSolution.solution.substring(0, 100)}...`;
445
454
  }
446
455
  }
447
- // --- šŸ“Š FEATURE 4: Meta-Cognition Score Check ---
456
+ // --- ā›” FEATURE 1.5: Anti-Insanity (Prevent Repeating Failed Executions) ---
457
+ const historyForCheck = this.thoughtHistory.filter(t => t.blockId === input.blockId || (input.blockId === this.currentBlockId && t.blockId === this.currentBlockId));
458
+ if (input.thoughtType === 'execution') {
459
+ const failedExecutions = historyForCheck.filter((t, index) => {
460
+ if (t.thoughtType !== 'execution')
461
+ return false;
462
+ // Find the observation immediately following this execution
463
+ // Note: This relies on thoughtNumber order
464
+ const nextThought = this.thoughtHistory.find(h => h.thoughtNumber === t.thoughtNumber + 1);
465
+ if (nextThought && nextThought.thoughtType === 'observation') {
466
+ const result = nextThought.toolResult?.toLowerCase() || "";
467
+ // Check for failure signals
468
+ return result.includes("error") || result.includes("fail") || result.includes("exception") || result.includes("enoent");
469
+ }
470
+ return false;
471
+ });
472
+ const isRepeatedFailure = failedExecutions.some(t => t.thought.trim() === input.thought.trim());
473
+ if (isRepeatedFailure) {
474
+ const failedItem = failedExecutions.find(t => t.thought.trim() === input.thought.trim());
475
+ warnings.push(`ā›” INSANITY CHECK: You are trying to run a command that ALREADY FAILED in thought #${failedItem?.thoughtNumber}. STOP. Do not repeat mistakes. Try a different parameter or tool.`);
476
+ this.confidenceScore -= 15;
477
+ }
478
+ }
479
+ // --- šŸ“Š FEATURE 4: Meta-Cognition Score Check (Reflexion Mandate & Smart Branching) ---
448
480
  if (this.confidenceScore < 50 && input.thoughtType !== 'reflexion' && input.thoughtType !== 'analysis') {
481
+ // Smart Branching: Find the last valid planning point
482
+ const lastGoodPlan = historyForCheck
483
+ .slice()
484
+ .reverse()
485
+ .find(t => t.thoughtType === 'planning' || t.thoughtType === 'hypothesis');
486
+ const recoveryAdvice = lastGoodPlan
487
+ ? `RECOMMENDATION: Branch from thought #${lastGoodPlan.thoughtNumber} to try a new approach.`
488
+ : `RECOMMENDATION: Use 'reflexion' to analyze why current attempts are failing.`;
449
489
  return {
450
490
  content: [{
451
491
  type: "text",
452
492
  text: JSON.stringify({
453
493
  status: "CRITICAL_STOP",
454
- feedback: ["🚨 CONFIDENCE TOO LOW (<50). Execution blocked. Please use 'reflexion' or 'analysis' to self-correct, or request human intervention."],
494
+ feedback: [
495
+ "🚨 CONFIDENCE CRITICAL (<50). Execution blocked to prevent further damage.",
496
+ "šŸ›‘ STOP: You are likely in a loop or making repeated errors.",
497
+ "šŸ‘‰ REQUIRED ACTION: You must switch thoughtType to 'reflexion' to critique your errors.",
498
+ recoveryAdvice
499
+ ],
455
500
  confidenceScore: this.confidenceScore
456
501
  }, null, 2)
457
502
  }],
@@ -523,7 +568,8 @@ ${typeof wrappedThought === 'string' && wrappedThought.startsWith('│') ? wrapp
523
568
  // Rule 3: Missing Observation
524
569
  if (lastThought &&
525
570
  lastThought.thoughtType === 'execution' &&
526
- input.thoughtType !== 'observation') {
571
+ input.thoughtType !== 'observation' &&
572
+ !input.branchFromThought) {
527
573
  warnings.push(`šŸ’” INTERLEAVED HINT: Your last step was 'execution'. The next step SHOULD be 'observation' to record and analyze the tool result before continuing.`);
528
574
  }
529
575
  // Rule 4: Skipping Planning (Adaptive)
@@ -637,6 +683,7 @@ ${typeof wrappedThought === 'string' && wrappedThought.startsWith('│') ? wrapp
637
683
  // D. Generate Contextual Output
638
684
  const currentBlock = this.blocks.find(b => b.id === input.blockId);
639
685
  const mermaid = this.generateMermaid();
686
+ const optimizedContext = await this.contextManager.getOptimizedContext(this.thoughtHistory, input.blockId || null);
640
687
  if (feedbackExtension)
641
688
  warnings.push(feedbackExtension);
642
689
  return {
@@ -650,6 +697,7 @@ ${typeof wrappedThought === 'string' && wrappedThought.startsWith('│') ? wrapp
650
697
  blockContext: currentBlock
651
698
  ? `Block '${currentBlock.topic.substring(0, 30)}' has ${currentBlock.thoughts.length} thoughts.`
652
699
  : 'No active block',
700
+ optimizedContext,
653
701
  branches: Object.keys(this.branches),
654
702
  thoughtHistoryLength: this.thoughtHistory.length,
655
703
  feedback: warnings.length > 0 ? warnings : "Flow Healthy āœ…",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotza02/sequential-thinking",
3
- "version": "2026.3.9",
3
+ "version": "2026.3.11",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },