tracelattice 1.4.0 → 1.4.1
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/dist/__tests__/integration/dag-edges.test.d.ts +15 -0
- package/dist/__tests__/integration/dag-edges.test.d.ts.map +1 -1
- package/dist/__tests__/typing.test-d.d.ts +16 -0
- package/dist/__tests__/typing.test-d.d.ts.map +1 -0
- package/dist/cli.js +165 -60
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +25 -2
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/contracts/PersistenceBackend.d.ts +6 -6
- package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
- package/dist/contracts/calibrator.d.ts +4 -3
- package/dist/contracts/calibrator.d.ts.map +1 -1
- package/dist/contracts/features.d.ts +0 -4
- package/dist/contracts/features.d.ts.map +1 -1
- package/dist/contracts/features.js +1 -4
- package/dist/contracts/features.js.map +1 -1
- package/dist/contracts/ids.d.ts +6 -0
- package/dist/contracts/ids.d.ts.map +1 -1
- package/dist/contracts/ids.js +8 -2
- package/dist/contracts/ids.js.map +1 -1
- package/dist/contracts/interfaces.d.ts +11 -11
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/contracts/summary.d.ts +6 -6
- package/dist/contracts/summary.d.ts.map +1 -1
- package/dist/contracts/suspension.d.ts +1 -1
- package/dist/contracts/suspension.d.ts.map +1 -1
- package/dist/contracts/transport.d.ts +2 -1
- package/dist/contracts/transport.d.ts.map +1 -1
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +7 -7
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/PersistenceBuffer.d.ts +3 -2
- package/dist/core/PersistenceBuffer.d.ts.map +1 -1
- package/dist/core/PersistenceBuffer.js +1 -2
- package/dist/core/PersistenceBuffer.js.map +1 -1
- package/dist/core/SessionLock.d.ts.map +1 -1
- package/dist/core/SessionLock.js +2 -2
- package/dist/core/SessionLock.js.map +1 -1
- package/dist/core/SessionManager.d.ts +4 -3
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
- package/dist/core/ThoughtEvaluator.js +2 -1
- package/dist/core/ThoughtEvaluator.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts +1 -1
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/core/compression/CompressionService.d.ts +2 -2
- package/dist/core/compression/CompressionService.d.ts.map +1 -1
- package/dist/core/compression/CompressionService.js +4 -5
- package/dist/core/compression/CompressionService.js.map +1 -1
- package/dist/core/compression/DehydrationPolicy.d.ts +2 -1
- package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -1
- package/dist/core/compression/DehydrationPolicy.js.map +1 -1
- package/dist/core/compression/InMemorySummaryStore.d.ts +1 -1
- package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -1
- package/dist/core/compression/InMemorySummaryStore.js +13 -12
- package/dist/core/compression/InMemorySummaryStore.js.map +1 -1
- package/dist/core/compression/Summary.d.ts +18 -0
- package/dist/core/compression/Summary.d.ts.map +1 -1
- package/dist/core/compression/Summary.js +16 -1
- package/dist/core/compression/Summary.js.map +1 -0
- package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
- package/dist/core/evaluator/Calibrator.js.map +1 -1
- package/dist/core/evaluator/PatternDetector.d.ts.map +1 -1
- package/dist/core/evaluator/PatternDetector.js +8 -4
- package/dist/core/evaluator/PatternDetector.js.map +1 -1
- package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
- package/dist/core/graph/EdgeEmitter.js +6 -0
- package/dist/core/graph/EdgeEmitter.js.map +1 -1
- package/dist/core/graph/EdgeStore.d.ts +1 -1
- package/dist/core/graph/EdgeStore.d.ts.map +1 -1
- package/dist/core/graph/EdgeStore.js +4 -3
- package/dist/core/graph/EdgeStore.js.map +1 -1
- package/dist/core/graph/GraphView.d.ts +7 -7
- package/dist/core/graph/GraphView.d.ts.map +1 -1
- package/dist/core/graph/GraphView.js.map +1 -1
- package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -1
- package/dist/core/reasoning/OutcomeRecorder.js +6 -4
- package/dist/core/reasoning/OutcomeRecorder.js.map +1 -1
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts.map +1 -1
- package/dist/core/reasoning/strategies/StrategyFactory.js +2 -1
- package/dist/core/reasoning/strategies/StrategyFactory.js.map +1 -1
- package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -1
- package/dist/core/reasoning/strategies/totScoring.js +10 -1
- package/dist/core/reasoning/strategies/totScoring.js.map +1 -1
- package/dist/core/thought.d.ts +1 -1
- package/dist/core/thought.d.ts.map +1 -1
- package/dist/core/tools/InMemorySuspensionStore.d.ts.map +1 -1
- package/dist/core/tools/InMemorySuspensionStore.js +4 -4
- package/dist/core/tools/InMemorySuspensionStore.js.map +1 -1
- package/dist/di/Container.d.ts +26 -6
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js +12 -0
- package/dist/di/Container.js.map +1 -1
- package/dist/di/ServiceRegistry.d.ts +2 -1
- package/dist/di/ServiceRegistry.d.ts.map +1 -1
- package/dist/errors.d.ts +7 -6
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/lib.d.ts +4 -4
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/persistence/FilePersistence.d.ts +6 -6
- package/dist/persistence/FilePersistence.d.ts.map +1 -1
- package/dist/persistence/FilePersistence.js +55 -15
- package/dist/persistence/FilePersistence.js.map +1 -1
- package/dist/persistence/MemoryPersistence.d.ts +7 -7
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
- package/dist/persistence/MemoryPersistence.js.map +1 -1
- package/dist/persistence/SqlitePersistence.d.ts +8 -6
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
- package/dist/persistence/SqlitePersistence.js +39 -11
- package/dist/persistence/SqlitePersistence.js.map +1 -1
- package/dist/pool/ConnectionPool.d.ts +7 -6
- package/dist/pool/ConnectionPool.d.ts.map +1 -1
- package/dist/pool/ConnectionPool.js +2 -1
- package/dist/pool/ConnectionPool.js.map +1 -1
- package/dist/pool/IConnectionPool.d.ts +5 -4
- package/dist/pool/IConnectionPool.d.ts.map +1 -1
- package/dist/registry/SkillRegistry.d.ts +1 -1
- package/dist/registry/SkillRegistry.d.ts.map +1 -1
- package/dist/registry/SkillRegistry.js.map +1 -1
- package/dist/registry/ToolRegistry.d.ts +1 -1
- package/dist/registry/ToolRegistry.d.ts.map +1 -1
- package/dist/registry/ToolRegistry.js.map +1 -1
- package/dist/transport/BaseTransport.d.ts +1 -1
- package/dist/transport/BaseTransport.d.ts.map +1 -1
- package/dist/transport/BaseTransport.js.map +1 -1
- package/dist/transport/HttpTransport.d.ts +1 -0
- package/dist/transport/HttpTransport.d.ts.map +1 -1
- package/dist/transport/HttpTransport.js +5 -1
- package/dist/transport/HttpTransport.js.map +1 -1
- package/dist/transport/SseTransport.d.ts +1 -0
- package/dist/transport/SseTransport.d.ts.map +1 -1
- package/dist/transport/SseTransport.js +8 -3
- package/dist/transport/SseTransport.js.map +1 -1
- package/dist/transport/StreamableHttpTransport.d.ts +2 -0
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
- package/dist/transport/StreamableHttpTransport.js +15 -6
- package/dist/transport/StreamableHttpTransport.js.map +1 -1
- package/dist/types/tool.d.ts +6 -1
- package/dist/types/tool.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1,2 +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
|
+
*/
|
|
1
16
|
export {};
|
|
2
17
|
//# sourceMappingURL=dag-edges.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dag-edges.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/dag-edges.test.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"dag-edges.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/dag-edges.test.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time type assertions covering critical typing invariants.
|
|
3
|
+
*
|
|
4
|
+
* This file contains NO runtime tests. Vitest's `*.test-d.ts` convention
|
|
5
|
+
* keeps the file inside the tsc pass (so type errors fail `npm run type-check`)
|
|
6
|
+
* while excluded from the test runner pattern (`*.{test,spec}.{ts,tsx}`).
|
|
7
|
+
*
|
|
8
|
+
* Coverage:
|
|
9
|
+
* 1. Branded ID assignability — branded types must NOT be cross-assignable.
|
|
10
|
+
* 2. ValidatedThought exhaustiveness — all 7 variants must satisfy the union;
|
|
11
|
+
* a plain `ThoughtData` without a discriminating `thought_type` must NOT.
|
|
12
|
+
* 3. Schema-type sync — `ThoughtData` must remain derivable from `SchemaOutput`.
|
|
13
|
+
* 4. DI ServiceRegistry — every service key resolved in `lib.ts` exists in the registry.
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=typing.test-d.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typing.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/typing.test-d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
|
package/dist/cli.js
CHANGED
|
@@ -67,6 +67,125 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
},
|
|
71
|
+
138(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
72
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
73
|
+
Kd: () => (asSessionId)
|
|
74
|
+
});
|
|
75
|
+
/* import */ var _core_ids_js__rspack_import_0 = __webpack_require__(352);
|
|
76
|
+
/* import */ var _errors_js__rspack_import_1 = __webpack_require__(937);
|
|
77
|
+
/**
|
|
78
|
+
* Branded identifier types for compile-time slot safety.
|
|
79
|
+
*
|
|
80
|
+
* These nominal types prevent accidental mixing of different ID kinds
|
|
81
|
+
* (e.g. passing a `ThoughtId` where a `SessionId` is expected). At
|
|
82
|
+
* runtime they are plain strings — the brand exists only in the type
|
|
83
|
+
* system.
|
|
84
|
+
*
|
|
85
|
+
* @module contracts/ids
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validate and brand a string as a {@link SessionId}.
|
|
90
|
+
*
|
|
91
|
+
* Enforces {@link SESSION_ID_PATTERN} and {@link MAX_SESSION_ID_LENGTH}.
|
|
92
|
+
* The reserved global session sentinel `__global__` is always accepted.
|
|
93
|
+
*
|
|
94
|
+
* @throws {ValidationError} when the input is not a valid session id.
|
|
95
|
+
*/ function asSessionId(value) {
|
|
96
|
+
if (value === '__global__') {
|
|
97
|
+
// eslint-disable-next-line no-restricted-syntax -- branding constructor, cannot self-reference
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
101
|
+
throw new _errors_js__rspack_import_1/* .ValidationError */.yI('session_id', 'must be a non-empty string');
|
|
102
|
+
}
|
|
103
|
+
if (value.length > _core_ids_js__rspack_import_0/* .MAX_SESSION_ID_LENGTH */.He) {
|
|
104
|
+
throw new _errors_js__rspack_import_1/* .ValidationError */.yI('session_id', `exceeds max length of ${_core_ids_js__rspack_import_0/* .MAX_SESSION_ID_LENGTH */.He}`);
|
|
105
|
+
}
|
|
106
|
+
if (!_core_ids_js__rspack_import_0/* .SESSION_ID_PATTERN.test */.Id.test(value)) {
|
|
107
|
+
throw new _errors_js__rspack_import_1/* .ValidationError */.yI('session_id', 'must match alphanumeric, hyphens, underscores');
|
|
108
|
+
}
|
|
109
|
+
// eslint-disable-next-line no-restricted-syntax -- branding constructor, cannot self-reference
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
/** Brand a string as a {@link ThoughtId} without validation. */ function asThoughtId(value) {
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
/** Brand a string as an {@link EdgeId} without validation. */ function asEdgeId(value) {
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
/** Brand a string as a {@link SuspensionToken} without validation. */ function asSuspensionToken(value) {
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
/** Brand a string as a {@link BranchId} without validation. */ function asBranchId(value) {
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
/** Brand a string as a {@link SummaryId} without validation. */ function asSummaryId(value) {
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
/** Generate a fresh {@link ThoughtId}. */ function generateThoughtId() {
|
|
128
|
+
return generateUlid();
|
|
129
|
+
}
|
|
130
|
+
/** Generate a fresh {@link EdgeId}. */ function generateEdgeId() {
|
|
131
|
+
return generateUlid();
|
|
132
|
+
}
|
|
133
|
+
/** Generate a fresh {@link SuspensionToken}. */ function generateSuspensionToken() {
|
|
134
|
+
return generateUlid();
|
|
135
|
+
}
|
|
136
|
+
/** Generate a fresh {@link SummaryId}. */ function generateSummaryId() {
|
|
137
|
+
return generateUlid();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Reserved sentinel session id used when callers omit `session_id`.
|
|
141
|
+
*
|
|
142
|
+
* Branded once here so production and test code share one constant
|
|
143
|
+
* instead of casting `'__global__'` ad-hoc.
|
|
144
|
+
*/ const GLOBAL_SESSION_ID = asSessionId('__global__');
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
},
|
|
148
|
+
352(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
149
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
150
|
+
He: () => (MAX_SESSION_ID_LENGTH),
|
|
151
|
+
Id: () => (SESSION_ID_PATTERN)
|
|
152
|
+
});
|
|
153
|
+
/* import */ var node_crypto__rspack_import_0 = __webpack_require__(561);
|
|
154
|
+
/**
|
|
155
|
+
* Unique identifier generation utilities for thoughts and edges.
|
|
156
|
+
*
|
|
157
|
+
* @module core/ids
|
|
158
|
+
*/
|
|
159
|
+
/**
|
|
160
|
+
* Generate a unique lexicographically-sortable identifier.
|
|
161
|
+
*
|
|
162
|
+
* Format: 8-char base36 timestamp + 20-char hex random (10 random bytes).
|
|
163
|
+
* Result is up to 28 characters, sortable by creation time.
|
|
164
|
+
*
|
|
165
|
+
* @returns A unique string identifier.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const id = generateUlid(); // '01h2k3m400a1b2c3d4e5f6...'
|
|
170
|
+
* ```
|
|
171
|
+
*/ function generateUlid() {
|
|
172
|
+
const timestamp = Date.now().toString(36).padStart(8, '0');
|
|
173
|
+
const random = crypto.randomBytes(10).toString('hex');
|
|
174
|
+
return `${timestamp}${random}`;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Valid session ID pattern: alphanumeric, hyphens, underscores.
|
|
178
|
+
*
|
|
179
|
+
* Length is enforced separately via {@link MAX_SESSION_ID_LENGTH}.
|
|
180
|
+
* Same character set as branch IDs.
|
|
181
|
+
*/ const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
182
|
+
/**
|
|
183
|
+
* Maximum session ID length (in characters).
|
|
184
|
+
*
|
|
185
|
+
* Allows compound identifiers (e.g. `user-123_task-abc`).
|
|
186
|
+
*/ const MAX_SESSION_ID_LENGTH = 100;
|
|
187
|
+
|
|
188
|
+
|
|
70
189
|
},
|
|
71
190
|
937(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
72
191
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -74,6 +193,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
74
193
|
m_: () => (PoolTerminatedError),
|
|
75
194
|
qA: () => (SessionNotActiveError),
|
|
76
195
|
u1: () => (getErrorMessage),
|
|
196
|
+
yI: () => (ValidationError),
|
|
77
197
|
yM: () => (MaxSessionsReachedError)
|
|
78
198
|
});
|
|
79
199
|
/**
|
|
@@ -803,6 +923,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
803
923
|
createConnectionPool: () => (createConnectionPool)
|
|
804
924
|
});
|
|
805
925
|
/* import */ var _errors_js__rspack_import_0 = __webpack_require__(937);
|
|
926
|
+
/* import */ var _contracts_ids_js__rspack_import_1 = __webpack_require__(138);
|
|
806
927
|
/**
|
|
807
928
|
* Connection Pool for managing concurrent user sessions.
|
|
808
929
|
*
|
|
@@ -821,6 +942,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
821
942
|
* await pool.closeSession(sessionId);
|
|
822
943
|
* ```
|
|
823
944
|
*/
|
|
945
|
+
|
|
824
946
|
/**
|
|
825
947
|
* Represents a user session with its own server instance.
|
|
826
948
|
*/ class Session {
|
|
@@ -973,7 +1095,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
973
1095
|
});
|
|
974
1096
|
try {
|
|
975
1097
|
// Generate unique session ID
|
|
976
|
-
const sessionId = `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}
|
|
1098
|
+
const sessionId = (0,_contracts_ids_js__rspack_import_1/* .asSessionId */.Kd)(`session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`);
|
|
977
1099
|
// Create a new server instance for this session
|
|
978
1100
|
const server = await this._serverFactory();
|
|
979
1101
|
// Create session
|
|
@@ -1629,51 +1751,11 @@ You should:
|
|
|
1629
1751
|
|
|
1630
1752
|
|
|
1631
1753
|
},
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
// EXPORTS
|
|
1754
|
+
932(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
1635
1755
|
__webpack_require__.d(__webpack_exports__, {
|
|
1636
|
-
j: () => (
|
|
1756
|
+
j: () => (BaseTransport)
|
|
1637
1757
|
});
|
|
1638
|
-
|
|
1639
|
-
// EXTERNAL MODULE: external "node:crypto"
|
|
1640
|
-
var external_node_crypto_ = __webpack_require__(561);
|
|
1641
|
-
;// CONCATENATED MODULE: ./src/core/ids.ts
|
|
1642
|
-
/**
|
|
1643
|
-
* Unique identifier generation utilities for thoughts and edges.
|
|
1644
|
-
*
|
|
1645
|
-
* @module core/ids
|
|
1646
|
-
*/
|
|
1647
|
-
/**
|
|
1648
|
-
* Generate a unique lexicographically-sortable identifier.
|
|
1649
|
-
*
|
|
1650
|
-
* Format: 8-char base36 timestamp + 20-char hex random (10 random bytes).
|
|
1651
|
-
* Result is up to 28 characters, sortable by creation time.
|
|
1652
|
-
*
|
|
1653
|
-
* @returns A unique string identifier.
|
|
1654
|
-
*
|
|
1655
|
-
* @example
|
|
1656
|
-
* ```typescript
|
|
1657
|
-
* const id = generateUlid(); // '01h2k3m400a1b2c3d4e5f6...'
|
|
1658
|
-
* ```
|
|
1659
|
-
*/ function generateUlid() {
|
|
1660
|
-
const timestamp = Date.now().toString(36).padStart(8, '0');
|
|
1661
|
-
const random = crypto.randomBytes(10).toString('hex');
|
|
1662
|
-
return `${timestamp}${random}`;
|
|
1663
|
-
}
|
|
1664
|
-
/**
|
|
1665
|
-
* Valid session ID pattern: alphanumeric, hyphens, underscores.
|
|
1666
|
-
*
|
|
1667
|
-
* Length is enforced separately via {@link MAX_SESSION_ID_LENGTH}.
|
|
1668
|
-
* Same character set as branch IDs.
|
|
1669
|
-
*/ const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
1670
|
-
/**
|
|
1671
|
-
* Maximum session ID length (in characters).
|
|
1672
|
-
*
|
|
1673
|
-
* Allows compound identifiers (e.g. `user-123_task-abc`).
|
|
1674
|
-
*/ const MAX_SESSION_ID_LENGTH = 100;
|
|
1675
|
-
|
|
1676
|
-
;// CONCATENATED MODULE: ./src/transport/BaseTransport.ts
|
|
1758
|
+
/* import */ var _core_ids_js__rspack_import_0 = __webpack_require__(352);
|
|
1677
1759
|
/**
|
|
1678
1760
|
* Base transport implementation.
|
|
1679
1761
|
*
|
|
@@ -1761,10 +1843,10 @@ class BaseTransport {
|
|
|
1761
1843
|
* @param sessionId - The session ID to validate
|
|
1762
1844
|
* @returns true if valid, false otherwise
|
|
1763
1845
|
*/ validateSessionId(sessionId) {
|
|
1764
|
-
if (sessionId.length > MAX_SESSION_ID_LENGTH) {
|
|
1846
|
+
if (sessionId.length > _core_ids_js__rspack_import_0/* .MAX_SESSION_ID_LENGTH */.He) {
|
|
1765
1847
|
return false;
|
|
1766
1848
|
}
|
|
1767
|
-
return SESSION_ID_PATTERN.test(sessionId);
|
|
1849
|
+
return _core_ids_js__rspack_import_0/* .SESSION_ID_PATTERN.test */.Id.test(sessionId);
|
|
1768
1850
|
}
|
|
1769
1851
|
/**
|
|
1770
1852
|
* Sanitize query parameters by removing any not in whitelist.
|
|
@@ -2013,8 +2095,9 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2013
2095
|
/* import */ var node_url__rspack_import_2 = __webpack_require__(61);
|
|
2014
2096
|
/* import */ var valibot__rspack_import_3 = __webpack_require__(821);
|
|
2015
2097
|
/* import */ var _schema_js__rspack_import_4 = __webpack_require__(613);
|
|
2016
|
-
/* import */ var _BaseTransport_js__rspack_import_5 = __webpack_require__(
|
|
2017
|
-
/* import */ var
|
|
2098
|
+
/* import */ var _BaseTransport_js__rspack_import_5 = __webpack_require__(932);
|
|
2099
|
+
/* import */ var _contracts_ids_js__rspack_import_6 = __webpack_require__(138);
|
|
2100
|
+
/* import */ var _context_RequestContext_js__rspack_import_7 = __webpack_require__(502);
|
|
2018
2101
|
/**
|
|
2019
2102
|
* SSE (Server-Sent Events) Transport implementation.
|
|
2020
2103
|
*
|
|
@@ -2039,6 +2122,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2039
2122
|
|
|
2040
2123
|
|
|
2041
2124
|
|
|
2125
|
+
|
|
2042
2126
|
/**
|
|
2043
2127
|
* SSE Transport for MCP server over HTTP.
|
|
2044
2128
|
*
|
|
@@ -2089,6 +2173,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2089
2173
|
});
|
|
2090
2174
|
}
|
|
2091
2175
|
_mcpServer = null;
|
|
2176
|
+
_requireMcpServer() {
|
|
2177
|
+
if (!this._mcpServer) {
|
|
2178
|
+
throw new Error('MCP server not initialized. Did you call connect()?');
|
|
2179
|
+
}
|
|
2180
|
+
return this._mcpServer;
|
|
2181
|
+
}
|
|
2092
2182
|
/**
|
|
2093
2183
|
* Handle incoming HTTP requests
|
|
2094
2184
|
*/ async _handleRequest(req, res) {
|
|
@@ -2258,7 +2348,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2258
2348
|
let sessionId;
|
|
2259
2349
|
if (this._connectionPool) {
|
|
2260
2350
|
const requestedSession = params.session ?? params.sessionId;
|
|
2261
|
-
if (requestedSession && this._connectionPool.getSessionInfo(requestedSession)) {
|
|
2351
|
+
if (requestedSession && this._connectionPool.getSessionInfo((0,_contracts_ids_js__rspack_import_6/* .asSessionId */.Kd)(requestedSession))) {
|
|
2262
2352
|
sessionId = requestedSession;
|
|
2263
2353
|
} else {
|
|
2264
2354
|
try {
|
|
@@ -2272,7 +2362,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2272
2362
|
return;
|
|
2273
2363
|
}
|
|
2274
2364
|
}
|
|
2275
|
-
this._clientSessionMap.set(res, sessionId);
|
|
2365
|
+
this._clientSessionMap.set(res, (0,_contracts_ids_js__rspack_import_6/* .asSessionId */.Kd)(sessionId));
|
|
2276
2366
|
this._updatePoolMetrics();
|
|
2277
2367
|
}
|
|
2278
2368
|
// Send initial connection event
|
|
@@ -2337,10 +2427,10 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2337
2427
|
if (this._mcpServer) {
|
|
2338
2428
|
const sessionId = this._clientSessionMap.get(res);
|
|
2339
2429
|
const owner = sessionId ?? `sse-${(0,node_crypto__rspack_import_1.randomUUID)()}`;
|
|
2340
|
-
const response = await (0,
|
|
2430
|
+
const response = await (0,_context_RequestContext_js__rspack_import_7/* .runWithContext */.Vo)({
|
|
2341
2431
|
requestId: (0,node_crypto__rspack_import_1.randomUUID)(),
|
|
2342
2432
|
owner
|
|
2343
|
-
}, ()=>this.
|
|
2433
|
+
}, ()=>this._requireMcpServer().receive(jsonRpcRequest, {
|
|
2344
2434
|
sessionInfo: {}
|
|
2345
2435
|
}));
|
|
2346
2436
|
res.writeHead(200, {
|
|
@@ -2494,8 +2584,10 @@ var external_valibot_ = __webpack_require__(821);
|
|
|
2494
2584
|
var errors = __webpack_require__(937);
|
|
2495
2585
|
// EXTERNAL MODULE: ./src/schema.ts
|
|
2496
2586
|
var schema = __webpack_require__(613);
|
|
2497
|
-
// EXTERNAL MODULE: ./src/transport/BaseTransport.ts
|
|
2498
|
-
var BaseTransport = __webpack_require__(
|
|
2587
|
+
// EXTERNAL MODULE: ./src/transport/BaseTransport.ts
|
|
2588
|
+
var BaseTransport = __webpack_require__(932);
|
|
2589
|
+
// EXTERNAL MODULE: ./src/contracts/ids.ts
|
|
2590
|
+
var ids = __webpack_require__(138);
|
|
2499
2591
|
;// CONCATENATED MODULE: ./src/transport/HttpHelpers.ts
|
|
2500
2592
|
/**
|
|
2501
2593
|
* Shared HTTP helper utilities for MCP transport implementations.
|
|
@@ -2620,6 +2712,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
2620
2712
|
|
|
2621
2713
|
|
|
2622
2714
|
|
|
2715
|
+
|
|
2623
2716
|
/**
|
|
2624
2717
|
* Streamable HTTP Transport for MCP server.
|
|
2625
2718
|
*
|
|
@@ -2682,6 +2775,18 @@ var RequestContext = __webpack_require__(502);
|
|
|
2682
2775
|
this._metrics = options.metrics;
|
|
2683
2776
|
this._metricsProvider = options.metricsProvider ?? null;
|
|
2684
2777
|
}
|
|
2778
|
+
_requireServer() {
|
|
2779
|
+
if (!this._server) {
|
|
2780
|
+
throw new Error('HTTP server not initialized. Did you call connect()?');
|
|
2781
|
+
}
|
|
2782
|
+
return this._server;
|
|
2783
|
+
}
|
|
2784
|
+
_requireMcpServer() {
|
|
2785
|
+
if (!this._mcpServer) {
|
|
2786
|
+
throw new Error('MCP server not initialized. Did you call connect()?');
|
|
2787
|
+
}
|
|
2788
|
+
return this._mcpServer;
|
|
2789
|
+
}
|
|
2685
2790
|
/**
|
|
2686
2791
|
* Get number of active sessions (stateful) or active requests (stateless).
|
|
2687
2792
|
*/ get clientCount() {
|
|
@@ -2698,7 +2803,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
2698
2803
|
this._mcpServer = mcpServer;
|
|
2699
2804
|
this._server = (0,external_node_http_.createServer)((req, res)=>this._handleRequest(req, res));
|
|
2700
2805
|
return new Promise((resolve)=>{
|
|
2701
|
-
this.
|
|
2806
|
+
this._requireServer().listen(this._port, this._host, ()=>{
|
|
2702
2807
|
this.log('info', `Streamable HTTP transport listening on http://${this._host}:${this._port}`);
|
|
2703
2808
|
resolve();
|
|
2704
2809
|
});
|
|
@@ -2876,7 +2981,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
2876
2981
|
const response = await (0,RequestContext/* .runWithContext */.Vo)({
|
|
2877
2982
|
requestId: (0,external_node_crypto_.randomUUID)(),
|
|
2878
2983
|
owner
|
|
2879
|
-
}, ()=>this.
|
|
2984
|
+
}, ()=>this._requireMcpServer().receive(jsonRpcRequest, {
|
|
2880
2985
|
sessionInfo: {}
|
|
2881
2986
|
}));
|
|
2882
2987
|
clearTimeout(timeout);
|
|
@@ -2941,7 +3046,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
2941
3046
|
}));
|
|
2942
3047
|
return;
|
|
2943
3048
|
}
|
|
2944
|
-
const session = this._sessions.get(sessionId);
|
|
3049
|
+
const session = this._sessions.get((0,ids/* .asSessionId */.Kd)(sessionId));
|
|
2945
3050
|
if (!session) {
|
|
2946
3051
|
res.writeHead(404, {
|
|
2947
3052
|
'Content-Type': 'application/json'
|
|
@@ -3001,7 +3106,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
3001
3106
|
return false;
|
|
3002
3107
|
}
|
|
3003
3108
|
// Check if session exists
|
|
3004
|
-
const session = this._sessions.get(headerSessionId);
|
|
3109
|
+
const session = this._sessions.get((0,ids/* .asSessionId */.Kd)(headerSessionId));
|
|
3005
3110
|
if (session) {
|
|
3006
3111
|
session.lastActivityAt = Date.now();
|
|
3007
3112
|
return headerSessionId;
|
|
@@ -3028,7 +3133,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
3028
3133
|
lastActivityAt: Date.now(),
|
|
3029
3134
|
notificationStreams: new Set()
|
|
3030
3135
|
};
|
|
3031
|
-
this._sessions.set(newSessionId, sessionState);
|
|
3136
|
+
this._sessions.set((0,ids/* .asSessionId */.Kd)(newSessionId), sessionState);
|
|
3032
3137
|
this.log('info', `New session created: ${newSessionId}`);
|
|
3033
3138
|
this._updateSessionMetrics();
|
|
3034
3139
|
return newSessionId;
|
|
@@ -3059,7 +3164,7 @@ var RequestContext = __webpack_require__(502);
|
|
|
3059
3164
|
* @param event - SSE event name
|
|
3060
3165
|
* @param data - Event payload
|
|
3061
3166
|
*/ broadcastToSession(sessionId, event, data) {
|
|
3062
|
-
const session = this._sessions.get(sessionId);
|
|
3167
|
+
const session = this._sessions.get((0,ids/* .asSessionId */.Kd)(sessionId));
|
|
3063
3168
|
if (!session) {
|
|
3064
3169
|
return;
|
|
3065
3170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA6B7D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAExD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE;QACzB;;;WAGG;QACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB;;WAEG;QACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEzC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAEtC;;;OAGG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAExC;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACtC;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;IAqEjC;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IA0CjC;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAOpB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;IAUnB;;;;;;;;;;;;;;;;;;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;QAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC7B;CAWD"}
|
|
@@ -3,6 +3,29 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { parse } from "yaml";
|
|
5
5
|
import { getErrorMessage } from "../errors.js";
|
|
6
|
+
import * as __rspack_external_valibot from "valibot";
|
|
7
|
+
const ConfigFileOptionsSchema = __rspack_external_valibot.looseObject({
|
|
8
|
+
maxHistorySize: __rspack_external_valibot.optional(__rspack_external_valibot.number()),
|
|
9
|
+
maxBranches: __rspack_external_valibot.optional(__rspack_external_valibot.number()),
|
|
10
|
+
maxBranchSize: __rspack_external_valibot.optional(__rspack_external_valibot.number()),
|
|
11
|
+
logLevel: __rspack_external_valibot.optional(__rspack_external_valibot.picklist([
|
|
12
|
+
'debug',
|
|
13
|
+
'info',
|
|
14
|
+
'warn',
|
|
15
|
+
'error'
|
|
16
|
+
])),
|
|
17
|
+
prettyLog: __rspack_external_valibot.optional(__rspack_external_valibot.boolean()),
|
|
18
|
+
skillDirs: __rspack_external_valibot.optional(__rspack_external_valibot.array(__rspack_external_valibot.string())),
|
|
19
|
+
discoveryCache: __rspack_external_valibot.optional(__rspack_external_valibot.looseObject({
|
|
20
|
+
ttl: __rspack_external_valibot.optional(__rspack_external_valibot.number()),
|
|
21
|
+
maxSize: __rspack_external_valibot.optional(__rspack_external_valibot.number())
|
|
22
|
+
})),
|
|
23
|
+
persistence: __rspack_external_valibot.optional(__rspack_external_valibot.looseObject({})),
|
|
24
|
+
features: __rspack_external_valibot.optional(__rspack_external_valibot.looseObject({})),
|
|
25
|
+
toolInterleaveTtlMs: __rspack_external_valibot.optional(__rspack_external_valibot.number()),
|
|
26
|
+
toolInterleaveSweepMs: __rspack_external_valibot.optional(__rspack_external_valibot.number()),
|
|
27
|
+
maxSessionsPerOwner: __rspack_external_valibot.optional(__rspack_external_valibot.number())
|
|
28
|
+
});
|
|
6
29
|
class ConfigLoader {
|
|
7
30
|
_configPaths;
|
|
8
31
|
constructor(customPath){
|
|
@@ -122,8 +145,8 @@ class ConfigLoader {
|
|
|
122
145
|
parseConfig(filePath) {
|
|
123
146
|
const content = readFileSync(filePath, 'utf-8');
|
|
124
147
|
const ext = filePath.split('.').pop()?.toLowerCase();
|
|
125
|
-
|
|
126
|
-
return
|
|
148
|
+
const raw = 'yaml' === ext || 'yml' === ext ? parse(content) : JSON.parse(content);
|
|
149
|
+
return __rspack_external_valibot.parse(ConfigFileOptionsSchema, raw);
|
|
127
150
|
}
|
|
128
151
|
toServerConfigOptions(config) {
|
|
129
152
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config/ConfigLoader.js","sources":["../../src/config/ConfigLoader.ts"],"sourcesContent":["/**\n * Configuration file loading with environment variable override support.\n *\n * This module provides the `ConfigLoader` class which handles loading configuration\n * from YAML and JSON files in standard locations, with automatic environment variable\n * overrides for all settings.\n *\n * @module config\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport { getErrorMessage } from '../errors.js';\nimport type { FeatureFlags } from '../contracts/features.js';\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\n/**\n * Configuration options loaded from config files.\n *\n * These options represent the structure of configuration files (JSON or YAML)\n * that can be loaded from standard locations. All values can be overridden\n * by environment variables.\n *\n * @example\n * ```yaml\n * # .claude/config.yaml\n * maxHistorySize: 500\n * maxBranches: 25\n * logLevel: debug\n * prettyLog: true\n * skillDirs:\n * - ./custom-skills\n * discoveryCache:\n * ttl: 600000\n * maxSize: 200\n * persistence:\n * enabled: true\n * backend: sqlite\n * options:\n * dbPath: ./data/history.db\n * ```\n */\nexport interface ConfigFileOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * Can be overridden by `MAX_HISTORY_SIZE` environment variable.\n\t */\n\treadonly maxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * Can be overridden by `MAX_BRANCHES` environment variable.\n\t */\n\treadonly maxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * Can be overridden by `MAX_BRANCH_SIZE` environment variable.\n\t */\n\treadonly maxBranchSize?: number;\n\n\t/**\n\t * Logging level for the application.\n\t * Can be overridden by `LOG_LEVEL` environment variable.\n\t */\n\treadonly logLevel?: 'debug' | 'info' | 'warn' | 'error';\n\n\t/**\n\t * Whether to enable pretty (formatted) logging output.\n\t * Can be overridden by `PRETTY_LOG` environment variable (set to \"false\" to disable).\n\t */\n\treadonly prettyLog?: boolean;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * Can be overridden by `SKILL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly skillDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t * Can be overridden by `DISCOVERY_CACHE_TTL` and `DISCOVERY_CACHE_MAX_SIZE` environment variables.\n\t */\n\treadonly discoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * Environment variable `DISCOVERY_CACHE_TTL` accepts seconds.\n\t\t */\n\t\treadonly ttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t */\n\t\treadonly maxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\treadonly persistence?: PersistenceConfig;\n\n\t/**\n\t * Feature flag overrides. Each field can be set independently.\n\t * Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.\n\t */\n\treadonly features?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` environment variable.\n\t */\n\treadonly toolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` environment variable.\n\t */\n\treadonly toolInterleaveSweepMs?: number;\n\n\t/**\n\t * Maximum sessions per owner. Per-owner LRU bucket prevents one user from\n\t * consuming all session slots.\n\t * Can be overridden by `SESSION_MAX_PER_OWNER` environment variable.\n\t */\n\treadonly maxSessionsPerOwner?: number;\n}\n\n/**\n * Loads configuration from files with environment variable overrides.\n *\n * This class searches for configuration files in standard locations and applies\n * environment variable overrides. Files are searched in priority order, with the\n * first match being used. Environment variables always take precedence over file values.\n *\n * @remarks\n * **Config File Search Order (priority):**\n * 1. Custom path (if provided to constructor)\n * 2. `.claude/config.json` (project-local)\n * 3. `.claude/config.yaml` (project-local)\n * 4. `.claude/config.yml` (project-local)\n * 5. `~/.claude/config.json` (user-global)\n * 6. `~/.claude/config.yaml` (user-global)\n * 7. `~/.claude/config.yml` (user-global)\n *\n * **Environment Variable Overrides:**\n * | Variable | Type | Description |\n * |----------|------|-------------|\n * | `MAX_HISTORY_SIZE` | number | Max thoughts in history |\n * | `MAX_BRANCHES` | number | Max number of branches |\n * | `MAX_BRANCH_SIZE` | number | Max size of each branch |\n * | `LOG_LEVEL` | string | Logging level (debug/info/warn/error) |\n * | `PRETTY_LOG` | string | \"false\" to disable pretty logging |\n * | `SKILL_DIRS` | string | Colon-separated directory paths |\n * | `DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |\n * | `DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |\n *\n * @example\n * ```typescript\n * // Use default search paths\n * const loader1 = new ConfigLoader();\n * const config1 = loader1.load();\n *\n * // Use custom config path\n * const loader2 = new ConfigLoader('./my-config.yaml');\n * const config2 = loader2.load();\n *\n * // Convert to ServerConfig options\n * const serverOptions = loader2.toServerConfigOptions(config2);\n * ```\n */\nexport class ConfigLoader {\n\t/** Array of config file paths to search, in priority order. */\n\tprivate _configPaths: string[];\n\n\t/**\n\t * Creates a new ConfigLoader instance.\n\t *\n\t * @param customPath - Optional custom config file path. If provided, only this path will be checked.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Use default search paths\n\t * const loader1 = new ConfigLoader();\n\t *\n\t * // Use a specific config file\n\t * const loader2 = new ConfigLoader('./custom-config.json');\n\t * ```\n\t */\n\tconstructor(customPath?: string) {\n\t\tthis._configPaths = customPath\n\t\t\t? [customPath]\n\t\t\t: [\n\t\t\t\t\t'.claude/config.json',\n\t\t\t\t\t'.claude/config.yaml',\n\t\t\t\t\t'.claude/config.yml',\n\t\t\t\t\tjoin(homedir(), '.claude/config.json'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yaml'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yml'),\n\t\t\t\t];\n\t}\n\n\t/**\n\t * Loads configuration from files and applies environment overrides.\n\t *\n\t * Searches for config files in the configured paths (in priority order),\n\t * parses the first match, and applies environment variable overrides.\n\t * Returns null if no config file is found and no environment overrides are set.\n\t *\n\t * @returns The loaded configuration with environment overrides applied, or null if no config found\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t *\n\t * if (config) {\n\t * console.log('Max history size:', config.maxHistorySize);\n\t * console.log('Log level:', config.logLevel);\n\t * }\n\t * ```\n\t */\n\tload(): ConfigFileOptions | null {\n\t\tlet config: ConfigFileOptions | null = null;\n\n\t\tfor (const configPath of this._configPaths) {\n\t\t\tif (existsSync(configPath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconfig = this.parseConfig(configPath);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Failed to load config from ${configPath}:`,\n\t\t\t\t\t\tgetErrorMessage(error)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.applyEnvironmentOverrides(config || {});\n\t}\n\n\t/**\n\t * Applies environment variable overrides to the configuration.\n\t *\n\t * Environment variables take precedence over file-based configuration.\n\t * Supported environment variables:\n\t * - `MAX_HISTORY_SIZE`, `MAX_BRANCHES`, `MAX_BRANCH_SIZE` (numbers)\n\t * - `LOG_LEVEL` (debug/info/warn/error)\n\t * - `PRETTY_LOG` (\"false\" to disable)\n\t * - `SKILL_DIRS` (colon-separated paths)\n\t * - `DISCOVERY_CACHE_TTL` (in seconds, converted to ms)\n\t * - `DISCOVERY_CACHE_MAX_SIZE` (number)\n\t *\n\t * @param config - The configuration to apply overrides to\n\t * @returns A new configuration object with environment overrides applied\n\t * @private\n\t */\n\tprivate applyEnvironmentOverrides(config: ConfigFileOptions): ConfigFileOptions {\n\t\tconst result: Mutable<ConfigFileOptions> = { ...config };\n\n\t\tif (process.env.MAX_HISTORY_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_HISTORY_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxHistorySize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCHES) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCHES, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranches = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCH_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCH_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranchSize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\tprocess.env.LOG_LEVEL &&\n\t\t\t['debug', 'info', 'warn', 'error'].includes(process.env.LOG_LEVEL)\n\t\t) {\n\t\t\tresult.logLevel = process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error';\n\t\t}\n\t\tif (process.env.PRETTY_LOG === 'false') {\n\t\t\tresult.prettyLog = false;\n\t\t}\n\t\tif (process.env.SKILL_DIRS) {\n\t\t\tresult.skillDirs = process.env.SKILL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_TTL) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_TTL, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = { ...(result.discoveryCache ?? {}), ttl: parsed * 1000 };\n\t\t\t}\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_MAX_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_MAX_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = { ...(result.discoveryCache ?? {}), maxSize: parsed };\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveTtlMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveSweepMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.SESSION_MAX_PER_OWNER) {\n\t\t\tconst parsed = parseInt(process.env.SESSION_MAX_PER_OWNER, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxSessionsPerOwner = parsed;\n\t\t\t}\n\t\t}\n\n\t\tthis.applyFeatureFlagOverrides(result);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Applies TRACELATTICE_FEATURES_* environment variable overrides for feature flags.\n\t * Booleans accept 'true'/'false'/'1'/'0' (case-insensitive).\n\t * Invalid reasoningStrategy values are warned and ignored (fall back to default).\n\t *\n\t * @param result - Configuration object to mutate with feature flag overrides\n\t * @private\n\t */\n\tprivate applyFeatureFlagOverrides(result: Mutable<ConfigFileOptions>): void {\n\t\tconst boolMap: Record<string, Exclude<keyof FeatureFlags, 'reasoningStrategy'>> = {\n\t\t\tTRACELATTICE_FEATURES_DAG_EDGES: 'dagEdges',\n\t\t\tTRACELATTICE_FEATURES_CALIBRATION: 'calibration',\n\t\t\tTRACELATTICE_FEATURES_COMPRESSION: 'compression',\n\t\t\tTRACELATTICE_FEATURES_TOOL_INTERLEAVE: 'toolInterleave',\n\t\t\tTRACELATTICE_FEATURES_NEW_THOUGHT_TYPES: 'newThoughtTypes',\n\t\t\tTRACELATTICE_FEATURES_OUTCOME_RECORDING: 'outcomeRecording',\n\t\t};\n\t\tfor (const [envVar, key] of Object.entries(boolMap)) {\n\t\t\tconst raw = process.env[envVar];\n\t\t\tif (raw === undefined) continue;\n\t\t\tconst parsed = this.parseBoolean(raw);\n\t\t\tif (parsed === undefined) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid boolean value for ${envVar}: \"${raw}\" (expected true/false/1/0). Ignoring.`\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\tresult.features ?? {};\n\t\t\tfeatures[key] = parsed;\n\t\t\tresult.features = features;\n\t\t}\n\n\t\tconst strategyRaw = process.env.TRACELATTICE_FEATURES_REASONING_STRATEGY;\n\t\tif (strategyRaw !== undefined) {\n\t\t\tconst allowed = ['sequential', 'tot'] as const;\n\t\t\tif ((allowed as readonly string[]).includes(strategyRaw)) {\n\t\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\t\tresult.features ?? {};\n\t\t\t\tfeatures.reasoningStrategy = strategyRaw as 'sequential' | 'tot';\n\t\t\t\tresult.features = features;\n\t\t\t} else {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid value for TRACELATTICE_FEATURES_REASONING_STRATEGY: \"${strategyRaw}\" ` +\n\t\t\t\t\t\t`(expected one of ${allowed.join(', ')}). Falling back to 'sequential'.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses a boolean from an environment variable string.\n\t * Accepts 'true'/'false'/'1'/'0' case-insensitively.\n\t *\n\t * @param raw - Raw environment variable string\n\t * @returns Parsed boolean, or undefined if the value is invalid\n\t * @private\n\t */\n\tprivate parseBoolean(raw: string): boolean | undefined {\n\t\tconst v = raw.trim().toLowerCase();\n\t\tif (v === 'true' || v === '1') return true;\n\t\tif (v === 'false' || v === '0') return false;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Parses a configuration file (JSON or YAML).\n\t *\n\t * Detects the file type by extension and uses the appropriate parser.\n\t * Supports `.json`, `.yaml`, and `.yml` file extensions.\n\t *\n\t * @param filePath - Path to the configuration file to parse\n\t * @returns The parsed configuration object\n\t * @throws {Error} If the file cannot be parsed\n\t * @private\n\t */\n\tprivate parseConfig(filePath: string): ConfigFileOptions {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst ext = filePath.split('.').pop()?.toLowerCase();\n\n\t\tif (ext === 'yaml' || ext === 'yml') {\n\t\t\treturn parseYaml(content) as ConfigFileOptions;\n\t\t}\n\n\t\treturn JSON.parse(content) as ConfigFileOptions;\n\t}\n\n\t/**\n\t * Converts file-based configuration to ServerConfig options.\n\t *\n\t * This is a convenience method for extracting the ServerConfig-relevant\n\t * options from a file-based configuration.\n\t *\n\t * @param config - The configuration to convert\n\t * @returns An object with ServerConfig-compatible options\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t * if (config) {\n\t * const serverOpts = loader.toServerConfigOptions(config);\n\t * const serverConfig = new ServerConfig(serverOpts);\n\t * }\n\t * ```\n\t */\n\ttoServerConfigOptions(config: ConfigFileOptions): {\n\t\tmaxHistorySize?: number;\n\t\tmaxBranches?: number;\n\t\tmaxBranchSize?: number;\n\t\tfeatures?: Partial<FeatureFlags>;\n\t\ttoolInterleaveTtlMs?: number;\n\t\ttoolInterleaveSweepMs?: number;\n\t\tmaxSessionsPerOwner?: number;\n\t} {\n\t\treturn {\n\t\t\tmaxHistorySize: config.maxHistorySize,\n\t\t\tmaxBranches: config.maxBranches,\n\t\t\tmaxBranchSize: config.maxBranchSize,\n\t\t\tfeatures: config.features,\n\t\t\ttoolInterleaveTtlMs: config.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: config.toolInterleaveSweepMs,\n\t\t\tmaxSessionsPerOwner: config.maxSessionsPerOwner,\n\t\t};\n\t}\n}\n"],"names":["ConfigLoader","customPath","join","homedir","config","configPath","existsSync","error","console","getErrorMessage","result","process","parsed","parseInt","Number","boolMap","envVar","key","Object","raw","undefined","features","strategyRaw","allowed","v","filePath","content","readFileSync","ext","parseYaml","JSON"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config/ConfigLoader.js","sources":["../../src/config/ConfigLoader.ts"],"sourcesContent":["/**\n * Configuration file loading with environment variable override support.\n *\n * This module provides the `ConfigLoader` class which handles loading configuration\n * from YAML and JSON files in standard locations, with automatic environment variable\n * overrides for all settings.\n *\n * @module config\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport * as v from 'valibot';\nimport type { PersistenceConfig } from '../contracts/PersistenceBackend.js';\nimport { getErrorMessage } from '../errors.js';\nimport type { FeatureFlags } from '../contracts/features.js';\n\n/**\n * Lenient runtime schema for config files. Only validates top-level shape;\n * unknown extra fields are preserved by Valibot's default object behavior\n * being strict is avoided by using `v.looseObject`. All fields are optional.\n */\nconst ConfigFileOptionsSchema = v.looseObject({\n\tmaxHistorySize: v.optional(v.number()),\n\tmaxBranches: v.optional(v.number()),\n\tmaxBranchSize: v.optional(v.number()),\n\tlogLevel: v.optional(v.picklist(['debug', 'info', 'warn', 'error'])),\n\tprettyLog: v.optional(v.boolean()),\n\tskillDirs: v.optional(v.array(v.string())),\n\tdiscoveryCache: v.optional(\n\t\tv.looseObject({\n\t\t\tttl: v.optional(v.number()),\n\t\t\tmaxSize: v.optional(v.number()),\n\t\t})\n\t),\n\tpersistence: v.optional(v.looseObject({})),\n\tfeatures: v.optional(v.looseObject({})),\n\ttoolInterleaveTtlMs: v.optional(v.number()),\n\ttoolInterleaveSweepMs: v.optional(v.number()),\n\tmaxSessionsPerOwner: v.optional(v.number()),\n});\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\n/**\n * Configuration options loaded from config files.\n *\n * These options represent the structure of configuration files (JSON or YAML)\n * that can be loaded from standard locations. All values can be overridden\n * by environment variables.\n *\n * @example\n * ```yaml\n * # .claude/config.yaml\n * maxHistorySize: 500\n * maxBranches: 25\n * logLevel: debug\n * prettyLog: true\n * skillDirs:\n * - ./custom-skills\n * discoveryCache:\n * ttl: 600000\n * maxSize: 200\n * persistence:\n * enabled: true\n * backend: sqlite\n * options:\n * dbPath: ./data/history.db\n * ```\n */\nexport interface ConfigFileOptions {\n\t/**\n\t * Maximum number of thoughts to keep in history.\n\t * Can be overridden by `MAX_HISTORY_SIZE` environment variable.\n\t */\n\treadonly maxHistorySize?: number;\n\n\t/**\n\t * Maximum number of branches to maintain.\n\t * Can be overridden by `MAX_BRANCHES` environment variable.\n\t */\n\treadonly maxBranches?: number;\n\n\t/**\n\t * Maximum size of each branch.\n\t * Can be overridden by `MAX_BRANCH_SIZE` environment variable.\n\t */\n\treadonly maxBranchSize?: number;\n\n\t/**\n\t * Logging level for the application.\n\t * Can be overridden by `LOG_LEVEL` environment variable.\n\t */\n\treadonly logLevel?: 'debug' | 'info' | 'warn' | 'error';\n\n\t/**\n\t * Whether to enable pretty (formatted) logging output.\n\t * Can be overridden by `PRETTY_LOG` environment variable (set to \"false\" to disable).\n\t */\n\treadonly prettyLog?: boolean;\n\n\t/**\n\t * Directory paths to search for skills.\n\t * Can be overridden by `SKILL_DIRS` environment variable (colon-separated).\n\t */\n\treadonly skillDirs?: string[];\n\n\t/**\n\t * Discovery cache configuration.\n\t * Can be overridden by `DISCOVERY_CACHE_TTL` and `DISCOVERY_CACHE_MAX_SIZE` environment variables.\n\t */\n\treadonly discoveryCache?: {\n\t\t/**\n\t\t * Time-to-live for cache entries in milliseconds.\n\t\t * Environment variable `DISCOVERY_CACHE_TTL` accepts seconds.\n\t\t */\n\t\treadonly ttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t */\n\t\treadonly maxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\treadonly persistence?: PersistenceConfig;\n\n\t/**\n\t * Feature flag overrides. Each field can be set independently.\n\t * Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.\n\t */\n\treadonly features?: Partial<FeatureFlags>;\n\n\t/**\n\t * TTL in milliseconds for suspended tool-interleave entries.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_TTL_MS` environment variable.\n\t */\n\treadonly toolInterleaveTtlMs?: number;\n\n\t/**\n\t * Sweep interval in milliseconds for SuspensionStore expiration cleanup.\n\t * Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` environment variable.\n\t */\n\treadonly toolInterleaveSweepMs?: number;\n\n\t/**\n\t * Maximum sessions per owner. Per-owner LRU bucket prevents one user from\n\t * consuming all session slots.\n\t * Can be overridden by `SESSION_MAX_PER_OWNER` environment variable.\n\t */\n\treadonly maxSessionsPerOwner?: number;\n}\n\n/**\n * Loads configuration from files with environment variable overrides.\n *\n * This class searches for configuration files in standard locations and applies\n * environment variable overrides. Files are searched in priority order, with the\n * first match being used. Environment variables always take precedence over file values.\n *\n * @remarks\n * **Config File Search Order (priority):**\n * 1. Custom path (if provided to constructor)\n * 2. `.claude/config.json` (project-local)\n * 3. `.claude/config.yaml` (project-local)\n * 4. `.claude/config.yml` (project-local)\n * 5. `~/.claude/config.json` (user-global)\n * 6. `~/.claude/config.yaml` (user-global)\n * 7. `~/.claude/config.yml` (user-global)\n *\n * **Environment Variable Overrides:**\n * | Variable | Type | Description |\n * |----------|------|-------------|\n * | `MAX_HISTORY_SIZE` | number | Max thoughts in history |\n * | `MAX_BRANCHES` | number | Max number of branches |\n * | `MAX_BRANCH_SIZE` | number | Max size of each branch |\n * | `LOG_LEVEL` | string | Logging level (debug/info/warn/error) |\n * | `PRETTY_LOG` | string | \"false\" to disable pretty logging |\n * | `SKILL_DIRS` | string | Colon-separated directory paths |\n * | `DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |\n * | `DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |\n *\n * @example\n * ```typescript\n * // Use default search paths\n * const loader1 = new ConfigLoader();\n * const config1 = loader1.load();\n *\n * // Use custom config path\n * const loader2 = new ConfigLoader('./my-config.yaml');\n * const config2 = loader2.load();\n *\n * // Convert to ServerConfig options\n * const serverOptions = loader2.toServerConfigOptions(config2);\n * ```\n */\nexport class ConfigLoader {\n\t/** Array of config file paths to search, in priority order. */\n\tprivate _configPaths: string[];\n\n\t/**\n\t * Creates a new ConfigLoader instance.\n\t *\n\t * @param customPath - Optional custom config file path. If provided, only this path will be checked.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Use default search paths\n\t * const loader1 = new ConfigLoader();\n\t *\n\t * // Use a specific config file\n\t * const loader2 = new ConfigLoader('./custom-config.json');\n\t * ```\n\t */\n\tconstructor(customPath?: string) {\n\t\tthis._configPaths = customPath\n\t\t\t? [customPath]\n\t\t\t: [\n\t\t\t\t\t'.claude/config.json',\n\t\t\t\t\t'.claude/config.yaml',\n\t\t\t\t\t'.claude/config.yml',\n\t\t\t\t\tjoin(homedir(), '.claude/config.json'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yaml'),\n\t\t\t\t\tjoin(homedir(), '.claude/config.yml'),\n\t\t\t\t];\n\t}\n\n\t/**\n\t * Loads configuration from files and applies environment overrides.\n\t *\n\t * Searches for config files in the configured paths (in priority order),\n\t * parses the first match, and applies environment variable overrides.\n\t * Returns null if no config file is found and no environment overrides are set.\n\t *\n\t * @returns The loaded configuration with environment overrides applied, or null if no config found\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t *\n\t * if (config) {\n\t * console.log('Max history size:', config.maxHistorySize);\n\t * console.log('Log level:', config.logLevel);\n\t * }\n\t * ```\n\t */\n\tload(): ConfigFileOptions | null {\n\t\tlet config: ConfigFileOptions | null = null;\n\n\t\tfor (const configPath of this._configPaths) {\n\t\t\tif (existsSync(configPath)) {\n\t\t\t\ttry {\n\t\t\t\t\tconfig = this.parseConfig(configPath);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Failed to load config from ${configPath}:`,\n\t\t\t\t\t\tgetErrorMessage(error)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.applyEnvironmentOverrides(config || {});\n\t}\n\n\t/**\n\t * Applies environment variable overrides to the configuration.\n\t *\n\t * Environment variables take precedence over file-based configuration.\n\t * Supported environment variables:\n\t * - `MAX_HISTORY_SIZE`, `MAX_BRANCHES`, `MAX_BRANCH_SIZE` (numbers)\n\t * - `LOG_LEVEL` (debug/info/warn/error)\n\t * - `PRETTY_LOG` (\"false\" to disable)\n\t * - `SKILL_DIRS` (colon-separated paths)\n\t * - `DISCOVERY_CACHE_TTL` (in seconds, converted to ms)\n\t * - `DISCOVERY_CACHE_MAX_SIZE` (number)\n\t *\n\t * @param config - The configuration to apply overrides to\n\t * @returns A new configuration object with environment overrides applied\n\t * @private\n\t */\n\tprivate applyEnvironmentOverrides(config: ConfigFileOptions): ConfigFileOptions {\n\t\tconst result: Mutable<ConfigFileOptions> = { ...config };\n\n\t\tif (process.env.MAX_HISTORY_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_HISTORY_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxHistorySize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCHES) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCHES, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranches = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.MAX_BRANCH_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.MAX_BRANCH_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxBranchSize = parsed;\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\tprocess.env.LOG_LEVEL &&\n\t\t\t['debug', 'info', 'warn', 'error'].includes(process.env.LOG_LEVEL)\n\t\t) {\n\t\t\tresult.logLevel = process.env.LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error';\n\t\t}\n\t\tif (process.env.PRETTY_LOG === 'false') {\n\t\t\tresult.prettyLog = false;\n\t\t}\n\t\tif (process.env.SKILL_DIRS) {\n\t\t\tresult.skillDirs = process.env.SKILL_DIRS.split(':');\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_TTL) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_TTL, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = { ...(result.discoveryCache ?? {}), ttl: parsed * 1000 };\n\t\t\t}\n\t\t}\n\t\tif (process.env.DISCOVERY_CACHE_MAX_SIZE) {\n\t\t\tconst parsed = parseInt(process.env.DISCOVERY_CACHE_MAX_SIZE, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.discoveryCache = { ...(result.discoveryCache ?? {}), maxSize: parsed };\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveTtlMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS) {\n\t\t\tconst parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.toolInterleaveSweepMs = parsed;\n\t\t\t}\n\t\t}\n\t\tif (process.env.SESSION_MAX_PER_OWNER) {\n\t\t\tconst parsed = parseInt(process.env.SESSION_MAX_PER_OWNER, 10);\n\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\tresult.maxSessionsPerOwner = parsed;\n\t\t\t}\n\t\t}\n\n\t\tthis.applyFeatureFlagOverrides(result);\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Applies TRACELATTICE_FEATURES_* environment variable overrides for feature flags.\n\t * Booleans accept 'true'/'false'/'1'/'0' (case-insensitive).\n\t * Invalid reasoningStrategy values are warned and ignored (fall back to default).\n\t *\n\t * @param result - Configuration object to mutate with feature flag overrides\n\t * @private\n\t */\n\tprivate applyFeatureFlagOverrides(result: Mutable<ConfigFileOptions>): void {\n\t\tconst boolMap: Record<string, Exclude<keyof FeatureFlags, 'reasoningStrategy'>> = {\n\t\t\tTRACELATTICE_FEATURES_DAG_EDGES: 'dagEdges',\n\t\t\tTRACELATTICE_FEATURES_CALIBRATION: 'calibration',\n\t\t\tTRACELATTICE_FEATURES_COMPRESSION: 'compression',\n\t\t\tTRACELATTICE_FEATURES_TOOL_INTERLEAVE: 'toolInterleave',\n\t\t\tTRACELATTICE_FEATURES_NEW_THOUGHT_TYPES: 'newThoughtTypes',\n\t\t\tTRACELATTICE_FEATURES_OUTCOME_RECORDING: 'outcomeRecording',\n\t\t};\n\t\tfor (const [envVar, key] of Object.entries(boolMap)) {\n\t\t\tconst raw = process.env[envVar];\n\t\t\tif (raw === undefined) continue;\n\t\t\tconst parsed = this.parseBoolean(raw);\n\t\t\tif (parsed === undefined) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid boolean value for ${envVar}: \"${raw}\" (expected true/false/1/0). Ignoring.`\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\tresult.features ?? {};\n\t\t\tfeatures[key] = parsed;\n\t\t\tresult.features = features;\n\t\t}\n\n\t\tconst strategyRaw = process.env.TRACELATTICE_FEATURES_REASONING_STRATEGY;\n\t\tif (strategyRaw !== undefined) {\n\t\t\tconst allowed = ['sequential', 'tot'] as const;\n\t\t\tif ((allowed as readonly string[]).includes(strategyRaw)) {\n\t\t\t\tconst features: { -readonly [K in keyof FeatureFlags]?: FeatureFlags[K] } =\n\t\t\t\t\tresult.features ?? {};\n\t\t\t\tfeatures.reasoningStrategy = strategyRaw as 'sequential' | 'tot';\n\t\t\t\tresult.features = features;\n\t\t\t} else {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Invalid value for TRACELATTICE_FEATURES_REASONING_STRATEGY: \"${strategyRaw}\" ` +\n\t\t\t\t\t\t`(expected one of ${allowed.join(', ')}). Falling back to 'sequential'.`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses a boolean from an environment variable string.\n\t * Accepts 'true'/'false'/'1'/'0' case-insensitively.\n\t *\n\t * @param raw - Raw environment variable string\n\t * @returns Parsed boolean, or undefined if the value is invalid\n\t * @private\n\t */\n\tprivate parseBoolean(raw: string): boolean | undefined {\n\t\tconst v = raw.trim().toLowerCase();\n\t\tif (v === 'true' || v === '1') return true;\n\t\tif (v === 'false' || v === '0') return false;\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Parses a configuration file (JSON or YAML).\n\t *\n\t * Detects the file type by extension and uses the appropriate parser.\n\t * Supports `.json`, `.yaml`, and `.yml` file extensions.\n\t *\n\t * @param filePath - Path to the configuration file to parse\n\t * @returns The parsed configuration object\n\t * @throws {Error} If the file cannot be parsed\n\t * @private\n\t */\n\tprivate parseConfig(filePath: string): ConfigFileOptions {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst ext = filePath.split('.').pop()?.toLowerCase();\n\n\t\tconst raw: unknown =\n\t\t\text === 'yaml' || ext === 'yml' ? parseYaml(content) : JSON.parse(content);\n\n\t\treturn v.parse(ConfigFileOptionsSchema, raw) as ConfigFileOptions;\n\t}\n\n\t/**\n\t * Converts file-based configuration to ServerConfig options.\n\t *\n\t * This is a convenience method for extracting the ServerConfig-relevant\n\t * options from a file-based configuration.\n\t *\n\t * @param config - The configuration to convert\n\t * @returns An object with ServerConfig-compatible options\n\t *\n\t * @example\n\t * ```typescript\n\t * const loader = new ConfigLoader();\n\t * const config = loader.load();\n\t * if (config) {\n\t * const serverOpts = loader.toServerConfigOptions(config);\n\t * const serverConfig = new ServerConfig(serverOpts);\n\t * }\n\t * ```\n\t */\n\ttoServerConfigOptions(config: ConfigFileOptions): {\n\t\tmaxHistorySize?: number;\n\t\tmaxBranches?: number;\n\t\tmaxBranchSize?: number;\n\t\tfeatures?: Partial<FeatureFlags>;\n\t\ttoolInterleaveTtlMs?: number;\n\t\ttoolInterleaveSweepMs?: number;\n\t\tmaxSessionsPerOwner?: number;\n\t} {\n\t\treturn {\n\t\t\tmaxHistorySize: config.maxHistorySize,\n\t\t\tmaxBranches: config.maxBranches,\n\t\t\tmaxBranchSize: config.maxBranchSize,\n\t\t\tfeatures: config.features,\n\t\t\ttoolInterleaveTtlMs: config.toolInterleaveTtlMs,\n\t\t\ttoolInterleaveSweepMs: config.toolInterleaveSweepMs,\n\t\t\tmaxSessionsPerOwner: config.maxSessionsPerOwner,\n\t\t};\n\t}\n}\n"],"names":["ConfigFileOptionsSchema","v","ConfigLoader","customPath","join","homedir","config","configPath","existsSync","error","console","getErrorMessage","result","process","parsed","parseInt","Number","boolMap","envVar","key","Object","raw","undefined","features","strategyRaw","allowed","filePath","content","readFileSync","ext","parseYaml","JSON"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ThoughtData } from '../core/thought.js';
|
|
2
2
|
import type { Edge } from '../core/graph/Edge.js';
|
|
3
3
|
import type { Summary } from '../core/compression/Summary.js';
|
|
4
|
-
import type { BranchId } from './ids.js';
|
|
4
|
+
import type { BranchId, SessionId } from './ids.js';
|
|
5
5
|
/**
|
|
6
6
|
* Persistence backend interface for storing thought history and branches.
|
|
7
7
|
*
|
|
@@ -63,7 +63,7 @@ export interface PersistenceBackend {
|
|
|
63
63
|
* @param sessionId - The session whose edges to persist
|
|
64
64
|
* @param edges - Array of edges to save
|
|
65
65
|
*/
|
|
66
|
-
saveEdges(sessionId:
|
|
66
|
+
saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void>;
|
|
67
67
|
/**
|
|
68
68
|
* Load edges for a session from persistent storage.
|
|
69
69
|
* Returns edges in chronological order (by createdAt ascending).
|
|
@@ -72,20 +72,20 @@ export interface PersistenceBackend {
|
|
|
72
72
|
* @param sessionId - The session whose edges to load
|
|
73
73
|
* @returns Array of persisted edges, sorted by createdAt
|
|
74
74
|
*/
|
|
75
|
-
loadEdges(sessionId:
|
|
75
|
+
loadEdges(sessionId: SessionId): Promise<Edge[]>;
|
|
76
76
|
/**
|
|
77
77
|
* List all session IDs that have persisted edge data.
|
|
78
78
|
*
|
|
79
79
|
* @returns Array of session identifiers with persisted edges
|
|
80
80
|
*/
|
|
81
|
-
listEdgeSessions(): Promise<
|
|
81
|
+
listEdgeSessions(): Promise<SessionId[]>;
|
|
82
82
|
/**
|
|
83
83
|
* Save summaries for a session, replacing any previously saved summaries.
|
|
84
84
|
*
|
|
85
85
|
* @param sessionId - The session whose summaries to persist
|
|
86
86
|
* @param summaries - Array of summaries to save
|
|
87
87
|
*/
|
|
88
|
-
saveSummaries(sessionId:
|
|
88
|
+
saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void>;
|
|
89
89
|
/**
|
|
90
90
|
* Load summaries for a session from persistent storage.
|
|
91
91
|
* Returns summaries in chronological order (by createdAt ascending).
|
|
@@ -94,7 +94,7 @@ export interface PersistenceBackend {
|
|
|
94
94
|
* @param sessionId - The session whose summaries to load
|
|
95
95
|
* @returns Array of persisted summaries, sorted by createdAt
|
|
96
96
|
*/
|
|
97
|
-
loadSummaries(sessionId:
|
|
97
|
+
loadSummaries(sessionId: SessionId): Promise<Summary[]>;
|
|
98
98
|
}
|
|
99
99
|
export interface PersistenceConfig {
|
|
100
100
|
enabled?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersistenceBackend.d.ts","sourceRoot":"","sources":["../../src/contracts/PersistenceBackend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"PersistenceBackend.d.ts","sourceRoot":"","sources":["../../src/contracts/PersistenceBackend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvE;;;;;OAKG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,CAAC;IAEnE;;;;OAIG;IACH,YAAY,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEpC;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5B;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvE;;;;;;;OAOG;IACH,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAEjD;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAEzC;;;;;OAKG;IACH,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF;;;;;;;OAOG;IACH,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,OAAO,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACF"}
|