@joshuaswarren/openclaw-engram 9.2.5 → 9.2.7
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/index.js +255 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6948,7 +6948,7 @@ var GraphDashboardServer = class {
|
|
|
6948
6948
|
|
|
6949
6949
|
// src/access-http.ts
|
|
6950
6950
|
import { createServer as createServer3 } from "http";
|
|
6951
|
-
import { randomUUID, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
6951
|
+
import { randomUUID as randomUUID2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
6952
6952
|
import { AsyncLocalStorage } from "async_hooks";
|
|
6953
6953
|
import { existsSync } from "fs";
|
|
6954
6954
|
import { readFile as readFile14 } from "fs/promises";
|
|
@@ -6957,6 +6957,7 @@ import { fileURLToPath, URL as URL3 } from "url";
|
|
|
6957
6957
|
|
|
6958
6958
|
// src/access-mcp.ts
|
|
6959
6959
|
import { readFile as readFile13 } from "fs/promises";
|
|
6960
|
+
import { randomUUID } from "crypto";
|
|
6960
6961
|
var MCP_PROTOCOL_VERSION = "2024-11-05";
|
|
6961
6962
|
async function getMcpServerVersion() {
|
|
6962
6963
|
const envVersion = readEnvVar("OPENCLAW_ENGRAM_VERSION")?.trim() || readEnvVar("npm_package_version")?.trim();
|
|
@@ -7611,6 +7612,33 @@ var EngramMcpServer = class {
|
|
|
7611
7612
|
flushTask = null;
|
|
7612
7613
|
tools;
|
|
7613
7614
|
authenticatedPrincipal;
|
|
7615
|
+
/**
|
|
7616
|
+
* MCP client info keyed by server-assigned session ID. On each `initialize`
|
|
7617
|
+
* handshake the server generates a UUID, stores the client's clientInfo
|
|
7618
|
+
* against it, and returns the ID as `Mcp-Session-Id` in the response
|
|
7619
|
+
* metadata. Subsequent requests from the same client include this header,
|
|
7620
|
+
* allowing per-session clientInfo lookup without cross-session leaks.
|
|
7621
|
+
*/
|
|
7622
|
+
clientInfoBySession = /* @__PURE__ */ new Map();
|
|
7623
|
+
/**
|
|
7624
|
+
* Session IDs generated during initialize, keyed by caller-supplied correlation
|
|
7625
|
+
* ID (unique per HTTP request) to avoid collisions when multiple clients send
|
|
7626
|
+
* initialize with the same JSON-RPC id concurrently.
|
|
7627
|
+
*/
|
|
7628
|
+
initSessionIds = /* @__PURE__ */ new Map();
|
|
7629
|
+
/** Get clientInfo for a specific MCP session. Returns undefined for non-MCP requests. */
|
|
7630
|
+
getClientInfo(sessionId) {
|
|
7631
|
+
if (sessionId) {
|
|
7632
|
+
return this.clientInfoBySession.get(sessionId);
|
|
7633
|
+
}
|
|
7634
|
+
return void 0;
|
|
7635
|
+
}
|
|
7636
|
+
/** Pop the session ID generated during an initialize handshake, keyed by correlation ID. */
|
|
7637
|
+
popInitSessionId(correlationId) {
|
|
7638
|
+
const sid = this.initSessionIds.get(correlationId);
|
|
7639
|
+
if (sid !== void 0) this.initSessionIds.delete(correlationId);
|
|
7640
|
+
return sid;
|
|
7641
|
+
}
|
|
7614
7642
|
async handleRequest(request, options) {
|
|
7615
7643
|
const id = request.id ?? null;
|
|
7616
7644
|
const method = request.method ?? "";
|
|
@@ -7619,7 +7647,20 @@ var EngramMcpServer = class {
|
|
|
7619
7647
|
return { jsonrpc: "2.0", id, result: {} };
|
|
7620
7648
|
}
|
|
7621
7649
|
if (method === "initialize") {
|
|
7650
|
+
const params = request.params ?? {};
|
|
7651
|
+
const rawClientInfo = params.clientInfo;
|
|
7652
|
+
const newSessionId = randomUUID();
|
|
7653
|
+
if (rawClientInfo && typeof rawClientInfo.name === "string") {
|
|
7654
|
+
const info = { name: rawClientInfo.name, version: rawClientInfo.version };
|
|
7655
|
+
this.clientInfoBySession.set(newSessionId, info);
|
|
7656
|
+
if (this.clientInfoBySession.size > 1e3) {
|
|
7657
|
+
const firstKey = this.clientInfoBySession.keys().next().value;
|
|
7658
|
+
if (firstKey) this.clientInfoBySession.delete(firstKey);
|
|
7659
|
+
}
|
|
7660
|
+
}
|
|
7622
7661
|
const version = await getMcpServerVersion();
|
|
7662
|
+
const corrId = options?.correlationId;
|
|
7663
|
+
if (corrId) this.initSessionIds.set(corrId, newSessionId);
|
|
7623
7664
|
return {
|
|
7624
7665
|
jsonrpc: "2.0",
|
|
7625
7666
|
id,
|
|
@@ -8240,6 +8281,137 @@ function validateRequest(schemaName, body) {
|
|
|
8240
8281
|
return { success: false, error: formatZodError(result.error) };
|
|
8241
8282
|
}
|
|
8242
8283
|
|
|
8284
|
+
// src/adapters/types.ts
|
|
8285
|
+
function headerValue(headers, key) {
|
|
8286
|
+
const raw = headers[key];
|
|
8287
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
8288
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
8289
|
+
}
|
|
8290
|
+
|
|
8291
|
+
// src/adapters/claude-code.ts
|
|
8292
|
+
var ClaudeCodeAdapter = class {
|
|
8293
|
+
id = "claude-code";
|
|
8294
|
+
matches(context) {
|
|
8295
|
+
if (context.clientInfo?.name === "claude-code") return true;
|
|
8296
|
+
const ua = headerValue(context.headers, "user-agent");
|
|
8297
|
+
if (ua && ua.toLowerCase().startsWith("claude-code/")) return true;
|
|
8298
|
+
const clientId = headerValue(context.headers, "x-engram-client-id");
|
|
8299
|
+
if (clientId?.toLowerCase() === "claude-code") return true;
|
|
8300
|
+
return false;
|
|
8301
|
+
}
|
|
8302
|
+
resolveIdentity(context) {
|
|
8303
|
+
const mcpSessionId = headerValue(context.headers, "mcp-session-id");
|
|
8304
|
+
const principal = headerValue(context.headers, "x-engram-principal") || "claude-code";
|
|
8305
|
+
const namespace = headerValue(context.headers, "x-engram-namespace") || "claude-code";
|
|
8306
|
+
return {
|
|
8307
|
+
namespace,
|
|
8308
|
+
principal,
|
|
8309
|
+
sessionKey: mcpSessionId ?? context.sessionKey,
|
|
8310
|
+
adapterId: this.id
|
|
8311
|
+
};
|
|
8312
|
+
}
|
|
8313
|
+
};
|
|
8314
|
+
|
|
8315
|
+
// src/adapters/codex.ts
|
|
8316
|
+
var CodexAdapter = class {
|
|
8317
|
+
id = "codex";
|
|
8318
|
+
matches(context) {
|
|
8319
|
+
if (context.clientInfo?.name === "codex-mcp-client") return true;
|
|
8320
|
+
const clientName = context.clientInfo?.name?.toLowerCase() ?? "";
|
|
8321
|
+
if (clientName.includes("codex") && clientName !== "codex-mcp-client") return true;
|
|
8322
|
+
const clientId = headerValue(context.headers, "x-engram-client-id");
|
|
8323
|
+
if (clientId?.toLowerCase() === "codex") return true;
|
|
8324
|
+
return false;
|
|
8325
|
+
}
|
|
8326
|
+
resolveIdentity(context) {
|
|
8327
|
+
const mcpSessionId = headerValue(context.headers, "mcp-session-id");
|
|
8328
|
+
const principal = headerValue(context.headers, "x-engram-principal") || "codex";
|
|
8329
|
+
const namespace = headerValue(context.headers, "x-engram-namespace") || "codex";
|
|
8330
|
+
return {
|
|
8331
|
+
namespace,
|
|
8332
|
+
principal,
|
|
8333
|
+
sessionKey: mcpSessionId ?? context.sessionKey,
|
|
8334
|
+
adapterId: this.id
|
|
8335
|
+
};
|
|
8336
|
+
}
|
|
8337
|
+
};
|
|
8338
|
+
|
|
8339
|
+
// src/adapters/replit.ts
|
|
8340
|
+
var ReplitAdapter = class {
|
|
8341
|
+
id = "replit";
|
|
8342
|
+
matches(context) {
|
|
8343
|
+
const clientId = headerValue(context.headers, "x-engram-client-id");
|
|
8344
|
+
if (clientId?.toLowerCase() === "replit") return true;
|
|
8345
|
+
const clientName = context.clientInfo?.name?.toLowerCase() ?? "";
|
|
8346
|
+
if (clientName.includes("replit")) return true;
|
|
8347
|
+
return false;
|
|
8348
|
+
}
|
|
8349
|
+
resolveIdentity(context) {
|
|
8350
|
+
const mcpSessionId = headerValue(context.headers, "mcp-session-id");
|
|
8351
|
+
const principal = headerValue(context.headers, "x-engram-principal") || "replit-agent";
|
|
8352
|
+
const namespace = headerValue(context.headers, "x-engram-namespace") || "replit";
|
|
8353
|
+
return {
|
|
8354
|
+
namespace,
|
|
8355
|
+
principal,
|
|
8356
|
+
sessionKey: mcpSessionId ?? context.sessionKey,
|
|
8357
|
+
adapterId: this.id
|
|
8358
|
+
};
|
|
8359
|
+
}
|
|
8360
|
+
};
|
|
8361
|
+
|
|
8362
|
+
// src/adapters/hermes.ts
|
|
8363
|
+
var HermesAdapter = class {
|
|
8364
|
+
id = "hermes";
|
|
8365
|
+
matches(context) {
|
|
8366
|
+
if (headerValue(context.headers, "x-hermes-session-id")) return true;
|
|
8367
|
+
const clientId = headerValue(context.headers, "x-engram-client-id");
|
|
8368
|
+
if (clientId?.toLowerCase() === "hermes") return true;
|
|
8369
|
+
const clientName = context.clientInfo?.name?.toLowerCase() ?? "";
|
|
8370
|
+
if (clientName.includes("hermes")) return true;
|
|
8371
|
+
return false;
|
|
8372
|
+
}
|
|
8373
|
+
resolveIdentity(context) {
|
|
8374
|
+
const sessionId = headerValue(context.headers, "x-hermes-session-id");
|
|
8375
|
+
const principal = headerValue(context.headers, "x-engram-principal") || "hermes-agent";
|
|
8376
|
+
const namespace = headerValue(context.headers, "x-engram-namespace") || "hermes";
|
|
8377
|
+
return {
|
|
8378
|
+
namespace,
|
|
8379
|
+
principal,
|
|
8380
|
+
sessionKey: sessionId ?? context.sessionKey,
|
|
8381
|
+
adapterId: this.id
|
|
8382
|
+
};
|
|
8383
|
+
}
|
|
8384
|
+
};
|
|
8385
|
+
|
|
8386
|
+
// src/adapters/registry.ts
|
|
8387
|
+
var AdapterRegistry = class {
|
|
8388
|
+
adapters;
|
|
8389
|
+
constructor(adapters) {
|
|
8390
|
+
this.adapters = adapters ?? [
|
|
8391
|
+
new HermesAdapter(),
|
|
8392
|
+
new ReplitAdapter(),
|
|
8393
|
+
new CodexAdapter(),
|
|
8394
|
+
new ClaudeCodeAdapter()
|
|
8395
|
+
];
|
|
8396
|
+
}
|
|
8397
|
+
/**
|
|
8398
|
+
* Try each adapter in order. Return the first match, or null if
|
|
8399
|
+
* no adapter recognizes the request context.
|
|
8400
|
+
*/
|
|
8401
|
+
resolve(context) {
|
|
8402
|
+
for (const adapter of this.adapters) {
|
|
8403
|
+
if (adapter.matches(context)) {
|
|
8404
|
+
return adapter.resolveIdentity(context);
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
8407
|
+
return null;
|
|
8408
|
+
}
|
|
8409
|
+
/** List registered adapter IDs */
|
|
8410
|
+
list() {
|
|
8411
|
+
return this.adapters.map((a) => a.id);
|
|
8412
|
+
}
|
|
8413
|
+
};
|
|
8414
|
+
|
|
8243
8415
|
// src/access-http.ts
|
|
8244
8416
|
function resolveDefaultAdminConsolePublicDir() {
|
|
8245
8417
|
const candidates = [
|
|
@@ -8302,6 +8474,7 @@ var EngramAccessHttpServer = class {
|
|
|
8302
8474
|
adminConsoleEnabled;
|
|
8303
8475
|
adminConsolePublicDir;
|
|
8304
8476
|
trustPrincipalHeader;
|
|
8477
|
+
adapterRegistry;
|
|
8305
8478
|
writeRequestTimestamps = [];
|
|
8306
8479
|
mcpServer;
|
|
8307
8480
|
server = null;
|
|
@@ -8316,6 +8489,7 @@ var EngramAccessHttpServer = class {
|
|
|
8316
8489
|
this.adminConsoleEnabled = options.adminConsoleEnabled !== false;
|
|
8317
8490
|
this.adminConsolePublicDir = options.adminConsolePublicDir ?? defaultAdminConsolePublicDir;
|
|
8318
8491
|
this.trustPrincipalHeader = options.trustPrincipalHeader === true;
|
|
8492
|
+
this.adapterRegistry = options.enableAdapters !== false ? options.adapterRegistry ?? new AdapterRegistry() : null;
|
|
8319
8493
|
this.mcpServer = new EngramMcpServer(this.service, { principal: options.principal });
|
|
8320
8494
|
}
|
|
8321
8495
|
async start() {
|
|
@@ -8324,7 +8498,7 @@ var EngramAccessHttpServer = class {
|
|
|
8324
8498
|
}
|
|
8325
8499
|
if (this.server) return this.status();
|
|
8326
8500
|
const server = createServer3((req, res) => {
|
|
8327
|
-
const correlationId =
|
|
8501
|
+
const correlationId = randomUUID2();
|
|
8328
8502
|
correlationIdStore.run(correlationId, () => {
|
|
8329
8503
|
void this.handle(req, res, correlationId).catch((err) => {
|
|
8330
8504
|
log.debug(`engram access HTTP request failed [${correlationId}]: ${err}`);
|
|
@@ -8386,18 +8560,62 @@ var EngramAccessHttpServer = class {
|
|
|
8386
8560
|
maxBodyBytes: this.maxBodyBytes
|
|
8387
8561
|
};
|
|
8388
8562
|
}
|
|
8389
|
-
|
|
8563
|
+
/**
|
|
8564
|
+
* Resolve the adapter identity for the incoming request.
|
|
8565
|
+
* Includes MCP clientInfo from the last initialize handshake if available.
|
|
8566
|
+
* Returns null if no adapter matches or adapters are disabled.
|
|
8567
|
+
*/
|
|
8568
|
+
resolveAdapterIdentity(req) {
|
|
8569
|
+
if (!this.adapterRegistry) return null;
|
|
8570
|
+
const sessionId = (() => {
|
|
8571
|
+
const raw = req.headers["mcp-session-id"];
|
|
8572
|
+
return typeof raw === "string" ? raw.trim() : void 0;
|
|
8573
|
+
})();
|
|
8574
|
+
return this.adapterRegistry.resolve({
|
|
8575
|
+
headers: req.headers,
|
|
8576
|
+
clientInfo: this.mcpServer.getClientInfo(sessionId)
|
|
8577
|
+
});
|
|
8578
|
+
}
|
|
8579
|
+
/** Cache for per-request identity resolution (avoids double adapter resolution) */
|
|
8580
|
+
identityCache = /* @__PURE__ */ new WeakMap();
|
|
8581
|
+
/** Resolve principal and namespace from request headers and adapter identity */
|
|
8582
|
+
resolveRequestIdentity(req) {
|
|
8583
|
+
const cached = this.identityCache.get(req);
|
|
8584
|
+
if (cached) return cached;
|
|
8585
|
+
let principal;
|
|
8586
|
+
let namespace;
|
|
8390
8587
|
if (this.trustPrincipalHeader) {
|
|
8391
|
-
const
|
|
8392
|
-
const raw = Array.isArray(
|
|
8588
|
+
const headerVal = req.headers["x-engram-principal"];
|
|
8589
|
+
const raw = Array.isArray(headerVal) ? headerVal[0] : headerVal;
|
|
8393
8590
|
if (typeof raw === "string") {
|
|
8394
8591
|
const trimmed = raw.trim();
|
|
8395
8592
|
if (trimmed.length > 0) {
|
|
8396
|
-
|
|
8593
|
+
principal = trimmed;
|
|
8397
8594
|
}
|
|
8398
8595
|
}
|
|
8399
8596
|
}
|
|
8400
|
-
|
|
8597
|
+
const adapterIdentity = this.resolveAdapterIdentity(req);
|
|
8598
|
+
if (adapterIdentity) {
|
|
8599
|
+
if (!principal) {
|
|
8600
|
+
principal = adapterIdentity.principal;
|
|
8601
|
+
}
|
|
8602
|
+
namespace = adapterIdentity.namespace;
|
|
8603
|
+
}
|
|
8604
|
+
if (!principal) {
|
|
8605
|
+
principal = this.authenticatedPrincipal;
|
|
8606
|
+
}
|
|
8607
|
+
const result = { principal, namespace };
|
|
8608
|
+
this.identityCache.set(req, result);
|
|
8609
|
+
return result;
|
|
8610
|
+
}
|
|
8611
|
+
resolveRequestPrincipal(req) {
|
|
8612
|
+
return this.resolveRequestIdentity(req).principal;
|
|
8613
|
+
}
|
|
8614
|
+
/** Resolve namespace: only use the explicit body value. Adapter-inferred namespace
|
|
8615
|
+
* is intentionally NOT used as a fallback for REST requests — omitting namespace
|
|
8616
|
+
* should default to the server's global namespace, not silently scope to an adapter. */
|
|
8617
|
+
resolveNamespace(_req, bodyNamespace) {
|
|
8618
|
+
return bodyNamespace || void 0;
|
|
8401
8619
|
}
|
|
8402
8620
|
async handle(req, res, correlationId) {
|
|
8403
8621
|
const parsed = new URL3(req.url ?? "/", `http://${hostToUrlAuthority2(this.host)}`);
|
|
@@ -8423,12 +8641,21 @@ var EngramAccessHttpServer = class {
|
|
|
8423
8641
|
this.respondJson(res, 200, await this.service.health());
|
|
8424
8642
|
return;
|
|
8425
8643
|
}
|
|
8644
|
+
if (req.method === "GET" && pathname === "/engram/v1/adapters") {
|
|
8645
|
+
const identity = this.resolveAdapterIdentity(req);
|
|
8646
|
+
this.respondJson(res, 200, {
|
|
8647
|
+
adaptersEnabled: this.adapterRegistry !== null,
|
|
8648
|
+
registered: this.adapterRegistry?.list() ?? [],
|
|
8649
|
+
resolved: identity
|
|
8650
|
+
});
|
|
8651
|
+
return;
|
|
8652
|
+
}
|
|
8426
8653
|
if (req.method === "POST" && pathname === "/engram/v1/recall") {
|
|
8427
8654
|
const body = await this.readValidatedBody(req, "recall");
|
|
8428
8655
|
const response = await this.service.recall({
|
|
8429
8656
|
query: body.query ?? "",
|
|
8430
8657
|
sessionKey: body.sessionKey,
|
|
8431
|
-
namespace: body.namespace,
|
|
8658
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8432
8659
|
topK: body.topK,
|
|
8433
8660
|
mode: body.mode,
|
|
8434
8661
|
includeDebug: body.includeDebug === true
|
|
@@ -8440,7 +8667,7 @@ var EngramAccessHttpServer = class {
|
|
|
8440
8667
|
const body = await this.readValidatedBody(req, "recallExplain");
|
|
8441
8668
|
const response = await this.service.recallExplain({
|
|
8442
8669
|
sessionKey: body.sessionKey,
|
|
8443
|
-
namespace: body.namespace
|
|
8670
|
+
namespace: this.resolveNamespace(req, body.namespace)
|
|
8444
8671
|
});
|
|
8445
8672
|
this.respondJson(res, 200, response);
|
|
8446
8673
|
return;
|
|
@@ -8451,7 +8678,7 @@ var EngramAccessHttpServer = class {
|
|
|
8451
8678
|
const response = await this.service.observe({
|
|
8452
8679
|
sessionKey: body.sessionKey,
|
|
8453
8680
|
messages: body.messages,
|
|
8454
|
-
namespace: body.namespace,
|
|
8681
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8455
8682
|
authenticatedPrincipal: this.resolveRequestPrincipal(req),
|
|
8456
8683
|
skipExtraction: body.skipExtraction === true
|
|
8457
8684
|
});
|
|
@@ -8464,7 +8691,7 @@ var EngramAccessHttpServer = class {
|
|
|
8464
8691
|
const response = await this.service.lcmSearch({
|
|
8465
8692
|
query: body.query,
|
|
8466
8693
|
sessionKey: body.sessionKey,
|
|
8467
|
-
namespace: body.namespace,
|
|
8694
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8468
8695
|
authenticatedPrincipal: this.resolveRequestPrincipal(req),
|
|
8469
8696
|
limit: body.limit
|
|
8470
8697
|
});
|
|
@@ -8486,7 +8713,7 @@ var EngramAccessHttpServer = class {
|
|
|
8486
8713
|
content: body.content,
|
|
8487
8714
|
category: body.category,
|
|
8488
8715
|
confidence: body.confidence,
|
|
8489
|
-
namespace: body.namespace,
|
|
8716
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8490
8717
|
tags: body.tags,
|
|
8491
8718
|
entityRef: body.entityRef,
|
|
8492
8719
|
ttl: body.ttl,
|
|
@@ -8514,7 +8741,7 @@ var EngramAccessHttpServer = class {
|
|
|
8514
8741
|
content: body.content,
|
|
8515
8742
|
category: body.category,
|
|
8516
8743
|
confidence: body.confidence,
|
|
8517
|
-
namespace: body.namespace,
|
|
8744
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8518
8745
|
tags: body.tags,
|
|
8519
8746
|
entityRef: body.entityRef,
|
|
8520
8747
|
ttl: body.ttl,
|
|
@@ -8633,7 +8860,7 @@ var EngramAccessHttpServer = class {
|
|
|
8633
8860
|
memoryId: body.memoryId,
|
|
8634
8861
|
status: body.status,
|
|
8635
8862
|
reasonCode: body.reasonCode,
|
|
8636
|
-
namespace: body.namespace,
|
|
8863
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8637
8864
|
authenticatedPrincipal: this.resolveRequestPrincipal(req)
|
|
8638
8865
|
});
|
|
8639
8866
|
if (this.shouldCountWriteRateLimit(response)) {
|
|
@@ -8655,7 +8882,7 @@ var EngramAccessHttpServer = class {
|
|
|
8655
8882
|
recordedAt: body.recordedAt,
|
|
8656
8883
|
summary: body.summary,
|
|
8657
8884
|
dryRun,
|
|
8658
|
-
namespace: body.namespace,
|
|
8885
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8659
8886
|
authenticatedPrincipal: this.resolveRequestPrincipal(req)
|
|
8660
8887
|
});
|
|
8661
8888
|
if (this.shouldCountWriteRateLimit(response)) {
|
|
@@ -8674,7 +8901,7 @@ var EngramAccessHttpServer = class {
|
|
|
8674
8901
|
scenario: body.scenario,
|
|
8675
8902
|
recordedAt: body.recordedAt,
|
|
8676
8903
|
dryRun,
|
|
8677
|
-
namespace: body.namespace,
|
|
8904
|
+
namespace: this.resolveNamespace(req, body.namespace),
|
|
8678
8905
|
authenticatedPrincipal: this.resolveRequestPrincipal(req)
|
|
8679
8906
|
});
|
|
8680
8907
|
if (this.shouldCountWriteRateLimit(response)) {
|
|
@@ -8692,8 +8919,15 @@ var EngramAccessHttpServer = class {
|
|
|
8692
8919
|
if (isMcpWrite) {
|
|
8693
8920
|
this.ensureWriteRateLimitAvailable();
|
|
8694
8921
|
}
|
|
8922
|
+
const sessionId = (() => {
|
|
8923
|
+
const raw = req.headers["mcp-session-id"];
|
|
8924
|
+
return typeof raw === "string" ? raw.trim() : void 0;
|
|
8925
|
+
})();
|
|
8926
|
+
const mcpCorrelationId = correlationIdStore.getStore() ?? randomUUID2();
|
|
8695
8927
|
const response = await this.mcpServer.handleRequest(request, {
|
|
8696
|
-
principalOverride: this.resolveRequestPrincipal(req)
|
|
8928
|
+
principalOverride: this.resolveRequestPrincipal(req),
|
|
8929
|
+
sessionId,
|
|
8930
|
+
correlationId: mcpCorrelationId
|
|
8697
8931
|
});
|
|
8698
8932
|
if (isMcpWrite && response !== null) {
|
|
8699
8933
|
const result = response.result;
|
|
@@ -8708,6 +8942,10 @@ var EngramAccessHttpServer = class {
|
|
|
8708
8942
|
res.end();
|
|
8709
8943
|
return;
|
|
8710
8944
|
}
|
|
8945
|
+
const assignedSessionId = this.mcpServer.popInitSessionId(mcpCorrelationId);
|
|
8946
|
+
if (assignedSessionId) {
|
|
8947
|
+
res.setHeader("mcp-session-id", assignedSessionId);
|
|
8948
|
+
}
|
|
8711
8949
|
this.respondJson(res, 200, response);
|
|
8712
8950
|
}
|
|
8713
8951
|
respondJson(res, status, payload) {
|