tracelattice 1.3.3 → 1.3.4
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/ServerConfig.d.ts +14 -0
- package/dist/ServerConfig.d.ts.map +1 -1
- package/dist/ServerConfig.js +12 -1
- package/dist/ServerConfig.js.map +1 -1
- package/dist/__tests__/core/HistoryManager.ownership.test.d.ts +2 -0
- package/dist/__tests__/core/HistoryManager.ownership.test.d.ts.map +1 -0
- package/dist/__tests__/core/SessionLock.test.d.ts +6 -0
- package/dist/__tests__/core/SessionLock.test.d.ts.map +1 -0
- package/dist/__tests__/core/SessionManager.test.d.ts +8 -0
- package/dist/__tests__/core/SessionManager.test.d.ts.map +1 -0
- package/dist/__tests__/core/ThoughtProcessor.toolAllowlist.test.d.ts +2 -0
- package/dist/__tests__/core/ThoughtProcessor.toolAllowlist.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/factories.d.ts +7 -0
- package/dist/__tests__/helpers/factories.d.ts.map +1 -1
- package/dist/__tests__/sanitize.enforceJsonShape.test.d.ts +2 -0
- package/dist/__tests__/sanitize.enforceJsonShape.test.d.ts.map +1 -0
- package/dist/__tests__/transport-owner-context.test.d.ts +8 -0
- package/dist/__tests__/transport-owner-context.test.d.ts.map +1 -0
- package/dist/cli.js +176 -57
- package/dist/config/ConfigLoader.d.ts +7 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +6 -1
- package/dist/config/ConfigLoader.js.map +1 -1
- package/dist/context/RequestContext.d.ts +26 -0
- package/dist/context/RequestContext.d.ts.map +1 -1
- package/dist/context/RequestContext.js +7 -1
- package/dist/context/RequestContext.js.map +1 -1
- package/dist/contracts/features.d.ts +2 -2
- package/dist/contracts/features.js.map +1 -1
- package/dist/contracts/interfaces.d.ts +42 -0
- package/dist/contracts/interfaces.d.ts.map +1 -1
- package/dist/core/HistoryManager.d.ts +13 -1
- package/dist/core/HistoryManager.d.ts.map +1 -1
- package/dist/core/HistoryManager.js +25 -14
- package/dist/core/HistoryManager.js.map +1 -1
- package/dist/core/InputNormalizer.d.ts.map +1 -1
- package/dist/core/InputNormalizer.js +5 -2
- package/dist/core/InputNormalizer.js.map +1 -1
- package/dist/core/SessionLock.d.ts +56 -0
- package/dist/core/SessionLock.d.ts.map +1 -0
- package/dist/core/SessionLock.js +43 -0
- package/dist/core/SessionLock.js.map +1 -0
- package/dist/core/SessionManager.d.ts +18 -3
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +34 -1
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/ThoughtProcessor.d.ts +21 -2
- package/dist/core/ThoughtProcessor.d.ts.map +1 -1
- package/dist/core/ThoughtProcessor.js +33 -13
- package/dist/core/ThoughtProcessor.js.map +1 -1
- package/dist/di/ServiceRegistry.d.ts +3 -3
- package/dist/di/ServiceRegistry.d.ts.map +1 -1
- package/dist/errors.d.ts +48 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +38 -2
- package/dist/errors.js.map +1 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +9 -3
- package/dist/lib.js.map +1 -1
- package/dist/registry/ToolRegistry.d.ts +1 -0
- package/dist/registry/ToolRegistry.d.ts.map +1 -1
- package/dist/registry/ToolRegistry.js +3 -0
- package/dist/registry/ToolRegistry.js.map +1 -1
- package/dist/sanitize.d.ts +70 -0
- package/dist/sanitize.d.ts.map +1 -1
- package/dist/sanitize.js +77 -1
- package/dist/sanitize.js.map +1 -1
- package/dist/schema.d.ts +35 -35
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +15 -5
- package/dist/schema.js.map +1 -1
- package/dist/transport/HttpTransport.d.ts.map +1 -1
- package/dist/transport/HttpTransport.js +9 -3
- package/dist/transport/HttpTransport.js.map +1 -1
- package/dist/transport/SseTransport.d.ts.map +1 -1
- package/dist/transport/SseTransport.js +10 -3
- package/dist/transport/SseTransport.js.map +1 -1
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
- package/dist/transport/StreamableHttpTransport.js +8 -3
- package/dist/transport/StreamableHttpTransport.js.map +1 -1
- package/dist/types/tool.d.ts +1 -1
- package/dist/types/tool.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -4,13 +4,70 @@ import * as __rspack_external_node_crypto_9ba42079 from "node:crypto";
|
|
|
4
4
|
import * as __rspack_external_node_http_2dc67212 from "node:http";
|
|
5
5
|
import * as __rspack_external_node_url_e96de089 from "node:url";
|
|
6
6
|
import * as __rspack_external_valibot from "valibot";
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
7
|
+
import * as __rspack_external_node_async_hooks_e65a2d6c from "node:async_hooks";
|
|
8
|
+
import * as __rspack_external__tmcp_adapter_valibot_fbccc1df from "@tmcp/adapter-valibot";
|
|
9
|
+
import * as __rspack_external__tmcp_transport_stdio_9731848f from "@tmcp/transport-stdio";
|
|
10
|
+
import * as __rspack_external_node_fs_5ea92f0c from "node:fs";
|
|
11
|
+
import * as __rspack_external_node_path_c5b9b54f from "node:path";
|
|
12
|
+
import * as __rspack_external_tmcp from "tmcp";
|
|
13
13
|
var __webpack_modules__ = ({
|
|
14
|
+
923(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
15
|
+
|
|
16
|
+
// EXPORTS
|
|
17
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
18
|
+
RE: () => (/* binding */ getRequestId),
|
|
19
|
+
Vo: () => (/* binding */ runWithContext)
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// UNUSED EXPORTS: getOwner
|
|
23
|
+
|
|
24
|
+
;// CONCATENATED MODULE: external "node:async_hooks"
|
|
25
|
+
|
|
26
|
+
;// CONCATENATED MODULE: ./src/context/RequestContext.ts
|
|
27
|
+
/**
|
|
28
|
+
* Request context management using AsyncLocalStorage for correlation IDs.
|
|
29
|
+
*
|
|
30
|
+
* Provides zero-cost request ID propagation across async boundaries
|
|
31
|
+
* via Node.js AsyncLocalStorage.
|
|
32
|
+
*
|
|
33
|
+
* @module context
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* AsyncLocalStorage instance for request context.
|
|
37
|
+
* Stores requestId that propagates across async boundaries.
|
|
38
|
+
*/ const store = new __rspack_external_node_async_hooks_e65a2d6c.AsyncLocalStorage();
|
|
39
|
+
/**
|
|
40
|
+
* Get the current request ID from context.
|
|
41
|
+
*
|
|
42
|
+
* Returns undefined if called outside of a runWithContext() call.
|
|
43
|
+
*
|
|
44
|
+
* @returns The current request ID or undefined
|
|
45
|
+
*/ function getRequestId() {
|
|
46
|
+
return store.getStore()?.requestId;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Run a function with the given request context. The context propagates
|
|
50
|
+
* across async boundaries via AsyncLocalStorage.
|
|
51
|
+
*
|
|
52
|
+
* @param ctx - Request context to install (requestId, optional owner)
|
|
53
|
+
* @param fn - Function to execute within the context
|
|
54
|
+
* @returns The return value of `fn`
|
|
55
|
+
*/ function runWithContext(ctx, fn) {
|
|
56
|
+
return store.run(ctx, fn);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the current owner identifier from context.
|
|
60
|
+
*
|
|
61
|
+
* Returns undefined when called outside of a runWithContext() call or when
|
|
62
|
+
* the context did not specify an owner (e.g. stdio transport).
|
|
63
|
+
*
|
|
64
|
+
* @returns The current owner or undefined
|
|
65
|
+
*/ function getOwner() {
|
|
66
|
+
return store.getStore()?.owner;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
},
|
|
14
71
|
937(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
15
72
|
__webpack_require__.d(__webpack_exports__, {
|
|
16
73
|
Ag: () => (SessionNotFoundError),
|
|
@@ -69,8 +126,17 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
69
126
|
SUSPENSION_EXPIRED: 'SUSPENSION_EXPIRED',
|
|
70
127
|
INVALID_TOOL_CALL: 'INVALID_TOOL_CALL',
|
|
71
128
|
INVALID_BACKTRACK: 'INVALID_BACKTRACK',
|
|
72
|
-
DUPLICATE_SUMMARY: 'DUPLICATE_SUMMARY'
|
|
129
|
+
DUPLICATE_SUMMARY: 'DUPLICATE_SUMMARY',
|
|
130
|
+
UNKNOWN_TOOL: 'UNKNOWN_TOOL',
|
|
131
|
+
LOCK_TIMEOUT: 'LOCK_TIMEOUT',
|
|
132
|
+
SESSION_ACCESS_DENIED: 'SESSION_ACCESS_DENIED'
|
|
73
133
|
};
|
|
134
|
+
/**
|
|
135
|
+
* All known warning codes as a const object.
|
|
136
|
+
* Warnings are non-fatal advisory signals returned alongside successful results.
|
|
137
|
+
*/ const WARNING_CODES = (/* unused pure expression or super */ null && ({
|
|
138
|
+
TOTAL_THOUGHTS_ADJUSTED: 'TOTAL_THOUGHTS_ADJUSTED'
|
|
139
|
+
}));
|
|
74
140
|
/**
|
|
75
141
|
* Base error class for all Sequential Thinking server errors.
|
|
76
142
|
*
|
|
@@ -655,6 +721,55 @@ class ConfigurationError extends SequentialThinkingError {
|
|
|
655
721
|
this.name = 'InvalidBacktrackError';
|
|
656
722
|
}
|
|
657
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Error thrown when a tool_call references a tool not registered with the server.
|
|
726
|
+
*
|
|
727
|
+
* Acts as an allowlist gate: only tools registered in the ToolRegistry may be
|
|
728
|
+
* invoked through tool interleave. Prevents arbitrary tool name injection.
|
|
729
|
+
*/ class UnknownToolError extends SequentialThinkingError {
|
|
730
|
+
toolName;
|
|
731
|
+
constructor(toolName, message){
|
|
732
|
+
super(message ?? `Unknown tool '${toolName}': not registered with the server`, ERROR_CODES.UNKNOWN_TOOL);
|
|
733
|
+
this.name = 'UnknownToolError';
|
|
734
|
+
this.toolName = toolName;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Error thrown when a per-session async lock cannot be acquired in time.
|
|
739
|
+
*
|
|
740
|
+
* Indicates that a critical section held the lock for longer than the
|
|
741
|
+
* configured timeout, suggesting a stuck handler or deadlock.
|
|
742
|
+
*/ class LockTimeoutError extends SequentialThinkingError {
|
|
743
|
+
sessionId;
|
|
744
|
+
timeoutMs;
|
|
745
|
+
constructor(sessionId, timeoutMs){
|
|
746
|
+
super(`Lock timeout for session '${sessionId}' after ${timeoutMs}ms`, ERROR_CODES.LOCK_TIMEOUT);
|
|
747
|
+
this.name = 'LockTimeoutError';
|
|
748
|
+
this.sessionId = sessionId;
|
|
749
|
+
this.timeoutMs = timeoutMs;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Error thrown when a session is accessed by a non-owner.
|
|
754
|
+
*
|
|
755
|
+
* Sessions are bound to an owner identifier on first creation when accessed
|
|
756
|
+
* via a multi-user transport (SSE/HTTP). Subsequent access attempts using a
|
|
757
|
+
* different owner are rejected to prevent IDOR (Insecure Direct Object
|
|
758
|
+
* Reference) vulnerabilities.
|
|
759
|
+
*
|
|
760
|
+
* The stdio transport does not set an owner, so its sessions are unaffected.
|
|
761
|
+
*/ class SessionAccessDeniedError extends SequentialThinkingError {
|
|
762
|
+
sessionId;
|
|
763
|
+
expectedOwner;
|
|
764
|
+
actualOwner;
|
|
765
|
+
constructor(sessionId, expectedOwner, actualOwner){
|
|
766
|
+
super(`Access denied to session '${sessionId}': owned by '${expectedOwner}', accessed by '${actualOwner ?? 'anonymous'}'`, ERROR_CODES.SESSION_ACCESS_DENIED);
|
|
767
|
+
this.name = 'SessionAccessDeniedError';
|
|
768
|
+
this.sessionId = sessionId;
|
|
769
|
+
this.expectedOwner = expectedOwner;
|
|
770
|
+
this.actualOwner = actualOwner;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
658
773
|
/**
|
|
659
774
|
* Type guard to check if an error has a specific error code.
|
|
660
775
|
*/ function isErrorCode(err, code) {
|
|
@@ -1178,9 +1293,14 @@ You should:
|
|
|
1178
1293
|
*/ const ToolRecommendationSchema = valibot__rspack_import_0.object({
|
|
1179
1294
|
tool_name: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Name of the tool being recommended')),
|
|
1180
1295
|
confidence: valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('0-1 indicating confidence in recommendation')),
|
|
1181
|
-
rationale: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Why this tool is recommended')),
|
|
1296
|
+
rationale: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.maxLength(2000), valibot__rspack_import_0.description('Why this tool is recommended')),
|
|
1182
1297
|
priority: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.description('Order in the recommendation sequence (default: 999)'))),
|
|
1183
|
-
suggested_inputs: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.
|
|
1298
|
+
suggested_inputs: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.union([
|
|
1299
|
+
valibot__rspack_import_0.string(),
|
|
1300
|
+
valibot__rspack_import_0.number(),
|
|
1301
|
+
valibot__rspack_import_0.boolean(),
|
|
1302
|
+
valibot__rspack_import_0["null"]()
|
|
1303
|
+
])), valibot__rspack_import_0.description('Optional suggested parameters (flat key-value pairs only)'))),
|
|
1184
1304
|
alternatives: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Alternative tools that could be used')))
|
|
1185
1305
|
});
|
|
1186
1306
|
/**
|
|
@@ -1211,7 +1331,7 @@ You should:
|
|
|
1211
1331
|
*/ const SkillRecommendationSchema = valibot__rspack_import_0.object({
|
|
1212
1332
|
skill_name: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Name of the skill being recommended')),
|
|
1213
1333
|
confidence: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('0-1 indicating confidence in recommendation (default: 0.5)'))),
|
|
1214
|
-
rationale: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Why this skill is recommended (default: empty string)'))),
|
|
1334
|
+
rationale: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.maxLength(2000), valibot__rspack_import_0.description('Why this skill is recommended (default: empty string)'))),
|
|
1215
1335
|
priority: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.description('Order in the recommendation sequence (default: 999)'))),
|
|
1216
1336
|
alternatives: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Alternative skills that could be used'))),
|
|
1217
1337
|
allowed_tools: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Tools this skill is allowed to use (from skill frontmatter)'))),
|
|
@@ -1280,10 +1400,15 @@ You should:
|
|
|
1280
1400
|
* ```
|
|
1281
1401
|
*/ const PartialToolRecommendationSchema = valibot__rspack_import_0.object({
|
|
1282
1402
|
tool_name: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Name of the tool being recommended')),
|
|
1283
|
-
rationale: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Why this tool is recommended (default: empty string)'))),
|
|
1403
|
+
rationale: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.maxLength(2000), valibot__rspack_import_0.description('Why this tool is recommended (default: empty string)'))),
|
|
1284
1404
|
confidence: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(0), valibot__rspack_import_0.maxValue(1), valibot__rspack_import_0.description('0-1 indicating confidence in recommendation (default: 0.5)'))),
|
|
1285
1405
|
priority: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.description('Order in the recommendation sequence (default: 999)'))),
|
|
1286
|
-
suggested_inputs: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.
|
|
1406
|
+
suggested_inputs: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.record(valibot__rspack_import_0.string(), valibot__rspack_import_0.union([
|
|
1407
|
+
valibot__rspack_import_0.string(),
|
|
1408
|
+
valibot__rspack_import_0.number(),
|
|
1409
|
+
valibot__rspack_import_0.boolean(),
|
|
1410
|
+
valibot__rspack_import_0["null"]()
|
|
1411
|
+
])), valibot__rspack_import_0.description('Optional suggested parameters (flat key-value pairs only)'))),
|
|
1287
1412
|
alternatives: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.array(valibot__rspack_import_0.string()), valibot__rspack_import_0.description('Alternative tools that could be used')))
|
|
1288
1413
|
});
|
|
1289
1414
|
/**
|
|
@@ -1884,10 +2009,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1884
2009
|
SseTransport: () => (SseTransport)
|
|
1885
2010
|
});
|
|
1886
2011
|
/* import */ var node_http__rspack_import_0 = __webpack_require__(316);
|
|
1887
|
-
/* import */ var
|
|
1888
|
-
/* import */ var
|
|
1889
|
-
/* import */ var
|
|
1890
|
-
/* import */ var
|
|
2012
|
+
/* import */ var node_crypto__rspack_import_1 = __webpack_require__(561);
|
|
2013
|
+
/* import */ var node_url__rspack_import_2 = __webpack_require__(61);
|
|
2014
|
+
/* import */ var valibot__rspack_import_3 = __webpack_require__(821);
|
|
2015
|
+
/* import */ var _schema_js__rspack_import_4 = __webpack_require__(613);
|
|
2016
|
+
/* import */ var _BaseTransport_js__rspack_import_5 = __webpack_require__(419);
|
|
2017
|
+
/* import */ var _context_RequestContext_js__rspack_import_6 = __webpack_require__(923);
|
|
1891
2018
|
/**
|
|
1892
2019
|
* SSE (Server-Sent Events) Transport implementation.
|
|
1893
2020
|
*
|
|
@@ -1910,6 +2037,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1910
2037
|
|
|
1911
2038
|
|
|
1912
2039
|
|
|
2040
|
+
|
|
2041
|
+
|
|
1913
2042
|
/**
|
|
1914
2043
|
* SSE Transport for MCP server over HTTP.
|
|
1915
2044
|
*
|
|
@@ -1927,7 +2056,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1927
2056
|
* - Tracks requests per IP address within a time window
|
|
1928
2057
|
* - Returns 429 Too Many Requests when limit exceeded
|
|
1929
2058
|
* - Can be disabled via `enableRateLimit: false`
|
|
1930
|
-
*/ class SseTransport extends
|
|
2059
|
+
*/ class SseTransport extends _BaseTransport_js__rspack_import_5/* .BaseTransport */.j {
|
|
1931
2060
|
get kind() {
|
|
1932
2061
|
return 'sse';
|
|
1933
2062
|
}
|
|
@@ -1991,7 +2120,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
1991
2120
|
}));
|
|
1992
2121
|
return;
|
|
1993
2122
|
}
|
|
1994
|
-
const url = new
|
|
2123
|
+
const url = new node_url__rspack_import_2.URL(req.url || '', `http://${req.headers.host}`);
|
|
1995
2124
|
// Check rate limit first
|
|
1996
2125
|
const clientIp = this.getClientIp(req);
|
|
1997
2126
|
if (this.checkRateLimit(clientIp)) {
|
|
@@ -2182,7 +2311,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2182
2311
|
}
|
|
2183
2312
|
try {
|
|
2184
2313
|
const jsonRpcRequest = JSON.parse(body);
|
|
2185
|
-
const parseResult = (0,
|
|
2314
|
+
const parseResult = (0,valibot__rspack_import_3.safeParse)(_schema_js__rspack_import_4/* .JsonRpcRequestSchema */.Uv, jsonRpcRequest);
|
|
2186
2315
|
if (!parseResult.success) {
|
|
2187
2316
|
this._metrics?.counter('http_request_errors_total', 1, {
|
|
2188
2317
|
transport: 'sse',
|
|
@@ -2202,11 +2331,16 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2202
2331
|
}));
|
|
2203
2332
|
return;
|
|
2204
2333
|
}
|
|
2205
|
-
// Process message through MCP server
|
|
2334
|
+
// Process message through MCP server with owner context
|
|
2206
2335
|
if (this._mcpServer) {
|
|
2207
|
-
const
|
|
2208
|
-
|
|
2209
|
-
|
|
2336
|
+
const sessionId = this._clientSessionMap.get(res);
|
|
2337
|
+
const owner = sessionId ?? `sse-${(0,node_crypto__rspack_import_1.randomUUID)()}`;
|
|
2338
|
+
const response = await (0,_context_RequestContext_js__rspack_import_6/* .runWithContext */.Vo)({
|
|
2339
|
+
requestId: (0,node_crypto__rspack_import_1.randomUUID)(),
|
|
2340
|
+
owner
|
|
2341
|
+
}, ()=>this._mcpServer.receive(jsonRpcRequest, {
|
|
2342
|
+
sessionInfo: {}
|
|
2343
|
+
}));
|
|
2210
2344
|
res.writeHead(200, {
|
|
2211
2345
|
'Content-Type': 'application/json'
|
|
2212
2346
|
});
|
|
@@ -2451,6 +2585,8 @@ var BaseTransport = __webpack_require__(419);
|
|
|
2451
2585
|
return body;
|
|
2452
2586
|
}
|
|
2453
2587
|
|
|
2588
|
+
// EXTERNAL MODULE: ./src/context/RequestContext.ts + 1 modules
|
|
2589
|
+
var RequestContext = __webpack_require__(923);
|
|
2454
2590
|
;// CONCATENATED MODULE: ./src/transport/StreamableHttpTransport.ts
|
|
2455
2591
|
/**
|
|
2456
2592
|
* Streamable HTTP Transport implementation (MCP spec recommended transport).
|
|
@@ -2481,6 +2617,7 @@ var BaseTransport = __webpack_require__(419);
|
|
|
2481
2617
|
|
|
2482
2618
|
|
|
2483
2619
|
|
|
2620
|
+
|
|
2484
2621
|
/**
|
|
2485
2622
|
* Streamable HTTP Transport for MCP server.
|
|
2486
2623
|
*
|
|
@@ -2730,9 +2867,14 @@ var BaseTransport = __webpack_require__(419);
|
|
|
2730
2867
|
return;
|
|
2731
2868
|
}
|
|
2732
2869
|
// Process JSON-RPC request through MCP server
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2870
|
+
// Process JSON-RPC request through MCP server with owner context
|
|
2871
|
+
const owner = this._stateful ? sessionId ?? (0,external_node_crypto_.randomUUID)() : (0,external_node_crypto_.randomUUID)();
|
|
2872
|
+
const response = await (0,RequestContext/* .runWithContext */.Vo)({
|
|
2873
|
+
requestId: (0,external_node_crypto_.randomUUID)(),
|
|
2874
|
+
owner
|
|
2875
|
+
}, ()=>this._mcpServer.receive(jsonRpcRequest, {
|
|
2876
|
+
sessionInfo: {}
|
|
2877
|
+
}));
|
|
2736
2878
|
clearTimeout(timeout);
|
|
2737
2879
|
this._activeRequests--;
|
|
2738
2880
|
// Send response with session header if applicable
|
|
@@ -3128,31 +3270,8 @@ var external_node_url_ = __webpack_require__(61);
|
|
|
3128
3270
|
|
|
3129
3271
|
// EXTERNAL MODULE: external "./lib.js"
|
|
3130
3272
|
var external_lib_js_ = __webpack_require__(65);
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
;// CONCATENATED MODULE: ./src/context/RequestContext.ts
|
|
3134
|
-
/**
|
|
3135
|
-
* Request context management using AsyncLocalStorage for correlation IDs.
|
|
3136
|
-
*
|
|
3137
|
-
* Provides zero-cost request ID propagation across async boundaries
|
|
3138
|
-
* via Node.js AsyncLocalStorage.
|
|
3139
|
-
*
|
|
3140
|
-
* @module context
|
|
3141
|
-
*/
|
|
3142
|
-
/**
|
|
3143
|
-
* AsyncLocalStorage instance for request context.
|
|
3144
|
-
* Stores requestId that propagates across async boundaries.
|
|
3145
|
-
*/ const store = new AsyncLocalStorage();
|
|
3146
|
-
/**
|
|
3147
|
-
* Get the current request ID from context.
|
|
3148
|
-
*
|
|
3149
|
-
* Returns undefined if called outside of a runWithContext() call.
|
|
3150
|
-
*
|
|
3151
|
-
* @returns The current request ID or undefined
|
|
3152
|
-
*/ function getRequestId() {
|
|
3153
|
-
return store.getStore()?.requestId;
|
|
3154
|
-
}
|
|
3155
|
-
|
|
3273
|
+
// EXTERNAL MODULE: ./src/context/RequestContext.ts + 1 modules
|
|
3274
|
+
var RequestContext = __webpack_require__(923);
|
|
3156
3275
|
;// CONCATENATED MODULE: ./src/logger/StructuredLogger.ts
|
|
3157
3276
|
/**
|
|
3158
3277
|
* Lightweight structured logging without external dependencies.
|
|
@@ -3268,7 +3387,7 @@ var external_lib_js_ = __webpack_require__(65);
|
|
|
3268
3387
|
* @private
|
|
3269
3388
|
*/ log(level, message, meta) {
|
|
3270
3389
|
if (!this.shouldLog(level)) return;
|
|
3271
|
-
const requestId = getRequestId();
|
|
3390
|
+
const requestId = (0,RequestContext/* .getRequestId */.RE)();
|
|
3272
3391
|
const entry = {
|
|
3273
3392
|
level,
|
|
3274
3393
|
message,
|
|
@@ -3429,8 +3548,8 @@ var schema = __webpack_require__(613);
|
|
|
3429
3548
|
|
|
3430
3549
|
// Get version from package.json
|
|
3431
3550
|
const cli_filename = (0,external_node_url_.fileURLToPath)(import.meta.url);
|
|
3432
|
-
const cli_dirname = dirname(cli_filename);
|
|
3433
|
-
const package_json = JSON.parse(readFileSync(join(cli_dirname, '../package.json'), 'utf-8'));
|
|
3551
|
+
const cli_dirname = (0,__rspack_external_node_path_c5b9b54f.dirname)(cli_filename);
|
|
3552
|
+
const package_json = JSON.parse((0,__rspack_external_node_fs_5ea92f0c.readFileSync)((0,__rspack_external_node_path_c5b9b54f.join)(cli_dirname, '../package.json'), 'utf-8'));
|
|
3434
3553
|
const { name: cli_name, version } = package_json;
|
|
3435
3554
|
// Handle CLI arguments
|
|
3436
3555
|
const args = process.argv.slice(2);
|
|
@@ -3440,8 +3559,8 @@ if (shouldShowVersion) {
|
|
|
3440
3559
|
process.exit(0);
|
|
3441
3560
|
}
|
|
3442
3561
|
async function main() {
|
|
3443
|
-
const adapter = new ValibotJsonSchemaAdapter();
|
|
3444
|
-
const server = new McpServer({
|
|
3562
|
+
const adapter = new __rspack_external__tmcp_adapter_valibot_fbccc1df.ValibotJsonSchemaAdapter();
|
|
3563
|
+
const server = new __rspack_external_tmcp.McpServer({
|
|
3445
3564
|
name: cli_name,
|
|
3446
3565
|
version,
|
|
3447
3566
|
description: 'Semantic Sequential Thinking MCP Server'
|
|
@@ -3540,7 +3659,7 @@ async function main() {
|
|
|
3540
3659
|
/**
|
|
3541
3660
|
* Start stdio transport (default, single-user)
|
|
3542
3661
|
*/ async function startStdioTransport(server, thinkingServer) {
|
|
3543
|
-
const transport = new StdioTransport(server);
|
|
3662
|
+
const transport = new __rspack_external__tmcp_transport_stdio_9731848f.StdioTransport(server);
|
|
3544
3663
|
transport.listen();
|
|
3545
3664
|
const shutdown = async ()=>{
|
|
3546
3665
|
const forceExit = setTimeout(()=>{
|
|
@@ -100,6 +100,12 @@ export interface ConfigFileOptions {
|
|
|
100
100
|
* Can be overridden by `TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS` environment variable.
|
|
101
101
|
*/
|
|
102
102
|
toolInterleaveSweepMs?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Maximum sessions per owner. Per-owner LRU bucket prevents one user from
|
|
105
|
+
* consuming all session slots.
|
|
106
|
+
* Can be overridden by `SESSION_MAX_PER_OWNER` environment variable.
|
|
107
|
+
*/
|
|
108
|
+
maxSessionsPerOwner?: number;
|
|
103
109
|
}
|
|
104
110
|
/**
|
|
105
111
|
* Loads configuration from files with environment variable overrides.
|
|
@@ -256,6 +262,7 @@ export declare class ConfigLoader {
|
|
|
256
262
|
features?: Partial<FeatureFlags>;
|
|
257
263
|
toolInterleaveTtlMs?: number;
|
|
258
264
|
toolInterleaveSweepMs?: number;
|
|
265
|
+
maxSessionsPerOwner?: number;
|
|
259
266
|
};
|
|
260
267
|
}
|
|
261
268
|
//# sourceMappingURL=ConfigLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigLoader.d.ts","sourceRoot":"","sources":["../../src/config/ConfigLoader.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAE/C;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE;QAChB;;;WAGG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;
|
|
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;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAE/C;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE;QAChB;;;WAGG;QACH,GAAG,CAAC,EAAE,MAAM,CAAC;QACb;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAEjC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;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;IAuEjC;;;;;;;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"}
|
|
@@ -73,6 +73,10 @@ class ConfigLoader {
|
|
|
73
73
|
const parsed = parseInt(process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS, 10);
|
|
74
74
|
if (Number.isFinite(parsed)) result.toolInterleaveSweepMs = parsed;
|
|
75
75
|
}
|
|
76
|
+
if (process.env.SESSION_MAX_PER_OWNER) {
|
|
77
|
+
const parsed = parseInt(process.env.SESSION_MAX_PER_OWNER, 10);
|
|
78
|
+
if (Number.isFinite(parsed)) result.maxSessionsPerOwner = parsed;
|
|
79
|
+
}
|
|
76
80
|
this.applyFeatureFlagOverrides(result);
|
|
77
81
|
return result;
|
|
78
82
|
}
|
|
@@ -128,7 +132,8 @@ class ConfigLoader {
|
|
|
128
132
|
maxBranchSize: config.maxBranchSize,
|
|
129
133
|
features: config.features,
|
|
130
134
|
toolInterleaveTtlMs: config.toolInterleaveTtlMs,
|
|
131
|
-
toolInterleaveSweepMs: config.toolInterleaveSweepMs
|
|
135
|
+
toolInterleaveSweepMs: config.toolInterleaveSweepMs,
|
|
136
|
+
maxSessionsPerOwner: config.maxSessionsPerOwner
|
|
132
137
|
};
|
|
133
138
|
}
|
|
134
139
|
}
|
|
@@ -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\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\tmaxHistorySize?: 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\tmaxBranches?: 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\tmaxBranchSize?: number;\n\n\t/**\n\t * Logging level for the application.\n\t * Can be overridden by `LOG_LEVEL` environment variable.\n\t */\n\tlogLevel?: '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\tprettyLog?: 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\tskillDirs?: 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\tdiscoveryCache?: {\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\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t */\n\t\tmaxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\tpersistence?: PersistenceConfig;\n\n\t/**\n\t * Feature flag overrides. Each field can be set independently.\n\t * Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.\n\t */\n\tfeatures?: 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\ttoolInterleaveTtlMs?: 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\ttoolInterleaveSweepMs?: 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: 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 || {};\n\t\t\t\tresult.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 || {};\n\t\t\t\tresult.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\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: 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} {\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};\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":";;;;;AAoKO,MAAMA;IAEJ,aAAuB;IAgB/B,YAAYC,UAAmB,CAAE;QAChC,IAAI,CAAC,YAAY,GAAGA,aACjB;YAACA;SAAW,GACZ;YACA;YACA;YACA;YACAC,KAAKC,WAAW;YAChBD,KAAKC,WAAW;YAChBD,KAAKC,WAAW;SAChB;IACJ;IAsBA,OAAiC;QAChC,IAAIC,SAAmC;QAEvC,KAAK,MAAMC,cAAc,IAAI,CAAC,YAAY,CACzC,IAAIC,WAAWD,aACd,IAAI;YACHD,SAAS,IAAI,CAAC,WAAW,CAACC;YAC1B;QACD,EAAE,OAAOE,OAAO;YACfC,QAAQ,KAAK,CACZ,CAAC,2BAA2B,EAAEH,WAAW,CAAC,CAAC,EAC3CI,gBAAgBF;QAElB;QAIF,OAAO,IAAI,CAAC,yBAAyB,CAACH,UAAU,CAAC;IAClD;IAkBQ,0BAA0BA,MAAyB,EAAqB;QAC/E,MAAMM,SAA4B;YAAE,GAAGN,MAAM;QAAC;QAE9C,IAAIO,QAAQ,GAAG,CAAC,gBAAgB,EAAE;YACjC,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,gBAAgB,EAAE;YACtD,IAAIG,OAAO,QAAQ,CAACF,SACnBF,OAAO,cAAc,GAAGE;QAE1B;QACA,IAAID,QAAQ,GAAG,CAAC,YAAY,EAAE;YAC7B,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,YAAY,EAAE;YAClD,IAAIG,OAAO,QAAQ,CAACF,SACnBF,OAAO,WAAW,GAAGE;QAEvB;QACA,IAAID,QAAQ,GAAG,CAAC,eAAe,EAAE;YAChC,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,eAAe,EAAE;YACrD,IAAIG,OAAO,QAAQ,CAACF,SACnBF,OAAO,aAAa,GAAGE;QAEzB;QACA,IACCD,QAAQ,GAAG,CAAC,SAAS,IACrB;YAAC;YAAS;YAAQ;YAAQ;SAAQ,CAAC,QAAQ,CAACA,QAAQ,GAAG,CAAC,SAAS,GAEjED,OAAO,QAAQ,GAAGC,QAAQ,GAAG,CAAC,SAAS;QAExC,IAAIA,AAA2B,YAA3BA,QAAQ,GAAG,CAAC,UAAU,EACzBD,OAAO,SAAS,GAAG;QAEpB,IAAIC,QAAQ,GAAG,CAAC,UAAU,EACzBD,OAAO,SAAS,GAAGC,QAAQ,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;QAEjD,IAAIA,QAAQ,GAAG,CAAC,mBAAmB,EAAE;YACpC,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,mBAAmB,EAAE;YACzD,IAAIG,OAAO,QAAQ,CAACF,SAAS;gBAC5BF,OAAO,cAAc,GAAGA,OAAO,cAAc,IAAI,CAAC;gBAClDA,OAAO,cAAc,CAAC,GAAG,GAAGE,AAAS,OAATA;YAC7B;QACD;QACA,IAAID,QAAQ,GAAG,CAAC,wBAAwB,EAAE;YACzC,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,wBAAwB,EAAE;YAC9D,IAAIG,OAAO,QAAQ,CAACF,SAAS;gBAC5BF,OAAO,cAAc,GAAGA,OAAO,cAAc,IAAI,CAAC;gBAClDA,OAAO,cAAc,CAAC,OAAO,GAAGE;YACjC;QACD;QACA,IAAID,QAAQ,GAAG,CAAC,mCAAmC,EAAE;YACpD,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,mCAAmC,EAAE;YACzE,IAAIG,OAAO,QAAQ,CAACF,SACnBF,OAAO,mBAAmB,GAAGE;QAE/B;QACA,IAAID,QAAQ,GAAG,CAAC,qCAAqC,EAAE;YACtD,MAAMC,SAASC,SAASF,QAAQ,GAAG,CAAC,qCAAqC,EAAE;YAC3E,IAAIG,OAAO,QAAQ,CAACF,SACnBF,OAAO,qBAAqB,GAAGE;QAEjC;QAEA,IAAI,CAAC,yBAAyB,CAACF;QAE/B,OAAOA;IACR;IAUQ,0BAA0BA,MAAyB,EAAQ;QAClE,MAAMK,UAA4E;YACjF,iCAAiC;YACjC,mCAAmC;YACnC,mCAAmC;YACnC,uCAAuC;YACvC,yCAAyC;YACzC,yCAAyC;QAC1C;QACA,KAAK,MAAM,CAACC,QAAQC,IAAI,IAAIC,OAAO,OAAO,CAACH,SAAU;YACpD,MAAMI,MAAMR,QAAQ,GAAG,CAACK,OAAO;YAC/B,IAAIG,AAAQC,WAARD,KAAmB;YACvB,MAAMP,SAAS,IAAI,CAAC,YAAY,CAACO;YACjC,IAAIP,AAAWQ,WAAXR,QAAsB;gBACzBJ,QAAQ,IAAI,CACX,CAAC,0BAA0B,EAAEQ,OAAO,GAAG,EAAEG,IAAI,sCAAsC,CAAC;gBAErF;YACD;YACA,MAAME,WACLX,OAAO,QAAQ,IAAI,CAAC;YACrBW,QAAQ,CAACJ,IAAI,GAAGL;YAChBF,OAAO,QAAQ,GAAGW;QACnB;QAEA,MAAMC,cAAcX,QAAQ,GAAG,CAAC,wCAAwC;QACxE,IAAIW,AAAgBF,WAAhBE,aAA2B;YAC9B,MAAMC,UAAU;gBAAC;gBAAc;aAAM;YACrC,IAAKA,QAA8B,QAAQ,CAACD,cAAc;gBACzD,MAAMD,WACLX,OAAO,QAAQ,IAAI,CAAC;gBACrBW,SAAS,iBAAiB,GAAGC;gBAC7BZ,OAAO,QAAQ,GAAGW;YACnB,OACCb,QAAQ,IAAI,CACX,CAAC,6DAA6D,EAAEc,YAC9D,mBAAiB,EAAEC,QAAQ,IAAI,CAAC,MAAM,gCAAgC,CADO;QAIlF;IACD;IAUQ,aAAaJ,GAAW,EAAuB;QACtD,MAAMK,IAAIL,IAAI,IAAI,GAAG,WAAW;QAChC,IAAIK,AAAM,WAANA,KAAgBA,AAAM,QAANA,GAAW,OAAO;QACtC,IAAIA,AAAM,YAANA,KAAiBA,AAAM,QAANA,GAAW,OAAO;IAExC;IAaQ,YAAYC,QAAgB,EAAqB;QACxD,MAAMC,UAAUC,aAAaF,UAAU;QACvC,MAAMG,MAAMH,SAAS,KAAK,CAAC,KAAK,GAAG,IAAI;QAEvC,IAAIG,AAAQ,WAARA,OAAkBA,AAAQ,UAARA,KACrB,OAAOC,MAAUH;QAGlB,OAAOI,KAAK,KAAK,CAACJ;IACnB;IAqBA,sBAAsBtB,MAAyB,EAO7C;QACD,OAAO;YACN,gBAAgBA,OAAO,cAAc;YACrC,aAAaA,OAAO,WAAW;YAC/B,eAAeA,OAAO,aAAa;YACnC,UAAUA,OAAO,QAAQ;YACzB,qBAAqBA,OAAO,mBAAmB;YAC/C,uBAAuBA,OAAO,qBAAqB;QACpD;IACD;AACD"}
|
|
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\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\tmaxHistorySize?: 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\tmaxBranches?: 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\tmaxBranchSize?: number;\n\n\t/**\n\t * Logging level for the application.\n\t * Can be overridden by `LOG_LEVEL` environment variable.\n\t */\n\tlogLevel?: '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\tprettyLog?: 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\tskillDirs?: 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\tdiscoveryCache?: {\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\tttl?: number;\n\t\t/**\n\t\t * Maximum number of entries in the cache.\n\t\t */\n\t\tmaxSize?: number;\n\t};\n\n\t/**\n\t * Persistence configuration for storing history and state.\n\t */\n\tpersistence?: PersistenceConfig;\n\n\t/**\n\t * Feature flag overrides. Each field can be set independently.\n\t * Can be overridden by `TRACELATTICE_FEATURES_*` environment variables.\n\t */\n\tfeatures?: 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\ttoolInterleaveTtlMs?: 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\ttoolInterleaveSweepMs?: 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\tmaxSessionsPerOwner?: 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: 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 || {};\n\t\t\t\tresult.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 || {};\n\t\t\t\tresult.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: 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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"}
|
|
@@ -6,6 +6,13 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module context
|
|
8
8
|
*/
|
|
9
|
+
/**
|
|
10
|
+
* Internal context structure stored per-request.
|
|
11
|
+
*/
|
|
12
|
+
interface RequestCtx {
|
|
13
|
+
requestId: string;
|
|
14
|
+
owner?: string;
|
|
15
|
+
}
|
|
9
16
|
/**
|
|
10
17
|
* Get the current request ID from context.
|
|
11
18
|
*
|
|
@@ -14,4 +21,23 @@
|
|
|
14
21
|
* @returns The current request ID or undefined
|
|
15
22
|
*/
|
|
16
23
|
export declare function getRequestId(): string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Run a function with the given request context. The context propagates
|
|
26
|
+
* across async boundaries via AsyncLocalStorage.
|
|
27
|
+
*
|
|
28
|
+
* @param ctx - Request context to install (requestId, optional owner)
|
|
29
|
+
* @param fn - Function to execute within the context
|
|
30
|
+
* @returns The return value of `fn`
|
|
31
|
+
*/
|
|
32
|
+
export declare function runWithContext<T>(ctx: RequestCtx, fn: () => T): T;
|
|
33
|
+
/**
|
|
34
|
+
* Get the current owner identifier from context.
|
|
35
|
+
*
|
|
36
|
+
* Returns undefined when called outside of a runWithContext() call or when
|
|
37
|
+
* the context did not specify an owner (e.g. stdio transport).
|
|
38
|
+
*
|
|
39
|
+
* @returns The current owner or undefined
|
|
40
|
+
*/
|
|
41
|
+
export declare function getOwner(): string | undefined;
|
|
42
|
+
export {};
|
|
17
43
|
//# sourceMappingURL=RequestContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../src/context/RequestContext.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"RequestContext.d.ts","sourceRoot":"","sources":["../../src/context/RequestContext.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;GAEG;AACH,UAAU,UAAU;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEjE;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7C"}
|
|
@@ -3,6 +3,12 @@ const store = new AsyncLocalStorage();
|
|
|
3
3
|
function getRequestId() {
|
|
4
4
|
return store.getStore()?.requestId;
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
function runWithContext(ctx, fn) {
|
|
7
|
+
return store.run(ctx, fn);
|
|
8
|
+
}
|
|
9
|
+
function getOwner() {
|
|
10
|
+
return store.getStore()?.owner;
|
|
11
|
+
}
|
|
12
|
+
export { getOwner, getRequestId, runWithContext };
|
|
7
13
|
|
|
8
14
|
//# sourceMappingURL=RequestContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context/RequestContext.js","sources":["../../src/context/RequestContext.ts"],"sourcesContent":["/**\n * Request context management using AsyncLocalStorage for correlation IDs.\n *\n * Provides zero-cost request ID propagation across async boundaries\n * via Node.js AsyncLocalStorage.\n *\n * @module context\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Internal context structure stored per-request.\n */\ninterface RequestCtx {\n\trequestId: string;\n}\n\n/**\n * AsyncLocalStorage instance for request context.\n * Stores requestId that propagates across async boundaries.\n */\nconst store = new AsyncLocalStorage<RequestCtx>();\n\n/**\n * Get the current request ID from context.\n *\n * Returns undefined if called outside of a runWithContext() call.\n *\n * @returns The current request ID or undefined\n */\nexport function getRequestId(): string | undefined {\n\treturn store.getStore()?.requestId;\n}\n"],"names":["store","AsyncLocalStorage","getRequestId"],"mappings":";
|
|
1
|
+
{"version":3,"file":"context/RequestContext.js","sources":["../../src/context/RequestContext.ts"],"sourcesContent":["/**\n * Request context management using AsyncLocalStorage for correlation IDs.\n *\n * Provides zero-cost request ID propagation across async boundaries\n * via Node.js AsyncLocalStorage.\n *\n * @module context\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Internal context structure stored per-request.\n */\ninterface RequestCtx {\n\trequestId: string;\n\towner?: string;\n}\n\n/**\n * AsyncLocalStorage instance for request context.\n * Stores requestId that propagates across async boundaries.\n */\nconst store = new AsyncLocalStorage<RequestCtx>();\n\n/**\n * Get the current request ID from context.\n *\n * Returns undefined if called outside of a runWithContext() call.\n *\n * @returns The current request ID or undefined\n */\nexport function getRequestId(): string | undefined {\n\treturn store.getStore()?.requestId;\n}\n\n/**\n * Run a function with the given request context. The context propagates\n * across async boundaries via AsyncLocalStorage.\n *\n * @param ctx - Request context to install (requestId, optional owner)\n * @param fn - Function to execute within the context\n * @returns The return value of `fn`\n */\nexport function runWithContext<T>(ctx: RequestCtx, fn: () => T): T {\n\treturn store.run(ctx, fn);\n}\n\n/**\n * Get the current owner identifier from context.\n *\n * Returns undefined when called outside of a runWithContext() call or when\n * the context did not specify an owner (e.g. stdio transport).\n *\n * @returns The current owner or undefined\n */\nexport function getOwner(): string | undefined {\n\treturn store.getStore()?.owner;\n}\n"],"names":["store","AsyncLocalStorage","getRequestId","runWithContext","ctx","fn","getOwner"],"mappings":";AAuBA,MAAMA,QAAQ,IAAIC;AASX,SAASC;IACf,OAAOF,MAAM,QAAQ,IAAI;AAC1B;AAUO,SAASG,eAAkBC,GAAe,EAAEC,EAAW;IAC7D,OAAOL,MAAM,GAAG,CAACI,KAAKC;AACvB;AAUO,SAASC;IACf,OAAON,MAAM,QAAQ,IAAI;AAC1B"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* Feature flags for opt-in/out TraceLattice capabilities.
|
|
8
8
|
*
|
|
9
|
-
* All flags default to true (enabled).
|
|
9
|
+
* All flags default to true (enabled). Opt-out via configuration.
|
|
10
10
|
*/
|
|
11
11
|
export interface FeatureFlags {
|
|
12
12
|
/** Enable DAG edges between thoughts. @default true */
|
|
@@ -29,7 +29,7 @@ export interface FeatureFlags {
|
|
|
29
29
|
*/
|
|
30
30
|
export type FeatureFlagKey = keyof FeatureFlags;
|
|
31
31
|
/**
|
|
32
|
-
* Default feature flag values. All features enabled.
|
|
32
|
+
* Default feature flag values. All features enabled by default.
|
|
33
33
|
*/
|
|
34
34
|
export declare const DEFAULT_FLAGS: FeatureFlags;
|
|
35
35
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts/features.js","sources":["../../src/contracts/features.ts"],"sourcesContent":["/**\n * Feature flag definitions with const-asserted shape.\n *\n * @module contracts/features\n */\n\n/**\n * Feature flags for opt-in/out TraceLattice capabilities.\n *\n * All flags default to true (enabled).\n */\nexport interface FeatureFlags {\n\t/** Enable DAG edges between thoughts. @default true */\n\treadonly dagEdges: boolean;\n\t/** Reasoning strategy selector. @default 'sequential' */\n\treadonly reasoningStrategy: 'sequential' | 'tot';\n\t/** Enable confidence calibration. @default true */\n\treadonly calibration: boolean;\n\t/** Enable thought compression. @default true */\n\treadonly compression: boolean;\n\t/** Enable tool interleaving. @default true */\n\treadonly toolInterleave: boolean;\n\t/** Enable new thought types. @default true */\n\treadonly newThoughtTypes: boolean;\n\t/** Enable outcome recording. @default true */\n\treadonly outcomeRecording: boolean;\n}\n\n/**\n * All feature flag keys as a union type.\n */\nexport type FeatureFlagKey = keyof FeatureFlags;\n\n/**\n * Default feature flag values. All features enabled.\n */\nexport const DEFAULT_FLAGS: FeatureFlags = {\n\tdagEdges: true,\n\treasoningStrategy: 'sequential',\n\tcalibration: true,\n\tcompression: true,\n\ttoolInterleave: true,\n\tnewThoughtTypes: true,\n\toutcomeRecording: true,\n} as const;\n\n/**\n * Type guard: check if a feature flag is enabled (not false/undefined).\n */\nexport function hasFeature(flags: FeatureFlags, key: FeatureFlagKey): boolean {\n\treturn flags[key] !== false && flags[key] !== undefined;\n}\n"],"names":["DEFAULT_FLAGS","hasFeature","flags","key","undefined"],"mappings":"AAoCO,MAAMA,gBAA8B;IAC1C,UAAU;IACV,mBAAmB;IACnB,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;AACnB;AAKO,SAASC,WAAWC,KAAmB,EAAEC,GAAmB;IAClE,OAAOD,AAAe,UAAfA,KAAK,CAACC,IAAI,IAAcD,AAAeE,WAAfF,KAAK,CAACC,IAAI;AAC1C"}
|
|
1
|
+
{"version":3,"file":"contracts/features.js","sources":["../../src/contracts/features.ts"],"sourcesContent":["/**\n * Feature flag definitions with const-asserted shape.\n *\n * @module contracts/features\n */\n\n/**\n * Feature flags for opt-in/out TraceLattice capabilities.\n *\n * All flags default to true (enabled). Opt-out via configuration.\n */\nexport interface FeatureFlags {\n\t/** Enable DAG edges between thoughts. @default true */\n\treadonly dagEdges: boolean;\n\t/** Reasoning strategy selector. @default 'sequential' */\n\treadonly reasoningStrategy: 'sequential' | 'tot';\n\t/** Enable confidence calibration. @default true */\n\treadonly calibration: boolean;\n\t/** Enable thought compression. @default true */\n\treadonly compression: boolean;\n\t/** Enable tool interleaving. @default true */\n\treadonly toolInterleave: boolean;\n\t/** Enable new thought types. @default true */\n\treadonly newThoughtTypes: boolean;\n\t/** Enable outcome recording. @default true */\n\treadonly outcomeRecording: boolean;\n}\n\n/**\n * All feature flag keys as a union type.\n */\nexport type FeatureFlagKey = keyof FeatureFlags;\n\n/**\n * Default feature flag values. All features enabled by default.\n */\nexport const DEFAULT_FLAGS: FeatureFlags = {\n\tdagEdges: true,\n\treasoningStrategy: 'sequential',\n\tcalibration: true,\n\tcompression: true,\n\ttoolInterleave: true,\n\tnewThoughtTypes: true,\n\toutcomeRecording: true,\n} as const;\n\n/**\n * Type guard: check if a feature flag is enabled (not false/undefined).\n */\nexport function hasFeature(flags: FeatureFlags, key: FeatureFlagKey): boolean {\n\treturn flags[key] !== false && flags[key] !== undefined;\n}\n"],"names":["DEFAULT_FLAGS","hasFeature","flags","key","undefined"],"mappings":"AAoCO,MAAMA,gBAA8B;IAC1C,UAAU;IACV,mBAAmB;IACnB,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;AACnB;AAKO,SAASC,WAAWC,KAAmB,EAAEC,GAAmB;IAClE,OAAOD,AAAe,UAAfA,KAAK,CAACC,IAAI,IAAcD,AAAeE,WAAfF,KAAK,CAACC,IAAI;AAC1C"}
|