@iworkforces/tracelattice 2.0.3 → 2.0.5

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/cli.js CHANGED
@@ -1,20 +1,29 @@
1
1
  #!/usr/bin/env bun
2
- import * as __rspack_external__lib_js_1645bc55 from "./lib.js";
3
- import * as __rspack_external_node_async_hooks_4d8b1b4a from "node:async_hooks";
2
+ import * as __rspack_external_valibot from "valibot";
4
3
  import * as __rspack_external_node_crypto_2e7c4b46 from "node:crypto";
5
4
  import * as __rspack_external_node_http_e245b239 from "node:http";
5
+ import * as __rspack_external_node_async_hooks_4d8b1b4a from "node:async_hooks";
6
+ import * as __rspack_external__tmcp_adapter_valibot_0faddfa6 from "@tmcp/adapter-valibot";
7
+ import * as __rspack_external__tmcp_transport_stdio_98e5584f from "@tmcp/transport-stdio";
8
+ import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
9
+ import * as __rspack_external_node_path_806ed179 from "node:path";
6
10
  import * as __rspack_external_node_url_3991086a from "node:url";
7
- import * as __rspack_external_valibot from "valibot";
8
- import { ValibotJsonSchemaAdapter } from "@tmcp/adapter-valibot";
9
- import { StdioTransport } from "@tmcp/transport-stdio";
10
- import { existsSync, readFileSync } from "node:fs";
11
- import { dirname, join } from "node:path";
12
- import { McpServer } from "tmcp";
13
- import { homedir } from "node:os";
14
- import { parse } from "yaml";
11
+ import * as __rspack_external_tmcp from "tmcp";
12
+ import * as __rspack_external__lib_js_1645bc55 from "./lib.js";
15
13
  var __webpack_modules__ = ({
16
- "y"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
17
- /* import */ var node_async_hooks__rspack_import_0 = __webpack_require__("A");
14
+ "i"(__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
18
27
  /**
19
28
  * Request context management using AsyncLocalStorage for correlation IDs.
20
29
  *
@@ -26,7 +35,7 @@ var __webpack_modules__ = ({
26
35
  /**
27
36
  * AsyncLocalStorage instance for request context.
28
37
  * Stores requestId that propagates across async boundaries.
29
- */ const store = new node_async_hooks__rspack_import_0.AsyncLocalStorage();
38
+ */ const store = new __rspack_external_node_async_hooks_4d8b1b4a.AsyncLocalStorage();
30
39
  /**
31
40
  * Get the current request ID from context.
32
41
  *
@@ -57,133 +66,6 @@ var __webpack_modules__ = ({
57
66
  return store.getStore()?.owner;
58
67
  }
59
68
 
60
- __webpack_require__.d(__webpack_exports__, {
61
- QQ: () => (getOwner),
62
- RE: () => (getRequestId),
63
- Vo: () => (runWithContext)
64
- });
65
-
66
-
67
- },
68
- "j"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
69
- /* import */ var _core_ids_js__rspack_import_0 = __webpack_require__("Uz");
70
- /* import */ var _errors_js__rspack_import_1 = __webpack_require__("U");
71
- /**
72
- * Branded identifier types for compile-time slot safety.
73
- *
74
- * These nominal types prevent accidental mixing of different ID kinds
75
- * (e.g. passing a `ThoughtId` where a `SessionId` is expected). At
76
- * runtime they are plain strings — the brand exists only in the type
77
- * system.
78
- *
79
- * @module contracts/ids
80
- */
81
-
82
- /**
83
- * Validate and brand a string as a {@link SessionId}.
84
- *
85
- * Enforces {@link SESSION_ID_PATTERN} and {@link MAX_SESSION_ID_LENGTH}.
86
- * The reserved global session sentinel `__global__` is always accepted.
87
- *
88
- * @throws {ValidationError} when the input is not a valid session id.
89
- */ function asSessionId(value) {
90
- if (value === '__global__') {
91
- // eslint-disable-next-line no-restricted-syntax -- branding constructor, cannot self-reference
92
- return value;
93
- }
94
- if (typeof value !== 'string' || value.length === 0) {
95
- throw new _errors_js__rspack_import_1/* .ValidationError */.yI('session_id', 'must be a non-empty string');
96
- }
97
- if (value.length > (/* inlined export .MAX_SESSION_ID_LENGTH */100)) {
98
- throw new _errors_js__rspack_import_1/* .ValidationError */.yI('session_id', `exceeds max length of ${(/* inlined export .MAX_SESSION_ID_LENGTH */100)}`);
99
- }
100
- if (!_core_ids_js__rspack_import_0/* .SESSION_ID_PATTERN.test */.I.test(value)) {
101
- throw new _errors_js__rspack_import_1/* .ValidationError */.yI('session_id', 'must match alphanumeric, hyphens, underscores');
102
- }
103
- // eslint-disable-next-line no-restricted-syntax -- branding constructor, cannot self-reference
104
- return value;
105
- }
106
- /** Brand a string as a {@link ThoughtId} without validation. */ function asThoughtId(value) {
107
- return value;
108
- }
109
- /** Brand a string as an {@link EdgeId} without validation. */ function asEdgeId(value) {
110
- return value;
111
- }
112
- /** Brand a string as a {@link SuspensionToken} without validation. */ function asSuspensionToken(value) {
113
- return value;
114
- }
115
- /** Brand a string as a {@link BranchId} without validation. */ function asBranchId(value) {
116
- return value;
117
- }
118
- /** Brand a string as a {@link SummaryId} without validation. */ function asSummaryId(value) {
119
- return value;
120
- }
121
- /** Generate a fresh {@link ThoughtId}. */ function generateThoughtId() {
122
- return generateUlid();
123
- }
124
- /** Generate a fresh {@link EdgeId}. */ function generateEdgeId() {
125
- return generateUlid();
126
- }
127
- /** Generate a fresh {@link SuspensionToken}. */ function generateSuspensionToken() {
128
- return generateUlid();
129
- }
130
- /** Generate a fresh {@link SummaryId}. */ function generateSummaryId() {
131
- return generateUlid();
132
- }
133
- /**
134
- * Reserved sentinel session id used when callers omit `session_id`.
135
- *
136
- * Branded once here so production and test code share one constant
137
- * instead of casting `'__global__'` ad-hoc.
138
- */ const GLOBAL_SESSION_ID = asSessionId('__global__');
139
-
140
- __webpack_require__.d(__webpack_exports__, {
141
- Kd: () => (asSessionId)
142
- });
143
-
144
-
145
- },
146
- "Uz"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
147
- /* import */ var node_crypto__rspack_import_0 = __webpack_require__("i");
148
- /**
149
- * Unique identifier generation utilities for thoughts and edges.
150
- *
151
- * @module core/ids
152
- */
153
- /**
154
- * Generate a unique lexicographically-sortable identifier.
155
- *
156
- * Format: 8-char base36 timestamp + 20-char hex random (10 random bytes).
157
- * Result is up to 28 characters, sortable by creation time.
158
- *
159
- * @returns A unique string identifier.
160
- *
161
- * @example
162
- * ```typescript
163
- * const id = generateUlid(); // '01h2k3m400a1b2c3d4e5f6...'
164
- * ```
165
- */ function generateUlid() {
166
- const timestamp = Date.now().toString(36).padStart(8, '0');
167
- const random = crypto.randomBytes(10).toString('hex');
168
- return `${timestamp}${random}`;
169
- }
170
- /**
171
- * Valid session ID pattern: alphanumeric, hyphens, underscores.
172
- *
173
- * Length is enforced separately via {@link MAX_SESSION_ID_LENGTH}.
174
- * Same character set as branch IDs.
175
- */ const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
176
- /**
177
- * Maximum session ID length (in characters).
178
- *
179
- * Allows compound identifiers (e.g. `user-123_task-abc`).
180
- */ const MAX_SESSION_ID_LENGTH = 100;
181
-
182
- __webpack_require__.d(__webpack_exports__, {
183
- }, {
184
- I: SESSION_ID_PATTERN
185
- });
186
-
187
69
 
188
70
  },
189
71
  "U"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
@@ -920,550 +802,68 @@ class PersistenceClosedError extends SequentialThinkingError {
920
802
 
921
803
  __webpack_require__.d(__webpack_exports__, {
922
804
  Qt: () => (CliShutdownTimeoutError),
923
- j1: () => (ConfigurationError),
924
- m_: () => (PoolTerminatedError),
925
- oN: () => (SequentialThinkingError),
926
805
  u1: () => (getErrorMessage),
927
- yI: () => (ValidationError),
928
- yM: () => (MaxSessionsReachedError)
929
- }, {
930
- OQ: ERROR_CODES
806
+ yI: () => (ValidationError)
931
807
  });
932
808
 
933
809
 
934
810
  },
935
- "v"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
936
- /* import */ var node_async_hooks__rspack_import_0 = __webpack_require__("A");
937
- /* import */ var _errors_js__rspack_import_1 = __webpack_require__("U");
938
- /* import */ var _contracts_ids_js__rspack_import_2 = __webpack_require__("j");
939
- /* import */ var _utils_js__rspack_import_4 = __webpack_require__("h");
940
- /* import */ var _PoolErrors_js__rspack_import_3 = __webpack_require__("K");
811
+ "R"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
812
+ /* import */ var valibot__rspack_import_0 = __webpack_require__("w");
941
813
  /**
942
- * Connection Pool for managing concurrent user sessions.
814
+ * Valibot validation schemas for the sequential thinking MCP tool.
815
+ *
816
+ * This module defines the validation schemas used for the sequential thinking tool,
817
+ * including schemas for tool recommendations, skill recommendations, step recommendations,
818
+ * and the main sequential thinking input. All schemas use Valibot for runtime validation
819
+ * and provide detailed descriptions for MCP protocol compatibility.
943
820
  *
944
- * This module provides session management for multi-user scenarios,
945
- * allowing multiple concurrent clients to each have isolated state.
821
+ * @remarks
822
+ * **Schema Overview:**
823
+ * - `ToolRecommendationSchema` - Validates tool recommendation objects with confidence scores
824
+ * - `SkillRecommendationSchema` - Validates skill recommendation objects
825
+ * - `StepRecommendationSchema` - Validates step coordination structures
826
+ * - `SequentialThinkingSchema` - Main schema for thought input validation
827
+ * - Reasoning enhancement fields: thought_type, quality_score, confidence, hypothesis_id, etc.
946
828
  *
947
829
  * @example
948
830
  * ```typescript
949
- * const pool = new ConnectionPool({
950
- * maxSessions: 100,
951
- * sessionTimeout: 300000 // 5 minutes
952
- * });
831
+ * import { SequentialThinkingSchema } from './schema.js';
832
+ * import { safeParse } from 'valibot';
953
833
  *
954
- * const sessionId = await pool.createSession();
955
- * await pool.process(sessionId, thought);
956
- * await pool.closeSession(sessionId);
834
+ * const result = safeParse(SequentialThinkingSchema, inputData);
835
+ * if (result.success) {
836
+ * const thought = result.output;
837
+ * // Process the valid thought
838
+ * } else {
839
+ * console.error('Validation failed:', result.issues);
840
+ * }
957
841
  * ```
842
+ * @module schema
958
843
  */
844
+ /**
845
+ * Detailed description for the sequential thinking tool.
846
+ *
847
+ * This description is shown to LLMs when they consider using this tool.
848
+ * It explains when to use the tool, its features, parameters, and best practices.
849
+ */ const TOOL_DESCRIPTION = `A detailed tool for dynamic and reflective problem-solving through thoughts.
850
+ This tool helps analyze problems through a flexible thinking process that can adapt and evolve.
851
+ Each thought can build on, question, or revise previous insights as understanding deepens.
959
852
 
853
+ IMPORTANT: This server facilitates sequential thinking with MCP tool coordination and skill recommendations. The LLM analyzes available tools and skills to make intelligent recommendations, which are then tracked and organized by this server.
960
854
 
855
+ Each invocation records exactly one authored thought and returns. When strategy_hint.action is continue, invoke this tool again with the next thought; do not stop or provide a final answer. terminate permits stopping. The server does not author later thoughts or call itself.
961
856
 
962
-
963
- /**
964
- * Represents a user session with its own server instance.
965
- */ class Session {
966
- _server;
967
- _id;
968
- _createdAt;
969
- _lastActivityAt;
970
- _isActiveValue;
971
- _timeout;
972
- _cleanupTimer = null;
973
- _logger;
974
- _closePromise = null;
975
- _activeOperationCount = 0;
976
- _operationDrain = null;
977
- constructor(id, server, timeout, logger){
978
- this._server = server;
979
- this._id = id;
980
- this._createdAt = Date.now();
981
- this._lastActivityAt = this._createdAt;
982
- this._isActiveValue = true;
983
- this._timeout = timeout;
984
- this._logger = logger;
985
- // Start session timeout timer
986
- this._startTimeout();
987
- }
988
- /**
989
- * Check if the session is active.
990
- */ get isActive() {
991
- return this._isActiveValue;
992
- }
993
- /**
994
- * Process a thought through this session's server instance.
995
- */ async process(input) {
996
- if (!this.isActive) {
997
- throw new _PoolErrors_js__rspack_import_3/* .SessionNotActiveError */.q(this._id);
998
- }
999
- // Update last activity
1000
- this._lastActivityAt = Date.now();
1001
- // Reset timeout timer
1002
- this._resetTimeout();
1003
- // Process the thought
1004
- return this._server.processThought(input);
1005
- }
1006
- processAdmitted(input) {
1007
- this._lastActivityAt = Date.now();
1008
- if (this.isActive) this._resetTimeout();
1009
- return this._server.processThought(input);
1010
- }
1011
- runWhileActive(operation) {
1012
- if (!this.isActive) return Promise.resolve({
1013
- status: 'inactive'
1014
- });
1015
- this._activeOperationCount++;
1016
- return (async ()=>{
1017
- try {
1018
- return {
1019
- status: 'completed',
1020
- value: await operation(this)
1021
- };
1022
- } finally{
1023
- this._activeOperationCount--;
1024
- if (this._activeOperationCount === 0) this._operationDrain?.resolve();
1025
- }
1026
- })();
1027
- }
1028
- /**
1029
- * Get session information.
1030
- */ getInfo() {
1031
- return {
1032
- id: this._id,
1033
- server: this._server,
1034
- createdAt: this._createdAt,
1035
- lastActivityAt: this._lastActivityAt,
1036
- isActive: this.isActive
1037
- };
1038
- }
1039
- /**
1040
- * Check if the session has timed out.
1041
- */ isTimedOut() {
1042
- return Date.now() - this._lastActivityAt > this._timeout;
1043
- }
1044
- /**
1045
- * Close the session and stop the server.
1046
- */ close() {
1047
- if (this._closePromise) {
1048
- return this._closePromise;
1049
- }
1050
- const completion = Promise.withResolvers();
1051
- this._closePromise = completion.promise;
1052
- this._isActiveValue = false;
1053
- // Stop timeout timer
1054
- if (this._cleanupTimer) {
1055
- clearTimeout(this._cleanupTimer);
1056
- this._cleanupTimer = null;
1057
- }
1058
- if (this._activeOperationCount === 0) {
1059
- this._stopServer(completion);
1060
- } else {
1061
- this._operationDrain = Promise.withResolvers();
1062
- void this._operationDrain.promise.then(()=>this._stopServer(completion));
1063
- }
1064
- return completion.promise;
1065
- }
1066
- _stopServer(completion) {
1067
- try {
1068
- Promise.resolve(this._server.stop()).then(completion.resolve, completion.reject);
1069
- } catch (error) {
1070
- completion.reject(error instanceof Error ? error : new AggregateError([
1071
- error
1072
- ], 'Session stop failed'));
1073
- }
1074
- }
1075
- /**
1076
- * Start the session timeout timer.
1077
- */ _startTimeout() {
1078
- if (this._cleanupTimer) {
1079
- clearTimeout(this._cleanupTimer);
1080
- }
1081
- this._cleanupTimer = setTimeout(()=>{
1082
- if (this.isTimedOut()) {
1083
- this._logger.warn(`Session ${this._id} timed out, closing`);
1084
- this.close().catch((err)=>{
1085
- this._logger.error(`Error closing timed out session ${this._id}:`, err);
1086
- });
1087
- }
1088
- }, this._timeout);
1089
- }
1090
- /**
1091
- * Reset the timeout timer after activity.
1092
- */ _resetTimeout() {
1093
- this._startTimeout();
1094
- }
1095
- }
1096
- /**
1097
- * ConnectionPool manages multiple concurrent user sessions.
1098
- *
1099
- * Each session has its own server instance with isolated state,
1100
- * allowing multiple users to interact with the system simultaneously.
1101
- */ class ConnectionPool {
1102
- _sessions = new Map();
1103
- _closingSessions = new Map();
1104
- _createSessionLock = null;
1105
- _maxSessions;
1106
- _sessionTimeout;
1107
- _autoCleanup;
1108
- _cleanupInterval;
1109
- _cleanupTimerId = null;
1110
- _terminated = false;
1111
- _logger;
1112
- _serverFactory;
1113
- _terminatePromise = null;
1114
- _admissionContext = new node_async_hooks__rspack_import_0.AsyncLocalStorage();
1115
- _pendingCreateStopFailures = new Set();
1116
- constructor(options = {}){
1117
- this._maxSessions = options.maxSessions ?? 100;
1118
- this._sessionTimeout = options.sessionTimeout ?? 300000; // 5 minutes
1119
- this._autoCleanup = options.autoCleanup ?? true;
1120
- this._cleanupInterval = options.cleanupInterval ?? 60000; // 1 minute
1121
- this._serverFactory = options.serverFactory ?? null;
1122
- this._logger = options.logger ?? this._createNoopLogger();
1123
- if (this._autoCleanup) {
1124
- this._startCleanup();
1125
- }
1126
- }
1127
- /**
1128
- * Create a no-op logger when none is provided.
1129
- */ _createNoopLogger() {
1130
- return {
1131
- info: ()=>{},
1132
- warn: ()=>{},
1133
- error: ()=>{},
1134
- debug: ()=>{},
1135
- setLevel: ()=>{},
1136
- getLevel: ()=>'info'
1137
- };
1138
- }
1139
- /**
1140
- * Create a new session.
1141
- *
1142
- * @returns The session ID
1143
- * @throws Error if max sessions reached
1144
- */ async createSession() {
1145
- while(this._createSessionLock){
1146
- await this._createSessionLock;
1147
- }
1148
- if (this._terminated) {
1149
- throw new _errors_js__rspack_import_1/* .PoolTerminatedError */.m_();
1150
- }
1151
- if (this._sessions.size >= this._maxSessions) {
1152
- throw new _errors_js__rspack_import_1/* .MaxSessionsReachedError */.yM(this._maxSessions);
1153
- }
1154
- if (!this._serverFactory) {
1155
- throw new Error('ConnectionPool requires a serverFactory option to create sessions');
1156
- }
1157
- let resolveLock;
1158
- this._createSessionLock = new Promise((resolve)=>{
1159
- resolveLock = resolve;
1160
- });
1161
- try {
1162
- // Generate unique session ID
1163
- const sessionId = (0,_contracts_ids_js__rspack_import_2/* .asSessionId */.Kd)(`session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`);
1164
- // Create a new server instance for this session
1165
- const server = await this._serverFactory();
1166
- if (this._terminated) {
1167
- try {
1168
- await server.stop();
1169
- } catch (error) {
1170
- this._pendingCreateStopFailures.add(error);
1171
- throw error;
1172
- }
1173
- throw new _errors_js__rspack_import_1/* .PoolTerminatedError */.m_();
1174
- }
1175
- // Create session
1176
- const session = new Session(sessionId, server, this._sessionTimeout, this._logger);
1177
- this._sessions.set(sessionId, session);
1178
- this._logger.info(`Created session ${sessionId} (${this._sessions.size}/${this._maxSessions} active sessions)`);
1179
- return sessionId;
1180
- } finally{
1181
- resolveLock();
1182
- this._createSessionLock = null;
1183
- }
1184
- }
1185
- /**
1186
- * Process a thought in the specified session.
1187
- *
1188
- * @param sessionId - The session ID
1189
- * @param input - The thought data to process
1190
- * @returns Promise with the processing result
1191
- * @throws Error if session not found
1192
- */ async process(sessionId, input) {
1193
- const result = await this._runWithSession(sessionId, (session)=>session.processAdmitted(input));
1194
- switch(result.status){
1195
- case 'completed':
1196
- return result.value;
1197
- case 'inactive':
1198
- throw new _PoolErrors_js__rspack_import_3/* .SessionNotActiveError */.q(sessionId);
1199
- case 'missing':
1200
- throw new _PoolErrors_js__rspack_import_3/* .SessionNotFoundError */.A(sessionId);
1201
- default:
1202
- return (0,_utils_js__rspack_import_4/* .assertNever */.x)(result);
1203
- }
1204
- }
1205
- runWithSession(sessionId, operation) {
1206
- return this._runWithSession(sessionId, (session)=>operation(session.getInfo().server));
1207
- }
1208
- _runWithSession(sessionId, operation) {
1209
- const activeFrame = this._admissionContext.getStore();
1210
- if (activeFrame?.open === true && activeFrame.sessionId === sessionId) {
1211
- return (async ()=>({
1212
- status: 'completed',
1213
- value: await operation(activeFrame.session)
1214
- }))();
1215
- }
1216
- const session = this._sessions.get(sessionId);
1217
- if (!session) {
1218
- return Promise.resolve(this._closingSessions.has(sessionId) ? {
1219
- status: 'inactive'
1220
- } : {
1221
- status: 'missing'
1222
- });
1223
- }
1224
- return session.runWhileActive((capturedSession)=>{
1225
- const frame = {
1226
- sessionId,
1227
- session: capturedSession,
1228
- open: true
1229
- };
1230
- return this._admissionContext.run(frame, async ()=>{
1231
- try {
1232
- return await operation(capturedSession);
1233
- } finally{
1234
- frame.open = false;
1235
- }
1236
- });
1237
- });
1238
- }
1239
- /**
1240
- * Close a session and release resources.
1241
- *
1242
- * @param sessionId - The session ID to close
1243
- * @throws Error if session not found
1244
- */ closeSession(sessionId) {
1245
- const closing = this._closingSessions.get(sessionId);
1246
- if (closing) {
1247
- return closing;
1248
- }
1249
- const session = this._sessions.get(sessionId);
1250
- if (!session) {
1251
- return Promise.reject(new _PoolErrors_js__rspack_import_3/* .SessionNotFoundError */.A(sessionId));
1252
- }
1253
- this._sessions.delete(sessionId);
1254
- const closePromise = session.close();
1255
- this._closingSessions.set(sessionId, closePromise);
1256
- void closePromise.then(()=>{
1257
- this._closingSessions.delete(sessionId);
1258
- this._logger.info(`Closed session ${sessionId} (${this._sessions.size}/${this._maxSessions} active sessions)`);
1259
- }, ()=>{
1260
- this._closingSessions.delete(sessionId);
1261
- });
1262
- return closePromise;
1263
- }
1264
- /**
1265
- * Get information about a session.
1266
- *
1267
- * @param sessionId - The session ID
1268
- * @returns Session info or undefined if not found
1269
- */ getSessionInfo(sessionId) {
1270
- return this._sessions.get(sessionId)?.getInfo();
1271
- }
1272
- /**
1273
- * Get all active sessions.
1274
- *
1275
- * @returns Array of session information
1276
- */ getActiveSessions() {
1277
- return Array.from(this._sessions.values()).filter((s)=>s.isActive).map((s)=>s.getInfo());
1278
- }
1279
- /**
1280
- * Get connection pool statistics.
1281
- */ getStats() {
1282
- const activeSessions = this.getActiveSessions();
1283
- return {
1284
- totalSessions: this._sessions.size,
1285
- activeSessions: activeSessions.length,
1286
- maxSessions: this._maxSessions,
1287
- cleanupEnabled: this._autoCleanup,
1288
- sessionTimeout: this._sessionTimeout
1289
- };
1290
- }
1291
- /**
1292
- * Start the automatic cleanup timer.
1293
- */ _startCleanup() {
1294
- if (this._cleanupTimerId !== null) {
1295
- clearInterval(this._cleanupTimerId);
1296
- }
1297
- this._cleanupTimerId = setInterval(()=>{
1298
- this._cleanupTimedOutSessions();
1299
- }, this._cleanupInterval);
1300
- }
1301
- /**
1302
- * Remove timed-out sessions.
1303
- */ _cleanupTimedOutSessions() {
1304
- let cleaned = 0;
1305
- for (const [sessionId, session] of this._sessions.entries()){
1306
- if (session.isTimedOut()) {
1307
- this.closeSession(sessionId).catch((err)=>{
1308
- this._logger.error(`Error closing timed out session ${sessionId}:`, err);
1309
- });
1310
- cleaned++;
1311
- }
1312
- }
1313
- if (cleaned > 0) {
1314
- this._logger.info(`Cleaned ${cleaned} timed-out sessions (${this._sessions.size}/${this._maxSessions} active sessions)`);
1315
- }
1316
- }
1317
- /**
1318
- * Close all sessions and stop the cleanup timer.
1319
- */ terminate() {
1320
- if (this._terminatePromise) {
1321
- return this._terminatePromise;
1322
- }
1323
- const completion = Promise.withResolvers();
1324
- this._terminatePromise = completion.promise;
1325
- this._terminated = true;
1326
- // Stop cleanup timer
1327
- if (this._cleanupTimerId !== null) {
1328
- clearInterval(this._cleanupTimerId);
1329
- this._cleanupTimerId = null;
1330
- }
1331
- const sessions = Array.from(this._sessions.values());
1332
- this._sessions.clear();
1333
- const closePromises = new Set(this._closingSessions.values());
1334
- if (this._createSessionLock) {
1335
- closePromises.add(this._createSessionLock);
1336
- }
1337
- for (const session of sessions){
1338
- closePromises.add(session.close());
1339
- }
1340
- void Promise.allSettled(closePromises).then((outcomes)=>{
1341
- const failures = [
1342
- ...this._pendingCreateStopFailures,
1343
- ...outcomes.filter((outcome)=>outcome.status === 'rejected').map((outcome)=>outcome.reason)
1344
- ];
1345
- if (failures.length > 0) {
1346
- completion.reject(new AggregateError(failures, 'ConnectionPool termination failed'));
1347
- return;
1348
- }
1349
- this._logger.info('ConnectionPool terminated');
1350
- completion.resolve();
1351
- });
1352
- return completion.promise;
1353
- }
1354
- /**
1355
- * Dispose of the connection pool, releasing all resources.
1356
- * Implements the IDisposable interface.
1357
- * Delegates to terminate() for backward compatibility.
1358
- */ dispose() {
1359
- return this.terminate();
1360
- }
1361
- /**
1362
- * Check if the connection pool is active.
1363
- */ isRunning() {
1364
- return !this._terminated;
1365
- }
1366
- }
1367
- /**
1368
- * Create a connection pool with the given options.
1369
- *
1370
- * @param options - Connection pool configuration
1371
- * @returns A configured connection pool
1372
- *
1373
- * @example
1374
- * ```typescript
1375
- * const pool = createConnectionPool({
1376
- * maxSessions: 50,
1377
- * sessionTimeout: 300000
1378
- * });
1379
- * ```
1380
- */ function createConnectionPool(options) {
1381
- return new ConnectionPool(options);
1382
- }
1383
-
1384
- __webpack_require__.d(__webpack_exports__, {
1385
- createConnectionPool: () => (createConnectionPool)
1386
- });
1387
-
1388
-
1389
- },
1390
- "K"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1391
- /* import */ var _errors_js__rspack_import_0 = __webpack_require__("U");
1392
-
1393
- /** Error thrown when attempting to process a session that is not active. */ class SessionNotActiveError extends _errors_js__rspack_import_0/* .SequentialThinkingError */.oN {
1394
- constructor(sessionId){
1395
- super(`Session '${sessionId}' is not active`, _errors_js__rspack_import_0/* .ERROR_CODES.SESSION_NOT_ACTIVE */.OQ.SESSION_NOT_ACTIVE);
1396
- this.name = 'SessionNotActiveError';
1397
- }
1398
- }
1399
- /** Error thrown when a requested session is not found in the pool. */ class SessionNotFoundError extends _errors_js__rspack_import_0/* .SequentialThinkingError */.oN {
1400
- constructor(sessionId){
1401
- super(`Session not found: ${sessionId}`, _errors_js__rspack_import_0/* .ERROR_CODES.SESSION_NOT_FOUND */.OQ.SESSION_NOT_FOUND);
1402
- this.name = 'SessionNotFoundError';
1403
- }
1404
- }
1405
-
1406
- __webpack_require__.d(__webpack_exports__, {
1407
- A: () => (SessionNotFoundError),
1408
- q: () => (SessionNotActiveError)
1409
- });
1410
-
1411
-
1412
- },
1413
- "R"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1414
- /* import */ var valibot__rspack_import_0 = __webpack_require__("w");
1415
- /**
1416
- * Valibot validation schemas for the sequential thinking MCP tool.
1417
- *
1418
- * This module defines the validation schemas used for the sequential thinking tool,
1419
- * including schemas for tool recommendations, skill recommendations, step recommendations,
1420
- * and the main sequential thinking input. All schemas use Valibot for runtime validation
1421
- * and provide detailed descriptions for MCP protocol compatibility.
1422
- *
1423
- * @remarks
1424
- * **Schema Overview:**
1425
- * - `ToolRecommendationSchema` - Validates tool recommendation objects with confidence scores
1426
- * - `SkillRecommendationSchema` - Validates skill recommendation objects
1427
- * - `StepRecommendationSchema` - Validates step coordination structures
1428
- * - `SequentialThinkingSchema` - Main schema for thought input validation
1429
- * - Reasoning enhancement fields: thought_type, quality_score, confidence, hypothesis_id, etc.
1430
- *
1431
- * @example
1432
- * ```typescript
1433
- * import { SequentialThinkingSchema } from './schema.js';
1434
- * import { safeParse } from 'valibot';
1435
- *
1436
- * const result = safeParse(SequentialThinkingSchema, inputData);
1437
- * if (result.success) {
1438
- * const thought = result.output;
1439
- * // Process the valid thought
1440
- * } else {
1441
- * console.error('Validation failed:', result.issues);
1442
- * }
1443
- * ```
1444
- * @module schema
1445
- */
1446
- /**
1447
- * Detailed description for the sequential thinking tool.
1448
- *
1449
- * This description is shown to LLMs when they consider using this tool.
1450
- * It explains when to use the tool, its features, parameters, and best practices.
1451
- */ const TOOL_DESCRIPTION = `A detailed tool for dynamic and reflective problem-solving through thoughts.
1452
- This tool helps analyze problems through a flexible thinking process that can adapt and evolve.
1453
- Each thought can build on, question, or revise previous insights as understanding deepens.
1454
-
1455
- IMPORTANT: This server facilitates sequential thinking with MCP tool coordination and skill recommendations. The LLM analyzes available tools and skills to make intelligent recommendations, which are then tracked and organized by this server.
1456
-
1457
- When to use this tool:
1458
- - Breaking down complex problems into steps
1459
- - Planning and design with room for revision
1460
- - Analysis that might need course correction
1461
- - Problems where the full scope might not be clear initially
1462
- - Problems that require a multi-step solution
1463
- - Tasks that need to maintain context over multiple steps
1464
- - Situations where irrelevant information needs to be filtered out
1465
- - When you need guidance on which tools to use and in what order
1466
- - When you need guidance on which skills to invoke for specific workflows
857
+ When to use this tool:
858
+ - Breaking down complex problems into steps
859
+ - Planning and design with room for revision
860
+ - Analysis that might need course correction
861
+ - Problems where the full scope might not be clear initially
862
+ - Problems that require a multi-step solution
863
+ - Tasks that need to maintain context over multiple steps
864
+ - Situations where irrelevant information needs to be filtered out
865
+ - When you need guidance on which tools to use and in what order
866
+ - When you need guidance on which skills to invoke for specific workflows
1467
867
 
1468
868
  Key features:
1469
869
  - You can adjust total_thoughts up or down as you progress
@@ -1491,7 +891,7 @@ Parameters explained:
1491
891
  * Hypothesis generation
1492
892
  * Hypothesis verification
1493
893
  * Tool recommendations and rationale
1494
- - next_thought_needed: True if you need more thinking, even if at what seemed like the end
894
+ - next_thought_needed: True if you need more thinking, even if at what seemed like the end. Omission defaults to true; the effective next action is in strategy_hint.
1495
895
  - thought_number: Current number in sequence (can go beyond initial total if needed)
1496
896
  - total_thoughts: Current estimate of thoughts needed (can be adjusted up/down)
1497
897
  - is_revision: A boolean indicating if this thought revises previous thinking
@@ -1785,7 +1185,7 @@ You should:
1785
1185
  available_skills: 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('Array of skill names available for use (e.g., ["commit", "review-pr", "pdf"])'))),
1786
1186
  thought: valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.description('Your current thinking step')),
1787
1187
  id: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.string(), valibot__rspack_import_0.minLength(1), valibot__rspack_import_0.maxLength(30), valibot__rspack_import_0.description('Unique identifier for this thought. Auto-generated if not provided.'))),
1788
- next_thought_needed: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('Whether another thought step is needed (defaults to true if not provided)'))),
1188
+ next_thought_needed: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('Omission defaults to true; the effective next action is returned in strategy_hint.'))),
1789
1189
  thought_number: valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Current thought number')),
1790
1190
  total_thoughts: valibot__rspack_import_0.pipe(valibot__rspack_import_0.number(), valibot__rspack_import_0.minValue(1), valibot__rspack_import_0.description('Estimated total thoughts needed')),
1791
1191
  is_revision: valibot__rspack_import_0.optional(valibot__rspack_import_0.pipe(valibot__rspack_import_0.boolean(), valibot__rspack_import_0.description('Whether this revises previous thinking'))),
@@ -1926,8 +1326,61 @@ __webpack_require__.d(__webpack_exports__, {
1926
1326
 
1927
1327
 
1928
1328
  },
1929
- "o"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1930
- /* import */ var _core_ids_js__rspack_import_0 = __webpack_require__("Uz");
1329
+ "E"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1330
+
1331
+ // EXPORTS
1332
+ __webpack_require__.d(__webpack_exports__, {
1333
+ StreamableHttpTransport: () => (/* binding */ StreamableHttpTransport)
1334
+ });
1335
+
1336
+ // UNUSED EXPORTS: createStreamableHttpTransport
1337
+
1338
+ ;// CONCATENATED MODULE: external "node:crypto"
1339
+
1340
+ ;// CONCATENATED MODULE: external "node:http"
1341
+
1342
+ // EXTERNAL MODULE: external "valibot"
1343
+ var external_valibot_ = __webpack_require__("w");
1344
+ // EXTERNAL MODULE: ./src/errors.ts
1345
+ var errors = __webpack_require__("U");
1346
+ // EXTERNAL MODULE: ./src/schema.ts
1347
+ var schema = __webpack_require__("R");
1348
+ ;// CONCATENATED MODULE: ./src/core/ids.ts
1349
+ /**
1350
+ * Unique identifier generation utilities for thoughts and edges.
1351
+ *
1352
+ * @module core/ids
1353
+ */
1354
+ /**
1355
+ * Generate a unique lexicographically-sortable identifier.
1356
+ *
1357
+ * Format: 8-char base36 timestamp + 20-char hex random (10 random bytes).
1358
+ * Result is up to 28 characters, sortable by creation time.
1359
+ *
1360
+ * @returns A unique string identifier.
1361
+ *
1362
+ * @example
1363
+ * ```typescript
1364
+ * const id = generateUlid(); // '01h2k3m400a1b2c3d4e5f6...'
1365
+ * ```
1366
+ */ function ids_generateUlid() {
1367
+ const timestamp = Date.now().toString(36).padStart(8, '0');
1368
+ const random = crypto.randomBytes(10).toString('hex');
1369
+ return `${timestamp}${random}`;
1370
+ }
1371
+ /**
1372
+ * Valid session ID pattern: alphanumeric, hyphens, underscores.
1373
+ *
1374
+ * Length is enforced separately via {@link MAX_SESSION_ID_LENGTH}.
1375
+ * Same character set as branch IDs.
1376
+ */ const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
1377
+ /**
1378
+ * Maximum session ID length (in characters).
1379
+ *
1380
+ * Allows compound identifiers (e.g. `user-123_task-abc`).
1381
+ */ const MAX_SESSION_ID_LENGTH = 100;
1382
+
1383
+ ;// CONCATENATED MODULE: ./src/transport/BaseTransport.ts
1931
1384
  /**
1932
1385
  * Base transport implementation.
1933
1386
  *
@@ -2018,7 +1471,7 @@ class BaseTransport {
2018
1471
  if (sessionId.length > (/* inlined export .MAX_SESSION_ID_LENGTH */100)) {
2019
1472
  return false;
2020
1473
  }
2021
- return _core_ids_js__rspack_import_0/* .SESSION_ID_PATTERN.test */.I.test(sessionId);
1474
+ return SESSION_ID_PATTERN.test(sessionId);
2022
1475
  }
2023
1476
  /**
2024
1477
  * Sanitize query parameters by removing any not in whitelist.
@@ -2256,669 +1709,83 @@ class BaseTransport {
2256
1709
  }
2257
1710
  }
2258
1711
 
2259
- __webpack_require__.d(__webpack_exports__, {
2260
- j: () => (BaseTransport)
2261
- });
2262
-
2263
-
2264
- },
2265
- "W"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2266
- /* import */ var node_http__rspack_import_0 = __webpack_require__("S");
2267
- /* import */ var node_crypto__rspack_import_1 = __webpack_require__("i");
2268
- /* import */ var node_url__rspack_import_2 = __webpack_require__("Y");
2269
- /* import */ var valibot__rspack_import_3 = __webpack_require__("w");
2270
- /* import */ var _errors_js__rspack_import_4 = __webpack_require__("U");
2271
- /* import */ var _pool_PoolErrors_js__rspack_import_5 = __webpack_require__("K");
2272
- /* import */ var _schema_js__rspack_import_6 = __webpack_require__("R");
2273
- /* import */ var _BaseTransport_js__rspack_import_7 = __webpack_require__("o");
2274
- /* import */ var _contracts_ids_js__rspack_import_8 = __webpack_require__("j");
2275
- /* import */ var _context_RequestContext_js__rspack_import_9 = __webpack_require__("y");
2276
- /* import */ var _utils_js__rspack_import_10 = __webpack_require__("h");
1712
+ ;// CONCATENATED MODULE: ./src/contracts/ids.ts
2277
1713
  /**
2278
- * SSE (Server-Sent Events) Transport implementation.
2279
- *
2280
- * This transport allows multiple concurrent connections over HTTP using Server-Sent Events,
2281
- * enabling multi-user scenarios and horizontal scaling.
1714
+ * Branded identifier types for compile-time slot safety.
2282
1715
  *
2283
- * When a ConnectionPool is provided, each SSE client gets an isolated session with its own
2284
- * thought history. Without a pool, all clients share a single server instance (backward compatible).
1716
+ * These nominal types prevent accidental mixing of different ID kinds
1717
+ * (e.g. passing a `ThoughtId` where a `SessionId` is expected). At
1718
+ * runtime they are plain strings — the brand exists only in the type
1719
+ * system.
2285
1720
  *
2286
- * @example
2287
- * ```typescript
2288
- * const transport = new SseTransport({
2289
- * port: 3000,
2290
- * host: 'localhost'
2291
- * });
2292
- * await transport.connect(server);
2293
- * ```
1721
+ * @module contracts/ids
2294
1722
  */
2295
1723
 
2296
-
2297
-
2298
-
2299
-
2300
-
2301
-
2302
-
2303
-
2304
-
2305
- /** Rejects persistence backends that cannot isolate pooled SSE child servers. */ function assertPooledSsePersistence(poolingEnabled, persistence) {
2306
- if (poolingEnabled && persistence?.enabled === true && (persistence.backend === 'file' || persistence.backend === 'sqlite')) {
2307
- throw new _errors_js__rspack_import_4/* .ConfigurationError */.j1(`pooled SSE does not support ${persistence.backend} persistence`);
2308
- }
2309
- }
2310
1724
  /**
2311
- * SSE Transport for MCP server over HTTP.
2312
- *
2313
- * This transport uses Server-Sent Events (SSE) to communicate with clients,
2314
- * allowing multiple concurrent connections and web-based clients.
1725
+ * Validate and brand a string as a {@link SessionId}.
2315
1726
  *
2316
- * @remarks
2317
- * **Security Features:**
2318
- * - Session ID validation (alphanumeric, max 64 chars)
2319
- * - Query parameter sanitization (whitelist allowed keys)
2320
- * - Rate limiting per IP (configurable, default 100 req/min)
2321
- * - CORS origin validation
1727
+ * Enforces {@link SESSION_ID_PATTERN} and {@link MAX_SESSION_ID_LENGTH}.
1728
+ * The reserved global session sentinel `__global__` is always accepted.
2322
1729
  *
2323
- * **Rate Limiting:**
2324
- * - Tracks requests per IP address within a time window
2325
- * - Returns 429 Too Many Requests when limit exceeded
2326
- * - Can be disabled via `enableRateLimit: false`
2327
- */ class SseTransport extends _BaseTransport_js__rspack_import_7/* .BaseTransport */.j {
2328
- get kind() {
2329
- return 'sse';
1730
+ * @throws {ValidationError} when the input is not a valid session id.
1731
+ */ function asSessionId(value) {
1732
+ if (value === '__global__') {
1733
+ // eslint-disable-next-line no-restricted-syntax -- branding constructor, cannot self-reference
1734
+ return value;
2330
1735
  }
2331
- _server;
2332
- _path;
2333
- _clients = new Set();
2334
- _clientSessionMap = new Map();
2335
- _sessionAttachmentCounts = new Map();
2336
- _releasePromises = new WeakMap();
2337
- _pendingReleases = new Set();
2338
- _releaseFailures = new Set();
2339
- _messageQueue = new Map();
2340
- _metrics;
2341
- _connectionPool;
2342
- _stopPromise = null;
2343
- constructor(options = {}){
2344
- assertPooledSsePersistence(options.connectionPool !== undefined, options.persistence);
2345
- super(options);
2346
- this._path = options.path ?? '/sse';
2347
- this._metrics = options.metrics;
2348
- this._connectionPool = options.connectionPool;
2349
- this._updateActiveConnectionsMetric();
2350
- this._server = (0,node_http__rspack_import_0.createServer)((req, res)=>this._handleRequest(req, res));
1736
+ if (typeof value !== 'string' || value.length === 0) {
1737
+ throw new errors/* .ValidationError */.yI('session_id', 'must be a non-empty string');
2351
1738
  }
2352
- /**
2353
- * Connect MCP server to this transport.
2354
- *
2355
- * @param mcpServer - The MCP server instance
2356
- */ async connect(mcpServer) {
2357
- this._mcpServer = mcpServer;
2358
- return new Promise((resolve, reject)=>{
2359
- const cleanup = ()=>{
2360
- this._server.off('error', onError);
2361
- this._server.off('listening', onListening);
2362
- };
2363
- const onError = (error)=>{
2364
- cleanup();
2365
- reject(error);
2366
- };
2367
- const onListening = ()=>{
2368
- cleanup();
2369
- this.log('info', `SSE transport listening on http://${this._host}:${this._port}`);
2370
- resolve();
2371
- };
2372
- this._server.once('error', onError);
2373
- this._server.once('listening', onListening);
2374
- try {
2375
- this._server.listen(this._port, this._host);
2376
- } catch (error) {
2377
- cleanup();
2378
- reject(error);
2379
- }
2380
- });
1739
+ if (value.length > (/* inlined export .MAX_SESSION_ID_LENGTH */100)) {
1740
+ throw new errors/* .ValidationError */.yI('session_id', `exceeds max length of ${(/* inlined export .MAX_SESSION_ID_LENGTH */100)}`);
2381
1741
  }
2382
- _mcpServer = null;
2383
- /**
2384
- * Handle incoming HTTP requests
2385
- */ async _handleRequest(req, res) {
2386
- const routing = this._prepareRequest(req, res);
2387
- if (!routing) return;
2388
- if (this._enableCors && req.method === 'OPTIONS') {
2389
- res.writeHead(204);
2390
- res.end();
2391
- return;
2392
- }
2393
- if (routing.url.pathname === this._path && req.method === 'GET') {
2394
- await this._handleSseConnection(req, res, routing.params);
2395
- return;
2396
- }
2397
- if (routing.url.pathname === `${this._path}/message` && req.method === 'POST') {
2398
- await this._handleMessage(req, res, routing.params);
2399
- return;
2400
- }
2401
- if (routing.url.pathname === '/health') {
2402
- this._handleHealthCheck(res);
2403
- return;
2404
- }
2405
- if (routing.url.pathname === '/ready') {
2406
- await this._handleReadinessCheck(res);
2407
- return;
2408
- }
2409
- res.writeHead(404, {
2410
- 'Content-Type': 'text/plain'
2411
- });
2412
- res.end('Not Found');
2413
- }
2414
- _prepareRequest(req, res) {
2415
- const startTime = Date.now();
2416
- const requestPath = req.url || '/';
2417
- const requestMethod = req.method || 'GET';
2418
- this._metrics?.counter('http_requests_total', 1, {
2419
- transport: 'sse',
2420
- method: requestMethod,
2421
- path: requestPath
2422
- }, 'Total HTTP requests');
2423
- res.once('finish', ()=>{
2424
- const durationSeconds = (Date.now() - startTime) / 1000;
2425
- this._metrics?.histogram('http_request_duration_seconds', durationSeconds, {
2426
- transport: 'sse',
2427
- path: requestPath
2428
- });
2429
- });
2430
- if (!this.validateHostHeader(req)) {
2431
- this._metrics?.counter('http_request_errors_total', 1, {
2432
- transport: 'sse',
2433
- error_type: 'forbidden'
2434
- }, 'Total HTTP request errors');
2435
- res.writeHead(403, {
2436
- 'Content-Type': 'application/json'
2437
- });
2438
- res.end(JSON.stringify({
2439
- error: 'Forbidden - invalid host header'
2440
- }));
2441
- return;
2442
- }
2443
- const url = new node_url__rspack_import_2.URL(req.url || '', `http://${req.headers.host}`);
2444
- // Check rate limit first
2445
- const clientIp = this.getClientIp(req);
2446
- if (this.checkRateLimit(clientIp)) {
2447
- this._metrics?.counter('http_request_errors_total', 1, {
2448
- transport: 'sse',
2449
- error_type: 'rate_limit'
2450
- }, 'Total HTTP request errors');
2451
- res.writeHead(429, {
2452
- 'Content-Type': 'application/json',
2453
- 'Retry-After': '60'
2454
- });
2455
- res.end(JSON.stringify({
2456
- error: 'Too many requests'
2457
- }));
2458
- return;
2459
- }
2460
- // Validate CORS origin
2461
- if (!this.validateCorsOrigin(req)) {
2462
- this._metrics?.counter('http_request_errors_total', 1, {
2463
- transport: 'sse',
2464
- error_type: 'forbidden'
2465
- }, 'Total HTTP request errors');
2466
- res.writeHead(403, {
2467
- 'Content-Type': 'application/json'
2468
- });
2469
- res.end(JSON.stringify({
2470
- error: 'Forbidden - invalid origin'
2471
- }));
2472
- return;
2473
- }
2474
- // Set CORS headers
2475
- this.setCorsHeaders(res);
2476
- // Sanitize query parameters
2477
- const sanitizedParams = this.sanitizeQueryParams(url);
2478
- // Validate session ID if present
2479
- const requestSessionId = sanitizedParams.session ?? sanitizedParams.sessionId;
2480
- if (requestSessionId !== undefined && !this.validateSessionId(requestSessionId)) {
2481
- this._metrics?.counter('http_request_errors_total', 1, {
2482
- transport: 'sse',
2483
- error_type: 'validation'
2484
- }, 'Total HTTP request errors');
2485
- res.writeHead(400, {
2486
- 'Content-Type': 'application/json'
2487
- });
2488
- res.end(JSON.stringify({
2489
- error: 'Invalid session ID format'
2490
- }));
2491
- return undefined;
2492
- }
2493
- return {
2494
- url,
2495
- params: sanitizedParams
2496
- };
2497
- }
2498
- /**
2499
- * Handle health check (liveness) endpoint
2500
- */ _handleHealthCheck(res) {
2501
- const healthData = {
2502
- status: 'healthy',
2503
- clients: this._clients.size
2504
- };
2505
- if (this._connectionPool) {
2506
- const poolStats = this._connectionPool.getStats();
2507
- healthData.pool = poolStats;
2508
- }
2509
- if (this._healthChecker) {
2510
- const liveness = this._healthChecker.checkLiveness();
2511
- healthData.liveness = liveness;
2512
- }
2513
- res.writeHead(200, {
2514
- 'Content-Type': 'application/json'
2515
- });
2516
- res.end(JSON.stringify(healthData));
2517
- }
2518
- /**
2519
- * Handle readiness check endpoint
2520
- */ async _handleReadinessCheck(res) {
2521
- if (this._healthChecker) {
2522
- const readiness = await this._healthChecker.checkReadiness();
2523
- const statusCode = readiness.status === 'ok' ? 200 : 503;
2524
- res.writeHead(statusCode, {
2525
- 'Content-Type': 'application/json'
2526
- });
2527
- res.end(JSON.stringify(readiness));
2528
- } else {
2529
- res.writeHead(200, {
2530
- 'Content-Type': 'application/json'
2531
- });
2532
- res.end(JSON.stringify({
2533
- status: 'ok',
2534
- timestamp: new Date().toISOString(),
2535
- components: {}
2536
- }));
2537
- }
2538
- }
2539
- /**
2540
- * Handle new SSE connection
2541
- */ async _handleSseConnection(req, res, params) {
2542
- // Set SSE headers
2543
- res.writeHead(200, {
2544
- 'Content-Type': 'text/event-stream',
2545
- 'Cache-Control': 'no-cache',
2546
- Connection: 'keep-alive'
2547
- });
2548
- // Resolve session ID when pool is active
2549
- let sessionId;
2550
- if (this._connectionPool) {
2551
- const requestedSession = params.session ?? params.sessionId;
2552
- const requestedSessionId = requestedSession ? (0,_contracts_ids_js__rspack_import_8/* .asSessionId */.Kd)(requestedSession) : undefined;
2553
- if (requestedSessionId && this._connectionPool.getSessionInfo(requestedSessionId)) {
2554
- sessionId = requestedSessionId;
2555
- } else {
2556
- try {
2557
- sessionId = await this._connectionPool.createSession();
2558
- } catch (error) {
2559
- res.write(`event: error\n`);
2560
- res.write(`data: ${JSON.stringify({
2561
- error: error instanceof Error ? error.message : 'Failed to create session'
2562
- })}\n\n`);
2563
- res.end();
2564
- return;
2565
- }
2566
- }
2567
- this._clientSessionMap.set(res, sessionId);
2568
- this._sessionAttachmentCounts.set(sessionId, (this._sessionAttachmentCounts.get(sessionId) ?? 0) + 1);
2569
- this._updatePoolMetrics();
2570
- }
2571
- this._clients.add(res);
2572
- this._updateActiveConnectionsMetric();
2573
- const release = ()=>this._releaseAfterDisconnect(res);
2574
- req.once('close', release);
2575
- res.once('close', release);
2576
- res.once('error', release);
2577
- // Send initial connection event
2578
- const connectedPayload = {
2579
- timestamp: Date.now()
2580
- };
2581
- if (sessionId) {
2582
- connectedPayload.sessionId = sessionId;
2583
- }
2584
- this._sendSseEvent(res, 'connected', connectedPayload);
2585
- // Send any queued messages
2586
- const clientId = this._generateClientId();
2587
- const queued = this._messageQueue.get(clientId);
2588
- if (queued) {
2589
- for (const message of queued){
2590
- this._sendSseEvent(res, 'message', message);
2591
- }
2592
- this._messageQueue.delete(clientId);
2593
- }
2594
- }
2595
- /**
2596
- * Handle incoming message from client
2597
- */ async _handleMessage(req, res, params) {
2598
- let pooledOwner;
2599
- if (this._connectionPool) {
2600
- const correlation = params.session ?? params.sessionId;
2601
- if (correlation === undefined) {
2602
- res.writeHead(400, {
2603
- 'Content-Type': 'application/json'
2604
- });
2605
- res.end(JSON.stringify({
2606
- error: 'Missing session ID'
2607
- }));
2608
- return;
2609
- }
2610
- pooledOwner = (0,_contracts_ids_js__rspack_import_8/* .asSessionId */.Kd)(correlation);
2611
- }
2612
- const jsonRpcRequest = await this._parseMessage(req, res);
2613
- if (!jsonRpcRequest) return;
2614
- const mcpServer = this._mcpServer;
2615
- if (!mcpServer) {
2616
- this._metrics?.counter('http_request_errors_total', 1, {
2617
- transport: 'sse',
2618
- error_type: 'server_not_ready'
2619
- }, 'Total HTTP request errors');
2620
- res.writeHead(503, {
2621
- 'Content-Type': 'application/json'
2622
- });
2623
- res.end(JSON.stringify({
2624
- error: 'Server not ready'
2625
- }));
2626
- return;
2627
- }
2628
- const owner = pooledOwner ?? `sse-${(0,node_crypto__rspack_import_1.randomUUID)()}`;
2629
- const receive = ()=>(0,_context_RequestContext_js__rspack_import_9/* .runWithContext */.Vo)({
2630
- requestId: (0,node_crypto__rspack_import_1.randomUUID)(),
2631
- owner
2632
- }, ()=>mcpServer.receive(jsonRpcRequest, {
2633
- sessionInfo: {}
2634
- }));
2635
- try {
2636
- let response;
2637
- if (this._connectionPool && pooledOwner) {
2638
- if (typeof this._connectionPool.runWithSession !== 'function') {
2639
- this._writeSessionUnavailable(res);
2640
- return;
2641
- }
2642
- const result = await this._connectionPool.runWithSession(pooledOwner, receive);
2643
- switch(result.status){
2644
- case 'completed':
2645
- response = result.value;
2646
- break;
2647
- case 'inactive':
2648
- case 'missing':
2649
- this._writeSessionUnavailable(res);
2650
- return;
2651
- default:
2652
- return (0,_utils_js__rspack_import_10/* .assertNever */.x)(result);
2653
- }
2654
- } else {
2655
- response = await receive();
2656
- }
2657
- res.writeHead(200, {
2658
- 'Content-Type': 'application/json'
2659
- });
2660
- res.end(JSON.stringify(response ?? {
2661
- jsonrpc: '2.0',
2662
- id: 'id' in jsonRpcRequest ? jsonRpcRequest.id : null,
2663
- result: null
2664
- }));
2665
- } catch (error) {
2666
- if (error instanceof _pool_PoolErrors_js__rspack_import_5/* .SessionNotFoundError */.A || error instanceof _pool_PoolErrors_js__rspack_import_5/* .SessionNotActiveError */.q) {
2667
- this._writeSessionUnavailable(res);
2668
- return;
2669
- }
2670
- throw error;
2671
- }
2672
- }
2673
- async _parseMessage(req, res) {
2674
- let body = '';
2675
- for await (const chunk of req){
2676
- body += chunk.toString();
2677
- }
2678
- let rawBody;
2679
- try {
2680
- rawBody = JSON.parse(body);
2681
- } catch (error) {
2682
- if (!(error instanceof SyntaxError)) throw error;
2683
- this._metrics?.counter('http_request_errors_total', 1, {
2684
- transport: 'sse',
2685
- error_type: 'parse_error'
2686
- }, 'Total HTTP request errors');
2687
- res.writeHead(400, {
2688
- 'Content-Type': 'application/json'
2689
- });
2690
- res.end(JSON.stringify({
2691
- error: 'Invalid JSON'
2692
- }));
2693
- return;
2694
- }
2695
- const parseResult = (0,valibot__rspack_import_3.safeParse)(_schema_js__rspack_import_6/* .JsonRpcRequestSchema */.Uv, rawBody);
2696
- const rawId = rawBody && typeof rawBody === 'object' && 'id' in rawBody ? rawBody.id ?? null : null;
2697
- if (!parseResult.success) {
2698
- this._metrics?.counter('http_request_errors_total', 1, {
2699
- transport: 'sse',
2700
- error_type: 'validation'
2701
- }, 'Total HTTP request errors');
2702
- res.writeHead(200, {
2703
- 'Content-Type': 'application/json'
2704
- });
2705
- res.end(JSON.stringify({
2706
- jsonrpc: '2.0',
2707
- id: rawId,
2708
- error: {
2709
- code: -32600,
2710
- message: 'Invalid Request',
2711
- data: parseResult.issues
2712
- }
2713
- }));
2714
- return;
2715
- }
2716
- return parseResult.output;
2717
- }
2718
- _writeSessionUnavailable(res) {
2719
- res.writeHead(404, {
2720
- 'Content-Type': 'application/json'
2721
- });
2722
- res.end(JSON.stringify({
2723
- error: 'Session not found'
2724
- }));
2725
- }
2726
- _releaseClient(res) {
2727
- const existing = this._releasePromises.get(res);
2728
- if (existing) {
2729
- return existing;
2730
- }
2731
- this._clients.delete(res);
2732
- const sessionId = this._clientSessionMap.get(res);
2733
- this._clientSessionMap.delete(res);
2734
- this._updateActiveConnectionsMetric();
2735
- let releasePromise = Promise.resolve();
2736
- if (sessionId && this._connectionPool) {
2737
- const attachmentCount = this._sessionAttachmentCounts.get(sessionId);
2738
- if (attachmentCount !== undefined && attachmentCount > 1) {
2739
- this._sessionAttachmentCounts.set(sessionId, attachmentCount - 1);
2740
- } else {
2741
- this._sessionAttachmentCounts.delete(sessionId);
2742
- releasePromise = this._connectionPool.closeSession(sessionId).catch((error)=>{
2743
- if (error instanceof _pool_PoolErrors_js__rspack_import_5/* .SessionNotFoundError */.A) {
2744
- return;
2745
- }
2746
- throw error;
2747
- });
2748
- }
2749
- this._updatePoolMetrics();
2750
- }
2751
- this._releasePromises.set(res, releasePromise);
2752
- this._pendingReleases.add(releasePromise);
2753
- void releasePromise.then(()=>this._pendingReleases.delete(releasePromise), (error)=>{
2754
- this._pendingReleases.delete(releasePromise);
2755
- this._releaseFailures.add(error);
2756
- });
2757
- return releasePromise;
2758
- }
2759
- _releaseAfterDisconnect(res) {
2760
- void this._releaseClient(res).catch((error)=>{
2761
- this.log('error', 'SSE pooled session release failed', {
2762
- error
2763
- });
2764
- });
2765
- }
2766
- /**
2767
- * Send an SSE event to a specific client
2768
- */ _sendSseEvent(res, event, data) {
2769
- try {
2770
- res.write(`event: ${event}\n`);
2771
- res.write(`data: ${JSON.stringify(data)}\n\n`);
2772
- } catch {
2773
- this._releaseAfterDisconnect(res);
2774
- }
2775
- }
2776
- _updateActiveConnectionsMetric() {
2777
- this._metrics?.gauge('sse_active_connections', this._clients.size, {}, 'Current active SSE connections');
2778
- }
2779
- _updatePoolMetrics() {
2780
- if (!this._connectionPool || !this._metrics) {
2781
- return;
2782
- }
2783
- const stats = this._connectionPool.getStats();
2784
- this._metrics.gauge('sse_pool_active_sessions', stats.activeSessions, {}, 'Active sessions in connection pool');
2785
- this._metrics.gauge('sse_pool_total_sessions', stats.totalSessions, {}, 'Total sessions in connection pool');
2786
- this._metrics.gauge('sse_pool_max_sessions', stats.maxSessions, {}, 'Maximum sessions in connection pool');
2787
- }
2788
- /**
2789
- * Broadcast a message to all connected clients
2790
- */ broadcast(event, data) {
2791
- for (const client of this._clients){
2792
- this._sendSseEvent(client, event, data);
2793
- }
2794
- }
2795
- /**
2796
- * Generate a unique client ID
2797
- */ _generateClientId() {
2798
- return `client_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
2799
- }
2800
- /**
2801
- * Get number of connected clients
2802
- */ get clientCount() {
2803
- return this._clients.size;
2804
- }
2805
- /**
2806
- * Get the connection pool, if one was configured.
2807
- */ get connectionPool() {
2808
- return this._connectionPool;
2809
- }
2810
- /**
2811
- * Stop the transport server with graceful shutdown.
2812
- *
2813
- * @param timeout - Maximum time to wait for requests to drain (not used for SSE)
2814
- * @returns Promise that resolves when shutdown is complete
2815
- */ stop(_timeout) {
2816
- if (this._stopPromise) {
2817
- return this._stopPromise;
2818
- }
2819
- const completion = Promise.withResolvers();
2820
- this._stopPromise = completion.promise;
2821
- this._isShuttingDown = true;
2822
- this._stopRateLimitCleanup();
2823
- const operations = new Set();
2824
- for (const client of Array.from(this._clients)){
2825
- operations.add(this._releaseClient(client));
2826
- try {
2827
- client.end();
2828
- } catch (error) {
2829
- operations.add(Promise.reject(error instanceof Error ? error : new AggregateError([
2830
- error
2831
- ], 'SSE client close failed')));
2832
- }
2833
- }
2834
- for (const release of this._pendingReleases){
2835
- operations.add(release);
2836
- }
2837
- if (this._connectionPool) {
2838
- operations.add(this._connectionPool.terminate());
2839
- }
2840
- operations.add(this._server.listening ? new Promise((resolve, reject)=>{
2841
- this._server.close((error)=>error ? reject(error) : resolve());
2842
- }) : Promise.resolve());
2843
- void Promise.allSettled(operations).then((outcomes)=>{
2844
- const failures = new Set(this._releaseFailures);
2845
- for (const outcome of outcomes){
2846
- if (outcome.status !== 'rejected') {
2847
- continue;
2848
- }
2849
- if (outcome.reason instanceof AggregateError) {
2850
- for (const error of outcome.reason.errors)failures.add(error);
2851
- } else {
2852
- failures.add(outcome.reason);
2853
- }
2854
- }
2855
- this._clients.clear();
2856
- this._clientSessionMap.clear();
2857
- this._sessionAttachmentCounts.clear();
2858
- this._updateActiveConnectionsMetric();
2859
- this._updatePoolMetrics();
2860
- if (failures.size > 0) {
2861
- completion.reject(new AggregateError(failures, 'SSE transport shutdown failed'));
2862
- return;
2863
- }
2864
- this.log('info', 'SSE transport stopped');
2865
- completion.resolve();
2866
- });
2867
- return completion.promise;
1742
+ if (!SESSION_ID_PATTERN.test(value)) {
1743
+ throw new errors/* .ValidationError */.yI('session_id', 'must match alphanumeric, hyphens, underscores');
2868
1744
  }
1745
+ // eslint-disable-next-line no-restricted-syntax -- branding constructor, cannot self-reference
1746
+ return value;
1747
+ }
1748
+ /** Brand a string as a {@link ThoughtId} without validation. */ function asThoughtId(value) {
1749
+ return value;
1750
+ }
1751
+ /** Brand a string as an {@link EdgeId} without validation. */ function asEdgeId(value) {
1752
+ return value;
1753
+ }
1754
+ /** Brand a string as a {@link SuspensionToken} without validation. */ function asSuspensionToken(value) {
1755
+ return value;
1756
+ }
1757
+ /** Brand a string as a {@link BranchId} without validation. */ function asBranchId(value) {
1758
+ return value;
1759
+ }
1760
+ /** Brand a string as a {@link SummaryId} without validation. */ function asSummaryId(value) {
1761
+ return value;
1762
+ }
1763
+ /** Generate a fresh {@link ThoughtId}. */ function generateThoughtId() {
1764
+ return generateUlid();
1765
+ }
1766
+ /** Generate a fresh {@link EdgeId}. */ function generateEdgeId() {
1767
+ return generateUlid();
1768
+ }
1769
+ /** Generate a fresh {@link SuspensionToken}. */ function generateSuspensionToken() {
1770
+ return generateUlid();
1771
+ }
1772
+ /** Generate a fresh {@link SummaryId}. */ function generateSummaryId() {
1773
+ return generateUlid();
2869
1774
  }
2870
1775
  /**
2871
- * Create an SSE transport with given options.
2872
- *
2873
- * @param options - Transport configuration
2874
- * @returns A configured SSE transport
1776
+ * Reserved sentinel session id used when callers omit `session_id`.
2875
1777
  *
2876
- * @example
2877
- * ```typescript
2878
- * const transport = createSseTransport({ port: 3000 });
2879
- * await transport.connect(mcpServer);
2880
- * ```
2881
- */ function createSseTransport(options = {}) {
2882
- return new SseTransport(options);
2883
- }
2884
-
2885
- __webpack_require__.d(__webpack_exports__, {
2886
- SseTransport: () => (SseTransport),
2887
- c: () => (assertPooledSsePersistence)
2888
- });
2889
-
2890
-
2891
- },
2892
- "J"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
2893
-
2894
- // EXPORTS
2895
- __webpack_require__.d(__webpack_exports__, {
2896
- StreamableHttpTransport: () => (/* binding */ StreamableHttpTransport)
2897
- });
2898
-
2899
- // UNUSED EXPORTS: createStreamableHttpTransport
1778
+ * Branded once here so production and test code share one constant
1779
+ * instead of casting `'__global__'` ad-hoc.
1780
+ */ const GLOBAL_SESSION_ID = asSessionId('__global__');
2900
1781
 
2901
- // EXTERNAL MODULE: external "node:crypto"
2902
- var external_node_crypto_ = __webpack_require__("i");
2903
- // EXTERNAL MODULE: external "node:http"
2904
- var external_node_http_ = __webpack_require__("S");
2905
- // EXTERNAL MODULE: external "valibot"
2906
- var external_valibot_ = __webpack_require__("w");
2907
- // EXTERNAL MODULE: ./src/errors.ts
2908
- var errors = __webpack_require__("U");
2909
- // EXTERNAL MODULE: ./src/schema.ts
2910
- var schema = __webpack_require__("R");
2911
- // EXTERNAL MODULE: ./src/transport/BaseTransport.ts
2912
- var BaseTransport = __webpack_require__("o");
2913
- // EXTERNAL MODULE: ./src/contracts/ids.ts
2914
- var ids = __webpack_require__("j");
2915
1782
  ;// CONCATENATED MODULE: ./src/transport/HttpHelpers.ts
2916
1783
  /**
2917
1784
  * Shared HTTP helper utilities for MCP transport implementations.
2918
1785
  *
2919
1786
  * Centralizes JSON-RPC response formatting, request body reading,
2920
1787
  * and common HTTP response patterns to eliminate duplication across
2921
- * HttpTransport, StreamableHttpTransport, and SseTransport.
1788
+ * HttpTransport and StreamableHttpTransport.
2922
1789
  *
2923
1790
  * @module transport/HttpHelpers
2924
1791
  */ /**
@@ -3003,8 +1870,8 @@ var ids = __webpack_require__("j");
3003
1870
  return body;
3004
1871
  }
3005
1872
 
3006
- // EXTERNAL MODULE: ./src/context/RequestContext.ts
3007
- var RequestContext = __webpack_require__("y");
1873
+ // EXTERNAL MODULE: ./src/context/RequestContext.ts + 1 modules
1874
+ var RequestContext = __webpack_require__("i");
3008
1875
  ;// CONCATENATED MODULE: ./src/transport/HttpRequestLifecycle.ts
3009
1876
  /** Maximum number of reporting failures retained for diagnostics. */ const LIFECYCLE_REPORTING_FAILURE_CAPACITY = 32;
3010
1877
  class LifecycleFailureReporter {
@@ -3160,7 +2027,7 @@ class AcceptedWorkTracker {
3160
2027
  * - 429: Too Many Requests
3161
2028
  * - 500: Internal Server Error
3162
2029
  * - 503: Server Not Ready / Shutting Down
3163
- */ class StreamableHttpTransport extends BaseTransport/* .BaseTransport */.j {
2030
+ */ class StreamableHttpTransport extends BaseTransport {
3164
2031
  get kind() {
3165
2032
  return 'streamable-http';
3166
2033
  }
@@ -3184,7 +2051,7 @@ class AcceptedWorkTracker {
3184
2051
  super(options);
3185
2052
  this._path = options.path ?? '/mcp';
3186
2053
  this._stateful = options.stateful ?? true;
3187
- this._sessionIdGenerator = options.sessionIdGenerator ?? (()=>(0,external_node_crypto_.randomUUID)());
2054
+ this._sessionIdGenerator = options.sessionIdGenerator ?? (()=>(0,__rspack_external_node_crypto_2e7c4b46.randomUUID)());
3188
2055
  this._bodySizeLimitEnabled = options.enableBodySizeLimit ?? true;
3189
2056
  this._maxBodySize = options.maxBodySize ?? 10 * 1024 * 1024;
3190
2057
  this._requestTimeout = options.requestTimeout ?? 30000;
@@ -3217,7 +2084,7 @@ class AcceptedWorkTracker {
3217
2084
  * Connects MCP server to this transport and starts listening.
3218
2085
  */ async connect(mcpServer) {
3219
2086
  this._mcpServer = mcpServer;
3220
- const server = (0,external_node_http_.createServer)((req, res)=>{
2087
+ const server = (0,__rspack_external_node_http_e245b239.createServer)((req, res)=>{
3221
2088
  const responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);
3222
2089
  void this._handleRequest(req, res).catch((error)=>{
3223
2090
  this._lifecycleFailureReporter.report(error);
@@ -3435,9 +2302,9 @@ class AcceptedWorkTracker {
3435
2302
  }
3436
2303
  }
3437
2304
  async _receiveAndFinalize(jsonRpcRequest, sessionId, responseFinalizer) {
3438
- const owner = this._stateful ? sessionId ?? (0,external_node_crypto_.randomUUID)() : (0,external_node_crypto_.randomUUID)();
2305
+ const owner = this._stateful ? sessionId ?? (0,__rspack_external_node_crypto_2e7c4b46.randomUUID)() : (0,__rspack_external_node_crypto_2e7c4b46.randomUUID)();
3439
2306
  const response = await (0,RequestContext/* .runWithContext */.Vo)({
3440
- requestId: (0,external_node_crypto_.randomUUID)(),
2307
+ requestId: (0,__rspack_external_node_crypto_2e7c4b46.randomUUID)(),
3441
2308
  owner
3442
2309
  }, ()=>this._requireMcpServer().receive(jsonRpcRequest, {
3443
2310
  sessionInfo: {}
@@ -3496,7 +2363,7 @@ class AcceptedWorkTracker {
3496
2363
  }));
3497
2364
  return;
3498
2365
  }
3499
- const session = this._sessions.get((0,ids/* .asSessionId */.Kd)(sessionId));
2366
+ const session = this._sessions.get(asSessionId(sessionId));
3500
2367
  if (!session) {
3501
2368
  res.writeHead(404, {
3502
2369
  'Content-Type': 'application/json'
@@ -3549,7 +2416,7 @@ class AcceptedWorkTracker {
3549
2416
  };
3550
2417
  }
3551
2418
  // Check if session exists
3552
- const session = this._sessions.get((0,ids/* .asSessionId */.Kd)(headerSessionId));
2419
+ const session = this._sessions.get(asSessionId(headerSessionId));
3553
2420
  if (session) {
3554
2421
  session.lastActivityAt = Date.now();
3555
2422
  return headerSessionId;
@@ -3569,7 +2436,7 @@ class AcceptedWorkTracker {
3569
2436
  lastActivityAt: Date.now(),
3570
2437
  notificationStreams: new Set()
3571
2438
  };
3572
- this._sessions.set((0,ids/* .asSessionId */.Kd)(newSessionId), sessionState);
2439
+ this._sessions.set(asSessionId(newSessionId), sessionState);
3573
2440
  this.log('info', `New session created: ${newSessionId}`);
3574
2441
  this._updateSessionMetrics();
3575
2442
  return newSessionId;
@@ -3600,7 +2467,7 @@ class AcceptedWorkTracker {
3600
2467
  * @param event - SSE event name
3601
2468
  * @param data - Event payload
3602
2469
  */ broadcastToSession(sessionId, event, data) {
3603
- const session = this._sessions.get((0,ids/* .asSessionId */.Kd)(sessionId));
2470
+ const session = this._sessions.get(asSessionId(sessionId));
3604
2471
  if (!session) {
3605
2472
  return;
3606
2473
  }
@@ -3741,76 +2608,12 @@ class AcceptedWorkTracker {
3741
2608
  *
3742
2609
  * @example
3743
2610
  * ```typescript
3744
- * const transport = createStreamableHttpTransport({ port: 3000, stateful: true });
3745
- * await transport.connect(server);
3746
- * ```
3747
- */ function createStreamableHttpTransport(options = {}) {
3748
- return new StreamableHttpTransport(options);
3749
- }
3750
-
3751
-
3752
- },
3753
- "h"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
3754
- /**
3755
- * Shared utility helpers.
3756
- *
3757
- * @module utils
3758
- */ /**
3759
- * Asserts that a value is `never`. Use in switch default cases to enforce
3760
- * exhaustiveness over discriminated unions. TypeScript will error at compile
3761
- * time if any variant of the union is unhandled.
3762
- *
3763
- * @param value - The value that should be statically `never`.
3764
- * @param message - Optional error message override.
3765
- * @returns Never returns; always throws.
3766
- *
3767
- * @example
3768
- * ```ts
3769
- * function handle(t: ThoughtType): string {
3770
- * switch (t) {
3771
- * case 'regular': return 'r';
3772
- * // ... all other cases ...
3773
- * default: assertNever(t);
3774
- * }
3775
- * }
3776
- * ```
3777
- */ function assertNever(value, message) {
3778
- throw new Error(message ?? `Unexpected value: ${String(value)}`);
3779
- }
3780
-
3781
- __webpack_require__.d(__webpack_exports__, {
3782
- x: () => (assertNever)
3783
- });
3784
-
3785
-
3786
- },
3787
- "r"(module) {
3788
-
3789
- module.exports = __rspack_external__lib_js_1645bc55;
3790
-
3791
-
3792
- },
3793
- "A"(module) {
3794
-
3795
- module.exports = __rspack_external_node_async_hooks_4d8b1b4a;
3796
-
3797
-
3798
- },
3799
- "i"(module) {
3800
-
3801
- module.exports = __rspack_external_node_crypto_2e7c4b46;
3802
-
3803
-
3804
- },
3805
- "S"(module) {
3806
-
3807
- module.exports = __rspack_external_node_http_e245b239;
3808
-
3809
-
3810
- },
3811
- "Y"(module) {
3812
-
3813
- module.exports = __rspack_external_node_url_3991086a;
2611
+ * const transport = createStreamableHttpTransport({ port: 3000, stateful: true });
2612
+ * await transport.connect(server);
2613
+ * ```
2614
+ */ function createStreamableHttpTransport(options = {}) {
2615
+ return new StreamableHttpTransport(options);
2616
+ }
3814
2617
 
3815
2618
 
3816
2619
  },
@@ -3875,8 +2678,8 @@ var __webpack_exports__ = {};
3875
2678
 
3876
2679
  ;// CONCATENATED MODULE: external "node:path"
3877
2680
 
3878
- // EXTERNAL MODULE: external "node:url"
3879
- var external_node_url_ = __webpack_require__("Y");
2681
+ ;// CONCATENATED MODULE: external "node:url"
2682
+
3880
2683
  ;// CONCATENATED MODULE: external "tmcp"
3881
2684
 
3882
2685
  // EXTERNAL MODULE: ./src/errors.ts
@@ -3974,734 +2777,10 @@ function createCliShutdownHandler(lifecycle, boundary) {
3974
2777
  };
3975
2778
  }
3976
2779
 
3977
- // EXTERNAL MODULE: external "./lib.js"
3978
- var external_lib_js_ = __webpack_require__("r");
3979
- ;// CONCATENATED MODULE: external "node:os"
3980
-
3981
- ;// CONCATENATED MODULE: ./src/ServerConfig.ts
3982
- /**
3983
- * Server configuration management with validation.
3984
- *
3985
- * This module provides the `ServerConfig` class which handles all server configuration
3986
- * with built-in validation and sensible defaults. Configuration values are validated
3987
- * on construction and warnings are emitted for out-of-range values.
3988
- *
3989
- * @module ServerConfig
3990
- */
3991
-
3992
-
3993
- /**
3994
- * Server configuration with validation and defaults.
3995
- *
3996
- * This class manages all server configuration including history limits,
3997
- * branch limits, discovery directories, cache settings, and persistence.
3998
- * All values are validated on construction with appropriate defaults applied.
3999
- *
4000
- * @remarks
4001
- * - Values outside recommended ranges trigger warnings but are still applied
4002
- * - Environment variables override file-based configuration
4003
- * - The `toJSON()` method provides a plain object representation
4004
- *
4005
- * @example
4006
- * ```typescript
4007
- * // Using defaults
4008
- * const config1 = new ServerConfig();
4009
- * console.log(config1.maxHistorySize); // 10000
4010
- *
4011
- * // With custom options
4012
- * const config2 = new ServerConfig({
4013
- * maxHistorySize: 500,
4014
- * persistence: { enabled: true, backend: 'file', options: { dataDir: './data' } }
4015
- * });
4016
- *
4017
- * // Export as plain object
4018
- * const json = config2.toJSON();
4019
- * ```
4020
- */ class ServerConfig {
4021
- /** Maximum number of thoughts to keep in history. */ maxHistorySize;
4022
- /** Maximum number of branches to maintain. */ maxBranches;
4023
- /** Maximum size of each branch. */ maxBranchSize;
4024
- /** Directory paths to search for skills. */ skillDirs;
4025
- /** Directory paths to search for tools. */ toolDirs;
4026
- /** Discovery cache configuration. */ discoveryCache;
4027
- /** Persistence configuration. */ persistence;
4028
- /** Maximum number of thoughts to buffer before flushing to persistence. */ persistenceBufferSize;
4029
- /** Interval in milliseconds between periodic persistence flushes. */ persistenceFlushInterval;
4030
- /** Maximum number of retries for failed persistence flushes. */ persistenceMaxRetries;
4031
- /** Feature flag toggles. */ features;
4032
- /** TTL in milliseconds for suspended tool-interleave entries. */ toolInterleaveTtlMs;
4033
- /** Sweep interval in milliseconds for SuspensionStore expiration cleanup. */ toolInterleaveSweepMs;
4034
- /** Maximum sessions per owner (LRU per-owner bucket). */ maxSessionsPerOwner;
4035
- /**
4036
- * Creates a new ServerConfig instance with validation.
4037
- *
4038
- * All values are validated and defaults are applied for undefined options.
4039
- * Warnings are emitted to console for values outside recommended ranges.
4040
- *
4041
- * @param options - Optional configuration overrides
4042
- *
4043
- * @example
4044
- * ```typescript
4045
- * const config = new ServerConfig({
4046
- * maxHistorySize: 500,
4047
- * skillDirs: ['./my-skills']
4048
- * });
4049
- * ```
4050
- */ constructor(options = {}){
4051
- this.maxHistorySize = this.validateMaxHistorySize(options.maxHistorySize);
4052
- this.maxBranches = this.validateMaxBranches(options.maxBranches);
4053
- this.maxBranchSize = this.validateMaxBranchSize(options.maxBranchSize);
4054
- this.skillDirs = this.validateSkillDirs(options.skillDirs);
4055
- this.toolDirs = this.validateToolDirs(options.toolDirs);
4056
- this.discoveryCache = this.validateDiscoveryCache(options.discoveryCache);
4057
- this.persistence = this.validatePersistence(options.persistence);
4058
- this.persistenceBufferSize = this.validatePersistenceBufferSize(options.persistenceBufferSize);
4059
- this.persistenceFlushInterval = this.validatePersistenceFlushInterval(options.persistenceFlushInterval);
4060
- this.persistenceMaxRetries = this.validatePersistenceMaxRetries(options.persistenceMaxRetries);
4061
- this.features = this.validateFeatures(options.features);
4062
- this.toolInterleaveTtlMs = this.validatePositiveMs(options.toolInterleaveTtlMs, 60000, 'toolInterleaveTtlMs');
4063
- this.toolInterleaveSweepMs = this.validatePositiveMs(options.toolInterleaveSweepMs, 60000, 'toolInterleaveSweepMs');
4064
- this.maxSessionsPerOwner = this.validateMaxSessionsPerOwner(options.maxSessionsPerOwner);
4065
- }
4066
- /**
4067
- * Validates the max history size value.
4068
- * @param value - The value to validate
4069
- * @returns The validated value or default (1000)
4070
- * @private
4071
- */ validateMaxHistorySize(value) {
4072
- const defaultValue = 10000;
4073
- if (value === undefined || value === null) return defaultValue;
4074
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4075
- throw new errors/* .ConfigurationError */.j1(`maxHistorySize must be a finite number, got ${value}`);
4076
- }
4077
- if (value < 1) {
4078
- throw new errors/* .ConfigurationError */.j1(`maxHistorySize must be at least 1, got ${value}`);
4079
- }
4080
- if (value > 10000) {
4081
- throw new errors/* .ConfigurationError */.j1(`maxHistorySize must not exceed 10000, got ${value}`);
4082
- }
4083
- return value;
4084
- }
4085
- /**
4086
- * Validates the max branches value.
4087
- * @param value - The value to validate
4088
- * @returns The validated value or default (50)
4089
- * @private
4090
- */ validateMaxBranches(value) {
4091
- const defaultValue = 50;
4092
- if (value === undefined || value === null) return defaultValue;
4093
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4094
- throw new errors/* .ConfigurationError */.j1(`maxBranches must be a finite number, got ${value}`);
4095
- }
4096
- if (value < 0) {
4097
- throw new errors/* .ConfigurationError */.j1(`maxBranches must be non-negative, got ${value}`);
4098
- }
4099
- if (value > 1000) {
4100
- throw new errors/* .ConfigurationError */.j1(`maxBranches must not exceed 1000, got ${value}`);
4101
- }
4102
- return value;
4103
- }
4104
- /**
4105
- * Validates the max branch size value.
4106
- * @param value - The value to validate
4107
- * @returns The validated value or default (100)
4108
- * @private
4109
- */ validateMaxBranchSize(value) {
4110
- const defaultValue = 100;
4111
- if (value === undefined || value === null) return defaultValue;
4112
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4113
- throw new errors/* .ConfigurationError */.j1(`maxBranchSize must be a finite number, got ${value}`);
4114
- }
4115
- if (value < 1) {
4116
- throw new errors/* .ConfigurationError */.j1(`maxBranchSize must be at least 1, got ${value}`);
4117
- }
4118
- if (value > 1000) {
4119
- throw new errors/* .ConfigurationError */.j1(`maxBranchSize must not exceed 1000, got ${value}`);
4120
- }
4121
- return value;
4122
- }
4123
- /**
4124
- * Validates the skill directories value.
4125
- * @param value - The value to validate
4126
- * @returns The validated value or default ['.claude/skills', '~/.claude/skills', '.agents/skills', '~/.agents/skills']
4127
- * @private
4128
- */ validateSkillDirs(value) {
4129
- const defaultValue = [
4130
- '.claude/skills',
4131
- join(homedir(), '.claude/skills'),
4132
- '.agents/skills',
4133
- join(homedir(), '.agents/skills')
4134
- ];
4135
- return value === undefined ? defaultValue : [
4136
- ...value
4137
- ];
4138
- }
4139
- validateToolDirs(value) {
4140
- const defaultValue = [
4141
- '.claude/tools',
4142
- join(homedir(), '.claude/tools')
4143
- ];
4144
- return value === undefined ? defaultValue : [
4145
- ...value
4146
- ];
4147
- }
4148
- /**
4149
- * Validates the discovery cache configuration.
4150
- * @param value - The value to validate
4151
- * @returns The validated value with defaults applied
4152
- * @private
4153
- */ validateDiscoveryCache(value) {
4154
- return {
4155
- ttl: value?.ttl ?? 300000,
4156
- maxSize: value?.maxSize ?? 100
4157
- };
4158
- }
4159
- /**
4160
- * Validates the persistence configuration.
4161
- * @param value - The value to validate
4162
- * @returns The validated value with defaults applied
4163
- * @private
4164
- */ validatePersistence(value) {
4165
- if (!value) {
4166
- // Default to in-memory (no actual persistence, just consistency)
4167
- return {
4168
- enabled: false,
4169
- backend: 'memory'
4170
- };
4171
- }
4172
- // Validate backend type
4173
- const validBackends = [
4174
- 'file',
4175
- 'sqlite',
4176
- 'memory'
4177
- ];
4178
- const backend = value.backend ?? 'memory';
4179
- if (!validBackends.includes(backend)) {
4180
- throw new errors/* .ConfigurationError */.j1(`persistence.backend must be one of ${validBackends.join(', ')}, got ${backend}`);
4181
- }
4182
- return {
4183
- enabled: value.enabled ?? false,
4184
- backend,
4185
- options: value.options ?? {}
4186
- };
4187
- }
4188
- /**
4189
- * Validates the persistence buffer size value.
4190
- * @param value - The value to validate
4191
- * @returns The validated value or default (100)
4192
- * @private
4193
- */ validatePersistenceBufferSize(value) {
4194
- const defaultValue = 100;
4195
- if (value === undefined || value === null) return defaultValue;
4196
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4197
- throw new errors/* .ConfigurationError */.j1(`persistenceBufferSize must be a finite number, got ${value}`);
4198
- }
4199
- if (value < 1) {
4200
- throw new errors/* .ConfigurationError */.j1(`persistenceBufferSize must be at least 1, got ${value}`);
4201
- }
4202
- if (value > 10000) {
4203
- throw new errors/* .ConfigurationError */.j1(`persistenceBufferSize must not exceed 10000, got ${value}`);
4204
- }
4205
- return value;
4206
- }
4207
- /**
4208
- * Validates the persistence flush interval value.
4209
- * @param value - The value to validate
4210
- * @returns The validated value or default (1000)
4211
- * @private
4212
- */ validatePersistenceFlushInterval(value) {
4213
- const defaultValue = 1000;
4214
- if (value === undefined || value === null) return defaultValue;
4215
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4216
- throw new errors/* .ConfigurationError */.j1(`persistenceFlushInterval must be a finite number, got ${value}`);
4217
- }
4218
- if (value < 100) {
4219
- throw new errors/* .ConfigurationError */.j1(`persistenceFlushInterval must be at least 100, got ${value}`);
4220
- }
4221
- if (value > 60000) {
4222
- throw new errors/* .ConfigurationError */.j1(`persistenceFlushInterval must not exceed 60000, got ${value}`);
4223
- }
4224
- return value;
4225
- }
4226
- /**
4227
- * Validates the persistence max retries value.
4228
- * @param value - The value to validate
4229
- * @returns The validated value or default (3)
4230
- * @private
4231
- */ validatePersistenceMaxRetries(value) {
4232
- const defaultValue = 3;
4233
- if (value === undefined || value === null) return defaultValue;
4234
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4235
- throw new errors/* .ConfigurationError */.j1(`persistenceMaxRetries must be a finite number, got ${value}`);
4236
- }
4237
- if (value < 0) {
4238
- throw new errors/* .ConfigurationError */.j1(`persistenceMaxRetries must be non-negative, got ${value}`);
4239
- }
4240
- if (value > 10) {
4241
- throw new errors/* .ConfigurationError */.j1(`persistenceMaxRetries must not exceed 10, got ${value}`);
4242
- }
4243
- return value;
4244
- }
4245
- /**
4246
- * Validates feature flags and fills defaults for missing fields.
4247
- * @param value - Partial feature flag overrides
4248
- * @returns Fully populated FeatureFlags with defaults applied
4249
- * @private
4250
- */ validateFeatures(value) {
4251
- const reasoningStrategy = value?.reasoningStrategy ?? 'sequential';
4252
- if (reasoningStrategy !== 'sequential' && reasoningStrategy !== 'tot') {
4253
- throw new errors/* .ConfigurationError */.j1(`features.reasoningStrategy must be one of sequential, tot, got ${reasoningStrategy}`);
4254
- }
4255
- return {
4256
- dagEdges: value?.dagEdges ?? true,
4257
- reasoningStrategy,
4258
- calibration: value?.calibration ?? true,
4259
- compression: value?.compression ?? true,
4260
- toolInterleave: value?.toolInterleave ?? true,
4261
- newThoughtTypes: value?.newThoughtTypes ?? true,
4262
- outcomeRecording: value?.outcomeRecording ?? true
4263
- };
4264
- }
4265
- /**
4266
- * Validates a positive millisecond value with a default fallback.
4267
- * @param value - The value to validate
4268
- * @param defaultValue - Default applied if value is undefined/null
4269
- * @param fieldName - Field name for error messages
4270
- * @returns The validated millisecond value
4271
- * @private
4272
- */ validatePositiveMs(value, defaultValue, fieldName) {
4273
- if (value === undefined || value === null) return defaultValue;
4274
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4275
- throw new errors/* .ConfigurationError */.j1(`${fieldName} must be a finite number, got ${value}`);
4276
- }
4277
- if (value < 1) {
4278
- throw new errors/* .ConfigurationError */.j1(`${fieldName} must be at least 1, got ${value}`);
4279
- }
4280
- return value;
4281
- }
4282
- /**
4283
- * Validates the max sessions per owner value.
4284
- * @param value - The value to validate
4285
- * @returns The validated value or default (50)
4286
- * @private
4287
- */ validateMaxSessionsPerOwner(value) {
4288
- const defaultValue = 50;
4289
- if (value === undefined || value === null) return defaultValue;
4290
- if (typeof value !== 'number' || !Number.isFinite(value)) {
4291
- throw new errors/* .ConfigurationError */.j1(`maxSessionsPerOwner must be a finite number, got ${value}`);
4292
- }
4293
- if (value < 1) {
4294
- throw new errors/* .ConfigurationError */.j1(`maxSessionsPerOwner must be at least 1, got ${value}`);
4295
- }
4296
- if (value > 10000) {
4297
- throw new errors/* .ConfigurationError */.j1(`maxSessionsPerOwner must not exceed 10000, got ${value}`);
4298
- }
4299
- return value;
4300
- }
4301
- /**
4302
- * Converts the configuration to a plain object.
4303
- *
4304
- * Useful for serialization, logging, or when a plain object representation
4305
- * is preferred over the ServerConfig instance.
4306
- *
4307
- * @returns A plain object representation of the configuration
4308
- *
4309
- * @example
4310
- * ```typescript
4311
- * const config = new ServerConfig({ maxHistorySize: 500 });
4312
- * const json = config.toJSON();
4313
- * console.log(JSON.stringify(json, null, 2));
4314
- * ```
4315
- */ toJSON() {
4316
- return {
4317
- maxHistorySize: this.maxHistorySize,
4318
- maxBranches: this.maxBranches,
4319
- maxBranchSize: this.maxBranchSize,
4320
- skillDirs: this.skillDirs,
4321
- toolDirs: this.toolDirs,
4322
- discoveryCache: this.discoveryCache,
4323
- persistence: this.persistence,
4324
- persistenceBufferSize: this.persistenceBufferSize,
4325
- persistenceFlushInterval: this.persistenceFlushInterval,
4326
- persistenceMaxRetries: this.persistenceMaxRetries,
4327
- features: this.features,
4328
- toolInterleaveTtlMs: this.toolInterleaveTtlMs,
4329
- toolInterleaveSweepMs: this.toolInterleaveSweepMs,
4330
- maxSessionsPerOwner: this.maxSessionsPerOwner
4331
- };
4332
- }
4333
- }
4334
-
4335
- ;// CONCATENATED MODULE: external "yaml"
4336
-
4337
- // EXTERNAL MODULE: external "valibot"
4338
- var external_valibot_ = __webpack_require__("w");
4339
- ;// CONCATENATED MODULE: ./src/config/ConfigLoader.ts
4340
- /**
4341
- * Configuration file loading with environment variable override support.
4342
- *
4343
- * This module provides the `ConfigLoader` class which handles loading configuration
4344
- * from YAML and JSON files in standard locations, with automatic environment variable
4345
- * overrides for all settings.
4346
- *
4347
- * @module config
4348
- */
4349
-
4350
-
4351
-
4352
-
4353
-
4354
- /**
4355
- * Lenient runtime schema for config files. Only validates top-level shape;
4356
- * unknown extra fields are preserved by Valibot's default object behavior
4357
- * being strict is avoided by using `v.looseObject`. All fields are optional.
4358
- */ const ConfigFileOptionsSchema = external_valibot_.looseObject({
4359
- maxHistorySize: external_valibot_.optional(external_valibot_.number()),
4360
- maxBranches: external_valibot_.optional(external_valibot_.number()),
4361
- maxBranchSize: external_valibot_.optional(external_valibot_.number()),
4362
- logLevel: external_valibot_.optional(external_valibot_.picklist([
4363
- 'debug',
4364
- 'info',
4365
- 'warn',
4366
- 'error'
4367
- ])),
4368
- prettyLog: external_valibot_.optional(external_valibot_.boolean()),
4369
- skillDirs: external_valibot_.optional(external_valibot_.array(external_valibot_.string())),
4370
- toolDirs: external_valibot_.optional(external_valibot_.array(external_valibot_.string())),
4371
- discoveryCache: external_valibot_.optional(external_valibot_.looseObject({
4372
- ttl: external_valibot_.optional(external_valibot_.number()),
4373
- maxSize: external_valibot_.optional(external_valibot_.number())
4374
- })),
4375
- persistence: external_valibot_.optional(external_valibot_.looseObject({})),
4376
- features: external_valibot_.optional(external_valibot_.looseObject({})),
4377
- toolInterleaveTtlMs: external_valibot_.optional(external_valibot_.number()),
4378
- toolInterleaveSweepMs: external_valibot_.optional(external_valibot_.number()),
4379
- maxSessionsPerOwner: external_valibot_.optional(external_valibot_.number())
4380
- });
4381
- /**
4382
- * Loads configuration from files with environment variable overrides.
4383
- *
4384
- * This class searches for configuration files in standard locations and applies
4385
- * environment variable overrides. Files are searched in priority order, with the
4386
- * first match being used. Environment variables always take precedence over file values.
4387
- *
4388
- * @remarks
4389
- * **Config File Search Order (priority):**
4390
- * 1. Custom path (if provided to constructor)
4391
- * 2. `.claude/config.json` (project-local)
4392
- * 3. `.claude/config.yaml` (project-local)
4393
- * 4. `.claude/config.yml` (project-local)
4394
- * 5. `~/.claude/config.json` (user-global)
4395
- * 6. `~/.claude/config.yaml` (user-global)
4396
- * 7. `~/.claude/config.yml` (user-global)
4397
- *
4398
- * **Environment Variable Overrides:**
4399
- * | Variable | Type | Description |
4400
- * |----------|------|-------------|
4401
- * | `MAX_HISTORY_SIZE` | number | Max thoughts in history |
4402
- * | `MAX_BRANCHES` | number | Max number of branches |
4403
- * | `MAX_BRANCH_SIZE` | number | Max size of each branch |
4404
- * | `LOG_LEVEL` | string | Logging level (debug/info/warn/error) |
4405
- * | `PRETTY_LOG` | string | "false" to disable pretty logging |
4406
- * | `SKILL_DIRS` | string | Colon-separated directory paths |
4407
- * | `TOOL_DIRS` | string | Colon-separated directory paths |
4408
- * | `DISCOVERY_CACHE_TTL` | number | TTL in seconds (converted to ms) |
4409
- * | `DISCOVERY_CACHE_MAX_SIZE` | number | Max cache entries |
4410
- *
4411
- * @example
4412
- * ```typescript
4413
- * // Use default search paths
4414
- * const loader1 = new ConfigLoader();
4415
- * const config1 = loader1.load();
4416
- *
4417
- * // Use custom config path
4418
- * const loader2 = new ConfigLoader('./my-config.yaml');
4419
- * const config2 = loader2.load();
4420
- *
4421
- * // Convert to ServerConfig options
4422
- * const serverOptions = loader2.toServerConfigOptions(config2);
4423
- * ```
4424
- */ class ConfigLoader {
4425
- /** Array of config file paths to search, in priority order. */ _configPaths;
4426
- /**
4427
- * Creates a new ConfigLoader instance.
4428
- *
4429
- * @param customPath - Optional custom config file path. If provided, only this path will be checked.
4430
- *
4431
- * @example
4432
- * ```typescript
4433
- * // Use default search paths
4434
- * const loader1 = new ConfigLoader();
4435
- *
4436
- * // Use a specific config file
4437
- * const loader2 = new ConfigLoader('./custom-config.json');
4438
- * ```
4439
- */ constructor(customPath){
4440
- this._configPaths = customPath ? [
4441
- customPath
4442
- ] : [
4443
- '.claude/config.json',
4444
- '.claude/config.yaml',
4445
- '.claude/config.yml',
4446
- join(homedir(), '.claude/config.json'),
4447
- join(homedir(), '.claude/config.yaml'),
4448
- join(homedir(), '.claude/config.yml')
4449
- ];
4450
- }
4451
- /**
4452
- * Loads configuration from files and applies environment overrides.
4453
- *
4454
- * Searches for config files in the configured paths (in priority order),
4455
- * parses the first match, and applies environment variable overrides.
4456
- * Returns null if no config file is found and no environment overrides are set.
4457
- *
4458
- * @returns The loaded configuration with environment overrides applied, or null if no config found
4459
- *
4460
- * @example
4461
- * ```typescript
4462
- * const loader = new ConfigLoader();
4463
- * const config = loader.load();
4464
- *
4465
- * if (config) {
4466
- * console.log('Max history size:', config.maxHistorySize);
4467
- * console.log('Log level:', config.logLevel);
4468
- * }
4469
- * ```
4470
- */ load() {
4471
- let config = null;
4472
- for (const configPath of this._configPaths){
4473
- if (existsSync(configPath)) {
4474
- try {
4475
- config = this.parseConfig(configPath);
4476
- break;
4477
- } catch (error) {
4478
- console.error(`Failed to load config from ${configPath}:`, (0,errors/* .getErrorMessage */.u1)(error));
4479
- }
4480
- }
4481
- }
4482
- return this.applyEnvironmentOverrides(config || {});
4483
- }
4484
- /**
4485
- * Applies environment variable overrides to the configuration.
4486
- *
4487
- * Environment variables take precedence over file-based configuration.
4488
- * Supported environment variables:
4489
- * - `MAX_HISTORY_SIZE`, `MAX_BRANCHES`, `MAX_BRANCH_SIZE` (numbers)
4490
- * - `LOG_LEVEL` (debug/info/warn/error)
4491
- * - `PRETTY_LOG` ("false" to disable)
4492
- * - `SKILL_DIRS` (colon-separated paths)
4493
- * - `TOOL_DIRS` (colon-separated paths)
4494
- * - `DISCOVERY_CACHE_TTL` (in seconds, converted to ms)
4495
- * - `DISCOVERY_CACHE_MAX_SIZE` (number)
4496
- *
4497
- * @param config - The configuration to apply overrides to
4498
- * @returns A new configuration object with environment overrides applied
4499
- */ applyEnvironmentOverrides(config) {
4500
- const result = {
4501
- ...config,
4502
- ...config.skillDirs === undefined ? {} : {
4503
- skillDirs: [
4504
- ...config.skillDirs
4505
- ]
4506
- },
4507
- ...config.toolDirs === undefined ? {} : {
4508
- toolDirs: [
4509
- ...config.toolDirs
4510
- ]
4511
- },
4512
- ...config.discoveryCache === undefined ? {} : {
4513
- discoveryCache: {
4514
- ...config.discoveryCache
4515
- }
4516
- },
4517
- ...config.persistence === undefined ? {} : {
4518
- persistence: {
4519
- ...config.persistence,
4520
- ...config.persistence.options === undefined ? {} : {
4521
- options: {
4522
- ...config.persistence.options
4523
- }
4524
- }
4525
- }
4526
- },
4527
- ...config.features === undefined ? {} : {
4528
- features: {
4529
- ...config.features
4530
- }
4531
- }
4532
- };
4533
- if (process.env.MAX_HISTORY_SIZE !== undefined) {
4534
- result.maxHistorySize = this.parseEnvironmentInteger('MAX_HISTORY_SIZE', process.env.MAX_HISTORY_SIZE);
4535
- }
4536
- if (process.env.MAX_BRANCHES !== undefined) {
4537
- result.maxBranches = this.parseEnvironmentInteger('MAX_BRANCHES', process.env.MAX_BRANCHES);
4538
- }
4539
- if (process.env.MAX_BRANCH_SIZE !== undefined) {
4540
- result.maxBranchSize = this.parseEnvironmentInteger('MAX_BRANCH_SIZE', process.env.MAX_BRANCH_SIZE);
4541
- }
4542
- if (process.env.LOG_LEVEL && [
4543
- 'debug',
4544
- 'info',
4545
- 'warn',
4546
- 'error'
4547
- ].includes(process.env.LOG_LEVEL)) {
4548
- result.logLevel = process.env.LOG_LEVEL;
4549
- }
4550
- if (process.env.PRETTY_LOG === 'false') {
4551
- result.prettyLog = false;
4552
- }
4553
- if (process.env.SKILL_DIRS !== undefined) {
4554
- result.skillDirs = process.env.SKILL_DIRS === '' ? [] : process.env.SKILL_DIRS.split(':');
4555
- }
4556
- if (process.env.TOOL_DIRS !== undefined) {
4557
- result.toolDirs = process.env.TOOL_DIRS === '' ? [] : process.env.TOOL_DIRS.split(':');
4558
- }
4559
- if (process.env.DISCOVERY_CACHE_TTL !== undefined) {
4560
- const seconds = this.parseEnvironmentInteger('DISCOVERY_CACHE_TTL', process.env.DISCOVERY_CACHE_TTL);
4561
- const ttl = seconds * 1000;
4562
- if (!Number.isSafeInteger(ttl)) {
4563
- throw new errors/* .ConfigurationError */.j1('DISCOVERY_CACHE_TTL exceeds the safe integer range');
4564
- }
4565
- result.discoveryCache = {
4566
- ...result.discoveryCache,
4567
- ttl
4568
- };
4569
- }
4570
- if (process.env.DISCOVERY_CACHE_MAX_SIZE !== undefined) {
4571
- const maxSize = this.parseEnvironmentInteger('DISCOVERY_CACHE_MAX_SIZE', process.env.DISCOVERY_CACHE_MAX_SIZE);
4572
- result.discoveryCache = {
4573
- ...result.discoveryCache,
4574
- maxSize
4575
- };
4576
- }
4577
- if (process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS !== undefined) {
4578
- result.toolInterleaveTtlMs = this.parseEnvironmentInteger('TRACELATTICE_TOOL_INTERLEAVE_TTL_MS', process.env.TRACELATTICE_TOOL_INTERLEAVE_TTL_MS);
4579
- }
4580
- if (process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS !== undefined) {
4581
- result.toolInterleaveSweepMs = this.parseEnvironmentInteger('TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS', process.env.TRACELATTICE_TOOL_INTERLEAVE_SWEEP_MS);
4582
- }
4583
- if (process.env.SESSION_MAX_PER_OWNER !== undefined) {
4584
- result.maxSessionsPerOwner = this.parseEnvironmentInteger('SESSION_MAX_PER_OWNER', process.env.SESSION_MAX_PER_OWNER);
4585
- }
4586
- this.applyFeatureFlagOverrides(result);
4587
- return result;
4588
- }
4589
- /**
4590
- * Applies TRACELATTICE_FEATURES_* environment variable overrides for feature flags.
4591
- * Booleans accept 'true'/'false'/'1'/'0' (case-insensitive).
4592
- * Invalid reasoningStrategy values are rejected.
4593
- *
4594
- * @param result - Configuration object to mutate with feature flag overrides
4595
- * @private
4596
- */ applyFeatureFlagOverrides(result) {
4597
- const boolMap = {
4598
- TRACELATTICE_FEATURES_DAG_EDGES: 'dagEdges',
4599
- TRACELATTICE_FEATURES_CALIBRATION: 'calibration',
4600
- TRACELATTICE_FEATURES_COMPRESSION: 'compression',
4601
- TRACELATTICE_FEATURES_TOOL_INTERLEAVE: 'toolInterleave',
4602
- TRACELATTICE_FEATURES_NEW_THOUGHT_TYPES: 'newThoughtTypes',
4603
- TRACELATTICE_FEATURES_OUTCOME_RECORDING: 'outcomeRecording'
4604
- };
4605
- for (const [envVar, key] of Object.entries(boolMap)){
4606
- const raw = process.env[envVar];
4607
- if (raw === undefined) continue;
4608
- const parsed = this.parseBoolean(raw);
4609
- if (parsed === undefined) {
4610
- console.warn(`Invalid boolean value for ${envVar}: "${raw}" (expected true/false/1/0). Ignoring.`);
4611
- continue;
4612
- }
4613
- const features = result.features ?? {};
4614
- features[key] = parsed;
4615
- result.features = features;
4616
- }
4617
- const strategyRaw = process.env.TRACELATTICE_FEATURES_REASONING_STRATEGY;
4618
- if (strategyRaw !== undefined) {
4619
- if (strategyRaw !== 'sequential' && strategyRaw !== 'tot') {
4620
- throw new errors/* .ConfigurationError */.j1(`TRACELATTICE_FEATURES_REASONING_STRATEGY must be one of sequential, tot, got ${strategyRaw}`);
4621
- }
4622
- const features = result.features ?? {};
4623
- features.reasoningStrategy = strategyRaw;
4624
- result.features = features;
4625
- }
4626
- }
4627
- parseEnvironmentInteger(environmentName, raw) {
4628
- if (!/^(0|[1-9]\d*)$/.test(raw)) {
4629
- throw new errors/* .ConfigurationError */.j1(`${environmentName} must be an integer, got ${raw}`);
4630
- }
4631
- const parsed = Number(raw);
4632
- if (!Number.isSafeInteger(parsed)) {
4633
- throw new errors/* .ConfigurationError */.j1(`${environmentName} must be a safe integer, got ${raw}`);
4634
- }
4635
- return parsed;
4636
- }
4637
- /**
4638
- * Parses a boolean from an environment variable string.
4639
- * Accepts 'true'/'false'/'1'/'0' case-insensitively.
4640
- *
4641
- * @param raw - Raw environment variable string
4642
- * @returns Parsed boolean, or undefined if the value is invalid
4643
- * @private
4644
- */ parseBoolean(raw) {
4645
- const v = raw.trim().toLowerCase();
4646
- if (v === 'true' || v === '1') return true;
4647
- if (v === 'false' || v === '0') return false;
4648
- return undefined;
4649
- }
4650
- /**
4651
- * Parses a configuration file (JSON or YAML).
4652
- *
4653
- * Detects the file type by extension and uses the appropriate parser.
4654
- * Supports `.json`, `.yaml`, and `.yml` file extensions.
4655
- *
4656
- * @param filePath - Path to the configuration file to parse
4657
- * @returns The parsed configuration object
4658
- * @throws {Error} If the file cannot be parsed
4659
- * @private
4660
- */ parseConfig(filePath) {
4661
- const content = readFileSync(filePath, 'utf-8');
4662
- const ext = filePath.split('.').pop()?.toLowerCase();
4663
- const raw = ext === 'yaml' || ext === 'yml' ? parse(content) : JSON.parse(content);
4664
- return external_valibot_.parse(ConfigFileOptionsSchema, raw);
4665
- }
4666
- /**
4667
- * Converts file-based configuration to ServerConfig options.
4668
- *
4669
- * This is a convenience method for extracting the ServerConfig-relevant
4670
- * options from a file-based configuration.
4671
- *
4672
- * @param config - The configuration to convert
4673
- * @returns An object with ServerConfig-compatible options
4674
- *
4675
- * @example
4676
- * ```typescript
4677
- * const loader = new ConfigLoader();
4678
- * const config = loader.load();
4679
- * if (config) {
4680
- * const serverOpts = loader.toServerConfigOptions(config);
4681
- * const serverConfig = new ServerConfig(serverOpts);
4682
- * }
4683
- * ```
4684
- */ toServerConfigOptions(config) {
4685
- return {
4686
- maxHistorySize: config.maxHistorySize,
4687
- maxBranches: config.maxBranches,
4688
- maxBranchSize: config.maxBranchSize,
4689
- skillDirs: config.skillDirs,
4690
- toolDirs: config.toolDirs,
4691
- discoveryCache: config.discoveryCache,
4692
- persistence: config.persistence,
4693
- features: config.features,
4694
- toolInterleaveTtlMs: config.toolInterleaveTtlMs,
4695
- toolInterleaveSweepMs: config.toolInterleaveSweepMs,
4696
- maxSessionsPerOwner: config.maxSessionsPerOwner
4697
- };
4698
- }
4699
- }
2780
+ ;// CONCATENATED MODULE: external "./lib.js"
4700
2781
 
4701
- // EXTERNAL MODULE: ./src/contracts/ids.ts
4702
- var ids = __webpack_require__("j");
4703
- // EXTERNAL MODULE: ./src/context/RequestContext.ts
4704
- var RequestContext = __webpack_require__("y");
2782
+ // EXTERNAL MODULE: ./src/context/RequestContext.ts + 1 modules
2783
+ var RequestContext = __webpack_require__("i");
4705
2784
  ;// CONCATENATED MODULE: ./src/logger/StructuredLogger.ts
4706
2785
  /**
4707
2786
  * Lightweight structured logging without external dependencies.
@@ -4959,8 +3038,6 @@ var RequestContext = __webpack_require__("y");
4959
3038
 
4960
3039
  // EXTERNAL MODULE: ./src/schema.ts
4961
3040
  var schema = __webpack_require__("R");
4962
- // EXTERNAL MODULE: ./src/transport/SseTransport.ts
4963
- var transport_SseTransport = __webpack_require__("W");
4964
3041
  ;// CONCATENATED MODULE: ./src/cli.ts
4965
3042
  //#!/usr/bin/env bun
4966
3043
  // CLI entry point for tracelattice MCP server.
@@ -4977,16 +3054,11 @@ var transport_SseTransport = __webpack_require__("W");
4977
3054
 
4978
3055
 
4979
3056
 
4980
-
4981
-
4982
-
4983
-
4984
-
4985
3057
  // Get version from package.json
4986
3058
  const CLI_NAME = 'tracelattice';
4987
- const cli_filename = (0,external_node_url_.fileURLToPath)(import.meta.url);
4988
- const cli_dirname = dirname(cli_filename);
4989
- const package_json = JSON.parse(readFileSync(join(cli_dirname, '../package.json'), 'utf-8'));
3059
+ const cli_filename = (0,__rspack_external_node_url_3991086a.fileURLToPath)(import.meta.url);
3060
+ const cli_dirname = (0,__rspack_external_node_path_806ed179.dirname)(cli_filename);
3061
+ const package_json = JSON.parse((0,__rspack_external_node_fs_1b05aee1.readFileSync)((0,__rspack_external_node_path_806ed179.join)(cli_dirname, '../package.json'), 'utf-8'));
4990
3062
  const { version } = package_json;
4991
3063
  // Handle CLI arguments
4992
3064
  const args = process.argv.slice(2);
@@ -4997,14 +3069,8 @@ if (shouldShowVersion) {
4997
3069
  }
4998
3070
  async function main() {
4999
3071
  const transportType = process.env.TRANSPORT_TYPE || 'stdio';
5000
- if (transportType === 'sse' && process.env.SSE_ENABLE_POOL !== 'false') {
5001
- const configLoader = new ConfigLoader();
5002
- const fileConfig = configLoader.load();
5003
- const effectiveConfig = new ServerConfig(configLoader.toServerConfigOptions(fileConfig ?? {}));
5004
- (0,transport_SseTransport/* .assertPooledSsePersistence */.c)(true, effectiveConfig.persistence);
5005
- }
5006
- const adapter = new ValibotJsonSchemaAdapter();
5007
- const server = new McpServer({
3072
+ const adapter = new __rspack_external__tmcp_adapter_valibot_0faddfa6.ValibotJsonSchemaAdapter();
3073
+ const server = new __rspack_external_tmcp.McpServer({
5008
3074
  name: CLI_NAME,
5009
3075
  version,
5010
3076
  description: 'Semantic Sequential Thinking MCP Server'
@@ -5016,88 +3082,30 @@ async function main() {
5016
3082
  }
5017
3083
  }
5018
3084
  });
5019
- const thinkingServer = await (0,external_lib_js_.initializeServer)();
3085
+ const thinkingServer = await (0,__rspack_external__lib_js_1645bc55.initializeServer)();
5020
3086
  const lifecycle = new CliLifecycle(thinkingServer);
5021
3087
  try {
5022
- if (transportType === 'sse') {
5023
- await startSseTransport(server, thinkingServer, lifecycle);
3088
+ server.tool({
3089
+ name: 'sequentialthinking_tools',
3090
+ description: schema/* .SEQUENTIAL_THINKING_TOOL.description */.iV.description,
3091
+ schema: schema/* .SequentialThinkingSchema */.ZK
3092
+ }, async (input)=>thinkingServer.processThought(input));
3093
+ if (transportType === 'streamable-http') {
3094
+ await startStreamableHttpTransport(server, thinkingServer, lifecycle);
5024
3095
  } else {
5025
- server.tool({
5026
- name: 'sequentialthinking_tools',
5027
- description: schema/* .SEQUENTIAL_THINKING_TOOL.description */.iV.description,
5028
- schema: schema/* .SequentialThinkingSchema */.ZK
5029
- }, async (input)=>thinkingServer.processThought(input));
5030
- if (transportType === 'streamable-http') {
5031
- await startStreamableHttpTransport(server, thinkingServer, lifecycle);
5032
- } else {
5033
- await startStdioTransport(server, thinkingServer, lifecycle);
5034
- }
3096
+ await startStdioTransport(server, thinkingServer, lifecycle);
5035
3097
  }
5036
3098
  registerShutdownHandlers(lifecycle, thinkingServer, transportType === 'stdio');
5037
3099
  } catch (error) {
5038
3100
  await lifecycle.rollbackStartup(error);
5039
3101
  }
5040
3102
  }
5041
- /**
5042
- * Start SSE transport for multi-user support
5043
- */ async function startSseTransport(server, thinkingServer, lifecycle) {
5044
- const { SseTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "W"));
5045
- const { createConnectionPool } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "v"));
5046
- const port = parseInt(process.env.SSE_PORT || '3000', 10);
5047
- const host = process.env.SSE_HOST || 'localhost';
5048
- const transportMetrics = thinkingServer.getContainer().resolve('Metrics');
5049
- const enablePool = process.env.SSE_ENABLE_POOL !== 'false';
5050
- const maxSessions = parseInt(process.env.SSE_MAX_SESSIONS || '100', 10);
5051
- const sessionTimeout = parseInt(process.env.SSE_SESSION_TIMEOUT || '300000', 10);
5052
- const connectionPool = enablePool ? createConnectionPool({
5053
- maxSessions,
5054
- sessionTimeout,
5055
- logger: thinkingServer['_logger'],
5056
- serverFactory: async ()=>{
5057
- const { createServer: createThinkingServer } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "r"));
5058
- const sessionServer = await createThinkingServer({
5059
- autoDiscover: true
5060
- });
5061
- return sessionServer;
5062
- }
5063
- }) : undefined;
5064
- const sseTransport = new SseTransport({
5065
- port,
5066
- host,
5067
- corsOrigin: process.env.CORS_ORIGIN || '*',
5068
- enableCors: process.env.ENABLE_CORS !== 'false',
5069
- allowedHosts: process.env.ALLOWED_HOSTS?.split(',').map((hostValue)=>hostValue.trim()),
5070
- metrics: transportMetrics,
5071
- connectionPool,
5072
- persistence: thinkingServer.config.persistence
5073
- });
5074
- lifecycle.attachTransport(sseTransport);
5075
- server.tool({
5076
- name: 'sequentialthinking_tools',
5077
- description: schema/* .SEQUENTIAL_THINKING_TOOL.description */.iV.description,
5078
- schema: schema/* .SequentialThinkingSchema */.ZK
5079
- }, async (input)=>{
5080
- if (!connectionPool) {
5081
- return thinkingServer.processThought(input);
5082
- }
5083
- const result = await connectionPool.process((0,ids/* .asSessionId */.Kd)((0,RequestContext/* .getOwner */.QQ)() ?? ''), input);
5084
- return {
5085
- content: result.content,
5086
- ...result.isError === undefined ? {} : {
5087
- isError: result.isError
5088
- }
5089
- };
5090
- });
5091
- // Connect the SSE transport
5092
- await sseTransport.connect(server);
5093
- thinkingServer['_logger'].info(`Sequential Thinking MCP Server running on SSE transport at http://${host}:${port}`);
5094
- }
5095
3103
  /**
5096
3104
  * Start Streamable HTTP transport (MCP spec recommended)
5097
3105
  */ async function startStreamableHttpTransport(server, thinkingServer, lifecycle) {
5098
- const { StreamableHttpTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "J"));
5099
- const port = parseInt(process.env.STREAMABLE_HTTP_PORT || process.env.SSE_PORT || '3000', 10);
5100
- const host = process.env.STREAMABLE_HTTP_HOST || process.env.SSE_HOST || 'localhost';
3106
+ const { StreamableHttpTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "E"));
3107
+ const port = parseInt(process.env.STREAMABLE_HTTP_PORT || '9007', 10);
3108
+ const host = process.env.STREAMABLE_HTTP_HOST || 'localhost';
5101
3109
  const transportMetrics = thinkingServer.getContainer().resolve('Metrics');
5102
3110
  const stateful = process.env.STREAMABLE_HTTP_STATEFUL !== 'false';
5103
3111
  const streamableTransport = new StreamableHttpTransport({
@@ -5117,7 +3125,7 @@ async function main() {
5117
3125
  /**
5118
3126
  * Start stdio transport (default, single-user)
5119
3127
  */ async function startStdioTransport(server, thinkingServer, lifecycle) {
5120
- const transport = new StdioTransport(server);
3128
+ const transport = new __rspack_external__tmcp_transport_stdio_98e5584f.StdioTransport(server);
5121
3129
  const processListeners = {
5122
3130
  sigint: new Set(process.listeners('SIGINT')),
5123
3131
  sigterm: new Set(process.listeners('SIGTERM')),