@iworkforces/tracelattice 2.0.7 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +205 -181
  3. package/dist/contracts/summary.d.ts +0 -1
  4. package/dist/contracts/summary.d.ts.map +1 -1
  5. package/dist/core/PersistenceRestore.d.ts +1 -1
  6. package/dist/core/PersistenceRestore.d.ts.map +1 -1
  7. package/dist/core/PersistenceRestore.js.map +1 -1
  8. package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
  9. package/dist/core/ThoughtEvaluator.js.map +1 -1
  10. package/dist/core/ThoughtFormatter.js.map +1 -1
  11. package/dist/core/ThoughtProcessor.d.ts.map +1 -1
  12. package/dist/core/ThoughtProcessor.js.map +1 -1
  13. package/dist/core/compression/CompressionService.d.ts +2 -1
  14. package/dist/core/compression/CompressionService.d.ts.map +1 -1
  15. package/dist/core/compression/CompressionService.js.map +1 -1
  16. package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -1
  17. package/dist/core/compression/DehydrationPolicy.js.map +1 -1
  18. package/dist/core/compression/InMemorySummaryStore.d.ts +2 -1
  19. package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -1
  20. package/dist/core/compression/InMemorySummaryStore.js.map +1 -1
  21. package/dist/core/evaluator/Calibrator.d.ts +1 -1
  22. package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
  23. package/dist/core/evaluator/Calibrator.js.map +1 -1
  24. package/dist/core/evaluator/SignalComputer.d.ts +2 -1
  25. package/dist/core/evaluator/SignalComputer.d.ts.map +1 -1
  26. package/dist/core/evaluator/SignalComputer.js.map +1 -1
  27. package/dist/core/evaluator/internals.d.ts +1 -1
  28. package/dist/core/evaluator/internals.d.ts.map +1 -1
  29. package/dist/core/evaluator/internals.js.map +1 -1
  30. package/dist/core/graph/GraphView.d.ts +13 -1
  31. package/dist/core/graph/GraphView.d.ts.map +1 -1
  32. package/dist/core/graph/GraphView.js +34 -0
  33. package/dist/core/graph/GraphView.js.map +1 -1
  34. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts +6 -6
  35. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -1
  36. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +16 -2
  37. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -1
  38. package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -1
  39. package/dist/core/reasoning/strategies/totScoring.js.map +1 -1
  40. package/dist/core/reasoning.d.ts +1 -3
  41. package/dist/core/reasoning.d.ts.map +1 -1
  42. package/dist/core/thought.d.ts +1 -1
  43. package/dist/core/thought.d.ts.map +1 -1
  44. package/dist/lib.d.ts +18 -4
  45. package/dist/lib.d.ts.map +1 -1
  46. package/dist/lib.js +51 -3
  47. package/dist/lib.js.map +1 -1
  48. package/dist/transport/HttpHelpers.d.ts +4 -1
  49. package/dist/transport/HttpHelpers.d.ts.map +1 -1
  50. package/dist/transport/HttpHelpers.js +61 -11
  51. package/dist/transport/HttpHelpers.js.map +1 -1
  52. package/dist/transport/HttpRequestLifecycle.d.ts +15 -1
  53. package/dist/transport/HttpRequestLifecycle.d.ts.map +1 -1
  54. package/dist/transport/HttpRequestLifecycle.js +66 -4
  55. package/dist/transport/HttpRequestLifecycle.js.map +1 -1
  56. package/dist/transport/HttpTransport.d.ts +2 -0
  57. package/dist/transport/HttpTransport.d.ts.map +1 -1
  58. package/dist/transport/HttpTransport.js +75 -38
  59. package/dist/transport/HttpTransport.js.map +1 -1
  60. package/dist/transport/StreamableHttpTransport.d.ts +5 -29
  61. package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
  62. package/dist/transport/StreamableHttpTransport.js +74 -116
  63. package/dist/transport/StreamableHttpTransport.js.map +1 -1
  64. package/package.json +2 -2
package/README.md CHANGED
@@ -202,7 +202,7 @@ Set `TRANSPORT_TYPE` to pick one:
202
202
  | `stdio` (default) | Local MCP clients | `tracelattice` |
203
203
  | `streamable-http` | Production deployments | `TRANSPORT_TYPE=streamable-http tracelattice` |
204
204
 
205
- The Streamable HTTP endpoint defaults to `POST /mcp` for JSON-RPC requests and supports stateful sessions via the `Mcp-Session-Id` header. In stateful mode, `GET /mcp` may expose `text/event-stream` notifications for that session. The library also exposes `HttpTransport` for stateless JSON-RPC over HTTP, but the CLI does not select it with `TRANSPORT_TYPE`.
205
+ The Streamable HTTP endpoint defaults to `POST /mcp` for JSON-RPC requests and supports stateful sessions via the `Mcp-Session-Id` header. `GET /mcp` is not allowed. The library also exposes `HttpTransport` for stateless JSON-RPC over HTTP, but the CLI does not select it with `TRANSPORT_TYPE`.
206
206
 
207
207
  ### Stateless HTTP library API
208
208
 
package/dist/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import * as __rspack_external_valibot from "valibot";
3
3
  import * as __rspack_external_node_crypto_2e7c4b46 from "node:crypto";
4
4
  import * as __rspack_external_node_http_e245b239 from "node:http";
5
+ import * as __rspack_external_node_string_decoder_69b9bd04 from "node:string_decoder";
5
6
  import * as __rspack_external_node_async_hooks_4d8b1b4a from "node:async_hooks";
6
7
  import * as __rspack_external__tmcp_adapter_valibot_0faddfa6 from "@tmcp/adapter-valibot";
7
8
  import * as __rspack_external__tmcp_transport_stdio_98e5584f from "@tmcp/transport-stdio";
@@ -1326,7 +1327,7 @@ __webpack_require__.d(__webpack_exports__, {
1326
1327
 
1327
1328
 
1328
1329
  },
1329
- "E"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1330
+ "q"(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
1330
1331
 
1331
1332
  // EXPORTS
1332
1333
  __webpack_require__.d(__webpack_exports__, {
@@ -1779,6 +1780,8 @@ class BaseTransport {
1779
1780
  * instead of casting `'__global__'` ad-hoc.
1780
1781
  */ const GLOBAL_SESSION_ID = asSessionId('__global__');
1781
1782
 
1783
+ ;// CONCATENATED MODULE: external "node:string_decoder"
1784
+
1782
1785
  ;// CONCATENATED MODULE: ./src/transport/HttpHelpers.ts
1783
1786
  /**
1784
1787
  * Shared HTTP helper utilities for MCP transport implementations.
@@ -1788,7 +1791,11 @@ class BaseTransport {
1788
1791
  * HttpTransport and StreamableHttpTransport.
1789
1792
  *
1790
1793
  * @module transport/HttpHelpers
1791
- */ /**
1794
+ */
1795
+ class RequestBodyAbortedError extends Error {
1796
+ name = 'RequestBodyAbortedError';
1797
+ }
1798
+ /**
1792
1799
  * Send a JSON-RPC 2.0 error response.
1793
1800
  *
1794
1801
  * Standardizes error response formatting across all transport implementations.
@@ -1856,23 +1863,118 @@ class BaseTransport {
1856
1863
  * @param req - The incoming HTTP request
1857
1864
  * @param maxBodySize - Maximum allowed body size in bytes (0 = unlimited)
1858
1865
  * @returns The body string, or `null` if the body exceeded the size limit
1859
- */ async function readRequestBody(req, maxBodySize) {
1860
- let body = '';
1861
- let bodySize = 0;
1862
- for await (const chunk of req){
1863
- const chunkStr = typeof chunk === 'string' ? chunk : chunk.toString();
1864
- bodySize += chunkStr.length;
1865
- if (maxBodySize > 0 && bodySize > maxBodySize) {
1866
- return null;
1867
- }
1868
- body += chunkStr;
1869
- }
1870
- return body;
1866
+ */ async function readRequestBody(req, maxBodySize, signal) {
1867
+ return new Promise((resolve, reject)=>{
1868
+ let body = '';
1869
+ let bodySize = 0;
1870
+ let settled = false;
1871
+ const decoder = new __rspack_external_node_string_decoder_69b9bd04.StringDecoder('utf8');
1872
+ const cleanup = ()=>{
1873
+ req.off('data', onData);
1874
+ req.off('end', onEnd);
1875
+ req.off('aborted', onAborted);
1876
+ req.off('close', onAborted);
1877
+ req.off('error', onError);
1878
+ signal?.removeEventListener('abort', onAborted);
1879
+ };
1880
+ const onData = (chunk)=>{
1881
+ if (settled) return;
1882
+ const chunkSize = typeof chunk === 'string' ? Buffer.byteLength(chunk) : chunk.byteLength;
1883
+ bodySize += chunkSize;
1884
+ if (maxBodySize > 0 && bodySize > maxBodySize) {
1885
+ settled = true;
1886
+ cleanup();
1887
+ req.resume();
1888
+ resolve(null);
1889
+ return;
1890
+ }
1891
+ body += typeof chunk === 'string' ? chunk : decoder.write(chunk);
1892
+ };
1893
+ const onEnd = ()=>{
1894
+ if (settled) return;
1895
+ settled = true;
1896
+ cleanup();
1897
+ resolve(body + decoder.end());
1898
+ };
1899
+ const onAborted = ()=>{
1900
+ if (settled) return;
1901
+ settled = true;
1902
+ cleanup();
1903
+ req.resume();
1904
+ reject(new RequestBodyAbortedError());
1905
+ };
1906
+ const onError = (error)=>{
1907
+ if (settled) return;
1908
+ settled = true;
1909
+ cleanup();
1910
+ reject(error);
1911
+ };
1912
+ req.on('data', onData);
1913
+ req.once('end', onEnd);
1914
+ req.once('aborted', onAborted);
1915
+ req.once('close', onAborted);
1916
+ req.once('error', onError);
1917
+ signal?.addEventListener('abort', onAborted, {
1918
+ once: true
1919
+ });
1920
+ if (signal?.aborted) onAborted();
1921
+ });
1871
1922
  }
1872
1923
 
1873
1924
  // EXTERNAL MODULE: ./src/context/RequestContext.ts + 1 modules
1874
1925
  var RequestContext = __webpack_require__("i");
1875
1926
  ;// CONCATENATED MODULE: ./src/transport/HttpRequestLifecycle.ts
1927
+ class TrackedPreDispatchLease {
1928
+ _onRelease;
1929
+ _controller = new AbortController();
1930
+ _settled = Promise.withResolvers();
1931
+ _active = true;
1932
+ _cancellationReason = null;
1933
+ constructor(_onRelease){
1934
+ this._onRelease = _onRelease;
1935
+ }
1936
+ get signal() {
1937
+ return this._controller.signal;
1938
+ }
1939
+ get cancellationReason() {
1940
+ return this._cancellationReason;
1941
+ }
1942
+ get settled() {
1943
+ return this._settled.promise;
1944
+ }
1945
+ cancel(reason) {
1946
+ if (!this._active || this._controller.signal.aborted) return;
1947
+ this._cancellationReason = reason;
1948
+ this._controller.abort();
1949
+ }
1950
+ release() {
1951
+ if (!this._active) return;
1952
+ this._active = false;
1953
+ this._onRelease(this);
1954
+ this._settled.resolve();
1955
+ }
1956
+ }
1957
+ class PreDispatchTracker {
1958
+ _leases = new Set();
1959
+ _accepting = true;
1960
+ acquire() {
1961
+ if (!this._accepting) return null;
1962
+ const lease = new TrackedPreDispatchLease((released)=>this._leases.delete(released));
1963
+ this._leases.add(lease);
1964
+ return lease;
1965
+ }
1966
+ closeAdmission(reason) {
1967
+ this._accepting = false;
1968
+ for (const lease of this._leases)lease.cancel(reason);
1969
+ }
1970
+ async join() {
1971
+ while(this._leases.size > 0){
1972
+ await Promise.all([
1973
+ ...this._leases
1974
+ ].map((lease)=>lease.settled));
1975
+ }
1976
+ }
1977
+ }
1876
1978
  /** Maximum number of reporting failures retained for diagnostics. */ const LIFECYCLE_REPORTING_FAILURE_CAPACITY = 32;
1877
1979
  class LifecycleFailureReporter {
1878
1980
  _onFailure;
@@ -1944,14 +2046,27 @@ class AcceptedWorkTracker {
1944
2046
  get size() {
1945
2047
  return this._work.size;
1946
2048
  }
1947
- track(work) {
2049
+ transfer(lease, start) {
2050
+ lease.signal.throwIfAborted();
2051
+ const reservation = Promise.withResolvers();
2052
+ this._work.add(reservation.promise);
2053
+ lease.release();
2054
+ let work;
2055
+ try {
2056
+ work = start();
2057
+ } catch (error) {
2058
+ this._work.delete(reservation.promise);
2059
+ reservation.resolve();
2060
+ throw error;
2061
+ }
1948
2062
  const observed = work.catch((error)=>{
1949
2063
  this._failureReporter.report(error);
1950
2064
  });
1951
- this._work.add(observed);
1952
2065
  void observed.then(()=>{
1953
- this._work.delete(observed);
2066
+ this._work.delete(reservation.promise);
2067
+ reservation.resolve();
1954
2068
  });
2069
+ return work;
1955
2070
  }
1956
2071
  async join() {
1957
2072
  while(this._work.size > 0){
@@ -1964,12 +2079,8 @@ class AcceptedWorkTracker {
1964
2079
  /**
1965
2080
  * Streamable HTTP Transport implementation (MCP spec recommended transport).
1966
2081
  *
1967
- * This transport implements the MCP Streamable HTTP specification, which replaces
1968
- * the deprecated SSE transport as the recommended HTTP-based transport since March 2025.
1969
- *
1970
2082
  * Key features:
1971
2083
  * - POST /mcp for JSON-RPC requests (main MCP endpoint)
1972
- * - GET /mcp for optional SSE server-to-client notifications
1973
2084
  * - Session management via Mcp-Session-Id header
1974
2085
  * - Supports both stateful (session-based) and stateless (per-request) modes
1975
2086
  * - Health endpoints (/health, /ready)
@@ -2011,8 +2122,7 @@ function parseSessionRetentionOptions(options) {
2011
2122
  * Streamable HTTP Transport for MCP server.
2012
2123
  *
2013
2124
  * This transport implements the MCP Streamable HTTP specification,
2014
- * providing JSON-RPC over HTTP with optional session management
2015
- * and server-to-client SSE notification streams.
2125
+ * providing JSON-RPC over HTTP with optional session management.
2016
2126
  *
2017
2127
  * @remarks
2018
2128
  * **Security Features (inherited from BaseTransport):**
@@ -2024,13 +2134,11 @@ function parseSessionRetentionOptions(options) {
2024
2134
  *
2025
2135
  * **MCP Streamable HTTP Spec Compliance:**
2026
2136
  * - POST /mcp — JSON-RPC method calls
2027
- * - GET /mcp — SSE notification stream (server-to-client)
2028
2137
  * - Mcp-Session-Id header for session management
2029
2138
  * - Content-Type: application/json for JSON-RPC responses
2030
- * - Content-Type: text/event-stream for SSE notification streams
2031
2139
  *
2032
2140
  * **HTTP Status Code Mapping:**
2033
- * - 200: Success (JSON-RPC response or SSE stream)
2141
+ * - 200: Success (JSON-RPC response)
2034
2142
  * - 202: Accepted (JSON-RPC notification, no response body)
2035
2143
  * - 204: CORS Preflight (empty body)
2036
2144
  * - 400: Bad Request (invalid JSON, invalid session ID)
@@ -2060,6 +2168,7 @@ function parseSessionRetentionOptions(options) {
2060
2168
  _metricsProvider;
2061
2169
  _lifecycleFailureReporter;
2062
2170
  _acceptedWork;
2171
+ _preDispatch = new PreDispatchTracker();
2063
2172
  _sessionRetention;
2064
2173
  _sessionSweepIntervalId = null;
2065
2174
  _stopPromise = null;
@@ -2142,15 +2251,18 @@ function parseSessionRetentionOptions(options) {
2142
2251
  }
2143
2252
  });
2144
2253
  }
2145
- /**
2146
- * Route and handle incoming HTTP requests.
2147
- */ async _handleRequest(req, res) {
2254
+ _recordRequestMetrics(res) {
2148
2255
  const startTime = Date.now();
2149
2256
  this._metrics?.counter('streamable_http_requests_total', 1, {}, 'Total Streamable HTTP transport requests');
2150
2257
  res.once('finish', ()=>{
2151
2258
  const durationSeconds = (Date.now() - startTime) / 1000;
2152
2259
  this._metrics?.histogram('streamable_http_request_duration_seconds', durationSeconds, {});
2153
2260
  });
2261
+ }
2262
+ /**
2263
+ * Route and handle incoming HTTP requests.
2264
+ */ async _handleRequest(req, res) {
2265
+ this._recordRequestMetrics(res);
2154
2266
  // Host validation
2155
2267
  if (!this.validateHostHeader(req)) {
2156
2268
  this._sendJsonRpcError(res, 403, -32000, 'Forbidden - invalid host header');
@@ -2201,16 +2313,20 @@ function parseSessionRetentionOptions(options) {
2201
2313
  // MCP endpoint routing
2202
2314
  if (urlPath === this._path) {
2203
2315
  if (req.method === 'POST') {
2204
- this._acceptedWork.track(this._handleMcpPost(req, res));
2205
- return;
2206
- }
2207
- if (req.method === 'GET') {
2208
- this._handleMcpGet(req, res);
2316
+ const lease = this._preDispatch.acquire();
2317
+ if (!lease) {
2318
+ const responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);
2319
+ responseFinalizer.finalize((response)=>{
2320
+ this._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');
2321
+ });
2322
+ return;
2323
+ }
2324
+ await this._handleMcpPost(req, res, lease);
2209
2325
  return;
2210
2326
  }
2211
2327
  res.writeHead(405, {
2212
2328
  'Content-Type': 'application/json',
2213
- Allow: 'GET, POST'
2329
+ Allow: 'POST'
2214
2330
  });
2215
2331
  res.end(JSON.stringify({
2216
2332
  jsonrpc: '2.0',
@@ -2244,6 +2360,28 @@ function parseSessionRetentionOptions(options) {
2244
2360
  error
2245
2361
  }));
2246
2362
  }
2363
+ _parseJsonRpcRequest(body, responseFinalizer) {
2364
+ let rawBody;
2365
+ try {
2366
+ rawBody = JSON.parse(body);
2367
+ } catch {
2368
+ responseFinalizer.finalize((response)=>{
2369
+ this._sendJsonRpcError(response, 200, -32700, 'Parse error');
2370
+ });
2371
+ return null;
2372
+ }
2373
+ const parseResult = (0,external_valibot_.safeParse)(schema/* .JsonRpcRequestSchema */.Uv, rawBody);
2374
+ const rawId = rawBody && typeof rawBody === 'object' && 'id' in rawBody ? rawBody.id ?? null : null;
2375
+ if (!parseResult.success) {
2376
+ responseFinalizer.finalize((response)=>{
2377
+ this._sendJsonRpcError(response, 200, -32600, 'Invalid Request', rawId, {
2378
+ data: parseResult.issues
2379
+ });
2380
+ });
2381
+ return null;
2382
+ }
2383
+ return parseResult.output;
2384
+ }
2247
2385
  /**
2248
2386
  * Handle POST /mcp — JSON-RPC method calls.
2249
2387
  *
@@ -2252,65 +2390,67 @@ function parseSessionRetentionOptions(options) {
2252
2390
  * - Returns Mcp-Session-Id header for new sessions (stateful mode)
2253
2391
  * - Validates Mcp-Session-Id for existing sessions (stateful mode)
2254
2392
  * - Content-Type: application/json for responses
2255
- */ async _handleMcpPost(req, res) {
2393
+ */ async _handleMcpPost(req, res, lease) {
2256
2394
  this._requestCount++;
2257
2395
  this._activeRequests++;
2258
2396
  const responseFinalizer = new ResponseFinalizer(res, this._lifecycleFailureReporter);
2259
2397
  let acceptedSession = null;
2398
+ const onAborted = ()=>lease.cancel('peer');
2399
+ req.once('aborted', onAborted);
2260
2400
  const timeout = setTimeout(()=>{
2261
2401
  responseFinalizer.finalize((response)=>{
2262
2402
  this._sendJsonRpcError(response, 500, -32603, 'Request timeout');
2263
2403
  });
2404
+ lease.cancel('timeout');
2264
2405
  }, this._requestTimeout);
2265
2406
  try {
2266
2407
  // Read request body with size limit
2267
- const body = await readRequestBody(req, this._bodySizeLimitEnabled ? this._maxBodySize : 0);
2408
+ const body = await readRequestBody(req, this._bodySizeLimitEnabled ? this._maxBodySize : 0, lease.signal);
2268
2409
  if (body === null) {
2269
2410
  responseFinalizer.finalize((response)=>{
2270
2411
  this._sendJsonRpcError(response, 413, -32000, 'Request body too large');
2271
2412
  });
2272
2413
  return;
2273
2414
  }
2274
- // Parse JSON
2275
- let rawBody;
2276
- try {
2277
- rawBody = JSON.parse(body);
2278
- } catch {
2279
- responseFinalizer.finalize((response)=>{
2280
- this._sendJsonRpcError(response, 200, -32700, 'Parse error');
2281
- });
2282
- return;
2283
- }
2284
- // Validate JSON-RPC schema
2285
- const parseResult = (0,external_valibot_.safeParse)(schema/* .JsonRpcRequestSchema */.Uv, rawBody);
2286
- const rawId = rawBody && typeof rawBody === 'object' && 'id' in rawBody ? rawBody.id ?? null : null;
2287
- if (!parseResult.success) {
2288
- responseFinalizer.finalize((response)=>{
2289
- this._sendJsonRpcError(response, 200, -32600, 'Invalid Request', rawId, {
2290
- data: parseResult.issues
2291
- });
2292
- });
2293
- return;
2294
- }
2295
- const jsonRpcRequest = parseResult.output;
2415
+ const jsonRpcRequest = this._parseJsonRpcRequest(body, responseFinalizer);
2416
+ if (jsonRpcRequest === null) return;
2296
2417
  const session = this._acceptPostSession(req, responseFinalizer);
2297
2418
  if (!session) return;
2298
2419
  acceptedSession = session.state;
2299
2420
  // Check if MCP server is ready
2300
2421
  if (!this._mcpServer) {
2422
+ const requestId = 'id' in jsonRpcRequest ? jsonRpcRequest.id ?? null : null;
2301
2423
  responseFinalizer.finalize((response)=>{
2302
- this._sendJsonRpcError(response, 503, -32603, 'Server not ready', jsonRpcRequest?.id ?? null);
2424
+ this._sendJsonRpcError(response, 503, -32603, 'Server not ready', requestId);
2303
2425
  });
2304
2426
  return;
2305
2427
  }
2306
- await this._receiveAndFinalize(jsonRpcRequest, session.id, responseFinalizer);
2428
+ req.off('aborted', onAborted);
2429
+ const acceptedWork = this._acceptedWork.transfer(lease, ()=>this._receiveAndFinalize(jsonRpcRequest, session.id, responseFinalizer).catch((error)=>{
2430
+ responseFinalizer.finalize((response)=>{
2431
+ this._sendJsonRpcError(response, 200, -32603, 'Internal error', null, {
2432
+ data: (0,errors/* .getErrorMessage */.u1)(error)
2433
+ });
2434
+ });
2435
+ }));
2436
+ await acceptedWork;
2307
2437
  } catch (error) {
2438
+ if (lease.signal.aborted) {
2439
+ if (lease.cancellationReason === 'shutdown') {
2440
+ responseFinalizer.finalize((response)=>{
2441
+ this._sendJsonRpcError(response, 503, -32603, 'Server is shutting down');
2442
+ });
2443
+ }
2444
+ return;
2445
+ }
2308
2446
  responseFinalizer.finalize((response)=>{
2309
2447
  this._sendJsonRpcError(response, 200, -32603, 'Internal error', null, {
2310
2448
  data: (0,errors/* .getErrorMessage */.u1)(error)
2311
2449
  });
2312
2450
  });
2313
2451
  } finally{
2452
+ req.off('aborted', onAborted);
2453
+ lease.release();
2314
2454
  if (acceptedSession) acceptedSession.acceptedPostCount--;
2315
2455
  clearTimeout(timeout);
2316
2456
  this._activeRequests--;
@@ -2363,82 +2503,6 @@ function parseSessionRetentionOptions(options) {
2363
2503
  httpResponse.end();
2364
2504
  });
2365
2505
  }
2366
- /**
2367
- * Handle GET /mcp — Optional SSE notification stream.
2368
- *
2369
- * Per the MCP Streamable HTTP spec, clients may open a GET request
2370
- * to receive server-initiated notifications as SSE events.
2371
- * Requires a valid Mcp-Session-Id in stateful mode.
2372
- */ _handleMcpGet(req, res) {
2373
- if (!this._stateful) {
2374
- // SSE notification streams require stateful mode
2375
- res.writeHead(405, {
2376
- 'Content-Type': 'application/json',
2377
- Allow: 'POST'
2378
- });
2379
- res.end(JSON.stringify({
2380
- jsonrpc: '2.0',
2381
- id: null,
2382
- error: {
2383
- code: -32601,
2384
- message: 'GET not supported in stateless mode'
2385
- }
2386
- }));
2387
- return;
2388
- }
2389
- // Require Mcp-Session-Id for GET requests
2390
- const sessionId = this._getSessionIdFromHeader(req);
2391
- if (!sessionId) {
2392
- res.writeHead(400, {
2393
- 'Content-Type': 'application/json'
2394
- });
2395
- res.end(JSON.stringify({
2396
- jsonrpc: '2.0',
2397
- id: null,
2398
- error: {
2399
- code: -32600,
2400
- message: 'Missing Mcp-Session-Id header'
2401
- }
2402
- }));
2403
- return;
2404
- }
2405
- const session = this._sessions.get(asSessionId(sessionId));
2406
- if (!session) {
2407
- res.writeHead(404, {
2408
- 'Content-Type': 'application/json'
2409
- });
2410
- res.end(JSON.stringify({
2411
- jsonrpc: '2.0',
2412
- id: null,
2413
- error: {
2414
- code: -32001,
2415
- message: 'Session not found'
2416
- }
2417
- }));
2418
- return;
2419
- }
2420
- session.lastActivityAt = Date.now();
2421
- // Set SSE headers
2422
- res.writeHead(200, {
2423
- 'Content-Type': 'text/event-stream',
2424
- 'Cache-Control': 'no-cache',
2425
- Connection: 'keep-alive',
2426
- 'Mcp-Session-Id': sessionId
2427
- });
2428
- // Send initial connected event
2429
- this._sendSseEvent(res, 'connected', {
2430
- sessionId,
2431
- timestamp: Date.now()
2432
- });
2433
- // Track this notification stream
2434
- session.notificationStreams.add(res);
2435
- this._updateSessionMetrics();
2436
- // Handle client disconnect
2437
- req.on('close', ()=>{
2438
- session.notificationStreams.delete(res);
2439
- this._updateSessionMetrics();
2440
- });
2441
- }
2442
2506
  /**
2443
2507
  * Resolve or create a session for a stateful request.
2444
2508
  *
@@ -2484,7 +2548,6 @@ function parseSessionRetentionOptions(options) {
2484
2548
  id: newSessionId,
2485
2549
  createdAt: now,
2486
2550
  lastActivityAt: now,
2487
- notificationStreams: new Set(),
2488
2551
  acceptedPostCount: 0
2489
2552
  };
2490
2553
  this._sessions.set(newSessionId, sessionState);
@@ -2505,17 +2568,7 @@ function parseSessionRetentionOptions(options) {
2505
2568
  }
2506
2569
  }
2507
2570
  _disposeSession(sessionId) {
2508
- const session = this._sessions.get(sessionId);
2509
- if (!session) return;
2510
- this._sessions.delete(sessionId);
2511
- for (const stream of session.notificationStreams){
2512
- try {
2513
- stream.end();
2514
- } catch (error) {
2515
- this._lifecycleFailureReporter.report(error);
2516
- }
2517
- }
2518
- session.notificationStreams.clear();
2571
+ if (!this._sessions.delete(sessionId)) return;
2519
2572
  this._updateSessionMetrics();
2520
2573
  }
2521
2574
  _stopSessionSweep() {
@@ -2534,31 +2587,6 @@ function parseSessionRetentionOptions(options) {
2534
2587
  }
2535
2588
  return undefined;
2536
2589
  }
2537
- /**
2538
- * Send an SSE event to a specific client response stream.
2539
- */ _sendSseEvent(res, event, data) {
2540
- try {
2541
- res.write(`event: ${event}\n`);
2542
- res.write(`data: ${JSON.stringify(data)}\n\n`);
2543
- } catch {
2544
- // Client disconnected — ignore
2545
- }
2546
- }
2547
- /**
2548
- * Broadcast a notification to all SSE streams in a given session.
2549
- *
2550
- * @param sessionId - Target session ID
2551
- * @param event - SSE event name
2552
- * @param data - Event payload
2553
- */ broadcastToSession(sessionId, event, data) {
2554
- const session = this._sessions.get(asSessionId(sessionId));
2555
- if (!session) {
2556
- return;
2557
- }
2558
- for (const stream of session.notificationStreams){
2559
- this._sendSseEvent(stream, event, data);
2560
- }
2561
- }
2562
2590
  /**
2563
2591
  * Handle GET /metrics endpoint.
2564
2592
  */ _handleMetrics(res) {
@@ -2617,11 +2645,6 @@ function parseSessionRetentionOptions(options) {
2617
2645
  * Update session-related metrics.
2618
2646
  */ _updateSessionMetrics() {
2619
2647
  this._metrics?.gauge('streamable_http_active_sessions', this._sessions.size, {}, 'Active Streamable HTTP sessions');
2620
- let totalStreams = 0;
2621
- for (const session of this._sessions.values()){
2622
- totalStreams += session.notificationStreams.size;
2623
- }
2624
- this._metrics?.gauge('streamable_http_notification_streams', totalStreams, {}, 'Active SSE notification streams');
2625
2648
  }
2626
2649
  /**
2627
2650
  * Stop transport server with graceful shutdown.
@@ -2630,6 +2653,7 @@ function parseSessionRetentionOptions(options) {
2630
2653
  */ stop(timeout) {
2631
2654
  if (this._stopPromise) return this._stopPromise;
2632
2655
  this._isShuttingDown = true;
2656
+ this._preDispatch.closeAdmission('shutdown');
2633
2657
  this._stopRateLimitCleanup();
2634
2658
  this._stopSessionSweep();
2635
2659
  const shutdownTimeout = timeout ?? 30000;
@@ -2665,7 +2689,7 @@ function parseSessionRetentionOptions(options) {
2665
2689
  });
2666
2690
  const stopPromise = Promise.all([
2667
2691
  serverClosed,
2668
- this._acceptedWork.join()
2692
+ this._preDispatch.join().then(()=>this._acceptedWork.join())
2669
2693
  ]).then(()=>{
2670
2694
  this.log('info', 'Streamable HTTP transport stopped');
2671
2695
  });
@@ -3179,7 +3203,7 @@ async function main() {
3179
3203
  /**
3180
3204
  * Start Streamable HTTP transport (MCP spec recommended)
3181
3205
  */ async function startStreamableHttpTransport(server, thinkingServer, lifecycle) {
3182
- const { StreamableHttpTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "E"));
3206
+ const { StreamableHttpTransport } = await Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, "q"));
3183
3207
  const port = parseInt(process.env.STREAMABLE_HTTP_PORT || '9007', 10);
3184
3208
  const host = process.env.STREAMABLE_HTTP_HOST || 'localhost';
3185
3209
  const transportMetrics = thinkingServer.getContainer().resolve('Metrics');
@@ -9,7 +9,6 @@
9
9
  */
10
10
  import type { Summary } from '../core/compression/Summary.js';
11
11
  import type { BranchId, SessionId, SummaryId } from './ids.js';
12
- export type { Summary };
13
12
  /**
14
13
  * Storage and query contract for {@link Summary} records.
15
14
  *
@@ -1 +1 @@
1
- {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/contracts/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE/D,YAAY,EAAE,OAAO,EAAE,CAAC;AAExB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;;;;;OASG;IACH,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAE5B;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAExC;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,OAAO,EAAE,CAAC;IAErD;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,OAAO,EAAE,CAAC;IAExE;;;;;;;;;OASG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAEzC;;;OAGG;IACH,QAAQ,IAAI,IAAI,CAAC;IAEjB;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CACpC"}
1
+ {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/contracts/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE/D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;IAC7B;;;;;;;;;OASG;IACH,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAE5B;;;;;;;;;;;OAWG;IACH,GAAG,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAExC;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,OAAO,EAAE,CAAC;IAErD;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,OAAO,EAAE,CAAC;IAExE;;;;;;;;;OASG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAEzC;;;OAGG;IACH,QAAQ,IAAI,IAAI,CAAC;IAEjB;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CACpC"}
@@ -1,6 +1,6 @@
1
1
  import type { PersistenceBackend } from '../contracts/PersistenceBackend.js';
2
2
  import { type BranchId, type SessionId } from '../contracts/ids.js';
3
- import type { Summary } from '../contracts/summary.js';
3
+ import type { Summary } from './compression/Summary.js';
4
4
  import type { Edge } from './graph/Edge.js';
5
5
  import type { ThoughtData } from './thought.js';
6
6
  export type RestoredBranch = {
@@ -1 +1 @@
1
- {"version":3,"file":"PersistenceRestore.d.ts","sourceRoot":"","sources":["../../src/core/PersistenceRestore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAkC,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACpG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAavD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,OAAO,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C,CAAC;AA2EF,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,0BAA0B,CAAC,CAiBrC"}
1
+ {"version":3,"file":"PersistenceRestore.d.ts","sourceRoot":"","sources":["../../src/core/PersistenceRestore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,kBAAkB,EAElB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAkC,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACpG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAaxD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,OAAO,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C,CAAC;AA2EF,wBAAsB,uBAAuB,CAC5C,OAAO,EAAE,kBAAkB,GACzB,OAAO,CAAC,0BAA0B,CAAC,CAiBrC"}