tracelattice 1.3.1 → 1.3.3
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 +27 -25
- package/dist/ServerConfig.d.ts +3 -25
- package/dist/ServerConfig.d.ts.map +1 -1
- package/dist/ServerConfig.js +7 -7
- package/dist/ServerConfig.js.map +1 -1
- package/dist/__tests__/eval/fixtures/scenarios.d.ts.map +1 -1
- package/dist/__tests__/helpers/factories.d.ts +13 -1
- package/dist/__tests__/helpers/factories.d.ts.map +1 -1
- package/dist/cache/DiscoveryCache.d.ts +1 -1
- package/dist/cache/DiscoveryCache.d.ts.map +1 -1
- package/dist/cache/DiscoveryCache.js.map +1 -1
- package/dist/cli.js +3483 -8
- package/dist/config/ConfigLoader.d.ts +2 -2
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +6 -4
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/contracts/PersistenceBackend.d.ts.map +1 -0
- package/dist/contracts/features.d.ts +39 -0
- package/dist/contracts/features.d.ts.map +1 -0
- package/dist/contracts/features.js +15 -0
- package/dist/contracts/features.js.map +1 -0
- package/dist/contracts/ids.d.ts +58 -0
- package/dist/contracts/ids.d.ts.map +1 -0
- package/dist/contracts/ids.js +31 -0
- package/dist/contracts/ids.js.map +1 -0
- package/dist/contracts/interfaces.d.ts +6 -3
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/contracts/strategy.d.ts +2 -2
- package/dist/contracts/strategy.d.ts.map +1 -1
- package/dist/contracts/suspension.d.ts +3 -2
- package/dist/contracts/suspension.d.ts.map +1 -1
- package/dist/contracts/transport.d.ts +25 -0
- package/dist/contracts/transport.d.ts.map +1 -0
- package/dist/core/HistoryManager.d.ts +4 -5
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +2 -2
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/IHistoryManager.d.ts +10 -0
- package/dist/core/IHistoryManager.d.ts.map +1 -1
- package/dist/core/IThoughtFormatter.d.ts +51 -0
- package/dist/core/IThoughtFormatter.d.ts.map +1 -0
- package/dist/core/IThoughtFormatter.js +1 -0
- package/dist/core/InputNormalizer.d.ts.map +1 -1
- package/dist/core/InputNormalizer.js +4 -3
- package/dist/core/InputNormalizer.js.map +1 -1
- package/dist/core/PersistenceBuffer.d.ts +1 -1
- package/dist/core/PersistenceBuffer.d.ts.map +1 -1
- package/dist/core/PersistenceBuffer.js.map +1 -1
- package/dist/core/ThoughtFormatter.d.ts +2 -1
- package/dist/core/ThoughtFormatter.d.ts.map +1 -1
- package/dist/core/ThoughtFormatter.js +3 -0
- package/dist/core/ThoughtFormatter.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts +2 -2
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +14 -9
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/compression/CompressionService.js +3 -3
- package/dist/core/compression/CompressionService.js.map +1 -1
- package/dist/core/compression/Summary.d.ts +4 -3
- package/dist/core/compression/Summary.d.ts.map +1 -1
- package/dist/core/evaluator/Aggregator.d.ts.map +1 -1
- package/dist/core/evaluator/Aggregator.js +6 -2
- package/dist/core/evaluator/Aggregator.js.map +1 -1
- package/dist/core/evaluator/PatternDetector.js +2 -2
- package/dist/core/evaluator/PatternDetector.js.map +1 -1
- package/dist/core/evaluator/SignalComputer.d.ts.map +1 -1
- package/dist/core/evaluator/SignalComputer.js +5 -1
- package/dist/core/evaluator/SignalComputer.js.map +1 -1
- package/dist/core/graph/Edge.d.ts +11 -4
- package/dist/core/graph/Edge.d.ts.map +1 -1
- package/dist/core/graph/EdgeEmitter.js +6 -6
- package/dist/core/graph/EdgeEmitter.js.map +1 -1
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts +1 -1
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts.map +1 -1
- package/dist/core/reasoning/strategies/StrategyFactory.js.map +1 -1
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -1
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +5 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -1
- package/dist/core/reasoning.d.ts +8 -1
- package/dist/core/reasoning.d.ts.map +1 -1
- package/dist/core/step.d.ts +5 -0
- package/dist/core/step.d.ts.map +1 -1
- package/dist/core/thought.d.ts +4 -3
- package/dist/core/thought.d.ts.map +1 -1
- package/dist/core/tools/InMemorySuspensionStore.d.ts +3 -1
- package/dist/core/tools/InMemorySuspensionStore.d.ts.map +1 -1
- package/dist/core/tools/InMemorySuspensionStore.js +3 -3
- package/dist/core/tools/InMemorySuspensionStore.js.map +1 -1
- package/dist/di/Container.d.ts +6 -3
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js.map +1 -1
- package/dist/di/ServiceRegistry.d.ts +3 -3
- package/dist/di/ServiceRegistry.d.ts.map +1 -1
- package/dist/errors.d.ts +36 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +49 -22
- package/dist/errors.js.map +1 -1
- package/dist/health/HealthChecker.d.ts +1 -1
- package/dist/health/HealthChecker.d.ts.map +1 -1
- package/dist/health/HealthChecker.js.map +1 -1
- package/dist/lib.d.ts +60 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/persistence/FilePersistence.d.ts +2 -2
- package/dist/persistence/FilePersistence.d.ts.map +1 -1
- package/dist/persistence/FilePersistence.js.map +1 -1
- package/dist/persistence/MemoryPersistence.d.ts +1 -1
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
- package/dist/persistence/MemoryPersistence.js.map +1 -1
- package/dist/persistence/PersistenceFactory.d.ts +1 -1
- package/dist/persistence/PersistenceFactory.d.ts.map +1 -1
- package/dist/persistence/PersistenceFactory.js.map +1 -1
- package/dist/persistence/SqlitePersistence.d.ts +1 -1
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/pool/ConnectionPool.d.ts +11 -13
- package/dist/pool/ConnectionPool.d.ts.map +1 -1
- package/dist/pool/ConnectionPool.js.map +1 -1
- package/dist/pool/IConnectionPool.d.ts +100 -0
- package/dist/pool/IConnectionPool.d.ts.map +1 -0
- package/dist/pool/IConnectionPool.js +1 -0
- package/dist/registry/BaseRegistry.d.ts +1 -1
- package/dist/registry/BaseRegistry.d.ts.map +1 -1
- package/dist/registry/BaseRegistry.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js.map +1 -1
- package/dist/transport/BaseTransport.d.ts +3 -2
- package/dist/transport/BaseTransport.d.ts.map +1 -1
- package/dist/transport/BaseTransport.js +1 -1
- package/dist/transport/BaseTransport.js.map +1 -1
- package/dist/transport/HttpTransport.d.ts +4 -2
- package/dist/transport/HttpTransport.d.ts.map +1 -1
- package/dist/transport/HttpTransport.js +4 -1
- package/dist/transport/HttpTransport.js.map +1 -1
- package/dist/transport/SseTransport.d.ts +4 -2
- package/dist/transport/SseTransport.d.ts.map +1 -1
- package/dist/transport/SseTransport.js +3 -0
- package/dist/transport/SseTransport.js.map +1 -1
- package/dist/transport/StreamableHttpTransport.d.ts +4 -2
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
- package/dist/transport/StreamableHttpTransport.js +4 -1
- package/dist/transport/StreamableHttpTransport.js.map +1 -1
- package/dist/types/skill.d.ts +5 -0
- package/dist/types/skill.d.ts.map +1 -1
- package/dist/types/tool.d.ts +5 -0
- package/dist/types/tool.d.ts.map +1 -1
- package/package.json +11 -11
- package/dist/__tests__/helpers/index.d.ts +0 -3
- package/dist/__tests__/helpers/index.d.ts.map +0 -1
- package/dist/contracts/index.d.ts +0 -14
- package/dist/contracts/index.d.ts.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -1
- package/dist/persistence/PersistenceBackend.d.ts.map +0 -1
- /package/dist/{persistence → contracts}/PersistenceBackend.d.ts +0 -0
- /package/dist/{persistence → contracts}/PersistenceBackend.js +0 -0
- /package/dist/contracts/{index.js → transport.js} +0 -0
package/README.md
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
# TraceLattice
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/tracelattice)
|
|
4
|
+
|
|
5
|
+
An MCP server that gives AI agents structured sequential thinking. Thoughts live in a DAG, reasoning strategies are pluggable, and confidence scores get calibrated against actual outcomes.
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
9
|
+
- 11 thought types: regular, hypothesis, verification, critique, synthesis, meta, tool_call, tool_observation, assumption, decomposition, backtrack
|
|
10
|
+
- DAG-based thought graph with 8 edge kinds (sequence, branch, merge, verifies, critiques, derives_from, tool_invocation, revises) and topological traversal
|
|
11
|
+
- Pluggable reasoning strategies. Sequential by default, or Tree-of-Thought with BFS/beam search and plateau detection
|
|
12
|
+
- Tool interleave: suspend a thinking chain, run a tool call, then resume where you left off
|
|
13
|
+
- Confidence calibration using Beta(2,2) priors, Brier score, and Expected Calibration Error (ECE)
|
|
14
|
+
- Branch compression: cold branches get rolled into summaries automatically, with a sliding-window dehydration policy
|
|
15
|
+
- Outcome recording for tool_call/tool_observation results with metadata
|
|
16
|
+
- Tool and skill recommendations with confidence scores, rationales, and automatic discovery
|
|
17
|
+
- Per-session isolation with TTL eviction and LRU caching
|
|
18
|
+
- Three transports: stdio (default), SSE (legacy), Streamable HTTP (production)
|
|
19
|
+
- Strict TypeScript, Valibot validation, 1913 tests, 18-service DI container
|
|
18
20
|
|
|
19
21
|
## Install
|
|
20
22
|
|
|
@@ -24,13 +26,13 @@ Requires [Node.js](https://nodejs.org/) v22+.
|
|
|
24
26
|
npm install -g tracelattice
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
## Configure MCP
|
|
29
|
+
## Configure your MCP client
|
|
28
30
|
|
|
29
|
-
The
|
|
31
|
+
The default transport is stdio. Add the server to your client:
|
|
30
32
|
|
|
31
33
|
### Claude Code
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
User-scoped (`~/.claude.json`) or project-scoped (`.mcp.json` in project root):
|
|
34
36
|
|
|
35
37
|
```json
|
|
36
38
|
{
|
|
@@ -50,7 +52,7 @@ claude mcp add tracelattice -- tracelattice
|
|
|
50
52
|
|
|
51
53
|
### Codex CLI
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
User-scoped (`~/.codex/config.toml`) or project-scoped (`.codex/config.toml`):
|
|
54
56
|
|
|
55
57
|
```toml
|
|
56
58
|
[mcp_servers.tracelattice]
|
|
@@ -65,7 +67,7 @@ codex mcp add tracelattice -- tracelattice
|
|
|
65
67
|
|
|
66
68
|
### OpenCode
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
Global (`~/.config/opencode/opencode.json`) or project-scoped (`.opencode.json`):
|
|
69
71
|
|
|
70
72
|
```json
|
|
71
73
|
{
|
|
@@ -81,8 +83,7 @@ codex mcp add tracelattice -- tracelattice
|
|
|
81
83
|
"environment": {
|
|
82
84
|
"MAX_HISTORY_SIZE": "10000"
|
|
83
85
|
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
+
}
|
|
86
87
|
}
|
|
87
88
|
```
|
|
88
89
|
|
|
@@ -98,7 +99,7 @@ codex mcp add tracelattice -- tracelattice
|
|
|
98
99
|
| `LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error` |
|
|
99
100
|
| `PRETTY_LOG` | `true` | Enable pretty log output |
|
|
100
101
|
|
|
101
|
-
### Feature
|
|
102
|
+
### Feature flags
|
|
102
103
|
|
|
103
104
|
All flags default to `false`. Set to `true` or `1` to enable.
|
|
104
105
|
|
|
@@ -129,7 +130,7 @@ All flags default to `false`. Set to `true` or `1` to enable.
|
|
|
129
130
|
| `ENABLE_CORS` | `true` | Enable CORS preflight |
|
|
130
131
|
| `ALLOWED_HOSTS` | (all) | Comma-separated allowed hosts |
|
|
131
132
|
|
|
132
|
-
### Skill
|
|
133
|
+
### Skill discovery
|
|
133
134
|
|
|
134
135
|
| Variable | Default | Description |
|
|
135
136
|
|----------|---------|-------------|
|
|
@@ -139,13 +140,14 @@ All flags default to `false`. Set to `true` or `1` to enable.
|
|
|
139
140
|
|
|
140
141
|
## Transports
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
Set `TRANSPORT_TYPE` to pick one:
|
|
143
144
|
|
|
144
|
-
| Transport |
|
|
145
|
-
|
|
145
|
+
| Transport | When to use | Command |
|
|
146
|
+
|-----------|-------------|---------|
|
|
146
147
|
| `stdio` (default) | Local MCP clients | `tracelattice` |
|
|
147
|
-
| `sse` (legacy) | Multi-user, backwards
|
|
148
|
+
| `sse` (legacy) | Multi-user setups, backwards compatibility | `TRANSPORT_TYPE=sse tracelattice` |
|
|
148
149
|
| `streamable-http` | Production deployments | `TRANSPORT_TYPE=streamable-http tracelattice` |
|
|
150
|
+
|
|
149
151
|
## Development
|
|
150
152
|
|
|
151
153
|
```bash
|
package/dist/ServerConfig.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module ServerConfig
|
|
9
9
|
*/
|
|
10
|
-
import type { PersistenceConfig } from './
|
|
10
|
+
import type { PersistenceConfig } from './contracts/PersistenceBackend.js';
|
|
11
11
|
/**
|
|
12
12
|
* Configuration options for creating a `ServerConfig` instance.
|
|
13
13
|
*
|
|
@@ -23,29 +23,7 @@ import type { PersistenceConfig } from './persistence/PersistenceBackend.js';
|
|
|
23
23
|
* };
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
|
|
27
|
-
* Feature flags for opt-in TraceLattice capabilities.
|
|
28
|
-
*
|
|
29
|
-
* All flags default to OFF so new features can be merged behind a flag
|
|
30
|
-
* without altering existing behavior. Flags are flat to keep env var
|
|
31
|
-
* mappings predictable (TRACELATTICE_FEATURES_*).
|
|
32
|
-
*/
|
|
33
|
-
export interface FeatureFlags {
|
|
34
|
-
/** Enable DAG edges between thoughts (Item #1). @default false */
|
|
35
|
-
dagEdges: boolean;
|
|
36
|
-
/** Reasoning strategy selector (Item #2). @default 'sequential' */
|
|
37
|
-
reasoningStrategy: 'sequential' | 'tot';
|
|
38
|
-
/** Enable confidence calibration (Item #3). @default false */
|
|
39
|
-
calibration: boolean;
|
|
40
|
-
/** Enable thought compression (Item #5). @default false */
|
|
41
|
-
compression: boolean;
|
|
42
|
-
/** Enable tool interleaving (Item #6). @default false */
|
|
43
|
-
toolInterleave: boolean;
|
|
44
|
-
/** Enable new thought types (Item #8). @default false */
|
|
45
|
-
newThoughtTypes: boolean;
|
|
46
|
-
/** Enable outcome recording (prereq for Item #10). @default false */
|
|
47
|
-
outcomeRecording: boolean;
|
|
48
|
-
}
|
|
26
|
+
import type { FeatureFlags } from './contracts/features.js';
|
|
49
27
|
export interface ServerConfigOptions {
|
|
50
28
|
/**
|
|
51
29
|
* Maximum number of thoughts to keep in history.
|
|
@@ -133,7 +111,7 @@ export interface ServerConfigOptions {
|
|
|
133
111
|
* ```typescript
|
|
134
112
|
* // Using defaults
|
|
135
113
|
* const config1 = new ServerConfig();
|
|
136
|
-
* console.log(config1.maxHistorySize); //
|
|
114
|
+
* console.log(config1.maxHistorySize); // 10000
|
|
137
115
|
*
|
|
138
116
|
* // With custom options
|
|
139
117
|
* const config2 = new ServerConfig({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerConfig.d.ts","sourceRoot":"","sources":["../src/ServerConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ServerConfig.d.ts","sourceRoot":"","sources":["../src/ServerConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAE3E;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,MAAM,WAAW,mBAAmB;IACnC;;;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,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE;QAChB;;;WAGG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;;WAGG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAElC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;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;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,YAAY;IACxB,qDAAqD;IAC9C,cAAc,EAAE,MAAM,CAAC;IAE9B,8CAA8C;IACvC,WAAW,EAAE,MAAM,CAAC;IAE3B,mCAAmC;IAC5B,aAAa,EAAE,MAAM,CAAC;IAE7B,4CAA4C;IACrC,SAAS,EAAE,MAAM,EAAE,CAAC;IAE3B,qCAAqC;IAC9B,cAAc,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAExD,iCAAiC;IAC1B,WAAW,EAAE,iBAAiB,CAAC;IAEtC,2EAA2E;IACpE,qBAAqB,EAAE,MAAM,CAAC;IAErC,qEAAqE;IAC9D,wBAAwB,EAAE,MAAM,CAAC;IAExC,gEAAgE;IACzD,qBAAqB,EAAE,MAAM,CAAC;IAErC,4BAA4B;IACrB,QAAQ,EAAE,YAAY,CAAC;IAE9B,iEAAiE;IAC1D,mBAAmB,EAAE,MAAM,CAAC;IAEnC,6EAA6E;IACtE,qBAAqB,EAAE,MAAM,CAAC;IAErC;;;;;;;;;;;;;;;OAeG;gBACS,OAAO,GAAE,mBAAwB;IAyB7C;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAe9B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAe7B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;;;;OAKG;IACH,OAAO,CAAC,6BAA6B;IAerC;;;;;OAKG;IACH,OAAO,CAAC,gCAAgC;IAiBxC;;;;;OAKG;IACH,OAAO,CAAC,6BAA6B;IAerC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;;;;;;;;;;;;;OAcG;IACI,MAAM,IAAI,mBAAmB;CAgBpC"}
|
package/dist/ServerConfig.js
CHANGED
|
@@ -29,7 +29,7 @@ class ServerConfig {
|
|
|
29
29
|
this.toolInterleaveSweepMs = this.validatePositiveMs(options.toolInterleaveSweepMs, 60000, 'toolInterleaveSweepMs');
|
|
30
30
|
}
|
|
31
31
|
validateMaxHistorySize(value) {
|
|
32
|
-
const defaultValue =
|
|
32
|
+
const defaultValue = 10000;
|
|
33
33
|
if (null == value) return defaultValue;
|
|
34
34
|
if ('number' != typeof value || !Number.isFinite(value)) throw new ConfigurationError(`maxHistorySize must be a finite number, got ${value}`);
|
|
35
35
|
if (value < 1) throw new ConfigurationError(`maxHistorySize must be at least 1, got ${value}`);
|
|
@@ -110,13 +110,13 @@ class ServerConfig {
|
|
|
110
110
|
}
|
|
111
111
|
validateFeatures(value) {
|
|
112
112
|
return {
|
|
113
|
-
dagEdges: value?.dagEdges ??
|
|
113
|
+
dagEdges: value?.dagEdges ?? true,
|
|
114
114
|
reasoningStrategy: value?.reasoningStrategy ?? 'sequential',
|
|
115
|
-
calibration: value?.calibration ??
|
|
116
|
-
compression: value?.compression ??
|
|
117
|
-
toolInterleave: value?.toolInterleave ??
|
|
118
|
-
newThoughtTypes: value?.newThoughtTypes ??
|
|
119
|
-
outcomeRecording: value?.outcomeRecording ??
|
|
115
|
+
calibration: value?.calibration ?? true,
|
|
116
|
+
compression: value?.compression ?? true,
|
|
117
|
+
toolInterleave: value?.toolInterleave ?? true,
|
|
118
|
+
newThoughtTypes: value?.newThoughtTypes ?? true,
|
|
119
|
+
outcomeRecording: value?.outcomeRecording ?? true
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
122
|
validatePositiveMs(value, defaultValue, fieldName) {
|
package/dist/ServerConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerConfig.js","sources":["../src/ServerConfig.ts"],"sourcesContent":["/**\n * Server configuration management with validation.\n *\n * This module provides the `ServerConfig` class which handles all server configuration\n * with built-in validation and sensible defaults. Configuration values are validated\n * on construction and warnings are emitted for out-of-range values.\n *\n * @module ServerConfig\n */\n\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { ConfigurationError } from './errors.js';\nimport type { PersistenceConfig } from './persistence/PersistenceBackend.js';\n\n/**\n * Configuration options for creating a `ServerConfig` instance.\n *\n * All properties are optional with sensible defaults applied during validation.\n *\n * @example\n * ```typescript\n * const options: ServerConfigOptions = {\n * maxHistorySize: 500,\n * maxBranches: 25,\n * skillDirs: ['./custom-skills'],\n * persistence: { enabled: true, backend: 'sqlite' }\n * };\n * ```\n */\n\n/**\n * Feature flags for opt-in TraceLattice capabilities.\n *\n * All flags default to OFF so new features can be merged behind a flag\n * without altering existing behavior. Flags are flat to keep env var\n * mappings predictable (TRACELATTICE_FEATURES_*).\n */\nexport interface FeatureFlags {\n\t/** Enable DAG edges between thoughts (Item #1). @default false */\n\tdagEdges: boolean;\n\t/** Reasoning strategy selector (Item #2). @default 'sequential' */\n\treasoningStrategy: 'sequential' | 'tot';\n\t/** Enable confidence calibration (Item #3). @default false */\n\tcalibration: boolean;\n\t/** Enable thought compression (Item #5). @default false */\n\tcompression: boolean;\n\t/** Enable tool interleaving (Item #6). @default false */\n\ttoolInterleave: boolean;\n\t/** Enable new thought types (Item #8). @default false */\n\tnewThoughtTypes: boolean;\n\t/** Enable outcome recording (prereq for Item #10). @default false */\n\toutcomeRecording: boolean;\n}\nexport interface ServerConfigOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * @default 1000\n\t */\n\tmaxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * @default 50\n\t */\n\tmaxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * @default 100\n\t */\n\tmaxBranchSize?: number;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * @default ['.claude/skills', '~/.claude/skills']\n\t */\n\tskillDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t */\n\tdiscoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * @default 300000 (5 minutes)\n\t\t */\n\t\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t * @default 100\n\t\t */\n\t\tmaxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\tpersistence?: PersistenceConfig;\n\n\t/**\n\t * Maximum number of thoughts to buffer before flushing to persistence.\n\t * @default 100\n\t */\n\tpersistenceBufferSize?: number;\n\n\t/**\n\t * Interval in milliseconds between periodic persistence flushes.\n\t * @default 1000\n\t */\n\tpersistenceFlushInterval?: number;\n\n\t/**\n\t * Maximum number of retries for failed persistence flushes.\n\t * @default 3\n\t */\n\tpersistenceMaxRetries?: number;\n\n\t/**\n\t * Feature flag overrides. Missing fields are filled with defaults (all OFF,\n\t * reasoningStrategy='sequential').\n\t */\n\tfeatures?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries in SuspensionStore.\n\t * @default 60000\n\t */\n\ttoolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * @default 60000\n\t */\n\ttoolInterleaveSweepMs?: number;\n}\n\n/**\n * Server configuration with validation and defaults.\n *\n * This class manages all server configuration including history limits,\n * branch limits, skill directories, discovery cache settings, and persistence.\n * All values are validated on construction with appropriate defaults applied.\n *\n * @remarks\n * - Values outside recommended ranges trigger warnings but are still applied\n * - Environment variables override file-based configuration\n * - The `toJSON()` method provides a plain object representation\n *\n * @example\n * ```typescript\n * // Using defaults\n * const config1 = new ServerConfig();\n * console.log(config1.maxHistorySize); // 1000\n *\n * // With custom options\n * const config2 = new ServerConfig({\n * maxHistorySize: 500,\n * persistence: { enabled: true, backend: 'file', options: { dataDir: './data' } }\n * });\n *\n * // Export as plain object\n * const json = config2.toJSON();\n * ```\n */\nexport class ServerConfig {\n\t/** Maximum number of thoughts to keep in history. */\n\tpublic maxHistorySize: number;\n\n\t/** Maximum number of branches to maintain. */\n\tpublic maxBranches: number;\n\n\t/** Maximum size of each branch. */\n\tpublic maxBranchSize: number;\n\n\t/** Directory paths to search for skills. */\n\tpublic skillDirs: string[];\n\n\t/** Discovery cache configuration. */\n\tpublic discoveryCache: { ttl: number; maxSize: number };\n\n\t/** Persistence configuration. */\n\tpublic persistence: PersistenceConfig;\n\n\t/** Maximum number of thoughts to buffer before flushing to persistence. */\n\tpublic persistenceBufferSize: number;\n\n\t/** Interval in milliseconds between periodic persistence flushes. */\n\tpublic persistenceFlushInterval: number;\n\n\t/** Maximum number of retries for failed persistence flushes. */\n\tpublic persistenceMaxRetries: number;\n\n\t/** Feature flag toggles. */\n\tpublic features: FeatureFlags;\n\n\t/** TTL in milliseconds for suspended tool-interleave entries. */\n\tpublic toolInterleaveTtlMs: number;\n\n\t/** Sweep interval in milliseconds for SuspensionStore expiration cleanup. */\n\tpublic toolInterleaveSweepMs: number;\n\n\t/**\n\t * Creates a new ServerConfig instance with validation.\n\t *\n\t * All values are validated and defaults are applied for undefined options.\n\t * Warnings are emitted to console for values outside recommended ranges.\n\t *\n\t * @param options - Optional configuration overrides\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({\n\t * maxHistorySize: 500,\n\t * skillDirs: ['./my-skills']\n\t * });\n\t * ```\n\t */\n\tconstructor(options: ServerConfigOptions = {}) {\n\t\tthis.maxHistorySize = this.validateMaxHistorySize(options.maxHistorySize);\n\t\tthis.maxBranches = this.validateMaxBranches(options.maxBranches);\n\t\tthis.maxBranchSize = this.validateMaxBranchSize(options.maxBranchSize);\n\t\tthis.skillDirs = this.validateSkillDirs(options.skillDirs);\n\t\tthis.discoveryCache = this.validateDiscoveryCache(options.discoveryCache);\n\t\tthis.persistence = this.validatePersistence(options.persistence);\n\t\tthis.persistenceBufferSize = this.validatePersistenceBufferSize(options.persistenceBufferSize);\n\t\tthis.persistenceFlushInterval = this.validatePersistenceFlushInterval(\n\t\t\toptions.persistenceFlushInterval\n\t\t);\n\t\tthis.persistenceMaxRetries = this.validatePersistenceMaxRetries(options.persistenceMaxRetries);\n\t\tthis.features = this.validateFeatures(options.features);\n\t\tthis.toolInterleaveTtlMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveTtlMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveTtlMs'\n\t\t);\n\t\tthis.toolInterleaveSweepMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveSweepMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveSweepMs'\n\t\t);\n\t}\n\n\t/**\n\t * Validates the max history size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validateMaxHistorySize(value?: number): number {\n\t\tconst defaultValue = 1000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branches value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (50)\n\t * @private\n\t */\n\tprivate validateMaxBranches(value?: number): number {\n\t\tconst defaultValue = 50;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranches must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branch size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validateMaxBranchSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the skill directories value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default ['.claude/skills', '~/.claude/skills']\n\t * @private\n\t */\n\tprivate validateSkillDirs(value?: string[]): string[] {\n\t\tconst defaultValue = ['.claude/skills', join(homedir(), '.claude/skills')];\n\t\tif (!value) return defaultValue;\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the discovery cache configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validateDiscoveryCache(value?: { ttl?: number; maxSize?: number }): {\n\t\tttl: number;\n\t\tmaxSize: number;\n\t} {\n\t\treturn {\n\t\t\tttl: value?.ttl ?? 300000,\n\t\t\tmaxSize: value?.maxSize ?? 100,\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validatePersistence(value?: PersistenceConfig): PersistenceConfig {\n\t\tif (!value) {\n\t\t\t// Default to in-memory (no actual persistence, just consistency)\n\t\t\treturn {\n\t\t\t\tenabled: false,\n\t\t\t\tbackend: 'memory',\n\t\t\t};\n\t\t}\n\n\t\t// Validate backend type\n\t\tconst validBackends = ['file', 'sqlite', 'memory'];\n\t\tconst backend = value.backend ?? 'memory';\n\t\tif (!validBackends.includes(backend)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistence.backend must be one of ${validBackends.join(', ')}, got ${backend}`\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tenabled: value.enabled ?? false,\n\t\t\tbackend,\n\t\t\toptions: value.options ?? {},\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence buffer size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validatePersistenceBufferSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence flush interval value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validatePersistenceFlushInterval(value?: number): number {\n\t\tconst defaultValue = 1000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistenceFlushInterval must be a finite number, got ${value}`\n\t\t\t);\n\t\t}\n\t\tif (value < 100) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must be at least 100, got ${value}`);\n\t\t}\n\t\tif (value > 60000) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must not exceed 60000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence max retries value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (3)\n\t * @private\n\t */\n\tprivate validatePersistenceMaxRetries(value?: number): number {\n\t\tconst defaultValue = 3;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 10) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must not exceed 10, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates feature flags and fills defaults for missing fields.\n\t * @param value - Partial feature flag overrides\n\t * @returns Fully populated FeatureFlags with defaults applied\n\t * @private\n\t */\n\tprivate validateFeatures(value?: Partial<FeatureFlags>): FeatureFlags {\n\t\treturn {\n\t\t\tdagEdges: value?.dagEdges ?? false,\n\t\t\treasoningStrategy: value?.reasoningStrategy ?? 'sequential',\n\t\t\tcalibration: value?.calibration ?? false,\n\t\t\tcompression: value?.compression ?? false,\n\t\t\ttoolInterleave: value?.toolInterleave ?? false,\n\t\t\tnewThoughtTypes: value?.newThoughtTypes ?? false,\n\t\t\toutcomeRecording: value?.outcomeRecording ?? false,\n\t\t};\n\t}\n\n\t/**\n\t * Validates a positive millisecond value with a default fallback.\n\t * @param value - The value to validate\n\t * @param defaultValue - Default applied if value is undefined/null\n\t * @param fieldName - Field name for error messages\n\t * @returns The validated millisecond value\n\t * @private\n\t */\n\tprivate validatePositiveMs(\n\t\tvalue: number | undefined,\n\t\tdefaultValue: number,\n\t\tfieldName: string\n\t): number {\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be at least 1, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Converts the configuration to a plain object.\n\t *\n\t * Useful for serialization, logging, or when a plain object representation\n\t * is preferred over the ServerConfig instance.\n\t *\n\t * @returns A plain object representation of the configuration\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({ maxHistorySize: 500 });\n\t * const json = config.toJSON();\n\t * console.log(JSON.stringify(json, null, 2));\n\t * ```\n\t */\n\tpublic toJSON(): ServerConfigOptions {\n\t\treturn {\n\t\t\tmaxHistorySize: this.maxHistorySize,\n\t\t\tmaxBranches: this.maxBranches,\n\t\t\tmaxBranchSize: this.maxBranchSize,\n\t\t\tskillDirs: this.skillDirs,\n\t\t\tdiscoveryCache: this.discoveryCache,\n\t\t\tpersistence: this.persistence,\n\t\t\tpersistenceBufferSize: this.persistenceBufferSize,\n\t\t\tpersistenceFlushInterval: this.persistenceFlushInterval,\n\t\t\tpersistenceMaxRetries: this.persistenceMaxRetries,\n\t\t\tfeatures: this.features,\n\t\t\ttoolInterleaveTtlMs: this.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: this.toolInterleaveSweepMs,\n\t\t};\n\t}\n}\n"],"names":["ServerConfig","options","value","defaultValue","Number","ConfigurationError","join","homedir","validBackends","backend","fieldName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ServerConfig.js","sources":["../src/ServerConfig.ts"],"sourcesContent":["/**\n * Server configuration management with validation.\n *\n * This module provides the `ServerConfig` class which handles all server configuration\n * with built-in validation and sensible defaults. Configuration values are validated\n * on construction and warnings are emitted for out-of-range values.\n *\n * @module ServerConfig\n */\n\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { ConfigurationError } from './errors.js';\nimport type { PersistenceConfig } from './contracts/PersistenceBackend.js';\n\n/**\n * Configuration options for creating a `ServerConfig` instance.\n *\n * All properties are optional with sensible defaults applied during validation.\n *\n * @example\n * ```typescript\n * const options: ServerConfigOptions = {\n * maxHistorySize: 500,\n * maxBranches: 25,\n * skillDirs: ['./custom-skills'],\n * persistence: { enabled: true, backend: 'sqlite' }\n * };\n * ```\n */\n\nimport type { FeatureFlags } from './contracts/features.js';\nexport interface ServerConfigOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * @default 1000\n\t */\n\tmaxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * @default 50\n\t */\n\tmaxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * @default 100\n\t */\n\tmaxBranchSize?: number;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * @default ['.claude/skills', '~/.claude/skills']\n\t */\n\tskillDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t */\n\tdiscoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * @default 300000 (5 minutes)\n\t\t */\n\t\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t * @default 100\n\t\t */\n\t\tmaxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\tpersistence?: PersistenceConfig;\n\n\t/**\n\t * Maximum number of thoughts to buffer before flushing to persistence.\n\t * @default 100\n\t */\n\tpersistenceBufferSize?: number;\n\n\t/**\n\t * Interval in milliseconds between periodic persistence flushes.\n\t * @default 1000\n\t */\n\tpersistenceFlushInterval?: number;\n\n\t/**\n\t * Maximum number of retries for failed persistence flushes.\n\t * @default 3\n\t */\n\tpersistenceMaxRetries?: number;\n\n\t/**\n\t * Feature flag overrides. Missing fields are filled with defaults (all OFF,\n\t * reasoningStrategy='sequential').\n\t */\n\tfeatures?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries in SuspensionStore.\n\t * @default 60000\n\t */\n\ttoolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * @default 60000\n\t */\n\ttoolInterleaveSweepMs?: number;\n}\n\n/**\n * Server configuration with validation and defaults.\n *\n * This class manages all server configuration including history limits,\n * branch limits, skill directories, discovery cache settings, and persistence.\n * All values are validated on construction with appropriate defaults applied.\n *\n * @remarks\n * - Values outside recommended ranges trigger warnings but are still applied\n * - Environment variables override file-based configuration\n * - The `toJSON()` method provides a plain object representation\n *\n * @example\n * ```typescript\n * // Using defaults\n * const config1 = new ServerConfig();\n * console.log(config1.maxHistorySize); // 10000\n *\n * // With custom options\n * const config2 = new ServerConfig({\n * maxHistorySize: 500,\n * persistence: { enabled: true, backend: 'file', options: { dataDir: './data' } }\n * });\n *\n * // Export as plain object\n * const json = config2.toJSON();\n * ```\n */\nexport class ServerConfig {\n\t/** Maximum number of thoughts to keep in history. */\n\tpublic maxHistorySize: number;\n\n\t/** Maximum number of branches to maintain. */\n\tpublic maxBranches: number;\n\n\t/** Maximum size of each branch. */\n\tpublic maxBranchSize: number;\n\n\t/** Directory paths to search for skills. */\n\tpublic skillDirs: string[];\n\n\t/** Discovery cache configuration. */\n\tpublic discoveryCache: { ttl: number; maxSize: number };\n\n\t/** Persistence configuration. */\n\tpublic persistence: PersistenceConfig;\n\n\t/** Maximum number of thoughts to buffer before flushing to persistence. */\n\tpublic persistenceBufferSize: number;\n\n\t/** Interval in milliseconds between periodic persistence flushes. */\n\tpublic persistenceFlushInterval: number;\n\n\t/** Maximum number of retries for failed persistence flushes. */\n\tpublic persistenceMaxRetries: number;\n\n\t/** Feature flag toggles. */\n\tpublic features: FeatureFlags;\n\n\t/** TTL in milliseconds for suspended tool-interleave entries. */\n\tpublic toolInterleaveTtlMs: number;\n\n\t/** Sweep interval in milliseconds for SuspensionStore expiration cleanup. */\n\tpublic toolInterleaveSweepMs: number;\n\n\t/**\n\t * Creates a new ServerConfig instance with validation.\n\t *\n\t * All values are validated and defaults are applied for undefined options.\n\t * Warnings are emitted to console for values outside recommended ranges.\n\t *\n\t * @param options - Optional configuration overrides\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({\n\t * maxHistorySize: 500,\n\t * skillDirs: ['./my-skills']\n\t * });\n\t * ```\n\t */\n\tconstructor(options: ServerConfigOptions = {}) {\n\t\tthis.maxHistorySize = this.validateMaxHistorySize(options.maxHistorySize);\n\t\tthis.maxBranches = this.validateMaxBranches(options.maxBranches);\n\t\tthis.maxBranchSize = this.validateMaxBranchSize(options.maxBranchSize);\n\t\tthis.skillDirs = this.validateSkillDirs(options.skillDirs);\n\t\tthis.discoveryCache = this.validateDiscoveryCache(options.discoveryCache);\n\t\tthis.persistence = this.validatePersistence(options.persistence);\n\t\tthis.persistenceBufferSize = this.validatePersistenceBufferSize(options.persistenceBufferSize);\n\t\tthis.persistenceFlushInterval = this.validatePersistenceFlushInterval(\n\t\t\toptions.persistenceFlushInterval\n\t\t);\n\t\tthis.persistenceMaxRetries = this.validatePersistenceMaxRetries(options.persistenceMaxRetries);\n\t\tthis.features = this.validateFeatures(options.features);\n\t\tthis.toolInterleaveTtlMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveTtlMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveTtlMs'\n\t\t);\n\t\tthis.toolInterleaveSweepMs = this.validatePositiveMs(\n\t\t\toptions.toolInterleaveSweepMs,\n\t\t\t60000,\n\t\t\t'toolInterleaveSweepMs'\n\t\t);\n\t}\n\n\t/**\n\t * Validates the max history size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validateMaxHistorySize(value?: number): number {\n\t\tconst defaultValue = 10000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`maxHistorySize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branches value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (50)\n\t * @private\n\t */\n\tprivate validateMaxBranches(value?: number): number {\n\t\tconst defaultValue = 50;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`maxBranches must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranches must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the max branch size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validateMaxBranchSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 1000) {\n\t\t\tthrow new ConfigurationError(`maxBranchSize must not exceed 1000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the skill directories value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default ['.claude/skills', '~/.claude/skills']\n\t * @private\n\t */\n\tprivate validateSkillDirs(value?: string[]): string[] {\n\t\tconst defaultValue = ['.claude/skills', join(homedir(), '.claude/skills')];\n\t\tif (!value) return defaultValue;\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the discovery cache configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validateDiscoveryCache(value?: { ttl?: number; maxSize?: number }): {\n\t\tttl: number;\n\t\tmaxSize: number;\n\t} {\n\t\treturn {\n\t\t\tttl: value?.ttl ?? 300000,\n\t\t\tmaxSize: value?.maxSize ?? 100,\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence configuration.\n\t * @param value - The value to validate\n\t * @returns The validated value with defaults applied\n\t * @private\n\t */\n\tprivate validatePersistence(value?: PersistenceConfig): PersistenceConfig {\n\t\tif (!value) {\n\t\t\t// Default to in-memory (no actual persistence, just consistency)\n\t\t\treturn {\n\t\t\t\tenabled: false,\n\t\t\t\tbackend: 'memory',\n\t\t\t};\n\t\t}\n\n\t\t// Validate backend type\n\t\tconst validBackends = ['file', 'sqlite', 'memory'];\n\t\tconst backend = value.backend ?? 'memory';\n\t\tif (!validBackends.includes(backend)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistence.backend must be one of ${validBackends.join(', ')}, got ${backend}`\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tenabled: value.enabled ?? false,\n\t\t\tbackend,\n\t\t\toptions: value.options ?? {},\n\t\t};\n\t}\n\n\t/**\n\t * Validates the persistence buffer size value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (100)\n\t * @private\n\t */\n\tprivate validatePersistenceBufferSize(value?: number): number {\n\t\tconst defaultValue = 100;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must be at least 1, got ${value}`);\n\t\t}\n\t\tif (value > 10000) {\n\t\t\tthrow new ConfigurationError(`persistenceBufferSize must not exceed 10000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence flush interval value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (1000)\n\t * @private\n\t */\n\tprivate validatePersistenceFlushInterval(value?: number): number {\n\t\tconst defaultValue = 1000;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(\n\t\t\t\t`persistenceFlushInterval must be a finite number, got ${value}`\n\t\t\t);\n\t\t}\n\t\tif (value < 100) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must be at least 100, got ${value}`);\n\t\t}\n\t\tif (value > 60000) {\n\t\t\tthrow new ConfigurationError(`persistenceFlushInterval must not exceed 60000, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates the persistence max retries value.\n\t * @param value - The value to validate\n\t * @returns The validated value or default (3)\n\t * @private\n\t */\n\tprivate validatePersistenceMaxRetries(value?: number): number {\n\t\tconst defaultValue = 3;\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 0) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must be non-negative, got ${value}`);\n\t\t}\n\t\tif (value > 10) {\n\t\t\tthrow new ConfigurationError(`persistenceMaxRetries must not exceed 10, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Validates feature flags and fills defaults for missing fields.\n\t * @param value - Partial feature flag overrides\n\t * @returns Fully populated FeatureFlags with defaults applied\n\t * @private\n\t */\n\tprivate validateFeatures(value?: Partial<FeatureFlags>): FeatureFlags {\n\t\treturn {\n\t\t\tdagEdges: value?.dagEdges ?? true,\n\t\t\treasoningStrategy: value?.reasoningStrategy ?? 'sequential',\n\t\t\tcalibration: value?.calibration ?? true,\n\t\t\tcompression: value?.compression ?? true,\n\t\t\ttoolInterleave: value?.toolInterleave ?? true,\n\t\t\tnewThoughtTypes: value?.newThoughtTypes ?? true,\n\t\t\toutcomeRecording: value?.outcomeRecording ?? true,\n\t\t};\n\t}\n\n\t/**\n\t * Validates a positive millisecond value with a default fallback.\n\t * @param value - The value to validate\n\t * @param defaultValue - Default applied if value is undefined/null\n\t * @param fieldName - Field name for error messages\n\t * @returns The validated millisecond value\n\t * @private\n\t */\n\tprivate validatePositiveMs(\n\t\tvalue: number | undefined,\n\t\tdefaultValue: number,\n\t\tfieldName: string\n\t): number {\n\t\tif (value === undefined || value === null) return defaultValue;\n\t\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be a finite number, got ${value}`);\n\t\t}\n\t\tif (value < 1) {\n\t\t\tthrow new ConfigurationError(`${fieldName} must be at least 1, got ${value}`);\n\t\t}\n\t\treturn value;\n\t}\n\n\t/**\n\t * Converts the configuration to a plain object.\n\t *\n\t * Useful for serialization, logging, or when a plain object representation\n\t * is preferred over the ServerConfig instance.\n\t *\n\t * @returns A plain object representation of the configuration\n\t *\n\t * @example\n\t * ```typescript\n\t * const config = new ServerConfig({ maxHistorySize: 500 });\n\t * const json = config.toJSON();\n\t * console.log(JSON.stringify(json, null, 2));\n\t * ```\n\t */\n\tpublic toJSON(): ServerConfigOptions {\n\t\treturn {\n\t\t\tmaxHistorySize: this.maxHistorySize,\n\t\t\tmaxBranches: this.maxBranches,\n\t\t\tmaxBranchSize: this.maxBranchSize,\n\t\t\tskillDirs: this.skillDirs,\n\t\t\tdiscoveryCache: this.discoveryCache,\n\t\t\tpersistence: this.persistence,\n\t\t\tpersistenceBufferSize: this.persistenceBufferSize,\n\t\t\tpersistenceFlushInterval: this.persistenceFlushInterval,\n\t\t\tpersistenceMaxRetries: this.persistenceMaxRetries,\n\t\t\tfeatures: this.features,\n\t\t\ttoolInterleaveTtlMs: this.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: this.toolInterleaveSweepMs,\n\t\t};\n\t}\n}\n"],"names":["ServerConfig","options","value","defaultValue","Number","ConfigurationError","join","homedir","validBackends","backend","fieldName"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenarios.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/eval/fixtures/scenarios.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"scenarios.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/eval/fixtures/scenarios.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAG5D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,8DAA8D;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAChE;AA+BD,uCAAuC;AACvC,eAAO,MAAM,SAAS,EAAE,SAAS,YAAY,EA8F5C,CAAC"}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { ThoughtData } from '../../core/thought.js';
|
|
2
|
+
import { type SessionId, type ThoughtId, type EdgeId, type SuspensionToken } from '../../contracts/ids.js';
|
|
2
3
|
import type { ToolRecommendation } from '../../types/tool.js';
|
|
3
4
|
import type { SkillRecommendation } from '../../types/skill.js';
|
|
4
5
|
import type { StepRecommendation } from '../../core/step.js';
|
|
5
6
|
import type { IHistoryManager } from '../../core/IHistoryManager.js';
|
|
6
7
|
import type { ThoughtFormatter } from '../../core/ThoughtFormatter.js';
|
|
7
|
-
export declare function
|
|
8
|
+
export declare function createTestSessionId(value?: string): SessionId;
|
|
9
|
+
export declare function createTestThoughtId(value?: string): ThoughtId;
|
|
10
|
+
export declare function createTestEdgeId(value?: string): EdgeId;
|
|
11
|
+
export declare function createTestSuspensionToken(value?: string): SuspensionToken;
|
|
12
|
+
type ThoughtOverrides = Partial<Omit<ThoughtData, 'id' | 'session_id' | 'continuation_token'>> & {
|
|
13
|
+
id?: string;
|
|
14
|
+
session_id?: string;
|
|
15
|
+
continuation_token?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function createTestThought(overrides?: ThoughtOverrides): ThoughtData;
|
|
8
18
|
export declare function createToolRecommendation(overrides?: Partial<ToolRecommendation>): ToolRecommendation;
|
|
9
19
|
export declare function createSkillRecommendation(overrides?: Partial<SkillRecommendation>): SkillRecommendation;
|
|
10
20
|
export declare function createStepRecommendation(overrides?: Partial<StepRecommendation>): StepRecommendation;
|
|
@@ -33,6 +43,8 @@ export declare class MockHistoryManager implements IHistoryManager {
|
|
|
33
43
|
getClearCallCount(): number;
|
|
34
44
|
getAvailableMcpTools(sessionId?: string): string[] | undefined;
|
|
35
45
|
getAvailableSkills(sessionId?: string): string[] | undefined;
|
|
46
|
+
getEdgeStore(): undefined;
|
|
36
47
|
}
|
|
37
48
|
export declare function createMockFormatter(): Pick<ThoughtFormatter, 'formatThought'>;
|
|
49
|
+
export {};
|
|
38
50
|
//# sourceMappingURL=factories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/factories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAIvE,wBAAgB,
|
|
1
|
+
{"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/factories.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscoveryCache.d.ts","sourceRoot":"","sources":["../../src/cache/DiscoveryCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"DiscoveryCache.d.ts","sourceRoot":"","sources":["../../src/cache/DiscoveryCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE3D;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,6BAA6B;IAC7B,IAAI,EAAE,CAAC,EAAE,CAAC;IAEV,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAElB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,qBAAa,cAAc,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,OAAO,CAAC,MAAM,CAA6B;IAE3C,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAS;IAEzB,sDAAsD;IACtD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,aAAa,CAA+B;IAEpD;;;;;;;;;;;;;;;;OAgBG;gBACS,OAAO,GAAE,qBAA0B;IAc/C,OAAO,CAAC,eAAe;IAWvB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI;IA8B5B;;;;;;;;;;;;;;;OAeG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI;IAuBjC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQzB;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B;;;;;;;;;;OAUG;IACH,KAAK,IAAI,IAAI;IAIb,OAAO,IAAI,IAAI;IAOf;;;;;;;;;;;;OAYG;IACH,IAAI,IAAI,MAAM;IAId;;;;;;;;;;;;;;OAcG;IACH,QAAQ,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE;CAM5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache/DiscoveryCache.js","sources":["../../src/cache/DiscoveryCache.ts"],"sourcesContent":["import type { IMetrics } from '../contracts/index.js';\n\n/**\n * LRU Cache for tool/skill discovery results with TTL support.\n *\n * This module provides a generic Least Recently Used (LRU) cache with time-to-live\n * (TTL) support. It's designed to cache discovery results to avoid repeated expensive\n * operations like filesystem scanning.\n *\n * @module cache\n */\n\n/**\n * A cache entry containing data and metadata for LRU tracking.\n *\n * @template T - The type of data being cached (typically Tool or Skill)\n *\n * @example\n * ```typescript\n * const entry: CacheEntry<string> = {\n * data: ['tool1', 'tool2'],\n * timestamp: 1705550000000,\n * accessCount: 5\n * };\n * ```\n */\nexport interface CacheEntry<T> {\n\t/** The cached data array. */\n\tdata: T[];\n\n\t/** Unix timestamp (milliseconds) when the entry was created/last accessed. */\n\ttimestamp: number;\n\n\t/** Number of times this entry has been accessed (for LRU tracking). */\n\taccessCount: number;\n}\n\n/**\n * Configuration options for creating a `DiscoveryCache` instance.\n *\n * @example\n * ```typescript\n * const options: DiscoveryCacheOptions = {\n * maxSize: 200,\n * ttl: 600000 // 10 minutes\n * };\n * ```\n */\nexport interface DiscoveryCacheOptions {\n\t/**\n\t * Maximum number of cache entries before LRU eviction begins.\n\t * @default 100\n\t */\n\tmaxSize?: number;\n\n\t/**\n\t * Time-to-live for cache entries in milliseconds.\n\t * Entries older than this are considered expired.\n\t * @default 300000 (5 minutes)\n\t */\n\tttl?: number;\n\n\tcleanupInterval?: number;\n\tmetrics?: IMetrics;\n}\n\n/**\n * LRU (Least Recently Used) cache with TTL support for caching discovery results.\n *\n * This cache implements an LRU eviction policy where entries that haven't been\n * accessed recently are removed first when the cache reaches maximum capacity.\n * Additionally, entries expire after a configurable TTL period.\n *\n * @remarks\n * **Eviction Policy:**\n * - When `maxSize` is reached, the least recently used entry is removed\n * - An entry's \"recent use\" is tracked by its position in the underlying Map\n * - Accessing an entry moves it to the \"most recently used\" position\n * - Setting an existing key also updates its position\n *\n * **Expiration:**\n * - Entries older than `ttl` milliseconds are automatically removed on access\n * - Expiration is checked lazily (when `get()` or `has()` is called)\n *\n * **Thread Safety:**\n * - This implementation is not thread-safe and should not be shared\n * across asynchronous operations without proper synchronization\n *\n * @template T - The type of data being cached\n *\n * @example\n * ```typescript\n * const cache = new DiscoveryCache<string>({\n * maxSize: 100,\n * ttl: 300000 // 5 minutes\n * });\n *\n * // Store discovery results\n * cache.set('.claude/skills', ['commit', 'pdf', 'test']);\n *\n * // Retrieve from cache\n * const skills = cache.get('.claude/skills');\n * if (skills) {\n * console.log('Cached skills:', skills);\n * } else {\n * console.log('Not cached or expired');\n * }\n *\n * // Check if cached and valid\n * if (cache.has('.claude/skills')) {\n * console.log('Skills are cached and fresh');\n * }\n *\n * // Manually invalidate\n * cache.invalidate('.claude/skills');\n *\n * // Clear all cache\n * cache.clear();\n *\n * // Get statistics\n * const stats = cache.getStats();\n * console.log(`Cache size: ${stats.size}, keys: ${stats.keys.join(', ')}`);\n * ```\n */\nexport class DiscoveryCache<T> {\n\t/** Internal Map storing cache entries. Insertion order tracks LRU status. */\n\tprivate _cache: Map<string, CacheEntry<T>>;\n\n\t/** Maximum number of entries before eviction begins. */\n\tprivate _maxSize: number;\n\n\t/** Time-to-live in milliseconds for cache entries. */\n\tprivate _ttl: number;\n\tprivate _metrics?: IMetrics;\n\tprivate _cleanupTimer: NodeJS.Timeout | null = null;\n\n\t/**\n\t * Creates a new DiscoveryCache instance.\n\t *\n\t * @param options - Configuration options for the cache\n\t *\n\t * @example\n\t * ```typescript\n\t * // Default configuration (100 entries, 5 minute TTL)\n\t * const cache1 = new DiscoveryCache();\n\t *\n\t * // Custom configuration\n\t * const cache2 = new DiscoveryCache({\n\t * maxSize: 200,\n\t * ttl: 600000 // 10 minutes\n\t * });\n\t * ```\n\t */\n\tconstructor(options: DiscoveryCacheOptions = {}) {\n\t\tthis._cache = new Map();\n\t\tthis._maxSize = options.maxSize ?? 100;\n\t\tthis._ttl = options.ttl ?? 300000; // 5 minutes default\n\t\tthis._metrics = options.metrics;\n\n\t\tif (options.cleanupInterval && options.cleanupInterval > 0) {\n\t\t\tthis._cleanupTimer = setInterval(() => {\n\t\t\t\tthis._cleanupExpired();\n\t\t\t}, options.cleanupInterval);\n\t\t\tif (this._cleanupTimer.unref) this._cleanupTimer.unref();\n\t\t}\n\t}\n\n\tprivate _cleanupExpired(): void {\n\t\tconst now = Date.now();\n\t\tfor (const [key, entry] of this._cache.entries()) {\n\t\t\tconst age = now - entry.timestamp;\n\t\t\tif (age > this._ttl) {\n\t\t\t\tthis._cache.delete(key);\n\t\t\t\tthis._metrics?.counter('cache_eviction_total', 1, { cause: 'ttl_cleanup' });\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves a value from the cache by key.\n\t *\n\t * Returns the cached data if the key exists and the entry hasn't expired.\n\t * Updates the entry's access time and moves it to the most-recently-used position.\n\t * Returns null if the key doesn't exist or the entry has expired (expired entries\n\t * are automatically deleted).\n\t *\n\t * @param key - The cache key to retrieve\n\t * @returns The cached data array, or null if not found or expired\n\t *\n\t * @example\n\t * ```typescript\n\t * const tools = cache.get('/path/to/tools');\n\t * if (tools) {\n\t * console.log('Found cached tools:', tools);\n\t * } else {\n\t * console.log('Tools not cached or expired, need to discover');\n\t * }\n\t * ```\n\t */\n\tget(key: string): T[] | null {\n\t\tconst entry = this._cache.get(key);\n\t\tif (!entry) {\n\t\t\tthis._metrics?.counter('cache_miss_total', 1, {}, 'Total discovery cache misses');\n\t\t\treturn null;\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst age = now - entry.timestamp;\n\n\t\t// Check TTL\n\t\tif (age > this._ttl) {\n\t\t\tthis._cache.delete(key);\n\t\t\tthis._metrics?.counter('cache_eviction_total', 1, { cause: 'ttl' }, 'Total cache evictions');\n\t\t\tthis._metrics?.counter('cache_miss_total', 1, {}, 'Total discovery cache misses');\n\t\t\treturn null;\n\t\t}\n\n\t\t// Update access metadata for LRU\n\t\tentry.accessCount++;\n\t\tentry.timestamp = now;\n\n\t\t// Move to end (most recently used)\n\t\tthis._cache.delete(key);\n\t\tthis._cache.set(key, entry);\n\t\tthis._metrics?.counter('cache_hit_total', 1, {}, 'Total discovery cache hits');\n\n\t\treturn entry.data;\n\t}\n\n\t/**\n\t * Stores a value in the cache with the given key.\n\t *\n\t * If the cache is at maximum capacity and this is a new key, the least\n\t * recently used entry is evicted before storing the new value. If the key\n\t * already exists, its value and access time are updated.\n\t *\n\t * @param key - The cache key to store under\n\t * @param data - The data array to cache\n\t *\n\t * @example\n\t * ```typescript\n\t * const discoveredTools = ['Read', 'Write', 'Bash', 'Grep'];\n\t * cache.set('/usr/local/tools', discoveredTools);\n\t * ```\n\t */\n\tset(key: string, data: T[]): void {\n\t\t// Enforce max size with LRU eviction\n\t\tif (this._cache.size >= this._maxSize && !this._cache.has(key)) {\n\t\t\t// Remove least recently used (first entry)\n\t\t\tconst lruKey = this._cache.keys().next().value;\n\t\t\tif (lruKey) {\n\t\t\t\tthis._cache.delete(lruKey);\n\t\t\t\tthis._metrics?.counter(\n\t\t\t\t\t'cache_eviction_total',\n\t\t\t\t\t1,\n\t\t\t\t\t{ cause: 'lru' },\n\t\t\t\t\t'Total cache evictions'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._cache.set(key, {\n\t\t\tdata,\n\t\t\ttimestamp: Date.now(),\n\t\t\taccessCount: 0,\n\t\t});\n\t}\n\n\t/**\n\t * Checks if a key exists in the cache and hasn't expired.\n\t *\n\t * Returns true only if the key exists and the entry is within its TTL.\n\t * Expired entries are not automatically removed by this method (use `get()`\n\t * for automatic expiration cleanup).\n\t *\n\t * @param key - The cache key to check\n\t * @returns true if the key exists and hasn't expired, false otherwise\n\t *\n\t * @example\n\t * ```typescript\n\t * if (cache.has('/path/to/skills')) {\n\t * // Key exists and is fresh\n\t * const skills = cache.get('/path/to/skills')!;\n\t * } else {\n\t * // Need to discover skills\n\t * }\n\t * ```\n\t */\n\thas(key: string): boolean {\n\t\tconst entry = this._cache.get(key);\n\t\tif (!entry) return false;\n\n\t\tconst age = Date.now() - entry.timestamp;\n\t\treturn age <= this._ttl;\n\t}\n\n\t/**\n\t * Removes a specific entry from the cache.\n\t *\n\t * This is useful for explicit invalidation when cached data is known\n\t * to be stale due to external changes.\n\t *\n\t * @param key - The cache key to invalidate\n\t *\n\t * @example\n\t * ```typescript\n\t * // Invalidate cache when files change\n\t * watcher.on('change', (path) => {\n\t * cache.invalidate(path);\n\t * });\n\t * ```\n\t */\n\tinvalidate(key: string): void {\n\t\tthis._cache.delete(key);\n\t}\n\n\t/**\n\t * Removes all entries from the cache.\n\t *\n\t * This completely resets the cache to an empty state.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Clear cache before running tests\n\t * cache.clear();\n\t * ```\n\t */\n\tclear(): void {\n\t\tthis._cache.clear();\n\t}\n\n\tdispose(): void {\n\t\tif (this._cleanupTimer) {\n\t\t\tclearInterval(this._cleanupTimer);\n\t\t\tthis._cleanupTimer = null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the current number of entries in the cache.\n\t *\n\t * @returns The number of cached entries\n\t *\n\t * @example\n\t * ```typescript\n\t * console.log(`Cache contains ${cache.size()} entries`);\n\t * if (cache.size() >= maxSize) {\n\t * console.log('Cache is at capacity');\n\t * }\n\t * ```\n\t */\n\tsize(): number {\n\t\treturn this._cache.size;\n\t}\n\n\t/**\n\t * Gets cache statistics including size and all cached keys.\n\t *\n\t * Useful for monitoring and debugging cache behavior.\n\t *\n\t * @returns An object with cache size and array of all keys\n\t *\n\t * @example\n\t * ```typescript\n\t * const stats = cache.getStats();\n\t * console.log(`Cache stats:`);\n\t * console.log(` Size: ${stats.size}`);\n\t * console.log(` Keys: ${stats.keys.join(', ')}`);\n\t * ```\n\t */\n\tgetStats(): { size: number; keys: string[] } {\n\t\treturn {\n\t\t\tsize: this._cache.size,\n\t\t\tkeys: Array.from(this._cache.keys()),\n\t\t};\n\t}\n}\n"],"names":["DiscoveryCache","options","Map","setInterval","now","Date","key","entry","age","data","lruKey","clearInterval","Array"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cache/DiscoveryCache.js","sources":["../../src/cache/DiscoveryCache.ts"],"sourcesContent":["import type { IMetrics } from '../contracts/interfaces.js';\n\n/**\n * LRU Cache for tool/skill discovery results with TTL support.\n *\n * This module provides a generic Least Recently Used (LRU) cache with time-to-live\n * (TTL) support. It's designed to cache discovery results to avoid repeated expensive\n * operations like filesystem scanning.\n *\n * @module cache\n */\n\n/**\n * A cache entry containing data and metadata for LRU tracking.\n *\n * @template T - The type of data being cached (typically Tool or Skill)\n *\n * @example\n * ```typescript\n * const entry: CacheEntry<string> = {\n * data: ['tool1', 'tool2'],\n * timestamp: 1705550000000,\n * accessCount: 5\n * };\n * ```\n */\nexport interface CacheEntry<T> {\n\t/** The cached data array. */\n\tdata: T[];\n\n\t/** Unix timestamp (milliseconds) when the entry was created/last accessed. */\n\ttimestamp: number;\n\n\t/** Number of times this entry has been accessed (for LRU tracking). */\n\taccessCount: number;\n}\n\n/**\n * Configuration options for creating a `DiscoveryCache` instance.\n *\n * @example\n * ```typescript\n * const options: DiscoveryCacheOptions = {\n * maxSize: 200,\n * ttl: 600000 // 10 minutes\n * };\n * ```\n */\nexport interface DiscoveryCacheOptions {\n\t/**\n\t * Maximum number of cache entries before LRU eviction begins.\n\t * @default 100\n\t */\n\tmaxSize?: number;\n\n\t/**\n\t * Time-to-live for cache entries in milliseconds.\n\t * Entries older than this are considered expired.\n\t * @default 300000 (5 minutes)\n\t */\n\tttl?: number;\n\n\tcleanupInterval?: number;\n\tmetrics?: IMetrics;\n}\n\n/**\n * LRU (Least Recently Used) cache with TTL support for caching discovery results.\n *\n * This cache implements an LRU eviction policy where entries that haven't been\n * accessed recently are removed first when the cache reaches maximum capacity.\n * Additionally, entries expire after a configurable TTL period.\n *\n * @remarks\n * **Eviction Policy:**\n * - When `maxSize` is reached, the least recently used entry is removed\n * - An entry's \"recent use\" is tracked by its position in the underlying Map\n * - Accessing an entry moves it to the \"most recently used\" position\n * - Setting an existing key also updates its position\n *\n * **Expiration:**\n * - Entries older than `ttl` milliseconds are automatically removed on access\n * - Expiration is checked lazily (when `get()` or `has()` is called)\n *\n * **Thread Safety:**\n * - This implementation is not thread-safe and should not be shared\n * across asynchronous operations without proper synchronization\n *\n * @template T - The type of data being cached\n *\n * @example\n * ```typescript\n * const cache = new DiscoveryCache<string>({\n * maxSize: 100,\n * ttl: 300000 // 5 minutes\n * });\n *\n * // Store discovery results\n * cache.set('.claude/skills', ['commit', 'pdf', 'test']);\n *\n * // Retrieve from cache\n * const skills = cache.get('.claude/skills');\n * if (skills) {\n * console.log('Cached skills:', skills);\n * } else {\n * console.log('Not cached or expired');\n * }\n *\n * // Check if cached and valid\n * if (cache.has('.claude/skills')) {\n * console.log('Skills are cached and fresh');\n * }\n *\n * // Manually invalidate\n * cache.invalidate('.claude/skills');\n *\n * // Clear all cache\n * cache.clear();\n *\n * // Get statistics\n * const stats = cache.getStats();\n * console.log(`Cache size: ${stats.size}, keys: ${stats.keys.join(', ')}`);\n * ```\n */\nexport class DiscoveryCache<T> {\n\t/** Internal Map storing cache entries. Insertion order tracks LRU status. */\n\tprivate _cache: Map<string, CacheEntry<T>>;\n\n\t/** Maximum number of entries before eviction begins. */\n\tprivate _maxSize: number;\n\n\t/** Time-to-live in milliseconds for cache entries. */\n\tprivate _ttl: number;\n\tprivate _metrics?: IMetrics;\n\tprivate _cleanupTimer: NodeJS.Timeout | null = null;\n\n\t/**\n\t * Creates a new DiscoveryCache instance.\n\t *\n\t * @param options - Configuration options for the cache\n\t *\n\t * @example\n\t * ```typescript\n\t * // Default configuration (100 entries, 5 minute TTL)\n\t * const cache1 = new DiscoveryCache();\n\t *\n\t * // Custom configuration\n\t * const cache2 = new DiscoveryCache({\n\t * maxSize: 200,\n\t * ttl: 600000 // 10 minutes\n\t * });\n\t * ```\n\t */\n\tconstructor(options: DiscoveryCacheOptions = {}) {\n\t\tthis._cache = new Map();\n\t\tthis._maxSize = options.maxSize ?? 100;\n\t\tthis._ttl = options.ttl ?? 300000; // 5 minutes default\n\t\tthis._metrics = options.metrics;\n\n\t\tif (options.cleanupInterval && options.cleanupInterval > 0) {\n\t\t\tthis._cleanupTimer = setInterval(() => {\n\t\t\t\tthis._cleanupExpired();\n\t\t\t}, options.cleanupInterval);\n\t\t\tif (this._cleanupTimer.unref) this._cleanupTimer.unref();\n\t\t}\n\t}\n\n\tprivate _cleanupExpired(): void {\n\t\tconst now = Date.now();\n\t\tfor (const [key, entry] of this._cache.entries()) {\n\t\t\tconst age = now - entry.timestamp;\n\t\t\tif (age > this._ttl) {\n\t\t\t\tthis._cache.delete(key);\n\t\t\t\tthis._metrics?.counter('cache_eviction_total', 1, { cause: 'ttl_cleanup' });\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves a value from the cache by key.\n\t *\n\t * Returns the cached data if the key exists and the entry hasn't expired.\n\t * Updates the entry's access time and moves it to the most-recently-used position.\n\t * Returns null if the key doesn't exist or the entry has expired (expired entries\n\t * are automatically deleted).\n\t *\n\t * @param key - The cache key to retrieve\n\t * @returns The cached data array, or null if not found or expired\n\t *\n\t * @example\n\t * ```typescript\n\t * const tools = cache.get('/path/to/tools');\n\t * if (tools) {\n\t * console.log('Found cached tools:', tools);\n\t * } else {\n\t * console.log('Tools not cached or expired, need to discover');\n\t * }\n\t * ```\n\t */\n\tget(key: string): T[] | null {\n\t\tconst entry = this._cache.get(key);\n\t\tif (!entry) {\n\t\t\tthis._metrics?.counter('cache_miss_total', 1, {}, 'Total discovery cache misses');\n\t\t\treturn null;\n\t\t}\n\n\t\tconst now = Date.now();\n\t\tconst age = now - entry.timestamp;\n\n\t\t// Check TTL\n\t\tif (age > this._ttl) {\n\t\t\tthis._cache.delete(key);\n\t\t\tthis._metrics?.counter('cache_eviction_total', 1, { cause: 'ttl' }, 'Total cache evictions');\n\t\t\tthis._metrics?.counter('cache_miss_total', 1, {}, 'Total discovery cache misses');\n\t\t\treturn null;\n\t\t}\n\n\t\t// Update access metadata for LRU\n\t\tentry.accessCount++;\n\t\tentry.timestamp = now;\n\n\t\t// Move to end (most recently used)\n\t\tthis._cache.delete(key);\n\t\tthis._cache.set(key, entry);\n\t\tthis._metrics?.counter('cache_hit_total', 1, {}, 'Total discovery cache hits');\n\n\t\treturn entry.data;\n\t}\n\n\t/**\n\t * Stores a value in the cache with the given key.\n\t *\n\t * If the cache is at maximum capacity and this is a new key, the least\n\t * recently used entry is evicted before storing the new value. If the key\n\t * already exists, its value and access time are updated.\n\t *\n\t * @param key - The cache key to store under\n\t * @param data - The data array to cache\n\t *\n\t * @example\n\t * ```typescript\n\t * const discoveredTools = ['Read', 'Write', 'Bash', 'Grep'];\n\t * cache.set('/usr/local/tools', discoveredTools);\n\t * ```\n\t */\n\tset(key: string, data: T[]): void {\n\t\t// Enforce max size with LRU eviction\n\t\tif (this._cache.size >= this._maxSize && !this._cache.has(key)) {\n\t\t\t// Remove least recently used (first entry)\n\t\t\tconst lruKey = this._cache.keys().next().value;\n\t\t\tif (lruKey) {\n\t\t\t\tthis._cache.delete(lruKey);\n\t\t\t\tthis._metrics?.counter(\n\t\t\t\t\t'cache_eviction_total',\n\t\t\t\t\t1,\n\t\t\t\t\t{ cause: 'lru' },\n\t\t\t\t\t'Total cache evictions'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._cache.set(key, {\n\t\t\tdata,\n\t\t\ttimestamp: Date.now(),\n\t\t\taccessCount: 0,\n\t\t});\n\t}\n\n\t/**\n\t * Checks if a key exists in the cache and hasn't expired.\n\t *\n\t * Returns true only if the key exists and the entry is within its TTL.\n\t * Expired entries are not automatically removed by this method (use `get()`\n\t * for automatic expiration cleanup).\n\t *\n\t * @param key - The cache key to check\n\t * @returns true if the key exists and hasn't expired, false otherwise\n\t *\n\t * @example\n\t * ```typescript\n\t * if (cache.has('/path/to/skills')) {\n\t * // Key exists and is fresh\n\t * const skills = cache.get('/path/to/skills')!;\n\t * } else {\n\t * // Need to discover skills\n\t * }\n\t * ```\n\t */\n\thas(key: string): boolean {\n\t\tconst entry = this._cache.get(key);\n\t\tif (!entry) return false;\n\n\t\tconst age = Date.now() - entry.timestamp;\n\t\treturn age <= this._ttl;\n\t}\n\n\t/**\n\t * Removes a specific entry from the cache.\n\t *\n\t * This is useful for explicit invalidation when cached data is known\n\t * to be stale due to external changes.\n\t *\n\t * @param key - The cache key to invalidate\n\t *\n\t * @example\n\t * ```typescript\n\t * // Invalidate cache when files change\n\t * watcher.on('change', (path) => {\n\t * cache.invalidate(path);\n\t * });\n\t * ```\n\t */\n\tinvalidate(key: string): void {\n\t\tthis._cache.delete(key);\n\t}\n\n\t/**\n\t * Removes all entries from the cache.\n\t *\n\t * This completely resets the cache to an empty state.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Clear cache before running tests\n\t * cache.clear();\n\t * ```\n\t */\n\tclear(): void {\n\t\tthis._cache.clear();\n\t}\n\n\tdispose(): void {\n\t\tif (this._cleanupTimer) {\n\t\t\tclearInterval(this._cleanupTimer);\n\t\t\tthis._cleanupTimer = null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the current number of entries in the cache.\n\t *\n\t * @returns The number of cached entries\n\t *\n\t * @example\n\t * ```typescript\n\t * console.log(`Cache contains ${cache.size()} entries`);\n\t * if (cache.size() >= maxSize) {\n\t * console.log('Cache is at capacity');\n\t * }\n\t * ```\n\t */\n\tsize(): number {\n\t\treturn this._cache.size;\n\t}\n\n\t/**\n\t * Gets cache statistics including size and all cached keys.\n\t *\n\t * Useful for monitoring and debugging cache behavior.\n\t *\n\t * @returns An object with cache size and array of all keys\n\t *\n\t * @example\n\t * ```typescript\n\t * const stats = cache.getStats();\n\t * console.log(`Cache stats:`);\n\t * console.log(` Size: ${stats.size}`);\n\t * console.log(` Keys: ${stats.keys.join(', ')}`);\n\t * ```\n\t */\n\tgetStats(): { size: number; keys: string[] } {\n\t\treturn {\n\t\t\tsize: this._cache.size,\n\t\t\tkeys: Array.from(this._cache.keys()),\n\t\t};\n\t}\n}\n"],"names":["DiscoveryCache","options","Map","setInterval","now","Date","key","entry","age","data","lruKey","clearInterval","Array"],"mappings":"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"}
|