tracelattice 1.2.9 → 1.3.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.
- package/README.md +83 -13
- package/dist/ServerConfig.d.ts +60 -0
- package/dist/ServerConfig.d.ts.map +1 -1
- package/dist/ServerConfig.js +27 -1
- package/dist/ServerConfig.js.map +1 -1
- package/dist/__tests__/calibrator/Calibrator.test.d.ts +6 -0
- package/dist/__tests__/calibrator/Calibrator.test.d.ts.map +1 -0
- package/dist/__tests__/compression/CompressionService.test.d.ts +5 -0
- package/dist/__tests__/compression/CompressionService.test.d.ts.map +1 -0
- package/dist/__tests__/compression/DehydrationPolicy.test.d.ts +5 -0
- package/dist/__tests__/compression/DehydrationPolicy.test.d.ts.map +1 -0
- package/dist/__tests__/compression/InMemorySummaryStore.test.d.ts +5 -0
- package/dist/__tests__/compression/InMemorySummaryStore.test.d.ts.map +1 -0
- package/dist/__tests__/config/ConfigLoader.features.test.d.ts +2 -0
- package/dist/__tests__/config/ConfigLoader.features.test.d.ts.map +1 -0
- package/dist/__tests__/core/HistoryManager.dag.test.d.ts +9 -0
- package/dist/__tests__/core/HistoryManager.dag.test.d.ts.map +1 -0
- package/dist/__tests__/core/HistoryManager.edge-persistence.test.d.ts +12 -0
- package/dist/__tests__/core/HistoryManager.edge-persistence.test.d.ts.map +1 -0
- package/dist/__tests__/core/HistoryManager.toolInvocation.test.d.ts +2 -0
- package/dist/__tests__/core/HistoryManager.toolInvocation.test.d.ts.map +1 -0
- package/dist/__tests__/core/ThoughtProcessor.newThoughtTypes.test.d.ts +2 -0
- package/dist/__tests__/core/ThoughtProcessor.newThoughtTypes.test.d.ts.map +1 -0
- package/dist/__tests__/core/ThoughtProcessor.toolInterleave.test.d.ts +2 -0
- package/dist/__tests__/core/ThoughtProcessor.toolInterleave.test.d.ts.map +1 -0
- package/dist/__tests__/core/graph/Edge.test.d.ts +5 -0
- package/dist/__tests__/core/graph/Edge.test.d.ts.map +1 -0
- package/dist/__tests__/core/graph/EdgeStore.test.d.ts +5 -0
- package/dist/__tests__/core/graph/EdgeStore.test.d.ts.map +1 -0
- package/dist/__tests__/core/graph/GraphView.test.d.ts +5 -0
- package/dist/__tests__/core/graph/GraphView.test.d.ts.map +1 -0
- package/dist/__tests__/core/reasoning/OutcomeRecorder.test.d.ts +5 -0
- package/dist/__tests__/core/reasoning/OutcomeRecorder.test.d.ts.map +1 -0
- package/dist/__tests__/core/reasoning/strategies/TreeOfThought.newTypes.test.d.ts +2 -0
- package/dist/__tests__/core/reasoning/strategies/TreeOfThought.newTypes.test.d.ts.map +1 -0
- package/dist/__tests__/core/thought-id.test.d.ts +13 -0
- package/dist/__tests__/core/thought-id.test.d.ts.map +1 -0
- package/dist/__tests__/core/tools/InMemorySuspensionStore.test.d.ts +2 -0
- package/dist/__tests__/core/tools/InMemorySuspensionStore.test.d.ts.map +1 -0
- package/dist/__tests__/eval/fixtures/scenarios.d.ts +37 -0
- package/dist/__tests__/eval/fixtures/scenarios.d.ts.map +1 -0
- package/dist/__tests__/eval/totVsSequential.eval.d.ts +16 -0
- package/dist/__tests__/eval/totVsSequential.eval.d.ts.map +1 -0
- package/dist/__tests__/evaluator/EvaluatorBackwardCompat.test.d.ts +15 -0
- package/dist/__tests__/evaluator/EvaluatorBackwardCompat.test.d.ts.map +1 -0
- package/dist/__tests__/integration/CompressionAutoTrigger.test.d.ts +11 -0
- package/dist/__tests__/integration/CompressionAutoTrigger.test.d.ts.map +1 -0
- package/dist/__tests__/integration/CompressionPersistence.test.d.ts +17 -0
- package/dist/__tests__/integration/CompressionPersistence.test.d.ts.map +1 -0
- package/dist/__tests__/integration/StrategyIntegration.test.d.ts +10 -0
- package/dist/__tests__/integration/StrategyIntegration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/ToTStrategyIntegration.test.d.ts +18 -0
- package/dist/__tests__/integration/ToTStrategyIntegration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/dag-edges.test.d.ts +17 -0
- package/dist/__tests__/integration/dag-edges.test.d.ts.map +1 -0
- package/dist/__tests__/strategies/SequentialStrategy.test.d.ts +2 -0
- package/dist/__tests__/strategies/SequentialStrategy.test.d.ts.map +1 -0
- package/dist/__tests__/strategies/StrategyContract.test.d.ts +18 -0
- package/dist/__tests__/strategies/StrategyContract.test.d.ts.map +1 -0
- package/dist/__tests__/strategies/TreeOfThoughtStrategy.test.d.ts +9 -0
- package/dist/__tests__/strategies/TreeOfThoughtStrategy.test.d.ts.map +1 -0
- package/dist/__tests__/strategies/plateau.test.d.ts +2 -0
- package/dist/__tests__/strategies/plateau.test.d.ts.map +1 -0
- package/dist/__tests__/strategies/totScoring.test.d.ts +2 -0
- package/dist/__tests__/strategies/totScoring.test.d.ts.map +1 -0
- package/dist/cli.js +4 -4
- package/dist/cli.js.map +1 -1
- package/dist/config/ConfigLoader.d.ts +37 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +52 -2
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/context/RequestContext.d.ts +2 -46
- package/dist/context/RequestContext.d.ts.map +1 -1
- package/dist/context/RequestContext.js +1 -10
- package/dist/context/RequestContext.js.map +1 -1
- package/dist/contracts/calibrator.d.ts +88 -0
- package/dist/contracts/calibrator.d.ts.map +1 -0
- package/dist/contracts/calibrator.js +1 -0
- package/dist/contracts/index.d.ts +5 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/interfaces.d.ts +114 -35
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/contracts/strategy.d.ts +106 -0
- package/dist/contracts/strategy.d.ts.map +1 -0
- package/dist/contracts/strategy.js +1 -0
- package/dist/contracts/summary.d.ts +104 -0
- package/dist/contracts/summary.d.ts.map +1 -0
- package/dist/contracts/summary.js +1 -0
- package/dist/contracts/suspension.d.ts +181 -0
- package/dist/contracts/suspension.d.ts.map +1 -0
- package/dist/contracts/suspension.js +1 -0
- package/dist/core/HistoryManager.d.ts +91 -0
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +140 -5
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/InputNormalizer.d.ts.map +1 -1
- package/dist/core/InputNormalizer.js +13 -24
- package/dist/core/InputNormalizer.js.map +1 -1
- package/dist/core/ThoughtEvaluator.d.ts +14 -99
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
- package/dist/core/ThoughtEvaluator.js +54 -331
- package/dist/core/ThoughtEvaluator.js.map +1 -1
- package/dist/core/ThoughtFormatter.d.ts.map +1 -1
- package/dist/core/ThoughtFormatter.js +21 -0
- package/dist/core/ThoughtFormatter.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts +50 -50
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +123 -2
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/compression/CompressionService.d.ts +74 -0
- package/dist/core/compression/CompressionService.d.ts.map +1 -0
- package/dist/core/compression/CompressionService.js +159 -0
- package/dist/core/compression/CompressionService.js.map +1 -0
- package/dist/core/compression/DehydrationPolicy.d.ts +74 -0
- package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -0
- package/dist/core/compression/DehydrationPolicy.js +45 -0
- package/dist/core/compression/DehydrationPolicy.js.map +1 -0
- package/dist/core/compression/InMemorySummaryStore.d.ts +130 -0
- package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -0
- package/dist/core/compression/InMemorySummaryStore.js +55 -0
- package/dist/core/compression/InMemorySummaryStore.js.map +1 -0
- package/dist/core/compression/Summary.d.ts +55 -0
- package/dist/core/compression/Summary.d.ts.map +1 -0
- package/dist/core/compression/Summary.js +1 -0
- package/dist/core/evaluator/Aggregator.d.ts +40 -0
- package/dist/core/evaluator/Aggregator.d.ts.map +1 -0
- package/dist/core/evaluator/Aggregator.js +32 -0
- package/dist/core/evaluator/Aggregator.js.map +1 -0
- package/dist/core/evaluator/Calibrator.d.ts +49 -0
- package/dist/core/evaluator/Calibrator.d.ts.map +1 -0
- package/dist/core/evaluator/Calibrator.js +172 -0
- package/dist/core/evaluator/Calibrator.js.map +1 -0
- package/dist/core/evaluator/PatternDetector.d.ts +69 -0
- package/dist/core/evaluator/PatternDetector.d.ts.map +1 -0
- package/dist/core/evaluator/PatternDetector.js +188 -0
- package/dist/core/evaluator/PatternDetector.js.map +1 -0
- package/dist/core/evaluator/SignalComputer.d.ts +64 -0
- package/dist/core/evaluator/SignalComputer.d.ts.map +1 -0
- package/dist/core/evaluator/SignalComputer.js +68 -0
- package/dist/core/evaluator/SignalComputer.js.map +1 -0
- package/dist/core/evaluator/internals.d.ts +36 -0
- package/dist/core/evaluator/internals.d.ts.map +1 -0
- package/dist/core/evaluator/internals.js +43 -0
- package/dist/core/evaluator/internals.js.map +1 -0
- package/dist/core/graph/Edge.d.ts +51 -0
- package/dist/core/graph/Edge.d.ts.map +1 -0
- package/dist/core/graph/Edge.js +1 -0
- package/dist/core/graph/EdgeStore.d.ts +104 -0
- package/dist/core/graph/EdgeStore.d.ts.map +1 -0
- package/dist/core/graph/EdgeStore.js +78 -0
- package/dist/core/graph/EdgeStore.js.map +1 -0
- package/dist/core/graph/GraphView.d.ts +156 -0
- package/dist/core/graph/GraphView.d.ts.map +1 -0
- package/dist/core/graph/GraphView.js +149 -0
- package/dist/core/graph/GraphView.js.map +1 -0
- package/dist/core/ids.d.ts +33 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +11 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/reasoning/OutcomeRecorder.d.ts +78 -0
- package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -0
- package/dist/core/reasoning/OutcomeRecorder.js +36 -0
- package/dist/core/reasoning/OutcomeRecorder.js.map +1 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.d.ts +54 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.js +22 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.js.map +1 -0
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts +25 -0
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/StrategyFactory.js +15 -0
- package/dist/core/reasoning/strategies/StrategyFactory.js.map +1 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts +58 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +98 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -0
- package/dist/core/reasoning/strategies/plateau.d.ts +18 -0
- package/dist/core/reasoning/strategies/plateau.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/plateau.js +12 -0
- package/dist/core/reasoning/strategies/plateau.js.map +1 -0
- package/dist/core/reasoning/strategies/totScoring.d.ts +90 -0
- package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/totScoring.js +79 -0
- package/dist/core/reasoning/strategies/totScoring.js.map +1 -0
- package/dist/core/reasoning.d.ts +6 -1
- package/dist/core/reasoning.d.ts.map +1 -1
- package/dist/core/thought.d.ts +29 -0
- package/dist/core/thought.d.ts.map +1 -1
- package/dist/core/tools/InMemorySuspensionStore.d.ts +59 -0
- package/dist/core/tools/InMemorySuspensionStore.d.ts.map +1 -0
- package/dist/core/tools/InMemorySuspensionStore.js +91 -0
- package/dist/core/tools/InMemorySuspensionStore.js.map +1 -0
- package/dist/di/ServiceRegistry.d.ts +14 -0
- package/dist/di/ServiceRegistry.d.ts.map +1 -1
- package/dist/errors.d.ts +117 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +40 -1
- package/dist/errors.js.map +1 -1
- package/dist/health/HealthChecker.d.ts.map +1 -1
- package/dist/health/HealthChecker.js +3 -2
- package/dist/health/HealthChecker.js.map +1 -1
- package/dist/lib.d.ts +0 -5
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +56 -12
- package/dist/lib.js.map +1 -1
- package/dist/persistence/FilePersistence.d.ts +49 -0
- package/dist/persistence/FilePersistence.d.ts.map +1 -1
- package/dist/persistence/FilePersistence.js +112 -1
- package/dist/persistence/FilePersistence.js.map +1 -1
- package/dist/persistence/MemoryPersistence.d.ts +34 -0
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
- package/dist/persistence/MemoryPersistence.js +30 -0
- package/dist/persistence/MemoryPersistence.js.map +1 -1
- package/dist/persistence/PersistenceBackend.d.ts +34 -0
- package/dist/persistence/PersistenceBackend.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.d.ts +35 -0
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js +98 -0
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/registry/BaseRegistry.d.ts.map +1 -1
- package/dist/registry/BaseRegistry.js +4 -3
- package/dist/registry/BaseRegistry.js.map +1 -1
- package/dist/registry/SkillRegistry.d.ts +1 -1
- package/dist/registry/SkillRegistry.js.map +1 -1
- package/dist/schema.d.ts +26 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +34 -3
- package/dist/schema.js.map +1 -1
- package/dist/transport/BaseTransport.d.ts +1 -20
- package/dist/transport/BaseTransport.d.ts.map +1 -1
- package/dist/transport/BaseTransport.js +1 -2
- package/dist/transport/BaseTransport.js.map +1 -1
- package/dist/transport/HttpHelpers.d.ts +0 -7
- package/dist/transport/HttpHelpers.d.ts.map +1 -1
- package/dist/transport/HttpHelpers.js +1 -7
- package/dist/transport/HttpHelpers.js.map +1 -1
- package/dist/transport/HttpTransport.d.ts.map +1 -1
- package/dist/transport/HttpTransport.js +2 -1
- package/dist/transport/HttpTransport.js.map +1 -1
- package/dist/transport/StreamableHttpTransport.d.ts +0 -6
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
- package/dist/transport/StreamableHttpTransport.js +4 -13
- package/dist/transport/StreamableHttpTransport.js.map +1 -1
- package/dist/watchers/SkillWatcher.d.ts.map +1 -1
- package/dist/watchers/SkillWatcher.js +3 -2
- package/dist/watchers/SkillWatcher.js.map +1 -1
- package/dist/watchers/ToolWatcher.d.ts.map +1 -1
- package/dist/watchers/ToolWatcher.js +2 -1
- package/dist/watchers/ToolWatcher.js.map +1 -1
- package/package.json +3 -3
- package/dist/__tests__/request-context.test.d.ts +0 -2
- package/dist/__tests__/request-context.test.d.ts.map +0 -1
- package/dist/__tests__/worker-manager-cov.test.d.ts +0 -2
- package/dist/__tests__/worker-manager-cov.test.d.ts.map +0 -1
- package/dist/__tests__/worker-manager.test.d.ts +0 -2
- package/dist/__tests__/worker-manager.test.d.ts.map +0 -1
- package/dist/cluster/WorkerManager.d.ts +0 -166
- package/dist/cluster/WorkerManager.d.ts.map +0 -1
- package/dist/cluster/WorkerManager.js +0 -202
- package/dist/cluster/WorkerManager.js.map +0 -1
- package/dist/cluster/worker.d.ts +0 -11
- package/dist/cluster/worker.d.ts.map +0 -1
- package/dist/cluster/worker.js +0 -36
- package/dist/cluster/worker.js.map +0 -1
- package/dist/telemetry/Telemetry.d.ts +0 -36
- package/dist/telemetry/Telemetry.d.ts.map +0 -1
- package/dist/telemetry/Telemetry.js +0 -68
- package/dist/telemetry/Telemetry.js.map +0 -1
- package/dist/telemetry/__tests__/Telemetry.test.d.ts +0 -2
- package/dist/telemetry/__tests__/Telemetry.test.d.ts.map +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backward-compatibility snapshot tests for the {@link ThoughtEvaluator} facade.
|
|
3
|
+
*
|
|
4
|
+
* These tests lock the public API of the post-refactor `ThoughtEvaluator`
|
|
5
|
+
* (which composes `SignalComputer` + `Aggregator` + `PatternDetector` +
|
|
6
|
+
* `Calibrator`) so that future changes cannot silently alter observable
|
|
7
|
+
* behavior.
|
|
8
|
+
*
|
|
9
|
+
* Tests intentionally exercise only the public {@link ThoughtEvaluator} API —
|
|
10
|
+
* no imports from `core/evaluator/*` internals.
|
|
11
|
+
*
|
|
12
|
+
* @module __tests__/evaluator/EvaluatorBackwardCompat
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=EvaluatorBackwardCompat.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EvaluatorBackwardCompat.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/evaluator/EvaluatorBackwardCompat.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for the auto-compression trigger in ThoughtProcessor.
|
|
3
|
+
*
|
|
4
|
+
* Verifies that when a reasoning strategy returns `action: 'terminate'` AND
|
|
5
|
+
* the compression service is wired AND the current thought has a `branch_id`,
|
|
6
|
+
* the processor invokes `CompressionService.compressBranch()` to produce a
|
|
7
|
+
* Summary in the SummaryStore. Also verifies that compression failures never
|
|
8
|
+
* break the thought pipeline.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=CompressionAutoTrigger.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompressionAutoTrigger.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/CompressionAutoTrigger.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for compression persistence across all 3 backends.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the end-to-end flow:
|
|
5
|
+
* 1. Build a branched session in HistoryManager (with dagEdges so the
|
|
6
|
+
* compression service can walk descendants).
|
|
7
|
+
* 2. Run CompressionService.compressBranch() to produce a Summary in the
|
|
8
|
+
* InMemorySummaryStore (flag-ON path).
|
|
9
|
+
* 3. Persist via persistence.saveSummaries(...) and round-trip via
|
|
10
|
+
* persistence.loadSummaries(...) — assert structural equality.
|
|
11
|
+
*
|
|
12
|
+
* Matrix: 3 backends (Memory / File / SQLite) × 2 flag states (on / off).
|
|
13
|
+
*
|
|
14
|
+
* SQLite: skipped at module level when `better-sqlite3` is unavailable.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=CompressionPersistence.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompressionPersistence.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/CompressionPersistence.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end integration tests for the Strategy layer.
|
|
3
|
+
*
|
|
4
|
+
* Tests the full Strategy integration from {@link ThoughtProcessor} through
|
|
5
|
+
* the MCP response shape. Covers default strategy wiring, terminal vs. ongoing
|
|
6
|
+
* thought hint emission, branch handling, multi-thought sequences, backward
|
|
7
|
+
* compatible response shape, and graceful degradation when a strategy throws.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=StrategyIntegration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StrategyIntegration.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/StrategyIntegration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end integration tests for the {@link TreeOfThoughtStrategy}.
|
|
3
|
+
*
|
|
4
|
+
* Drives the strategy through the full {@link ThoughtProcessor} pipeline
|
|
5
|
+
* with a real {@link HistoryManager} + {@link EdgeStore} + {@link MemoryPersistence}
|
|
6
|
+
* so that `ctx.graph.leaves(sessionId)` reflects the actual DAG built from
|
|
7
|
+
* processed thoughts.
|
|
8
|
+
*
|
|
9
|
+
* Scenarios covered:
|
|
10
|
+
* a. Single thought → no strategy_hint (frontier empty → continue)
|
|
11
|
+
* b. High-confidence frontier → terminate with reason 'confidence threshold'
|
|
12
|
+
* c. Wide frontier (branches) → branch hint emitted when current is outside beam
|
|
13
|
+
* d. Flag-off (SequentialStrategy) → no strategy_hint for ongoing thoughts
|
|
14
|
+
* e. Plateau across low-score thoughts → terminate with reason 'plateau'
|
|
15
|
+
* f. Strategy throws → graceful degradation: response intact, no strategy_hint
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=ToTStrategyIntegration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToTStrategyIntegration.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/ToTStrategyIntegration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for DAG edge emission and persistence.
|
|
3
|
+
*
|
|
4
|
+
* Covers end-to-end behavior across all 3 persistence backends:
|
|
5
|
+
* - Memory (MemoryPersistence)
|
|
6
|
+
* - File (FilePersistence with os.tmpdir())
|
|
7
|
+
* - SQLite (SqlitePersistence with :memory:)
|
|
8
|
+
*
|
|
9
|
+
* Scenarios:
|
|
10
|
+
* 1. Flag-OFF parity — no edges emitted/persisted when dagEdges=false
|
|
11
|
+
* 2. Flag-ON edge kinds — every relational edge kind (except tool_invocation)
|
|
12
|
+
* 3. Three-backend roundtrip — flush + load preserves edges across all backends
|
|
13
|
+
* 4. Multi-session isolation — edges stay scoped to their session
|
|
14
|
+
* 5. Restart roundtrip with GraphView — restored edges traverse correctly
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=dag-edges.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag-edges.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/dag-edges.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SequentialStrategy.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/strategies/SequentialStrategy.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Contract Tests — enforces purity constraints on all
|
|
3
|
+
* {@link IReasoningStrategy} implementations (Oracle review concern C2).
|
|
4
|
+
*
|
|
5
|
+
* Every strategy MUST be:
|
|
6
|
+
* - Idempotent: repeated `decide()` calls with identical context produce
|
|
7
|
+
* deeply-equal output.
|
|
8
|
+
* - Stateless: instances hold no own mutable fields (only the readonly
|
|
9
|
+
* `name` discriminator is allowed).
|
|
10
|
+
* - Deterministic: separate instances yield identical decisions for the
|
|
11
|
+
* same context.
|
|
12
|
+
* - Side-effect free: `decide()` must not mutate the input
|
|
13
|
+
* {@link StrategyContext}.
|
|
14
|
+
*
|
|
15
|
+
* @module __tests__/strategies/StrategyContract.test
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=StrategyContract.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StrategyContract.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/strategies/StrategyContract.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TreeOfThoughtStrategy tests — covers default config, decide() ordering,
|
|
3
|
+
* shouldBranch / shouldTerminate predicates, edge cases (empty frontier,
|
|
4
|
+
* empty history), and purity (deterministic / non-mutating).
|
|
5
|
+
*
|
|
6
|
+
* @module __tests__/strategies/TreeOfThoughtStrategy.test
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=TreeOfThoughtStrategy.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeOfThoughtStrategy.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/strategies/TreeOfThoughtStrategy.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plateau.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/strategies/plateau.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totScoring.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/strategies/totScoring.test.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import*as e from"./lib.js";import*as t from"node:crypto";import*as s from"node:http";import*as i from"node:url";import*as n from"valibot";import{ValibotJsonSchemaAdapter as o}from"@tmcp/adapter-valibot";import{StdioTransport as r}from"@tmcp/transport-stdio";import{readFileSync as a}from"node:fs";import{dirname as l,join as c}from"node:path";import{McpServer as h}from"tmcp";import{AsyncLocalStorage as p}from"node:async_hooks";var d={
|
|
2
|
+
import*as e from"./lib.js";import*as t from"node:crypto";import*as s from"node:http";import*as i from"node:url";import*as n from"valibot";import{ValibotJsonSchemaAdapter as o}from"@tmcp/adapter-valibot";import{StdioTransport as r}from"@tmcp/transport-stdio";import{readFileSync as a}from"node:fs";import{dirname as l,join as c}from"node:path";import{McpServer as h}from"tmcp";import{AsyncLocalStorage as p}from"node:async_hooks";var d={787(e,t,s){s.d(t,{Ag:()=>o,m_:()=>a,qA:()=>n,u1:()=>l,yM:()=>r});class i extends Error{code;constructor(e,t){super(e),this.code=t,this.name="SequentialThinkingError",Error.captureStackTrace(this,this.constructor)}}class n extends i{constructor(e){super(`Session '${e}' is not active`,"SESSION_NOT_ACTIVE"),this.name="SessionNotActiveError"}}class o extends i{constructor(e){super(`Session not found: ${e}`,"SESSION_NOT_FOUND"),this.name="SessionNotFoundError"}}class r extends i{constructor(e){super(`Max sessions (${e}) reached. Wait for a session to close or increase maxSessions.`,"MAX_SESSIONS_REACHED"),this.name="MaxSessionsReachedError"}}class a extends i{constructor(){super("ConnectionPool has been terminated","POOL_TERMINATED"),this.name="PoolTerminatedError"}}function l(e){return e instanceof Error?e.message:String(e)}},527(e,t,s){s.d(t,{createConnectionPool:()=>r});var i=s(787);class n{_server;_id;_createdAt;_lastActivityAt;_isActiveValue;_timeout;_cleanupTimer=null;_logger;constructor(e,t,s,i){this._server=t,this._id=e,this._createdAt=Date.now(),this._lastActivityAt=this._createdAt,this._isActiveValue=!0,this._timeout=s,this._logger=i,this._startTimeout()}get isActive(){return this._isActiveValue}async process(e){if(!this.isActive)throw new i.qA(this._id);return this._lastActivityAt=Date.now(),this._resetTimeout(),this._server.processThought(e)}getInfo(){return{id:this._id,server:this._server,createdAt:this._createdAt,lastActivityAt:this._lastActivityAt,isActive:this.isActive}}isTimedOut(){return Date.now()-this._lastActivityAt>this._timeout}async close(){this._isActiveValue=!1,this._cleanupTimer&&(clearTimeout(this._cleanupTimer),this._cleanupTimer=null),this._server.stop()}_startTimeout(){this._cleanupTimer&&clearTimeout(this._cleanupTimer),this._cleanupTimer=setTimeout(()=>{this.isTimedOut()&&(this._logger.warn(`Session ${this._id} timed out, closing`),this.close().catch(e=>{this._logger.error(`Error closing timed out session ${this._id}:`,e)}))},this._timeout)}_resetTimeout(){this._startTimeout()}}class o{_sessions=new Map;_createSessionLock=null;_maxSessions;_sessionTimeout;_autoCleanup;_cleanupInterval;_cleanupTimerId=null;_terminated=!1;_logger;_serverFactory;constructor(e={}){this._maxSessions=e.maxSessions??100,this._sessionTimeout=e.sessionTimeout??3e5,this._autoCleanup=e.autoCleanup??!0,this._cleanupInterval=e.cleanupInterval??6e4,this._serverFactory=e.serverFactory??null,this._logger=e.logger??this._createNoopLogger(),this._autoCleanup&&this._startCleanup()}_createNoopLogger(){return{info:()=>{},warn:()=>{},error:()=>{},debug:()=>{},setLevel:()=>{},getLevel:()=>"info"}}async createSession(){let e;for(;this._createSessionLock;)await this._createSessionLock;if(this._terminated)throw new i.m_;if(this._sessions.size>=this._maxSessions)throw new i.yM(this._maxSessions);if(!this._serverFactory)throw Error("ConnectionPool requires a serverFactory option to create sessions");this._createSessionLock=new Promise(t=>{e=t});try{let e=`session_${Date.now()}_${Math.random().toString(36).substring(2,11)}`,t=await this._serverFactory(),s=new n(e,t,this._sessionTimeout,this._logger);return this._sessions.set(e,s),this._logger.info(`Created session ${e} (${this._sessions.size}/${this._maxSessions} active sessions)`),e}finally{e(),this._createSessionLock=null}}async process(e,t){let s=this._sessions.get(e);if(!s)throw new i.Ag(e);return s.process(t)}async closeSession(e){let t=this._sessions.get(e);if(!t)throw new i.Ag(e);await t.close(),this._sessions.delete(e),this._logger.info(`Closed session ${e} (${this._sessions.size}/${this._maxSessions} active sessions)`)}getSessionInfo(e){var t;return null==(t=this._sessions.get(e))?void 0:t.getInfo()}getActiveSessions(){return Array.from(this._sessions.values()).filter(e=>e.isActive).map(e=>e.getInfo())}getStats(){let e=this.getActiveSessions();return{totalSessions:this._sessions.size,activeSessions:e.length,maxSessions:this._maxSessions,cleanupEnabled:this._autoCleanup,sessionTimeout:this._sessionTimeout}}_startCleanup(){null!==this._cleanupTimerId&&clearInterval(this._cleanupTimerId),this._cleanupTimerId=setInterval(()=>{this._cleanupTimedOutSessions()},this._cleanupInterval)}_cleanupTimedOutSessions(){let e=0;for(let[t,s]of this._sessions.entries())s.isTimedOut()&&(s.close().catch(e=>{this._logger.error(`Error closing timed out session ${t}:`,e)}),this._sessions.delete(t),e++);e>0&&this._logger.info(`Cleaned ${e} timed-out sessions (${this._sessions.size}/${this._maxSessions} active sessions)`)}async terminate(){if(this._terminated)return;this._terminated=!0,null!==this._cleanupTimerId&&(clearInterval(this._cleanupTimerId),this._cleanupTimerId=null);let e=Array.from(this._sessions.values()).map(e=>e.close().catch(t=>{this._logger.error(`Error closing session ${e.getInfo().id}:`,t)}));await Promise.all(e),this._sessions.clear(),this._logger.info("ConnectionPool terminated")}async dispose(){await this.terminate()}isRunning(){return!this._terminated}}function r(e){return new o(e)}},555(e,t,s){s.d(t,{Uv:()=>d,ZK:()=>h,iV:()=>p});var i=s(821);let n=`A detailed tool for dynamic and reflective problem-solving through thoughts.
|
|
3
3
|
This tool helps analyze problems through a flexible thinking process that can adapt and evolve.
|
|
4
4
|
Each thought can build on, question, or revise previous insights as understanding deepens.
|
|
5
5
|
|
|
@@ -102,13 +102,13 @@ You should:
|
|
|
102
102
|
20. Self-assess quality and confidence to track reasoning reliability
|
|
103
103
|
21. Use merge_from_thoughts to combine insights from multiple reasoning branches
|
|
104
104
|
22. Use session_id to isolate independent reasoning chains from each other
|
|
105
|
-
23. Use reset_state: true when starting a completely new analysis to avoid statistical contamination from previous chains`,o=i.object({tool_name:i.pipe(i.string(),i.description("Name of the tool being recommended")),confidence:i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation")),rationale:i.pipe(i.string(),i.description("Why this tool is recommended")),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),suggested_inputs:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Optional suggested parameters"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative tools that could be used")))}),r=i.object({skill_name:i.pipe(i.string(),i.description("Name of the skill being recommended")),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation (default: 0.5)"))),rationale:i.optional(i.pipe(i.string(),i.description("Why this skill is recommended (default: empty string)"))),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative skills that could be used"))),allowed_tools:i.optional(i.pipe(i.array(i.string()),i.description("Tools this skill is allowed to use (from skill frontmatter)"))),user_invocable:i.optional(i.pipe(i.boolean(),i.description("Whether this skill can be user-invoked")))}),a=i.object({step_description:i.pipe(i.string(),i.description("What needs to be done")),recommended_tools:i.pipe(i.array(o),i.description("Tools recommended for this step")),recommended_skills:i.optional(i.pipe(i.array(r),i.description("Skills recommended for this step"))),expected_outcome:i.pipe(i.string(),i.description("What to expect from this step")),next_step_conditions:i.optional(i.pipe(i.array(i.string()),i.description("Conditions to consider for the next step")))}),l=i.object({tool_name:i.pipe(i.string(),i.description("Name of the tool being recommended")),rationale:i.optional(i.pipe(i.string(),i.description("Why this tool is recommended (default: empty string)"))),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation (default: 0.5)"))),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),suggested_inputs:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Optional suggested parameters"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative tools that could be used")))}),c=i.object({step_description:i.pipe(i.string(),i.description("What needs to be done")),recommended_tools:i.pipe(i.array(l),i.description("Tools recommended for this step")),recommended_skills:i.optional(i.pipe(i.array(r),i.description("Skills recommended for this step"))),expected_outcome:i.optional(i.pipe(i.string(),i.description("What to expect from this step (default: empty string)"))),next_step_conditions:i.optional(i.pipe(i.array(i.string()),i.description("Conditions to consider for the next step")))}),h=i.object({available_mcp_tools:i.optional(i.pipe(i.array(i.string()),i.description('Array of MCP tool names available for use (e.g., ["mcp-omnisearch", "mcp-turso-cloud"])'))),available_skills:i.optional(i.pipe(i.array(i.string()),i.description('Array of skill names available for use (e.g., ["commit", "review-pr", "pdf"])'))),thought:i.pipe(i.string(),i.description("Your current thinking step")),next_thought_needed:i.optional(i.pipe(i.boolean(),i.description("Whether another thought step is needed (defaults to true if not provided)"))),thought_number:i.pipe(i.number(),i.minValue(1),i.description("Current thought number")),total_thoughts:i.pipe(i.number(),i.minValue(1),i.description("Estimated total thoughts needed")),is_revision:i.optional(i.pipe(i.boolean(),i.description("Whether this revises previous thinking"))),revises_thought:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Which thought is being reconsidered"))),branch_from_thought:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Branching point thought number"))),branch_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Branch ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Branch identifier (alphanumeric, hyphens, underscores only, max 50 chars)"))),needs_more_thoughts:i.optional(i.pipe(i.boolean(),i.description("If more thoughts are needed"))),current_step:i.optional(i.pipe(a,i.description("Current step recommendation"))),previous_steps:i.optional(i.pipe(i.array(c),i.description("Steps already recommended (lenient schema - allows partial data with defaults)"))),remaining_steps:i.optional(i.pipe(i.array(i.string()),i.description("High-level descriptions of upcoming steps"))),thought_type:i.optional(i.pipe(i.picklist(["regular","hypothesis","verification","critique","synthesis","meta"]),i.description("Classified purpose: regular, hypothesis, verification, critique, synthesis, meta"))),quality_score:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("Self-assessed quality score (0-1)"))),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("Explicit confidence in correctness (0-1)"))),hypothesis_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Hypothesis ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Identifier linking hypothesis to verification thoughts"))),verification_target:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Thought number being verified or critiqued"))),synthesis_sources:i.optional(i.pipe(i.array(i.pipe(i.number(),i.minValue(1))),i.description("Thought numbers being synthesized"))),merge_from_thoughts:i.optional(i.pipe(i.array(i.pipe(i.number(),i.minValue(1))),i.description("Thought numbers from other branches being merged (DAG)"))),merge_branch_ids:i.optional(i.pipe(i.array(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/),i.maxLength(50))),i.description("Branch IDs being merged into current context"))),meta_observation:i.optional(i.pipe(i.string(),i.description("Metacognitive observation about reasoning process"))),reasoning_depth:i.optional(i.pipe(i.picklist(["shallow","moderate","deep"]),i.description("Effort signal: how deep reasoning should go"))),session_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Session ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(100),i.description("Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior."))),reset_state:i.optional(i.pipe(i.boolean(),i.description("When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session.")))}),p={name:"sequentialthinking_tools",description:n,inputSchema:{}},d=i.object({jsonrpc:i.pipe(i.string(),i.literal("2.0"),i.description('JSON-RPC protocol version (must be "2.0")')),method:i.pipe(i.string(),i.minLength(1),i.description("Method name to invoke")),params:i.optional(i.pipe(i.union([i.object({}),i.array(i.unknown())]),i.description("Method parameters (object or array)"))),id:i.optional(i.pipe(i.union([i.string(),i.number(),i.null()]),i.description("Request ID (omit for notifications)")))})},434(e,t,s){s.d(t,{j:()=>r});class i{_level="info";info(e,t){}warn(e,t){}error(e,t){}debug(e,t){}setLevel(e){this._level=e}getLevel(){return this._level}}let n=new Set(["session","sessionId","client","clientId"]),o=/^[a-zA-Z0-9_-]+$/;class r{_port;_host;_corsOrigin;_enableCors;_rateLimitEnabled;_maxRequestsPerMinute;_allowedHosts;_rateLimitMap=new Map;_rateLimitCleanupIntervalId=null;_wasHostExplicitlySet;_isShuttingDown=!1;_logger;_healthChecker;constructor(e={}){this._port=e.port??9108,this._host=e.host??"127.0.0.1",this._wasHostExplicitlySet=void 0!==e.host,this._corsOrigin=e.corsOrigin??"*",this._enableCors=e.enableCors??!0,this._rateLimitEnabled=e.enableRateLimit??!0,this._maxRequestsPerMinute=e.maxRequestsPerMinute??100,this._allowedHosts=this._buildAllowedHosts(e.allowedHosts),this._isShuttingDown=!1,this._logger=e.logger??new i,this._healthChecker=e.healthChecker??null,this._rateLimitEnabled&&this._startRateLimitCleanup()}get serverUrl(){let e=this._wasHostExplicitlySet||"127.0.0.1"!==this._host?this._host:"localhost";return`http://${e}:${this._port}`}validateSessionId(e){return!(e.length>64)&&o.test(e)}sanitizeQueryParams(e){let t={};for(let[s,i]of e.searchParams.entries())n.has(s)&&(t[s]=i);return t}checkRateLimit(e){if(!this._rateLimitEnabled)return!1;let t=Date.now();this._cleanupExpiredRateLimitEntries(t);let s=this._rateLimitMap.get(e);return!s||t>s.resetTime?(this._rateLimitMap.set(e,{count:1,resetTime:t+6e4}),!1):s.count>=this._maxRequestsPerMinute||(s.count++,!1)}_cleanupExpiredRateLimitEntries(e=Date.now()){for(let[t,s]of this._rateLimitMap.entries())s.resetTime<=e&&this._rateLimitMap.delete(t)}_startRateLimitCleanup(){null!==this._rateLimitCleanupIntervalId&&clearInterval(this._rateLimitCleanupIntervalId),this._rateLimitCleanupIntervalId=setInterval(()=>{this._cleanupExpiredRateLimitEntries()},6e4)}_stopRateLimitCleanup(){null!==this._rateLimitCleanupIntervalId&&(clearInterval(this._rateLimitCleanupIntervalId),this._rateLimitCleanupIntervalId=null)}getClientIp(e){let t=e.headers["x-forwarded-for"];return t&&"string"==typeof t?t.split(",")[0].trim():e.socket.remoteAddress||"unknown"}validateCorsOrigin(e){if("*"===this._corsOrigin)return!0;let t=e.headers.origin;if(!t||this._corsOrigin===t)return!0;if(this._corsOrigin.includes("*")){let e=this._corsOrigin.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[a-zA-Z0-9.-]*");return RegExp(`^${e}$`).test(t)}return!1}setCorsHeaders(e){this._enableCors&&(e.setHeader("Access-Control-Allow-Origin",this._corsOrigin),e.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"))}validateHostHeader(e){let t=e.headers.host;if(!t)return!0;let s=t.split(":")[0].trim().toLowerCase();return!!s&&(0===this._allowedHosts.size||this._allowedHosts.has(s))}_buildAllowedHosts(e){if(e&&e.length>0)return new Set(e.map(e=>e.toLowerCase().trim()).filter(Boolean));let t=this._host.toLowerCase(),s=["localhost","127.0.0.1","::1"];return new Set(s.includes(t)||"0.0.0.0"===t||"::"===t?s:[t])}log(e,t,s){"info"===e?this._logger.info(t,s):"warn"===e?this._logger.warn(t,s):this._logger.error(t,s)}isShuttingDown(){return this._isShuttingDown}handleHealthEndpoint(e,t){let s={status:"healthy",...t};this._healthChecker&&(s.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s))}async handleReadinessEndpoint(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}handleMetricsEndpoint(e,t){if(!t){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found");return}e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(t())}}},504(e,t,s){s.d(t,{SseTransport:()=>l});var i=s(316),n=s(61),o=s(821),r=s(555),a=s(434);class l extends a.j{_server;_path;_clients=new Set;_clientSessionMap=new Map;_messageQueue=new Map;_metrics;_connectionPool;constructor(e={}){super(e),this._path=e.path??"/sse",this._metrics=e.metrics,this._connectionPool=e.connectionPool,this._updateActiveConnectionsMetric(),this._server=(0,i.createServer)((e,t)=>this._handleRequest(e,t))}async connect(e){return this._mcpServer=e,new Promise(e=>{this._server.listen(this._port,this._host,()=>{this.log("info",`SSE transport listening on http://${this._host}:${this._port}`),e()})})}_mcpServer=null;async _handleRequest(e,t){var s,i,o,r,a;let l=Date.now(),c=e.url||"/",h=e.method||"GET";if(null==(s=this._metrics)||s.counter("http_requests_total",1,{transport:"sse",method:h,path:c},"Total HTTP requests"),t.once("finish",()=>{var e;let t=(Date.now()-l)/1e3;null==(e=this._metrics)||e.histogram("http_request_duration_seconds",t,{transport:"sse",path:c})}),!this.validateHostHeader(e)){null==(i=this._metrics)||i.counter("http_request_errors_total",1,{transport:"sse",error_type:"forbidden"},"Total HTTP request errors"),t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Forbidden - invalid host header"}));return}let p=new n.URL(e.url||"",`http://${e.headers.host}`),d=this.getClientIp(e);if(this.checkRateLimit(d)){null==(o=this._metrics)||o.counter("http_request_errors_total",1,{transport:"sse",error_type:"rate_limit"},"Total HTTP request errors"),t.writeHead(429,{"Content-Type":"application/json","Retry-After":"60"}),t.end(JSON.stringify({error:"Too many requests"}));return}if(!this.validateCorsOrigin(e)){null==(r=this._metrics)||r.counter("http_request_errors_total",1,{transport:"sse",error_type:"forbidden"},"Total HTTP request errors"),t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Forbidden - invalid origin"}));return}this.setCorsHeaders(t);let u=this.sanitizeQueryParams(p);if(u.session||u.sessionId){let e=u.session??u.sessionId;if(!this.validateSessionId(e)){null==(a=this._metrics)||a.counter("http_request_errors_total",1,{transport:"sse",error_type:"validation"},"Total HTTP request errors"),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid session ID format"}));return}}if(this._enableCors&&"OPTIONS"===e.method){t.writeHead(204),t.end();return}p.pathname===this._path&&"GET"===e.method?await this._handleSseConnection(e,t,u):p.pathname===`${this._path}/message`&&"POST"===e.method?await this._handleMessage(e,t,u):"/health"===p.pathname?this._handleHealthCheck(t):"/ready"===p.pathname?await this._handleReadinessCheck(t):(t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Not Found"))}_handleHealthCheck(e){let t={status:"healthy",clients:this._clients.size};this._connectionPool&&(t.pool=this._connectionPool.getStats()),this._healthChecker&&(t.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}async _handleReadinessCheck(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}async _handleSseConnection(e,t,s){let i;if(t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this._connectionPool){let e=s.session??s.sessionId;if(e&&this._connectionPool.getSessionInfo(e))i=e;else try{i=await this._connectionPool.createSession()}catch(e){t.write(`event: error
|
|
105
|
+
23. Use reset_state: true when starting a completely new analysis to avoid statistical contamination from previous chains`,o=i.object({tool_name:i.pipe(i.string(),i.description("Name of the tool being recommended")),confidence:i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation")),rationale:i.pipe(i.string(),i.description("Why this tool is recommended")),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),suggested_inputs:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Optional suggested parameters"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative tools that could be used")))}),r=i.object({skill_name:i.pipe(i.string(),i.description("Name of the skill being recommended")),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation (default: 0.5)"))),rationale:i.optional(i.pipe(i.string(),i.description("Why this skill is recommended (default: empty string)"))),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative skills that could be used"))),allowed_tools:i.optional(i.pipe(i.array(i.string()),i.description("Tools this skill is allowed to use (from skill frontmatter)"))),user_invocable:i.optional(i.pipe(i.boolean(),i.description("Whether this skill can be user-invoked")))}),a=i.object({step_description:i.pipe(i.string(),i.description("What needs to be done")),recommended_tools:i.pipe(i.array(o),i.description("Tools recommended for this step")),recommended_skills:i.optional(i.pipe(i.array(r),i.description("Skills recommended for this step"))),expected_outcome:i.pipe(i.string(),i.description("What to expect from this step")),next_step_conditions:i.optional(i.pipe(i.array(i.string()),i.description("Conditions to consider for the next step")))}),l=i.object({tool_name:i.pipe(i.string(),i.description("Name of the tool being recommended")),rationale:i.optional(i.pipe(i.string(),i.description("Why this tool is recommended (default: empty string)"))),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("0-1 indicating confidence in recommendation (default: 0.5)"))),priority:i.optional(i.pipe(i.number(),i.description("Order in the recommendation sequence (default: 999)"))),suggested_inputs:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Optional suggested parameters"))),alternatives:i.optional(i.pipe(i.array(i.string()),i.description("Alternative tools that could be used")))}),c=i.object({step_description:i.pipe(i.string(),i.description("What needs to be done")),recommended_tools:i.pipe(i.array(l),i.description("Tools recommended for this step")),recommended_skills:i.optional(i.pipe(i.array(r),i.description("Skills recommended for this step"))),expected_outcome:i.optional(i.pipe(i.string(),i.description("What to expect from this step (default: empty string)"))),next_step_conditions:i.optional(i.pipe(i.array(i.string()),i.description("Conditions to consider for the next step")))}),h=i.object({available_mcp_tools:i.optional(i.pipe(i.array(i.string()),i.description('Array of MCP tool names available for use (e.g., ["mcp-omnisearch", "mcp-turso-cloud"])'))),available_skills:i.optional(i.pipe(i.array(i.string()),i.description('Array of skill names available for use (e.g., ["commit", "review-pr", "pdf"])'))),thought:i.pipe(i.string(),i.description("Your current thinking step")),id:i.optional(i.pipe(i.string(),i.minLength(1),i.maxLength(30),i.description("Unique identifier for this thought. Auto-generated if not provided."))),next_thought_needed:i.optional(i.pipe(i.boolean(),i.description("Whether another thought step is needed (defaults to true if not provided)"))),thought_number:i.pipe(i.number(),i.minValue(1),i.description("Current thought number")),total_thoughts:i.pipe(i.number(),i.minValue(1),i.description("Estimated total thoughts needed")),is_revision:i.optional(i.pipe(i.boolean(),i.description("Whether this revises previous thinking"))),revises_thought:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Which thought is being reconsidered"))),branch_from_thought:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Branching point thought number"))),branch_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Branch ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Branch identifier (alphanumeric, hyphens, underscores only, max 50 chars)"))),needs_more_thoughts:i.optional(i.pipe(i.boolean(),i.description("If more thoughts are needed"))),current_step:i.optional(i.pipe(a,i.description("Current step recommendation"))),previous_steps:i.optional(i.pipe(i.array(c),i.description("Steps already recommended (lenient schema - allows partial data with defaults)"))),remaining_steps:i.optional(i.pipe(i.array(i.string()),i.description("High-level descriptions of upcoming steps"))),thought_type:i.optional(i.pipe(i.picklist(["regular","hypothesis","verification","critique","synthesis","meta","tool_call","tool_observation","assumption","decomposition","backtrack"]),i.description("Classified purpose: regular, hypothesis, verification, critique, synthesis, meta"))),quality_score:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("Self-assessed quality score (0-1)"))),confidence:i.optional(i.pipe(i.number(),i.minValue(0),i.maxValue(1),i.description("Explicit confidence in correctness (0-1)"))),hypothesis_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Hypothesis ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(50),i.description("Identifier linking hypothesis to verification thoughts"))),verification_target:i.optional(i.pipe(i.number(),i.minValue(1),i.description("Thought number being verified or critiqued"))),synthesis_sources:i.optional(i.pipe(i.array(i.pipe(i.number(),i.minValue(1))),i.description("Thought numbers being synthesized"))),merge_from_thoughts:i.optional(i.pipe(i.array(i.pipe(i.number(),i.minValue(1))),i.description("Thought numbers from other branches being merged (DAG)"))),merge_branch_ids:i.optional(i.pipe(i.array(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/),i.maxLength(50))),i.description("Branch IDs being merged into current context"))),meta_observation:i.optional(i.pipe(i.string(),i.description("Metacognitive observation about reasoning process"))),reasoning_depth:i.optional(i.pipe(i.picklist(["shallow","moderate","deep"]),i.description("Effort signal: how deep reasoning should go"))),session_id:i.optional(i.pipe(i.string(),i.regex(/^[a-zA-Z0-9_-]+$/,"Session ID must contain only letters, numbers, hyphens, and underscores"),i.minLength(1),i.maxLength(100),i.description("Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior."))),reset_state:i.optional(i.pipe(i.boolean(),i.description("When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session."))),tool_name:i.optional(i.pipe(i.string(),i.minLength(1),i.description("Name of the tool being invoked (for tool_call thoughts)"))),tool_arguments:i.optional(i.pipe(i.record(i.string(),i.unknown()),i.description("Arguments passed to the tool (for tool_call thoughts)"))),tool_result:i.optional(i.pipe(i.unknown(),i.description("Result returned by the tool (for tool_observation thoughts)"))),continuation_token:i.optional(i.pipe(i.string(),i.minLength(1),i.description("Token for resuming long-running tool invocations"))),decomposition_children:i.optional(i.pipe(i.array(i.string()),i.description("Child thought IDs produced by decomposition"))),backtrack_target:i.optional(i.pipe(i.number(),i.integer(),i.minValue(1),i.description("Thought number to backtrack to")))}),p={name:"sequentialthinking_tools",description:n,inputSchema:{}},d=i.object({jsonrpc:i.pipe(i.string(),i.literal("2.0"),i.description('JSON-RPC protocol version (must be "2.0")')),method:i.pipe(i.string(),i.minLength(1),i.description("Method name to invoke")),params:i.optional(i.pipe(i.union([i.object({}),i.array(i.unknown())]),i.description("Method parameters (object or array)"))),id:i.optional(i.pipe(i.union([i.string(),i.number(),i.null()]),i.description("Request ID (omit for notifications)")))}),u=i.union([i.literal("sequence"),i.literal("branch"),i.literal("merge"),i.literal("verifies"),i.literal("critiques"),i.literal("derives_from"),i.literal("tool_invocation"),i.literal("revises")]);i.object({id:i.pipe(i.string(),i.minLength(1),i.maxLength(30)),from:i.pipe(i.string(),i.minLength(1),i.maxLength(30)),to:i.pipe(i.string(),i.minLength(1),i.maxLength(30)),kind:u,sessionId:i.pipe(i.string(),i.minLength(1)),createdAt:i.number(),metadata:i.optional(i.record(i.string(),i.unknown()))})},681(e,t,s){s.d(t,{j:()=>r}),s(561);let i=/^[a-zA-Z0-9_-]+$/;class n{_level="info";info(e,t){}warn(e,t){}error(e,t){}debug(e,t){}setLevel(e){this._level=e}getLevel(){return this._level}}let o=new Set(["session","sessionId","client","clientId"]);class r{_port;_host;_corsOrigin;_enableCors;_rateLimitEnabled;_maxRequestsPerMinute;_allowedHosts;_rateLimitMap=new Map;_rateLimitCleanupIntervalId=null;_wasHostExplicitlySet;_isShuttingDown=!1;_logger;_healthChecker;constructor(e={}){this._port=e.port??9108,this._host=e.host??"127.0.0.1",this._wasHostExplicitlySet=void 0!==e.host,this._corsOrigin=e.corsOrigin??"*",this._enableCors=e.enableCors??!0,this._rateLimitEnabled=e.enableRateLimit??!0,this._maxRequestsPerMinute=e.maxRequestsPerMinute??100,this._allowedHosts=this._buildAllowedHosts(e.allowedHosts),this._isShuttingDown=!1,this._logger=e.logger??new n,this._healthChecker=e.healthChecker??null,this._rateLimitEnabled&&this._startRateLimitCleanup()}get serverUrl(){let e=this._wasHostExplicitlySet||"127.0.0.1"!==this._host?this._host:"localhost";return`http://${e}:${this._port}`}validateSessionId(e){return!(e.length>100)&&i.test(e)}sanitizeQueryParams(e){let t={};for(let[s,i]of e.searchParams.entries())o.has(s)&&(t[s]=i);return t}checkRateLimit(e){if(!this._rateLimitEnabled)return!1;let t=Date.now();this._cleanupExpiredRateLimitEntries(t);let s=this._rateLimitMap.get(e);return!s||t>s.resetTime?(this._rateLimitMap.set(e,{count:1,resetTime:t+6e4}),!1):s.count>=this._maxRequestsPerMinute||(s.count++,!1)}_cleanupExpiredRateLimitEntries(e=Date.now()){for(let[t,s]of this._rateLimitMap.entries())s.resetTime<=e&&this._rateLimitMap.delete(t)}_startRateLimitCleanup(){null!==this._rateLimitCleanupIntervalId&&clearInterval(this._rateLimitCleanupIntervalId),this._rateLimitCleanupIntervalId=setInterval(()=>{this._cleanupExpiredRateLimitEntries()},6e4)}_stopRateLimitCleanup(){null!==this._rateLimitCleanupIntervalId&&(clearInterval(this._rateLimitCleanupIntervalId),this._rateLimitCleanupIntervalId=null)}getClientIp(e){let t=e.headers["x-forwarded-for"];return t&&"string"==typeof t?t.split(",")[0].trim():e.socket.remoteAddress||"unknown"}validateCorsOrigin(e){if("*"===this._corsOrigin)return!0;let t=e.headers.origin;if(!t||this._corsOrigin===t)return!0;if(this._corsOrigin.includes("*")){let e=this._corsOrigin.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[a-zA-Z0-9.-]*");return RegExp(`^${e}$`).test(t)}return!1}setCorsHeaders(e){this._enableCors&&(e.setHeader("Access-Control-Allow-Origin",this._corsOrigin),e.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"))}validateHostHeader(e){let t=e.headers.host;if(!t)return!0;let s=t.split(":")[0].trim().toLowerCase();return!!s&&(0===this._allowedHosts.size||this._allowedHosts.has(s))}_buildAllowedHosts(e){if(e&&e.length>0)return new Set(e.map(e=>e.toLowerCase().trim()).filter(Boolean));let t=this._host.toLowerCase(),s=["localhost","127.0.0.1","::1"];return new Set(s.includes(t)||"0.0.0.0"===t||"::"===t?s:[t])}log(e,t,s){"info"===e?this._logger.info(t,s):"warn"===e?this._logger.warn(t,s):this._logger.error(t,s)}isShuttingDown(){return this._isShuttingDown}handleHealthEndpoint(e,t){let s={status:"healthy",...t};this._healthChecker&&(s.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(s))}async handleReadinessEndpoint(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}handleMetricsEndpoint(e,t){if(!t){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found");return}e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(t())}}},504(e,t,s){s.d(t,{SseTransport:()=>l});var i=s(316),n=s(61),o=s(821),r=s(555),a=s(681);class l extends a.j{_server;_path;_clients=new Set;_clientSessionMap=new Map;_messageQueue=new Map;_metrics;_connectionPool;constructor(e={}){super(e),this._path=e.path??"/sse",this._metrics=e.metrics,this._connectionPool=e.connectionPool,this._updateActiveConnectionsMetric(),this._server=(0,i.createServer)((e,t)=>this._handleRequest(e,t))}async connect(e){return this._mcpServer=e,new Promise(e=>{this._server.listen(this._port,this._host,()=>{this.log("info",`SSE transport listening on http://${this._host}:${this._port}`),e()})})}_mcpServer=null;async _handleRequest(e,t){var s,i,o,r,a;let l=Date.now(),c=e.url||"/",h=e.method||"GET";if(null==(s=this._metrics)||s.counter("http_requests_total",1,{transport:"sse",method:h,path:c},"Total HTTP requests"),t.once("finish",()=>{var e;let t=(Date.now()-l)/1e3;null==(e=this._metrics)||e.histogram("http_request_duration_seconds",t,{transport:"sse",path:c})}),!this.validateHostHeader(e)){null==(i=this._metrics)||i.counter("http_request_errors_total",1,{transport:"sse",error_type:"forbidden"},"Total HTTP request errors"),t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Forbidden - invalid host header"}));return}let p=new n.URL(e.url||"",`http://${e.headers.host}`),d=this.getClientIp(e);if(this.checkRateLimit(d)){null==(o=this._metrics)||o.counter("http_request_errors_total",1,{transport:"sse",error_type:"rate_limit"},"Total HTTP request errors"),t.writeHead(429,{"Content-Type":"application/json","Retry-After":"60"}),t.end(JSON.stringify({error:"Too many requests"}));return}if(!this.validateCorsOrigin(e)){null==(r=this._metrics)||r.counter("http_request_errors_total",1,{transport:"sse",error_type:"forbidden"},"Total HTTP request errors"),t.writeHead(403,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Forbidden - invalid origin"}));return}this.setCorsHeaders(t);let u=this.sanitizeQueryParams(p);if(u.session||u.sessionId){let e=u.session??u.sessionId;if(!this.validateSessionId(e)){null==(a=this._metrics)||a.counter("http_request_errors_total",1,{transport:"sse",error_type:"validation"},"Total HTTP request errors"),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid session ID format"}));return}}if(this._enableCors&&"OPTIONS"===e.method){t.writeHead(204),t.end();return}p.pathname===this._path&&"GET"===e.method?await this._handleSseConnection(e,t,u):p.pathname===`${this._path}/message`&&"POST"===e.method?await this._handleMessage(e,t,u):"/health"===p.pathname?this._handleHealthCheck(t):"/ready"===p.pathname?await this._handleReadinessCheck(t):(t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Not Found"))}_handleHealthCheck(e){let t={status:"healthy",clients:this._clients.size};this._connectionPool&&(t.pool=this._connectionPool.getStats()),this._healthChecker&&(t.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}async _handleReadinessCheck(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}async _handleSseConnection(e,t,s){let i;if(t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),this._connectionPool){let e=s.session??s.sessionId;if(e&&this._connectionPool.getSessionInfo(e))i=e;else try{i=await this._connectionPool.createSession()}catch(e){t.write(`event: error
|
|
106
106
|
`),t.write(`data: ${JSON.stringify({error:e instanceof Error?e.message:"Failed to create session"})}
|
|
107
107
|
|
|
108
108
|
`),t.end();return}this._clientSessionMap.set(t,i),this._updatePoolMetrics()}let n={timestamp:Date.now()};i&&(n.sessionId=i),this._sendSseEvent(t,"connected",n),this._clients.add(t),this._updateActiveConnectionsMetric(),e.on("close",()=>{this._clients.delete(t),this._clientSessionMap.delete(t),this._updateActiveConnectionsMetric()});let o=this._generateClientId(),r=this._messageQueue.get(o);if(r){for(let e of r)this._sendSseEvent(t,"message",e);this._messageQueue.delete(o)}}async _handleMessage(e,t,s){var i,n,a;let l="";for await(let t of e)l+=t.toString();try{let e=JSON.parse(l),s=(0,o.safeParse)(r.Uv,e);if(!s.success){null==(i=this._metrics)||i.counter("http_request_errors_total",1,{transport:"sse",error_type:"validation"},"Total HTTP request errors"),t.writeHead(200,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:(null==e?void 0:e.id)??null,error:{code:-32600,message:"Invalid Request",data:s.issues}}));return}if(this._mcpServer){let s=await this._mcpServer.receive(e,{sessionInfo:{}});t.writeHead(200,{"Content-Type":"application/json"}),s?t.end(JSON.stringify(s)):t.end(JSON.stringify({jsonrpc:"2.0",id:(null==e?void 0:e.id)??null,result:null}))}else null==(n=this._metrics)||n.counter("http_request_errors_total",1,{transport:"sse",error_type:"server_not_ready"},"Total HTTP request errors"),t.writeHead(503,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Server not ready"}))}catch{null==(a=this._metrics)||a.counter("http_request_errors_total",1,{transport:"sse",error_type:"parse_error"},"Total HTTP request errors"),t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({error:"Invalid JSON"}))}}_sendSseEvent(e,t,s){try{e.write(`event: ${t}
|
|
109
109
|
`),e.write(`data: ${JSON.stringify(s)}
|
|
110
110
|
|
|
111
|
-
`)}catch{this._clients.delete(e),this._updateActiveConnectionsMetric()}}_updateActiveConnectionsMetric(){var e;null==(e=this._metrics)||e.gauge("sse_active_connections",this._clients.size,{},"Current active SSE connections")}_updatePoolMetrics(){if(!this._connectionPool||!this._metrics)return;let e=this._connectionPool.getStats();this._metrics.gauge("sse_pool_active_sessions",e.activeSessions,{},"Active sessions in connection pool"),this._metrics.gauge("sse_pool_total_sessions",e.totalSessions,{},"Total sessions in connection pool"),this._metrics.gauge("sse_pool_max_sessions",e.maxSessions,{},"Maximum sessions in connection pool")}broadcast(e,t){for(let s of this._clients)this._sendSseEvent(s,e,t)}_generateClientId(){return`client_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}get clientCount(){return this._clients.size}get connectionPool(){return this._connectionPool}async stop(e){return this._isShuttingDown=!0,this._stopRateLimitCleanup(),this._connectionPool&&await this._connectionPool.terminate(),new Promise(e=>{for(let e of this._clients)try{e.end()}catch{}this._clients.clear(),this._clientSessionMap.clear(),this._updateActiveConnectionsMetric(),this._server.close(()=>{this.log("info","SSE transport stopped"),e()})})}}},
|
|
111
|
+
`)}catch{this._clients.delete(e),this._updateActiveConnectionsMetric()}}_updateActiveConnectionsMetric(){var e;null==(e=this._metrics)||e.gauge("sse_active_connections",this._clients.size,{},"Current active SSE connections")}_updatePoolMetrics(){if(!this._connectionPool||!this._metrics)return;let e=this._connectionPool.getStats();this._metrics.gauge("sse_pool_active_sessions",e.activeSessions,{},"Active sessions in connection pool"),this._metrics.gauge("sse_pool_total_sessions",e.totalSessions,{},"Total sessions in connection pool"),this._metrics.gauge("sse_pool_max_sessions",e.maxSessions,{},"Maximum sessions in connection pool")}broadcast(e,t){for(let s of this._clients)this._sendSseEvent(s,e,t)}_generateClientId(){return`client_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}get clientCount(){return this._clients.size}get connectionPool(){return this._connectionPool}async stop(e){return this._isShuttingDown=!0,this._stopRateLimitCleanup(),this._connectionPool&&await this._connectionPool.terminate(),new Promise(e=>{for(let e of this._clients)try{e.end()}catch{}this._clients.clear(),this._clientSessionMap.clear(),this._updateActiveConnectionsMetric(),this._server.close(()=>{this.log("info","SSE transport stopped"),e()})})}}},756(e,t,s){s.d(t,{StreamableHttpTransport:()=>h});var i=s(561),n=s(316),o=s(821),r=s(787),a=s(555),l=s(681);async function c(e,t){let s="",i=0;for await(let n of e){let e="string"==typeof n?n:n.toString();if(i+=e.length,t>0&&i>t)return null;s+=e}return s}class h extends l.j{_server=null;_mcpServer=null;_path;_stateful;_sessionIdGenerator;_sessions=new Map;_requestCount=0;_activeRequests=0;_bodySizeLimitEnabled;_maxBodySize;_requestTimeout;_metrics;_metricsProvider;constructor(e={}){super(e),this._path=e.path??"/mcp",this._stateful=e.stateful??!0,this._sessionIdGenerator=e.sessionIdGenerator??(()=>(0,i.randomUUID)()),this._bodySizeLimitEnabled=e.enableBodySizeLimit??!0,this._maxBodySize=e.maxBodySize??0xa00000,this._requestTimeout=e.requestTimeout??3e4,this._metrics=e.metrics,this._metricsProvider=e.metricsProvider??null}get clientCount(){return this._stateful?this._sessions.size:this._activeRequests}get requestCount(){return this._requestCount}async connect(e){return this._mcpServer=e,this._server=(0,n.createServer)((e,t)=>this._handleRequest(e,t)),new Promise(e=>{this._server.listen(this._port,this._host,()=>{this.log("info",`Streamable HTTP transport listening on http://${this._host}:${this._port}`),e()})})}async _handleRequest(e,t){var s,i;let n=Date.now();if(null==(s=this._metrics)||s.counter("streamable_http_requests_total",1,{},"Total Streamable HTTP transport requests"),t.once("finish",()=>{var e;let t=(Date.now()-n)/1e3;null==(e=this._metrics)||e.histogram("streamable_http_request_duration_seconds",t,{})}),!this.validateHostHeader(e))return void this._sendJsonRpcError(t,403,-32e3,"Forbidden - invalid host header");if(this.isShuttingDown())return void this._sendJsonRpcError(t,503,-32603,"Server is shutting down");let o=this.getClientIp(e);if(this.checkRateLimit(o)){t.setHeader("Retry-After","60"),this._sendJsonRpcError(t,429,-32e3,"Too many requests");return}if(!this.validateCorsOrigin(e))return void this._sendJsonRpcError(t,403,-32e3,"Forbidden - invalid origin");if(this.setCorsHeaders(t),"OPTIONS"===e.method){t.setHeader("Access-Control-Allow-Headers","Content-Type, Mcp-Session-Id"),t.writeHead(204),t.end();return}let r=(null==(i=e.url)?void 0:i.split("?")[0])??"/";"GET"===e.method&&"/metrics"===r?this._handleMetrics(t):"GET"===e.method&&"/health"===r?this._handleHealthCheck(t):"GET"===e.method&&"/ready"===r?await this._handleReadinessCheck(t):r===this._path?"POST"===e.method?await this._handleMcpPost(e,t):"GET"===e.method?this._handleMcpGet(e,t):(t.writeHead(405,{"Content-Type":"application/json",Allow:"GET, POST"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32601,message:"Method not allowed"}}))):this._sendJsonRpcError(t,404,-32601,"Not Found")}_sendJsonRpcError(e,t,s,i,n=null,o){let r={code:s,message:i};o&&Object.assign(r,o),e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify({jsonrpc:"2.0",id:n,error:r}))}async _handleMcpPost(e,t){this._requestCount++,this._activeRequests++;let s=setTimeout(()=>{this._activeRequests--,this._sendJsonRpcError(t,500,-32603,"Request timeout")},this._requestTimeout);try{let i,n,r=await c(e,this._bodySizeLimitEnabled?this._maxBodySize:0);if(null===r){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,413,-32e3,"Request body too large");return}try{i=JSON.parse(r)}catch{clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,200,-32700,"Parse error");return}let l=(0,o.safeParse)(a.Uv,i);if(!l.success){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,200,-32600,"Invalid Request",(null==i?void 0:i.id)??null,{data:l.issues});return}if(this._stateful){let i=this._resolveSession(e,t);if(!1===i){clearTimeout(s),this._activeRequests--;return}n=i}if(!this._mcpServer){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,503,-32603,"Server not ready",(null==i?void 0:i.id)??null);return}let h=await this._mcpServer.receive(i,{sessionInfo:{}});clearTimeout(s),this._activeRequests--;let p={"Content-Type":"application/json"};n&&(p["Mcp-Session-Id"]=n),h?(t.writeHead(200,p),t.end(JSON.stringify(h))):(n&&t.setHeader("Mcp-Session-Id",n),t.writeHead(202),t.end())}catch(e){clearTimeout(s),this._activeRequests--,this._sendJsonRpcError(t,200,-32603,"Internal error",null,{data:(0,r.u1)(e)})}}_handleMcpGet(e,t){if(!this._stateful){t.writeHead(405,{"Content-Type":"application/json",Allow:"POST"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32601,message:"GET not supported in stateless mode"}}));return}let s=this._getSessionIdFromHeader(e);if(!s){t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Missing Mcp-Session-Id header"}}));return}let i=this._sessions.get(s);if(!i){t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32001,message:"Session not found"}}));return}t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","Mcp-Session-Id":s}),this._sendSseEvent(t,"connected",{sessionId:s,timestamp:Date.now()}),i.notificationStreams.add(t),i.lastActivityAt=Date.now(),this._updateSessionMetrics(),e.on("close",()=>{i.notificationStreams.delete(t),this._updateSessionMetrics()})}_resolveSession(e,t){let s=this._getSessionIdFromHeader(e);if(s){if(!this.validateSessionId(s))return t.writeHead(400,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Invalid Mcp-Session-Id format"}})),!1;let e=this._sessions.get(s);return e?(e.lastActivityAt=Date.now(),s):(t.writeHead(404,{"Content-Type":"application/json"}),t.end(JSON.stringify({jsonrpc:"2.0",id:null,error:{code:-32001,message:"Session not found"}})),!1)}let i=this._sessionIdGenerator(),n={id:i,createdAt:Date.now(),lastActivityAt:Date.now(),notificationStreams:new Set};return this._sessions.set(i,n),this.log("info",`New session created: ${i}`),this._updateSessionMetrics(),i}_getSessionIdFromHeader(e){let t=e.headers["mcp-session-id"];if("string"==typeof t&&t.length>0)return t}_sendSseEvent(e,t,s){try{e.write(`event: ${t}
|
|
112
112
|
`),e.write(`data: ${JSON.stringify(s)}
|
|
113
113
|
|
|
114
|
-
`)}catch{}}broadcastToSession(e,t,s){let i=this._sessions.get(e);if(i)for(let e of i.notificationStreams)this._sendSseEvent(e,t,s)}_handleMetrics(e){if(!this._metricsProvider){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found");return}e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(this._metricsProvider())}_handleHealthCheck(e){let t={status:"healthy",requests:this._requestCount,sessions:this._sessions.size,transport:"streamable-http"};this._healthChecker&&(t.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}async _handleReadinessCheck(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}_updateSessionMetrics(){var e,t;null==(e=this._metrics)||e.gauge("streamable_http_active_sessions",this._sessions.size,{},"Active Streamable HTTP sessions");let s=0;for(let e of this._sessions.values())s+=e.notificationStreams.size;null==(t=this._metrics)||t.gauge("streamable_http_notification_streams",s,{},"Active SSE notification streams")}async stop(e){this._isShuttingDown=!0,this._stopRateLimitCleanup();let t=e??3e4;for(let e of this._sessions.values()){for(let t of e.notificationStreams)try{t.end()}catch{}e.notificationStreams.clear()}return this._sessions.clear(),new Promise(e=>{if(!this._server){this.log("info","Streamable HTTP transport stopped (no server)"),e();return}let s=setTimeout(()=>{this.log("warn","Streamable HTTP transport force-closing after timeout"),e()},t);this._server.close(()=>{clearTimeout(s),this.log("info","Streamable HTTP transport stopped"),e()})})}}},65(t){t.exports=e},561(e){e.exports=t},316(e){e.exports=s},61(e){e.exports=i},821(e){e.exports=n}},u={};function _(e){var t=u[e];if(void 0!==t)return t.exports;var s=u[e]={exports:{}};return d[e](s,s.exports,_),s.exports}_.d=(e,t)=>{for(var s in t)_.o(t,s)&&!_.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},_.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e=_(61),t=_(65);
|
|
114
|
+
`)}catch{}}broadcastToSession(e,t,s){let i=this._sessions.get(e);if(i)for(let e of i.notificationStreams)this._sendSseEvent(e,t,s)}_handleMetrics(e){if(!this._metricsProvider){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Not Found");return}e.writeHead(200,{"Content-Type":"text/plain; version=0.0.4; charset=utf-8"}),e.end(this._metricsProvider())}_handleHealthCheck(e){let t={status:"healthy",requests:this._requestCount,sessions:this._sessions.size,transport:"streamable-http"};this._healthChecker&&(t.liveness=this._healthChecker.checkLiveness()),e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}async _handleReadinessCheck(e){if(this._healthChecker){let t=await this._healthChecker.checkReadiness(),s="ok"===t.status?200:503;e.writeHead(s,{"Content-Type":"application/json"}),e.end(JSON.stringify(t))}else e.writeHead(200,{"Content-Type":"application/json"}),e.end(JSON.stringify({status:"ok",timestamp:new Date().toISOString(),components:{}}))}_updateSessionMetrics(){var e,t;null==(e=this._metrics)||e.gauge("streamable_http_active_sessions",this._sessions.size,{},"Active Streamable HTTP sessions");let s=0;for(let e of this._sessions.values())s+=e.notificationStreams.size;null==(t=this._metrics)||t.gauge("streamable_http_notification_streams",s,{},"Active SSE notification streams")}async stop(e){this._isShuttingDown=!0,this._stopRateLimitCleanup();let t=e??3e4;for(let e of this._sessions.values()){for(let t of e.notificationStreams)try{t.end()}catch{}e.notificationStreams.clear()}return this._sessions.clear(),new Promise(e=>{if(!this._server){this.log("info","Streamable HTTP transport stopped (no server)"),e();return}let s=setTimeout(()=>{this.log("warn","Streamable HTTP transport force-closing after timeout"),e()},t);this._server.close(()=>{clearTimeout(s),this.log("info","Streamable HTTP transport stopped"),e()})})}}},65(t){t.exports=e},561(e){e.exports=t},316(e){e.exports=s},61(e){e.exports=i},821(e){e.exports=n}},u={};function _(e){var t=u[e];if(void 0!==t)return t.exports;var s=u[e]={exports:{}};return d[e](s,s.exports,_),s.exports}_.d=(e,t)=>{for(var s in t)_.o(t,s)&&!_.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},_.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e=_(61),t=_(65);let s=new p;class i{_level;_context;_pretty;static LEVEL_PRIORITY={debug:0,info:1,warn:2,error:3};constructor(e={}){this._level=e.level??"info",this._context=e.context??"SequentialThinking",this._pretty=e.pretty??!0}shouldLog(e){return i.LEVEL_PRIORITY[e]>=i.LEVEL_PRIORITY[this._level]}format(e){if(this._pretty){let t=e.meta?` ${JSON.stringify(e.meta)}`:"",s=e.requestId?` [${e.requestId}]`:"";return`[${e.timestamp}] [${e.level.toUpperCase()}]${e.context?` [${e.context}]`:""}${s} ${e.message}${t}`}return JSON.stringify(e)}log(e,t,i){var n;if(!this.shouldLog(e))return;let o=null==(n=s.getStore())?void 0:n.requestId,r={level:e,message:t,timestamp:new Date().toISOString(),context:this._context,meta:i,...o?{requestId:o}:{}};console.error(this.format(r))}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}createChild(e){return new i({level:this._level,context:`${this._context}:${e}`,pretty:this._pretty})}setLevel(e){this._level=e}getLevel(){return this._level}}var n=_(787),d=_(555);let{name:u,version:m}=JSON.parse(a(c(l((0,e.fileURLToPath)(import.meta.url)),"../package.json"),"utf-8")),g=process.argv.slice(2);async function f(e,t){var s;let{SseTransport:i}=await Promise.resolve().then(_.bind(_,504)),{createConnectionPool:n}=await Promise.resolve().then(_.bind(_,527)),o=parseInt(process.env.SSE_PORT||"3000",10),r=process.env.SSE_HOST||"localhost",a=t.getContainer().resolve("Metrics"),l="false"!==process.env.SSE_ENABLE_POOL,c=parseInt(process.env.SSE_MAX_SESSIONS||"100",10),h=parseInt(process.env.SSE_SESSION_TIMEOUT||"300000",10),p=l?n({maxSessions:c,sessionTimeout:h,logger:t._logger,serverFactory:async()=>{let{createServer:e}=await Promise.resolve().then(_.bind(_,65));return await e({autoDiscover:!0})}}):void 0,d=new i({port:o,host:r,corsOrigin:process.env.CORS_ORIGIN||"*",enableCors:"false"!==process.env.ENABLE_CORS,allowedHosts:null==(s=process.env.ALLOWED_HOSTS)?void 0:s.split(",").map(e=>e.trim()),metrics:a,connectionPool:p});await d.connect(e),S(async()=>{await d.stop(),await t.stop()}),t._logger.info(`Sequential Thinking MCP Server running on SSE transport at http://${r}:${o}`)}async function v(e,t){var s;let{StreamableHttpTransport:i}=await Promise.resolve().then(_.bind(_,756)),n=parseInt(process.env.STREAMABLE_HTTP_PORT||process.env.SSE_PORT||"3000",10),o=process.env.STREAMABLE_HTTP_HOST||process.env.SSE_HOST||"localhost",r=t.getContainer().resolve("Metrics"),a="false"!==process.env.STREAMABLE_HTTP_STATEFUL,l=new i({port:n,host:o,corsOrigin:process.env.CORS_ORIGIN||"*",enableCors:"false"!==process.env.ENABLE_CORS,allowedHosts:null==(s=process.env.ALLOWED_HOSTS)?void 0:s.split(",").map(e=>e.trim()),metrics:r,stateful:a});await l.connect(e),S(async()=>{await l.stop(),await t.stop()}),t._logger.info(`Sequential Thinking MCP Server running on Streamable HTTP transport at http://${o}:${n}`)}async function y(e,t){new r(e).listen();let s=async()=>{let e=setTimeout(()=>{t._logger.error("Graceful shutdown timed out after 30s - forcing exit"),process.exit(1)},3e4).unref();try{await t.stop(),clearTimeout(e),process.exit(0)}catch(e){t._logger.error("Error during shutdown",{error:(0,n.u1)(e)}),process.exit(1)}};process.once("SIGINT",()=>void s()),process.once("SIGTERM",()=>void s()),t._logger.info("Sequential Thinking MCP Server running on stdio")}function S(e){process.once("SIGINT",()=>{e().then(()=>process.exit(0)).catch(()=>process.exit(1))}),process.once("SIGTERM",()=>{e().then(()=>process.exit(0)).catch(()=>process.exit(1))})}(g.includes("--version")||g.includes("-v"))&&(console.log(`${u} v${m}`),process.exit(0)),(async function(){let e=new h({name:u,version:m,description:"Semantic Sequential Thinking MCP Server"},{adapter:new o,capabilities:{tools:{listChanged:!0}}}),s=await (0,t.initializeServer)();e.tool({name:"sequentialthinking_tools",description:d.iV.description,schema:d.ZK},async e=>s.processThought(e));let i=process.env.TRANSPORT_TYPE||"stdio";"sse"===i?await f(e,s):"streamable-http"===i?await v(e,s):await y(e,s)})().catch(e=>{new i({level:"error",context:"SequentialThinking",pretty:!0}).error("Fatal error running server",{error:(0,n.u1)(e)}),process.exit(1)})})();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env bun\n\n// CLI entry point for tracelattice MCP server.\n// This file handles CLI argument parsing, transport selection, and signal handlers.\n// For library usage, import from './lib.js' or './index.js' instead.\n\nimport { ValibotJsonSchemaAdapter } from '@tmcp/adapter-valibot';\nimport { StdioTransport } from '@tmcp/transport-stdio';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { McpServer } from 'tmcp';\nimport type { ToolAwareSequentialThinkingServer } from './lib.js';\nimport { initializeServer } from './lib.js';\nimport { StructuredLogger } from './logger/StructuredLogger.js';\nimport { Metrics } from './metrics/metrics.impl.js';\nimport { SEQUENTIAL_THINKING_TOOL, SequentialThinkingSchema } from './schema.js';\n\n// Get version from package.json\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst package_json = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));\nconst { name, version } = package_json;\n// Handle CLI arguments\nconst args = process.argv.slice(2);\nconst shouldShowVersion = args.includes('--version') || args.includes('-v');\n\nif (shouldShowVersion) {\n\tconsole.log(`${name} v${version}`);\n\tprocess.exit(0);\n}\nasync function main() {\n\tconst adapter = new ValibotJsonSchemaAdapter();\n\tconst server = new McpServer(\n\t\t{\n\t\t\tname,\n\t\t\tversion,\n\t\t\tdescription: 'Semantic Sequential Thinking MCP Server',\n\t\t},\n\t\t{\n\t\t\tadapter,\n\t\t\tcapabilities: {\n\t\t\t\ttools: { listChanged: true },\n\t\t\t},\n\t\t}\n\t);\n\n\tconst thinkingServer = await initializeServer();\n\n\tserver.tool(\n\t\t{\n\t\t\tname: 'sequentialthinking_tools',\n\t\t\tdescription: SEQUENTIAL_THINKING_TOOL.description,\n\t\t\tschema: SequentialThinkingSchema,\n\t\t},\n\t\tasync (input) => {\n\t\t\treturn thinkingServer.processThought(input);\n\t\t}\n\t);\n\n\tconst transportType = process.env.TRANSPORT_TYPE || 'stdio';\n\tif (transportType === 'sse') {\n\t\tawait startSseTransport(server, thinkingServer);\n\t} else if (transportType === 'streamable-http') {\n\t\tawait startStreamableHttpTransport(server, thinkingServer);\n\t} else {\n\t\tawait startStdioTransport(server, thinkingServer);\n\t}\n}\n/**\n * Start SSE transport for multi-user support\n */\nasync function startSseTransport(server: McpServer, thinkingServer: ToolAwareSequentialThinkingServer): Promise<void> {\n const { SseTransport } = await import('./transport/SseTransport.js');\n const { createConnectionPool } = await import('./pool/ConnectionPool.js');\n const port = parseInt(process.env.SSE_PORT || '3000', 10);\n const host = process.env.SSE_HOST || 'localhost';\n const transportMetrics = thinkingServer.getContainer().resolve<Metrics>('Metrics');\n const enablePool = process.env.SSE_ENABLE_POOL !== 'false';\n const maxSessions = parseInt(process.env.SSE_MAX_SESSIONS || '100', 10);\n const sessionTimeout = parseInt(process.env.SSE_SESSION_TIMEOUT || '300000', 10);\n const connectionPool = enablePool\n ? createConnectionPool({\n maxSessions,\n sessionTimeout,\n logger: thinkingServer['_logger'],\n serverFactory: async () => {\n const { createServer: createThinkingServer } = await import('./lib.js');\n const sessionServer = await createThinkingServer({ autoDiscover: true });\n return sessionServer;\n },\n })\n : undefined;\n const sseTransport = new SseTransport({\n port,\n host,\n corsOrigin: process.env.CORS_ORIGIN || '*',\n enableCors: process.env.ENABLE_CORS !== 'false',\n allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue) => hostValue.trim()),\n metrics: transportMetrics,\n connectionPool,\n });\n // Connect the SSE transport\n await sseTransport.connect(server);\n const shutdown = async (): Promise<void> => {\n await sseTransport.stop();\n await thinkingServer.stop();\n };\n registerShutdownHandlers(shutdown);\n thinkingServer['_logger'].info(\n `Sequential Thinking MCP Server running on SSE transport at http://${host}:${port}`\n );\n}\n/**\n * Start Streamable HTTP transport (MCP spec recommended)\n */\nasync function startStreamableHttpTransport(server: McpServer, thinkingServer: ToolAwareSequentialThinkingServer): Promise<void> {\n const { StreamableHttpTransport } = await import('./transport/StreamableHttpTransport.js');\n const port = parseInt(process.env.STREAMABLE_HTTP_PORT || process.env.SSE_PORT || '3000', 10);\n const host = process.env.STREAMABLE_HTTP_HOST || process.env.SSE_HOST || 'localhost';\n const transportMetrics = thinkingServer.getContainer().resolve<Metrics>('Metrics');\n const stateful = process.env.STREAMABLE_HTTP_STATEFUL !== 'false';\n const streamableTransport = new StreamableHttpTransport({\n\t port,\n host,\n corsOrigin: process.env.CORS_ORIGIN || '*',\n enableCors: process.env.ENABLE_CORS !== 'false',\n allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue) => hostValue.trim()),\n\t metrics: transportMetrics,\n\t stateful,\n });\n // Connect the Streamable HTTP transport\n await streamableTransport.connect(server);\n const shutdown = async (): Promise<void> => {\n await streamableTransport.stop();\n await thinkingServer.stop();\n };\n registerShutdownHandlers(shutdown);\n thinkingServer['_logger'].info(\n `Sequential Thinking MCP Server running on Streamable HTTP transport at http://${host}:${port}`\n );\n}\n/**\n * Start stdio transport (default, single-user)\n */\nasync function startStdioTransport(server: McpServer, thinkingServer: ToolAwareSequentialThinkingServer): Promise<void> {\n const transport = new StdioTransport(server);\n transport.listen();\n const shutdown = async (): Promise<void> => {\n const forceExit = setTimeout(() => {\n thinkingServer['_logger'].error('Graceful shutdown timed out after 30s - forcing exit');\n process.exit(1);\n }, 30_000).unref(); // 30s timeout, don't keep process alive\n try {\n await thinkingServer.stop();\n clearTimeout(forceExit);\n process.exit(0);\n } catch (error) {\n thinkingServer['_logger'].error('Error during shutdown', {\n error: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n }\n };\n // Register signal handlers ONCE (fixes double-registration bug)\n process.once('SIGINT', () => void shutdown());\n process.once('SIGTERM', () => void shutdown());\n thinkingServer['_logger'].info('Sequential Thinking MCP Server running on stdio');\n}\n/**\n * Register shutdown signal handlers for a common pattern\n */\nfunction registerShutdownHandlers(shutdown: () => Promise<void>): void {\n process.once('SIGINT', () => {\n shutdown()\n .then(() => process.exit(0))\n .catch(() => process.exit(1));\n });\n process.once('SIGTERM', () => {\n shutdown()\n .then(() => process.exit(0))\n .catch(() => process.exit(1));\n });\n}\nmain().catch((error) => {\n const logger = new StructuredLogger({\n level: 'error',\n context: 'SequentialThinking',\n pretty: true,\n });\n logger.error('Fatal error running server', {\n error: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n});\n"],"names":["__filename","fileURLToPath","__dirname","dirname","package_json","JSON","readFileSync","join","name","version","args","process","shouldShowVersion","console","main","adapter","ValibotJsonSchemaAdapter","server","McpServer","thinkingServer","initializeServer","SEQUENTIAL_THINKING_TOOL","SequentialThinkingSchema","input","transportType","startSseTransport","startStreamableHttpTransport","startStdioTransport","SseTransport","createConnectionPool","port","parseInt","host","transportMetrics","enablePool","maxSessions","sessionTimeout","connectionPool","createThinkingServer","sessionServer","undefined","sseTransport","hostValue","shutdown","registerShutdownHandlers","StreamableHttpTransport","stateful","streamableTransport","transport","StdioTransport","forceExit","setTimeout","clearTimeout","error","Error","String","logger","StructuredLogger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env bun\n\n// CLI entry point for tracelattice MCP server.\n// This file handles CLI argument parsing, transport selection, and signal handlers.\n// For library usage, import from './lib.js' or './index.js' instead.\n\nimport { ValibotJsonSchemaAdapter } from '@tmcp/adapter-valibot';\nimport { StdioTransport } from '@tmcp/transport-stdio';\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { McpServer } from 'tmcp';\nimport type { ToolAwareSequentialThinkingServer } from './lib.js';\nimport { initializeServer } from './lib.js';\nimport { StructuredLogger } from './logger/StructuredLogger.js';\nimport { getErrorMessage } from './errors.js';\nimport { Metrics } from './metrics/metrics.impl.js';\nimport { SEQUENTIAL_THINKING_TOOL, SequentialThinkingSchema } from './schema.js';\n\n// Get version from package.json\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst package_json = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));\nconst { name, version } = package_json;\n// Handle CLI arguments\nconst args = process.argv.slice(2);\nconst shouldShowVersion = args.includes('--version') || args.includes('-v');\n\nif (shouldShowVersion) {\n\tconsole.log(`${name} v${version}`);\n\tprocess.exit(0);\n}\nasync function main() {\n\tconst adapter = new ValibotJsonSchemaAdapter();\n\tconst server = new McpServer(\n\t\t{\n\t\t\tname,\n\t\t\tversion,\n\t\t\tdescription: 'Semantic Sequential Thinking MCP Server',\n\t\t},\n\t\t{\n\t\t\tadapter,\n\t\t\tcapabilities: {\n\t\t\t\ttools: { listChanged: true },\n\t\t\t},\n\t\t}\n\t);\n\n\tconst thinkingServer = await initializeServer();\n\n\tserver.tool(\n\t\t{\n\t\t\tname: 'sequentialthinking_tools',\n\t\t\tdescription: SEQUENTIAL_THINKING_TOOL.description,\n\t\t\tschema: SequentialThinkingSchema,\n\t\t},\n\t\tasync (input) => {\n\t\t\treturn thinkingServer.processThought(input);\n\t\t}\n\t);\n\n\tconst transportType = process.env.TRANSPORT_TYPE || 'stdio';\n\tif (transportType === 'sse') {\n\t\tawait startSseTransport(server, thinkingServer);\n\t} else if (transportType === 'streamable-http') {\n\t\tawait startStreamableHttpTransport(server, thinkingServer);\n\t} else {\n\t\tawait startStdioTransport(server, thinkingServer);\n\t}\n}\n/**\n * Start SSE transport for multi-user support\n */\nasync function startSseTransport(server: McpServer, thinkingServer: ToolAwareSequentialThinkingServer): Promise<void> {\n const { SseTransport } = await import('./transport/SseTransport.js');\n const { createConnectionPool } = await import('./pool/ConnectionPool.js');\n const port = parseInt(process.env.SSE_PORT || '3000', 10);\n const host = process.env.SSE_HOST || 'localhost';\n const transportMetrics = thinkingServer.getContainer().resolve<Metrics>('Metrics');\n const enablePool = process.env.SSE_ENABLE_POOL !== 'false';\n const maxSessions = parseInt(process.env.SSE_MAX_SESSIONS || '100', 10);\n const sessionTimeout = parseInt(process.env.SSE_SESSION_TIMEOUT || '300000', 10);\n const connectionPool = enablePool\n ? createConnectionPool({\n maxSessions,\n sessionTimeout,\n logger: thinkingServer['_logger'],\n serverFactory: async () => {\n const { createServer: createThinkingServer } = await import('./lib.js');\n const sessionServer = await createThinkingServer({ autoDiscover: true });\n return sessionServer;\n },\n })\n : undefined;\n const sseTransport = new SseTransport({\n port,\n host,\n corsOrigin: process.env.CORS_ORIGIN || '*',\n enableCors: process.env.ENABLE_CORS !== 'false',\n allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue) => hostValue.trim()),\n metrics: transportMetrics,\n connectionPool,\n });\n // Connect the SSE transport\n await sseTransport.connect(server);\n const shutdown = async (): Promise<void> => {\n await sseTransport.stop();\n await thinkingServer.stop();\n };\n registerShutdownHandlers(shutdown);\n thinkingServer['_logger'].info(\n `Sequential Thinking MCP Server running on SSE transport at http://${host}:${port}`\n );\n}\n/**\n * Start Streamable HTTP transport (MCP spec recommended)\n */\nasync function startStreamableHttpTransport(server: McpServer, thinkingServer: ToolAwareSequentialThinkingServer): Promise<void> {\n const { StreamableHttpTransport } = await import('./transport/StreamableHttpTransport.js');\n const port = parseInt(process.env.STREAMABLE_HTTP_PORT || process.env.SSE_PORT || '3000', 10);\n const host = process.env.STREAMABLE_HTTP_HOST || process.env.SSE_HOST || 'localhost';\n const transportMetrics = thinkingServer.getContainer().resolve<Metrics>('Metrics');\n const stateful = process.env.STREAMABLE_HTTP_STATEFUL !== 'false';\n const streamableTransport = new StreamableHttpTransport({\n\t port,\n host,\n corsOrigin: process.env.CORS_ORIGIN || '*',\n enableCors: process.env.ENABLE_CORS !== 'false',\n allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue) => hostValue.trim()),\n\t metrics: transportMetrics,\n\t stateful,\n });\n // Connect the Streamable HTTP transport\n await streamableTransport.connect(server);\n const shutdown = async (): Promise<void> => {\n await streamableTransport.stop();\n await thinkingServer.stop();\n };\n registerShutdownHandlers(shutdown);\n thinkingServer['_logger'].info(\n `Sequential Thinking MCP Server running on Streamable HTTP transport at http://${host}:${port}`\n );\n}\n/**\n * Start stdio transport (default, single-user)\n */\nasync function startStdioTransport(server: McpServer, thinkingServer: ToolAwareSequentialThinkingServer): Promise<void> {\n const transport = new StdioTransport(server);\n transport.listen();\n const shutdown = async (): Promise<void> => {\n const forceExit = setTimeout(() => {\n thinkingServer['_logger'].error('Graceful shutdown timed out after 30s - forcing exit');\n process.exit(1);\n }, 30_000).unref(); // 30s timeout, don't keep process alive\n try {\n await thinkingServer.stop();\n clearTimeout(forceExit);\n process.exit(0);\n } catch (error) {\n thinkingServer['_logger'].error('Error during shutdown', {\n error: getErrorMessage(error),\n });\n process.exit(1);\n }\n };\n // Register signal handlers ONCE (fixes double-registration bug)\n process.once('SIGINT', () => void shutdown());\n process.once('SIGTERM', () => void shutdown());\n thinkingServer['_logger'].info('Sequential Thinking MCP Server running on stdio');\n}\n/**\n * Register shutdown signal handlers for a common pattern\n */\nfunction registerShutdownHandlers(shutdown: () => Promise<void>): void {\n process.once('SIGINT', () => {\n shutdown()\n .then(() => process.exit(0))\n .catch(() => process.exit(1));\n });\n process.once('SIGTERM', () => {\n shutdown()\n .then(() => process.exit(0))\n .catch(() => process.exit(1));\n });\n}\nmain().catch((error) => {\n const logger = new StructuredLogger({\n level: 'error',\n context: 'SequentialThinking',\n pretty: true,\n });\n logger.error('Fatal error running server', {\n error: getErrorMessage(error),\n });\n process.exit(1);\n});\n"],"names":["__filename","fileURLToPath","__dirname","dirname","package_json","JSON","readFileSync","join","name","version","args","process","shouldShowVersion","console","main","adapter","ValibotJsonSchemaAdapter","server","McpServer","thinkingServer","initializeServer","SEQUENTIAL_THINKING_TOOL","SequentialThinkingSchema","input","transportType","startSseTransport","startStreamableHttpTransport","startStdioTransport","SseTransport","createConnectionPool","port","parseInt","host","transportMetrics","enablePool","maxSessions","sessionTimeout","connectionPool","createThinkingServer","sessionServer","undefined","sseTransport","hostValue","shutdown","registerShutdownHandlers","StreamableHttpTransport","stateful","streamableTransport","transport","StdioTransport","forceExit","setTimeout","clearTimeout","error","getErrorMessage","logger","StructuredLogger"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* @module config
|
|
9
9
|
*/
|
|
10
10
|
import type { PersistenceConfig } from '../persistence/PersistenceBackend.js';
|
|
11
|
+
import type { FeatureFlags } from '../ServerConfig.js';
|
|
11
12
|
/**
|
|
12
13
|
* Configuration options loaded from config files.
|
|
13
14
|
*
|
|
@@ -84,6 +85,21 @@ export interface ConfigFileOptions {
|
|
|
84
85
|
* Persistence configuration for storing history and state.
|
|
85
86
|
*/
|
|
86
87
|
persistence?: PersistenceConfig;
|
|
88
|
+
/**
|
|
89
|
+
* Feature flag overrides. Each field can be set independently.
|
|
90
|
+
* Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.
|
|
91
|
+
*/
|
|
92
|
+
features?: Partial<FeatureFlags>;
|
|
93
|
+
/**
|
|
94
|
+
* TTL in milliseconds for suspended tool-interleave entries.
|
|
95
|
+
* Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` environment variable.
|
|
96
|
+
*/
|
|
97
|
+
toolInterleaveTtlMs?: number;
|
|
98
|
+
/**
|
|
99
|
+
* Sweep interval in milliseconds for SuspensionStore expiration cleanup.
|
|
100
|
+
* Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` environment variable.
|
|
101
|
+
*/
|
|
102
|
+
toolInterleaveSweepMs?: number;
|
|
87
103
|
}
|
|
88
104
|
/**
|
|
89
105
|
* Loads configuration from files with environment variable overrides.
|
|
@@ -184,6 +200,24 @@ export declare class ConfigLoader {
|
|
|
184
200
|
* @private
|
|
185
201
|
*/
|
|
186
202
|
private applyEnvironmentOverrides;
|
|
203
|
+
/**
|
|
204
|
+
* Applies TRACELATTICE_FEATURES_* environment variable overrides for feature flags.
|
|
205
|
+
* Booleans accept 'true'/'false'/'1'/'0' (case-insensitive).
|
|
206
|
+
* Invalid reasoningStrategy values are warned and ignored (fall back to default).
|
|
207
|
+
*
|
|
208
|
+
* @param result - Configuration object to mutate with feature flag overrides
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
211
|
+
private applyFeatureFlagOverrides;
|
|
212
|
+
/**
|
|
213
|
+
* Parses a boolean from an environment variable string.
|
|
214
|
+
* Accepts 'true'/'false'/'1'/'0' case-insensitively.
|
|
215
|
+
*
|
|
216
|
+
* @param raw - Raw environment variable string
|
|
217
|
+
* @returns Parsed boolean, or undefined if the value is invalid
|
|
218
|
+
* @private
|
|
219
|
+
*/
|
|
220
|
+
private parseBoolean;
|
|
187
221
|
/**
|
|
188
222
|
* Parses a configuration file (JSON or YAML).
|
|
189
223
|
*
|
|
@@ -219,6 +253,9 @@ export declare class ConfigLoader {
|
|
|
219
253
|
maxHistorySize?: number;
|
|
220
254
|
maxBranches?: number;
|
|
221
255
|
maxBranchSize?: number;
|
|
256
|
+
features?: Partial<FeatureFlags>;
|
|
257
|
+
toolInterleaveTtlMs?: number;
|
|
258
|
+
toolInterleaveSweepMs?: number;
|
|
222
259
|
};
|
|
223
260
|
}
|
|
224
261
|
//# sourceMappingURL=ConfigLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAE/C;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE;QAChB;;;WAGG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAE9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAE/C;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE;QAChB;;;WAGG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,YAAY;IACxB,+DAA+D;IAC/D,OAAO,CAAC,YAAY,CAAW;IAE/B;;;;;;;;;;;;;OAaG;gBACS,UAAU,CAAC,EAAE,MAAM;IAa/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,IAAI,IAAI,iBAAiB,GAAG,IAAI;IAoBhC;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,yBAAyB;IAiEjC;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAuCjC;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAOpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;IAWnB;;;;;;;;;;;;;;;;;;OAkBG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG;QACjD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAC/B;CAUD"}
|
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { parse } from "yaml";
|
|
5
|
+
import { getErrorMessage } from "../errors.js";
|
|
5
6
|
class ConfigLoader {
|
|
6
7
|
_configPaths;
|
|
7
8
|
constructor(customPath){
|
|
@@ -22,7 +23,7 @@ class ConfigLoader {
|
|
|
22
23
|
config = this.parseConfig(configPath);
|
|
23
24
|
break;
|
|
24
25
|
} catch (error) {
|
|
25
|
-
console.error(`Failed to load config from ${configPath}:`,
|
|
26
|
+
console.error(`Failed to load config from ${configPath}:`, getErrorMessage(error));
|
|
26
27
|
}
|
|
27
28
|
return this.applyEnvironmentOverrides(config || {});
|
|
28
29
|
}
|
|
@@ -64,8 +65,54 @@ class ConfigLoader {
|
|
|
64
65
|
result.discoveryCache.maxSize = parsed;
|
|
65
66
|
}
|
|
66
67
|
}
|
|
68
|
+
if (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS) {
|
|
69
|
+
const parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS, 10);
|
|
70
|
+
if (Number.isFinite(parsed)) result.toolInterleaveTtlMs = parsed;
|
|
71
|
+
}
|
|
72
|
+
if (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS) {
|
|
73
|
+
const parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS, 10);
|
|
74
|
+
if (Number.isFinite(parsed)) result.toolInterleaveSweepMs = parsed;
|
|
75
|
+
}
|
|
76
|
+
this.applyFeatureFlagOverrides(result);
|
|
67
77
|
return result;
|
|
68
78
|
}
|
|
79
|
+
applyFeatureFlagOverrides(result) {
|
|
80
|
+
const boolMap = {
|
|
81
|
+
TRACELATTICE_FEATURES_DAG_EDGES: 'dagEdges',
|
|
82
|
+
TRACELATTICE_FEATURES_CALIBRATION: 'calibration',
|
|
83
|
+
TRACELATTICE_FEATURES_COMPRESSION: 'compression',
|
|
84
|
+
TRACELATTICE_FEATURES_TOOL_INTERLEAVE: 'toolInterleave',
|
|
85
|
+
TRACELATTICE_FEATURES_NEW_THOUGHT_TYPES: 'newThoughtTypes',
|
|
86
|
+
TRACELATTICE_FEATURES_OUTCOME_RECORDING: 'outcomeRecording'
|
|
87
|
+
};
|
|
88
|
+
for (const [envVar, key] of Object.entries(boolMap)){
|
|
89
|
+
const raw = process.env[envVar];
|
|
90
|
+
if (void 0 === raw) continue;
|
|
91
|
+
const parsed = this.parseBoolean(raw);
|
|
92
|
+
if (void 0 === parsed) {
|
|
93
|
+
console.warn(`Invalid boolean value for ${envVar}: "${raw}" (expected true/false/1/0). Ignoring.`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
result.features = result.features || {};
|
|
97
|
+
result.features[key] = parsed;
|
|
98
|
+
}
|
|
99
|
+
const strategyRaw = process.env.TRACELATTICE_FEATURES_REASONING_STRATEGY;
|
|
100
|
+
if (void 0 !== strategyRaw) {
|
|
101
|
+
const allowed = [
|
|
102
|
+
'sequential',
|
|
103
|
+
'tot'
|
|
104
|
+
];
|
|
105
|
+
if (allowed.includes(strategyRaw)) {
|
|
106
|
+
result.features = result.features || {};
|
|
107
|
+
result.features.reasoningStrategy = strategyRaw;
|
|
108
|
+
} else console.warn(`Invalid value for TRACELATTICE_FEATURES_REASONING_STRATEGY: "${strategyRaw}" (expected one of ${allowed.join(', ')}). Falling back to 'sequential'.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
parseBoolean(raw) {
|
|
112
|
+
const v = raw.trim().toLowerCase();
|
|
113
|
+
if ('true' === v || '1' === v) return true;
|
|
114
|
+
if ('false' === v || '0' === v) return false;
|
|
115
|
+
}
|
|
69
116
|
parseConfig(filePath) {
|
|
70
117
|
const content = readFileSync(filePath, 'utf-8');
|
|
71
118
|
const ext = filePath.split('.').pop()?.toLowerCase();
|
|
@@ -76,7 +123,10 @@ class ConfigLoader {
|
|
|
76
123
|
return {
|
|
77
124
|
maxHistorySize: config.maxHistorySize,
|
|
78
125
|
maxBranches: config.maxBranches,
|
|
79
|
-
maxBranchSize: config.maxBranchSize
|
|
126
|
+
maxBranchSize: config.maxBranchSize,
|
|
127
|
+
features: config.features,
|
|
128
|
+
toolInterleaveTtlMs: config.toolInterleaveTtlMs,
|
|
129
|
+
toolInterleaveSweepMs: config.toolInterleaveSweepMs
|
|
80
130
|
};
|
|
81
131
|
}
|
|
82
132
|
}
|