tracelattice 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/dist/__tests__/integration/dag-edges.test.d.ts +15 -0
  2. package/dist/__tests__/integration/dag-edges.test.d.ts.map +1 -1
  3. package/dist/__tests__/typing.test-d.d.ts +16 -0
  4. package/dist/__tests__/typing.test-d.d.ts.map +1 -0
  5. package/dist/cli.js +165 -60
  6. package/dist/config/ConfigLoader.d.ts.map +1 -1
  7. package/dist/config/ConfigLoader.js +25 -2
  8. package/dist/config/ConfigLoader.js.map +1 -1
  9. package/dist/contracts/PersistenceBackend.d.ts +6 -6
  10. package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
  11. package/dist/contracts/calibrator.d.ts +4 -3
  12. package/dist/contracts/calibrator.d.ts.map +1 -1
  13. package/dist/contracts/features.d.ts +0 -4
  14. package/dist/contracts/features.d.ts.map +1 -1
  15. package/dist/contracts/features.js +1 -4
  16. package/dist/contracts/features.js.map +1 -1
  17. package/dist/contracts/ids.d.ts +6 -0
  18. package/dist/contracts/ids.d.ts.map +1 -1
  19. package/dist/contracts/ids.js +8 -2
  20. package/dist/contracts/ids.js.map +1 -1
  21. package/dist/contracts/interfaces.d.ts +11 -11
  22. package/dist/contracts/interfaces.d.ts.map +1 -1
  23. package/dist/contracts/summary.d.ts +6 -6
  24. package/dist/contracts/summary.d.ts.map +1 -1
  25. package/dist/contracts/suspension.d.ts +1 -1
  26. package/dist/contracts/suspension.d.ts.map +1 -1
  27. package/dist/contracts/transport.d.ts +2 -1
  28. package/dist/contracts/transport.d.ts.map +1 -1
  29. package/dist/core/HistoryManager.d.ts.map +1 -1
  30. package/dist/core/HistoryManager.js +7 -7
  31. package/dist/core/HistoryManager.js.map +1 -1
  32. package/dist/core/PersistenceBuffer.d.ts +3 -2
  33. package/dist/core/PersistenceBuffer.d.ts.map +1 -1
  34. package/dist/core/PersistenceBuffer.js +1 -2
  35. package/dist/core/PersistenceBuffer.js.map +1 -1
  36. package/dist/core/SessionLock.d.ts.map +1 -1
  37. package/dist/core/SessionLock.js +2 -2
  38. package/dist/core/SessionLock.js.map +1 -1
  39. package/dist/core/SessionManager.d.ts +4 -3
  40. package/dist/core/SessionManager.d.ts.map +1 -1
  41. package/dist/core/SessionManager.js.map +1 -1
  42. package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
  43. package/dist/core/ThoughtEvaluator.js +2 -1
  44. package/dist/core/ThoughtEvaluator.js.map +1 -1
  45. package/dist/core/ThoughtProcessor.d.ts +1 -1
  46. package/dist/core/ThoughtProcessor.d.ts.map +1 -1
  47. package/dist/core/ThoughtProcessor.js.map +1 -1
  48. package/dist/core/compression/CompressionService.d.ts +2 -2
  49. package/dist/core/compression/CompressionService.d.ts.map +1 -1
  50. package/dist/core/compression/CompressionService.js +4 -5
  51. package/dist/core/compression/CompressionService.js.map +1 -1
  52. package/dist/core/compression/DehydrationPolicy.d.ts +2 -1
  53. package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -1
  54. package/dist/core/compression/DehydrationPolicy.js.map +1 -1
  55. package/dist/core/compression/InMemorySummaryStore.d.ts +1 -1
  56. package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -1
  57. package/dist/core/compression/InMemorySummaryStore.js +13 -12
  58. package/dist/core/compression/InMemorySummaryStore.js.map +1 -1
  59. package/dist/core/compression/Summary.d.ts +18 -0
  60. package/dist/core/compression/Summary.d.ts.map +1 -1
  61. package/dist/core/compression/Summary.js +16 -1
  62. package/dist/core/compression/Summary.js.map +1 -0
  63. package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
  64. package/dist/core/evaluator/Calibrator.js.map +1 -1
  65. package/dist/core/evaluator/PatternDetector.d.ts.map +1 -1
  66. package/dist/core/evaluator/PatternDetector.js +8 -4
  67. package/dist/core/evaluator/PatternDetector.js.map +1 -1
  68. package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
  69. package/dist/core/graph/EdgeEmitter.js +6 -0
  70. package/dist/core/graph/EdgeEmitter.js.map +1 -1
  71. package/dist/core/graph/EdgeStore.d.ts +1 -1
  72. package/dist/core/graph/EdgeStore.d.ts.map +1 -1
  73. package/dist/core/graph/EdgeStore.js +4 -3
  74. package/dist/core/graph/EdgeStore.js.map +1 -1
  75. package/dist/core/graph/GraphView.d.ts +7 -7
  76. package/dist/core/graph/GraphView.d.ts.map +1 -1
  77. package/dist/core/graph/GraphView.js.map +1 -1
  78. package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -1
  79. package/dist/core/reasoning/OutcomeRecorder.js +6 -4
  80. package/dist/core/reasoning/OutcomeRecorder.js.map +1 -1
  81. package/dist/core/reasoning/strategies/StrategyFactory.d.ts.map +1 -1
  82. package/dist/core/reasoning/strategies/StrategyFactory.js +2 -1
  83. package/dist/core/reasoning/strategies/StrategyFactory.js.map +1 -1
  84. package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -1
  85. package/dist/core/reasoning/strategies/totScoring.js +10 -1
  86. package/dist/core/reasoning/strategies/totScoring.js.map +1 -1
  87. package/dist/core/thought.d.ts +1 -1
  88. package/dist/core/thought.d.ts.map +1 -1
  89. package/dist/core/tools/InMemorySuspensionStore.d.ts.map +1 -1
  90. package/dist/core/tools/InMemorySuspensionStore.js +4 -4
  91. package/dist/core/tools/InMemorySuspensionStore.js.map +1 -1
  92. package/dist/di/Container.d.ts +26 -6
  93. package/dist/di/Container.d.ts.map +1 -1
  94. package/dist/di/Container.js +12 -0
  95. package/dist/di/Container.js.map +1 -1
  96. package/dist/di/ServiceRegistry.d.ts +2 -1
  97. package/dist/di/ServiceRegistry.d.ts.map +1 -1
  98. package/dist/errors.d.ts +7 -6
  99. package/dist/errors.d.ts.map +1 -1
  100. package/dist/errors.js.map +1 -1
  101. package/dist/lib.d.ts +4 -4
  102. package/dist/lib.d.ts.map +1 -1
  103. package/dist/lib.js.map +1 -1
  104. package/dist/persistence/FilePersistence.d.ts +6 -6
  105. package/dist/persistence/FilePersistence.d.ts.map +1 -1
  106. package/dist/persistence/FilePersistence.js +55 -15
  107. package/dist/persistence/FilePersistence.js.map +1 -1
  108. package/dist/persistence/MemoryPersistence.d.ts +7 -7
  109. package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
  110. package/dist/persistence/MemoryPersistence.js.map +1 -1
  111. package/dist/persistence/SqlitePersistence.d.ts +8 -6
  112. package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
  113. package/dist/persistence/SqlitePersistence.js +39 -11
  114. package/dist/persistence/SqlitePersistence.js.map +1 -1
  115. package/dist/pool/ConnectionPool.d.ts +7 -6
  116. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  117. package/dist/pool/ConnectionPool.js +2 -1
  118. package/dist/pool/ConnectionPool.js.map +1 -1
  119. package/dist/pool/IConnectionPool.d.ts +5 -4
  120. package/dist/pool/IConnectionPool.d.ts.map +1 -1
  121. package/dist/registry/SkillRegistry.d.ts +1 -1
  122. package/dist/registry/SkillRegistry.d.ts.map +1 -1
  123. package/dist/registry/SkillRegistry.js.map +1 -1
  124. package/dist/registry/ToolRegistry.d.ts +1 -1
  125. package/dist/registry/ToolRegistry.d.ts.map +1 -1
  126. package/dist/registry/ToolRegistry.js.map +1 -1
  127. package/dist/transport/BaseTransport.d.ts +1 -1
  128. package/dist/transport/BaseTransport.d.ts.map +1 -1
  129. package/dist/transport/BaseTransport.js.map +1 -1
  130. package/dist/transport/HttpTransport.d.ts +1 -0
  131. package/dist/transport/HttpTransport.d.ts.map +1 -1
  132. package/dist/transport/HttpTransport.js +5 -1
  133. package/dist/transport/HttpTransport.js.map +1 -1
  134. package/dist/transport/SseTransport.d.ts +1 -0
  135. package/dist/transport/SseTransport.d.ts.map +1 -1
  136. package/dist/transport/SseTransport.js +8 -3
  137. package/dist/transport/SseTransport.js.map +1 -1
  138. package/dist/transport/StreamableHttpTransport.d.ts +2 -0
  139. package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
  140. package/dist/transport/StreamableHttpTransport.js +15 -6
  141. package/dist/transport/StreamableHttpTransport.js.map +1 -1
  142. package/dist/types/tool.d.ts +6 -1
  143. package/dist/types/tool.d.ts.map +1 -1
  144. package/package.json +17 -17
@@ -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
- 130(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1633
-
1634
- // EXPORTS
1754
+ 932(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1635
1755
  __webpack_require__.d(__webpack_exports__, {
1636
- j: () => (/* binding */ BaseTransport)
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__(130);
2017
- /* import */ var _context_RequestContext_js__rspack_import_6 = __webpack_require__(502);
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,_context_RequestContext_js__rspack_import_6/* .runWithContext */.Vo)({
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._mcpServer.receive(jsonRpcRequest, {
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 + 1 modules
2498
- var BaseTransport = __webpack_require__(130);
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._server.listen(this._port, this._host, ()=>{
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._mcpServer.receive(jsonRpcRequest, {
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;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAI7D;;;;;;;;;;;;;;;;;;;;;;;;;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;IAWnB;;;;;;;;;;;;;;;;;;OAkBG;IACH,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG;QACjD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC7B;CAWD"}
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
- if ('yaml' === ext || 'yml' === ext) return parse(content);
126
- return JSON.parse(content);
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: string, edges: readonly Edge[]): Promise<void>;
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: string): Promise<Edge[]>;
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<string[]>;
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: string, summaries: readonly Summary[]): Promise<void>;
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: string): Promise<Summary[]>;
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;AAEzC;;;;;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,MAAM,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;;;;;OAOG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAE9C;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtC;;;;;OAKG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/E;;;;;;;OAOG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACrD;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"}
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"}