@joshuaswarren/openclaw-engram 9.2.5 → 9.2.6
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 +195 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8240,6 +8240,174 @@ function validateRequest(schemaName, body) {
|
|
|
8240
8240
|
return { success: false, error: formatZodError(result.error) };
|
|
8241
8241
|
}
|
|
8242
8242
|
|
|
8243
|
+
// src/adapters/claude-code.ts
|
|
8244
|
+
var ClaudeCodeAdapter = class {
|
|
8245
|
+
id = "claude-code";
|
|
8246
|
+
matches(context) {
|
|
8247
|
+
const clientName = context.clientInfo?.name?.toLowerCase() ?? "";
|
|
8248
|
+
if (clientName.includes("claude")) return true;
|
|
8249
|
+
const sessionHeader = headerValue(context.headers, "x-claude-session-id");
|
|
8250
|
+
if (sessionHeader) return true;
|
|
8251
|
+
return false;
|
|
8252
|
+
}
|
|
8253
|
+
resolveIdentity(context) {
|
|
8254
|
+
const sessionId = headerValue(context.headers, "x-claude-session-id");
|
|
8255
|
+
const projectPath = headerValue(context.headers, "x-claude-project-path");
|
|
8256
|
+
const namespace = projectPath ? slugify(projectPath) : "claude-code";
|
|
8257
|
+
const principal = headerValue(context.headers, "x-engram-principal") || context.clientInfo?.name || "claude-code";
|
|
8258
|
+
return {
|
|
8259
|
+
namespace,
|
|
8260
|
+
principal,
|
|
8261
|
+
sessionKey: sessionId ?? context.sessionKey,
|
|
8262
|
+
adapterId: this.id
|
|
8263
|
+
};
|
|
8264
|
+
}
|
|
8265
|
+
};
|
|
8266
|
+
function headerValue(headers, key) {
|
|
8267
|
+
const raw = headers[key];
|
|
8268
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
8269
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
8270
|
+
}
|
|
8271
|
+
function slugify(s) {
|
|
8272
|
+
let slug = s.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
8273
|
+
let start = 0;
|
|
8274
|
+
while (start < slug.length && slug[start] === "-") start++;
|
|
8275
|
+
let end = slug.length;
|
|
8276
|
+
while (end > start && slug[end - 1] === "-") end--;
|
|
8277
|
+
return slug.slice(start, end).slice(0, 80) || "claude-code";
|
|
8278
|
+
}
|
|
8279
|
+
|
|
8280
|
+
// src/adapters/codex.ts
|
|
8281
|
+
var CodexAdapter = class {
|
|
8282
|
+
id = "codex";
|
|
8283
|
+
matches(context) {
|
|
8284
|
+
const clientName = context.clientInfo?.name?.toLowerCase() ?? "";
|
|
8285
|
+
if (clientName.includes("codex")) return true;
|
|
8286
|
+
const agentHeader = headerValue2(context.headers, "x-codex-agent-name");
|
|
8287
|
+
if (agentHeader) return true;
|
|
8288
|
+
return false;
|
|
8289
|
+
}
|
|
8290
|
+
resolveIdentity(context) {
|
|
8291
|
+
const agentName = headerValue2(context.headers, "x-codex-agent-name");
|
|
8292
|
+
const projectDir = headerValue2(context.headers, "x-codex-project-dir");
|
|
8293
|
+
const namespace = projectDir ? slugify2(projectDir) : "codex";
|
|
8294
|
+
const principal = headerValue2(context.headers, "x-engram-principal") || agentName || context.clientInfo?.name || "codex";
|
|
8295
|
+
return {
|
|
8296
|
+
namespace,
|
|
8297
|
+
principal,
|
|
8298
|
+
sessionKey: context.sessionKey,
|
|
8299
|
+
adapterId: this.id
|
|
8300
|
+
};
|
|
8301
|
+
}
|
|
8302
|
+
};
|
|
8303
|
+
function headerValue2(headers, key) {
|
|
8304
|
+
const raw = headers[key];
|
|
8305
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
8306
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
8307
|
+
}
|
|
8308
|
+
function slugify2(s) {
|
|
8309
|
+
let slug = s.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
8310
|
+
let start = 0;
|
|
8311
|
+
while (start < slug.length && slug[start] === "-") start++;
|
|
8312
|
+
let end = slug.length;
|
|
8313
|
+
while (end > start && slug[end - 1] === "-") end--;
|
|
8314
|
+
return slug.slice(start, end).slice(0, 80) || "codex";
|
|
8315
|
+
}
|
|
8316
|
+
|
|
8317
|
+
// src/adapters/replit.ts
|
|
8318
|
+
var ReplitAdapter = class {
|
|
8319
|
+
id = "replit";
|
|
8320
|
+
matches(context) {
|
|
8321
|
+
if (headerValue3(context.headers, "x-replit-project-id")) return true;
|
|
8322
|
+
if (headerValue3(context.headers, "x-replit-user-id")) return true;
|
|
8323
|
+
return false;
|
|
8324
|
+
}
|
|
8325
|
+
resolveIdentity(context) {
|
|
8326
|
+
const projectId = headerValue3(context.headers, "x-replit-project-id");
|
|
8327
|
+
const userId = headerValue3(context.headers, "x-replit-user-id");
|
|
8328
|
+
const namespace = projectId ? `replit-${sanitizeId(projectId)}` : "replit";
|
|
8329
|
+
const principal = headerValue3(context.headers, "x-engram-principal") || (userId ? `replit-user-${sanitizeId(userId)}` : "replit-agent");
|
|
8330
|
+
return {
|
|
8331
|
+
namespace,
|
|
8332
|
+
principal,
|
|
8333
|
+
sessionKey: context.sessionKey,
|
|
8334
|
+
adapterId: this.id
|
|
8335
|
+
};
|
|
8336
|
+
}
|
|
8337
|
+
};
|
|
8338
|
+
function headerValue3(headers, key) {
|
|
8339
|
+
const raw = headers[key];
|
|
8340
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
8341
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
8342
|
+
}
|
|
8343
|
+
function sanitizeId(s) {
|
|
8344
|
+
return s.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 64);
|
|
8345
|
+
}
|
|
8346
|
+
|
|
8347
|
+
// src/adapters/hermes.ts
|
|
8348
|
+
var HermesAdapter = class {
|
|
8349
|
+
id = "hermes";
|
|
8350
|
+
matches(context) {
|
|
8351
|
+
if (headerValue4(context.headers, "x-hermes-session-id")) return true;
|
|
8352
|
+
if (headerValue4(context.headers, "x-hermes-profile")) return true;
|
|
8353
|
+
return false;
|
|
8354
|
+
}
|
|
8355
|
+
resolveIdentity(context) {
|
|
8356
|
+
const sessionId = headerValue4(context.headers, "x-hermes-session-id");
|
|
8357
|
+
const profile = headerValue4(context.headers, "x-hermes-profile");
|
|
8358
|
+
const namespace = profile ? slugify3(profile) : "hermes";
|
|
8359
|
+
const principal = headerValue4(context.headers, "x-engram-principal") || profile || "hermes-agent";
|
|
8360
|
+
return {
|
|
8361
|
+
namespace,
|
|
8362
|
+
principal,
|
|
8363
|
+
sessionKey: sessionId ?? context.sessionKey,
|
|
8364
|
+
adapterId: this.id
|
|
8365
|
+
};
|
|
8366
|
+
}
|
|
8367
|
+
};
|
|
8368
|
+
function headerValue4(headers, key) {
|
|
8369
|
+
const raw = headers[key];
|
|
8370
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
8371
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
8372
|
+
}
|
|
8373
|
+
function slugify3(s) {
|
|
8374
|
+
let slug = s.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
8375
|
+
let start = 0;
|
|
8376
|
+
while (start < slug.length && slug[start] === "-") start++;
|
|
8377
|
+
let end = slug.length;
|
|
8378
|
+
while (end > start && slug[end - 1] === "-") end--;
|
|
8379
|
+
return slug.slice(start, end).slice(0, 80) || "hermes";
|
|
8380
|
+
}
|
|
8381
|
+
|
|
8382
|
+
// src/adapters/registry.ts
|
|
8383
|
+
var AdapterRegistry = class {
|
|
8384
|
+
adapters;
|
|
8385
|
+
constructor(adapters) {
|
|
8386
|
+
this.adapters = adapters ?? [
|
|
8387
|
+
new HermesAdapter(),
|
|
8388
|
+
new ReplitAdapter(),
|
|
8389
|
+
new CodexAdapter(),
|
|
8390
|
+
new ClaudeCodeAdapter()
|
|
8391
|
+
];
|
|
8392
|
+
}
|
|
8393
|
+
/**
|
|
8394
|
+
* Try each adapter in order. Return the first match, or null if
|
|
8395
|
+
* no adapter recognizes the request context.
|
|
8396
|
+
*/
|
|
8397
|
+
resolve(context) {
|
|
8398
|
+
for (const adapter of this.adapters) {
|
|
8399
|
+
if (adapter.matches(context)) {
|
|
8400
|
+
return adapter.resolveIdentity(context);
|
|
8401
|
+
}
|
|
8402
|
+
}
|
|
8403
|
+
return null;
|
|
8404
|
+
}
|
|
8405
|
+
/** List registered adapter IDs */
|
|
8406
|
+
list() {
|
|
8407
|
+
return this.adapters.map((a) => a.id);
|
|
8408
|
+
}
|
|
8409
|
+
};
|
|
8410
|
+
|
|
8243
8411
|
// src/access-http.ts
|
|
8244
8412
|
function resolveDefaultAdminConsolePublicDir() {
|
|
8245
8413
|
const candidates = [
|
|
@@ -8302,6 +8470,7 @@ var EngramAccessHttpServer = class {
|
|
|
8302
8470
|
adminConsoleEnabled;
|
|
8303
8471
|
adminConsolePublicDir;
|
|
8304
8472
|
trustPrincipalHeader;
|
|
8473
|
+
adapterRegistry;
|
|
8305
8474
|
writeRequestTimestamps = [];
|
|
8306
8475
|
mcpServer;
|
|
8307
8476
|
server = null;
|
|
@@ -8316,6 +8485,7 @@ var EngramAccessHttpServer = class {
|
|
|
8316
8485
|
this.adminConsoleEnabled = options.adminConsoleEnabled !== false;
|
|
8317
8486
|
this.adminConsolePublicDir = options.adminConsolePublicDir ?? defaultAdminConsolePublicDir;
|
|
8318
8487
|
this.trustPrincipalHeader = options.trustPrincipalHeader === true;
|
|
8488
|
+
this.adapterRegistry = options.enableAdapters !== false ? options.adapterRegistry ?? new AdapterRegistry() : null;
|
|
8319
8489
|
this.mcpServer = new EngramMcpServer(this.service, { principal: options.principal });
|
|
8320
8490
|
}
|
|
8321
8491
|
async start() {
|
|
@@ -8386,10 +8556,20 @@ var EngramAccessHttpServer = class {
|
|
|
8386
8556
|
maxBodyBytes: this.maxBodyBytes
|
|
8387
8557
|
};
|
|
8388
8558
|
}
|
|
8559
|
+
/**
|
|
8560
|
+
* Resolve the adapter identity for the incoming request.
|
|
8561
|
+
* Returns null if no adapter matches or adapters are disabled.
|
|
8562
|
+
*/
|
|
8563
|
+
resolveAdapterIdentity(req) {
|
|
8564
|
+
if (!this.adapterRegistry) return null;
|
|
8565
|
+
return this.adapterRegistry.resolve({
|
|
8566
|
+
headers: req.headers
|
|
8567
|
+
});
|
|
8568
|
+
}
|
|
8389
8569
|
resolveRequestPrincipal(req) {
|
|
8390
8570
|
if (this.trustPrincipalHeader) {
|
|
8391
|
-
const
|
|
8392
|
-
const raw = Array.isArray(
|
|
8571
|
+
const headerValue5 = req.headers["x-engram-principal"];
|
|
8572
|
+
const raw = Array.isArray(headerValue5) ? headerValue5[0] : headerValue5;
|
|
8393
8573
|
if (typeof raw === "string") {
|
|
8394
8574
|
const trimmed = raw.trim();
|
|
8395
8575
|
if (trimmed.length > 0) {
|
|
@@ -8397,6 +8577,10 @@ var EngramAccessHttpServer = class {
|
|
|
8397
8577
|
}
|
|
8398
8578
|
}
|
|
8399
8579
|
}
|
|
8580
|
+
const adapterIdentity = this.resolveAdapterIdentity(req);
|
|
8581
|
+
if (adapterIdentity) {
|
|
8582
|
+
return adapterIdentity.principal;
|
|
8583
|
+
}
|
|
8400
8584
|
return this.authenticatedPrincipal;
|
|
8401
8585
|
}
|
|
8402
8586
|
async handle(req, res, correlationId) {
|
|
@@ -8423,6 +8607,15 @@ var EngramAccessHttpServer = class {
|
|
|
8423
8607
|
this.respondJson(res, 200, await this.service.health());
|
|
8424
8608
|
return;
|
|
8425
8609
|
}
|
|
8610
|
+
if (req.method === "GET" && pathname === "/engram/v1/adapters") {
|
|
8611
|
+
const identity = this.resolveAdapterIdentity(req);
|
|
8612
|
+
this.respondJson(res, 200, {
|
|
8613
|
+
adaptersEnabled: this.adapterRegistry !== null,
|
|
8614
|
+
registered: this.adapterRegistry?.list() ?? [],
|
|
8615
|
+
resolved: identity
|
|
8616
|
+
});
|
|
8617
|
+
return;
|
|
8618
|
+
}
|
|
8426
8619
|
if (req.method === "POST" && pathname === "/engram/v1/recall") {
|
|
8427
8620
|
const body = await this.readValidatedBody(req, "recall");
|
|
8428
8621
|
const response = await this.service.recall({
|