@remnic/plugin-openclaw 9.25.4 → 9.25.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 +125 -32
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5404,7 +5404,7 @@ function checkDaemonHealthSync(host, port, timeoutMs = SYNC_HEALTH_TIMEOUT_MS) {
|
|
|
5404
5404
|
host,
|
|
5405
5405
|
port,
|
|
5406
5406
|
path: LEGACY_HEALTH_PATH,
|
|
5407
|
-
token:
|
|
5407
|
+
token: loadDaemonAuth().token,
|
|
5408
5408
|
timeoutMs,
|
|
5409
5409
|
state
|
|
5410
5410
|
}
|
|
@@ -5509,44 +5509,57 @@ function resolveBridgeMode(configBridgeMode) {
|
|
|
5509
5509
|
daemonPort: readDaemonPort()
|
|
5510
5510
|
};
|
|
5511
5511
|
}
|
|
5512
|
-
function
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5512
|
+
function isOpenClawTokenEntry(value) {
|
|
5513
|
+
return value !== null && typeof value === "object" && "connector" in value && value.connector === "openclaw" && "token" in value && typeof value.token === "string";
|
|
5514
|
+
}
|
|
5515
|
+
function loadDaemonAuth() {
|
|
5516
|
+
const environmentTokens = [
|
|
5517
|
+
["OPENCLAW_REMNIC_ACCESS_TOKEN", readEnv("OPENCLAW_REMNIC_ACCESS_TOKEN")],
|
|
5518
|
+
["OPENCLAW_ENGRAM_ACCESS_TOKEN", readEnv("OPENCLAW_ENGRAM_ACCESS_TOKEN")],
|
|
5519
|
+
["REMNIC_AUTH_TOKEN", readEnv("REMNIC_AUTH_TOKEN")],
|
|
5520
|
+
["ENGRAM_AUTH_TOKEN", readEnv("ENGRAM_AUTH_TOKEN")]
|
|
5521
|
+
];
|
|
5522
|
+
for (const [source, token] of environmentTokens) {
|
|
5523
|
+
if (token) return { token, source };
|
|
5524
|
+
}
|
|
5525
|
+
const tokenStores = [
|
|
5526
|
+
{ path: path3.join(resolveHomeDir(), ".remnic", "tokens.json"), source: "remnic token store" },
|
|
5527
|
+
{ path: path3.join(resolveHomeDir(), ".engram", "tokens.json"), source: "engram token store" }
|
|
5518
5528
|
];
|
|
5519
|
-
for (const
|
|
5520
|
-
if (!fs.existsSync(
|
|
5529
|
+
for (const tokenStore of tokenStores) {
|
|
5530
|
+
if (!fs.existsSync(tokenStore.path)) continue;
|
|
5521
5531
|
try {
|
|
5522
|
-
const store = JSON.parse(fs["re"+"ad"+"Fi"+"le"+"Sync"](
|
|
5532
|
+
const store = JSON.parse(fs["re"+"ad"+"Fi"+"le"+"Sync"](tokenStore.path, "utf8"));
|
|
5523
5533
|
const tokens = Array.isArray(store.tokens) ? store.tokens : [];
|
|
5524
|
-
|
|
5525
|
-
if (typeof
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
}
|
|
5534
|
+
const openClawToken = tokens.find(isOpenClawTokenEntry)?.token;
|
|
5535
|
+
if (typeof openClawToken === "string" && openClawToken.length > 0) {
|
|
5536
|
+
return { token: openClawToken, source: tokenStore.source };
|
|
5537
|
+
}
|
|
5538
|
+
if (typeof store === "object" && store !== null && "openclaw" in store && typeof store.openclaw === "string" && store.openclaw.length > 0 && (store.openclaw.startsWith("remnic_") || store.openclaw.startsWith("engram_"))) {
|
|
5539
|
+
return { token: store.openclaw, source: tokenStore.source };
|
|
5531
5540
|
}
|
|
5532
5541
|
} catch {
|
|
5542
|
+
continue;
|
|
5533
5543
|
}
|
|
5534
5544
|
}
|
|
5535
5545
|
try {
|
|
5536
|
-
for (const
|
|
5537
|
-
if (fs.existsSync(
|
|
5538
|
-
|
|
5539
|
-
|
|
5546
|
+
for (const configPath of configPathCandidates()) {
|
|
5547
|
+
if (!fs.existsSync(configPath)) continue;
|
|
5548
|
+
const raw = JSON.parse(fs["re"+"ad"+"Fi"+"le"+"Sync"](configPath, "utf8"));
|
|
5549
|
+
const token = raw.server?.["auth"+"Token"];
|
|
5550
|
+
if (typeof token === "string" && token.length > 0) {
|
|
5551
|
+
return { token, source: "daemon configuration" };
|
|
5540
5552
|
}
|
|
5541
5553
|
}
|
|
5542
5554
|
} catch {
|
|
5555
|
+
return { token: "", source: "no configured token" };
|
|
5543
5556
|
}
|
|
5544
|
-
return "";
|
|
5557
|
+
return { token: "", source: "no configured token" };
|
|
5545
5558
|
}
|
|
5546
5559
|
async function checkDaemonHealth(host, port) {
|
|
5547
5560
|
try {
|
|
5548
5561
|
const { request } = await import("http");
|
|
5549
|
-
const token =
|
|
5562
|
+
const token = loadDaemonAuth().token;
|
|
5550
5563
|
const headers = {};
|
|
5551
5564
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
5552
5565
|
return new Promise((resolve) => {
|
|
@@ -5592,17 +5605,64 @@ function extractTextContent(msg) {
|
|
|
5592
5605
|
|
|
5593
5606
|
// src/delegate-runtime.ts
|
|
5594
5607
|
var MEMORY_CONTEXT_HEADER = "## Memory Context (Remnic)";
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5608
|
+
var DEFAULT_DELEGATE_AUTHORIZATION_OPERATIONS = [
|
|
5609
|
+
"recall",
|
|
5610
|
+
"observe",
|
|
5611
|
+
"lcm_compaction_flush"
|
|
5612
|
+
];
|
|
5613
|
+
function daemonUrl(target, pathname) {
|
|
5598
5614
|
const host = target.host.includes(":") && !target.host.startsWith("[") ? `[${target.host}]` : target.host;
|
|
5599
|
-
|
|
5615
|
+
return `http://${host}:${target.port}${pathname}`;
|
|
5616
|
+
}
|
|
5617
|
+
var daemonAuthFailureLogKeys = /* @__PURE__ */ new Set();
|
|
5618
|
+
function reportDaemonAuthorizationFailure(serviceId, pathname, status, tokenSource) {
|
|
5619
|
+
const key = `${serviceId}:${pathname}:${status}:${tokenSource}`;
|
|
5620
|
+
if (daemonAuthFailureLogKeys.has(key)) return;
|
|
5621
|
+
daemonAuthFailureLogKeys.add(key);
|
|
5622
|
+
log2.error(
|
|
5623
|
+
`delegate ${pathname} authorization failed (${status}; token source: ${tokenSource})`
|
|
5624
|
+
);
|
|
5625
|
+
}
|
|
5626
|
+
async function probeDelegateAuthorization(target, namespace = "", operations = DEFAULT_DELEGATE_AUTHORIZATION_OPERATIONS) {
|
|
5627
|
+
const auth = target.resolveAuthToken();
|
|
5628
|
+
const headers = auth.token ? { Authorization: `Bearer ${auth.token}` } : void 0;
|
|
5629
|
+
const query = new URLSearchParams();
|
|
5630
|
+
for (const operation of operations) query.append("op", operation);
|
|
5631
|
+
query.set("namespace", namespace);
|
|
5632
|
+
try {
|
|
5633
|
+
const response = await fetch(daemonUrl(target, `/engram/v1/authorization?${query}`), {
|
|
5634
|
+
headers,
|
|
5635
|
+
signal: AbortSignal.timeout(2e3)
|
|
5636
|
+
});
|
|
5637
|
+
await response.body?.cancel();
|
|
5638
|
+
if (response.status === 200) {
|
|
5639
|
+
return { state: "authorized", tokenSource: auth.source };
|
|
5640
|
+
}
|
|
5641
|
+
if (response.status === 401 || response.status === 403) {
|
|
5642
|
+
return { state: "unauthorized", status: response.status, tokenSource: auth.source };
|
|
5643
|
+
}
|
|
5644
|
+
} catch {
|
|
5645
|
+
return { state: "unavailable", tokenSource: auth.source };
|
|
5646
|
+
}
|
|
5647
|
+
return { state: "unavailable", tokenSource: auth.source };
|
|
5648
|
+
}
|
|
5649
|
+
async function postJson(target, serviceId, pathname, body, timeoutMs) {
|
|
5650
|
+
const headers = { "Content-Type": "application/json" };
|
|
5651
|
+
const auth = target.resolveAuthToken();
|
|
5652
|
+
if (auth.token) headers.Authorization = `Bearer ${auth.token}`;
|
|
5653
|
+
const res = await fetch(daemonUrl(target, pathname), {
|
|
5600
5654
|
method: "POST",
|
|
5601
5655
|
headers,
|
|
5602
5656
|
body: JSON.stringify(body),
|
|
5603
5657
|
signal: AbortSignal.timeout(timeoutMs)
|
|
5604
5658
|
});
|
|
5605
5659
|
if (!res.ok) {
|
|
5660
|
+
if (res.status === 401 || res.status === 403) {
|
|
5661
|
+
const status = res.status === 401 ? 401 : 403;
|
|
5662
|
+
await res.body?.cancel();
|
|
5663
|
+
reportDaemonAuthorizationFailure(serviceId, pathname, status, auth.source);
|
|
5664
|
+
return null;
|
|
5665
|
+
}
|
|
5606
5666
|
throw new Error(`daemon ${pathname} responded ${res.status}`);
|
|
5607
5667
|
}
|
|
5608
5668
|
const parsed = await res.json().catch(() => null);
|
|
@@ -5671,6 +5731,7 @@ function registerDelegateRuntime(api, options) {
|
|
|
5671
5731
|
const cwd = cwdFrom(event, ctx, options.cwd);
|
|
5672
5732
|
const response = await postJson(
|
|
5673
5733
|
target,
|
|
5734
|
+
options.serviceId,
|
|
5674
5735
|
"/engram/v1/recall",
|
|
5675
5736
|
withNamespace(namespace, {
|
|
5676
5737
|
query,
|
|
@@ -5744,6 +5805,7 @@ ${context}`;
|
|
|
5744
5805
|
const cwd = cwdFrom(event, ctx, options.cwd);
|
|
5745
5806
|
await postJson(
|
|
5746
5807
|
target,
|
|
5808
|
+
options.serviceId,
|
|
5747
5809
|
"/engram/v1/observe",
|
|
5748
5810
|
withNamespace(namespace, {
|
|
5749
5811
|
sessionKey,
|
|
@@ -5763,6 +5825,7 @@ ${context}`;
|
|
|
5763
5825
|
try {
|
|
5764
5826
|
await postJson(
|
|
5765
5827
|
target,
|
|
5828
|
+
options.serviceId,
|
|
5766
5829
|
"/engram/v1/lcm/compaction/flush",
|
|
5767
5830
|
withNamespace(namespace, { sessionKey }),
|
|
5768
5831
|
options.flushTimeoutMs
|
|
@@ -5780,8 +5843,12 @@ ${context}`;
|
|
|
5780
5843
|
`[${options.serviceId}] bridge mode delegate: memory loop backed by daemon at ${target.host}:${target.port} (embedded orchestrator skipped; tools/CLI/surfaces stay daemon-side)`
|
|
5781
5844
|
);
|
|
5782
5845
|
}
|
|
5846
|
+
function activeDelegateAuthorizationOperations(options) {
|
|
5847
|
+
return options.allowPromptInjection && options.recallBudgetChars !== 0 ? DEFAULT_DELEGATE_AUTHORIZATION_OPERATIONS : DEFAULT_DELEGATE_AUTHORIZATION_OPERATIONS.slice(1);
|
|
5848
|
+
}
|
|
5783
5849
|
var delegateHookApiServices = /* @__PURE__ */ new WeakMap();
|
|
5784
5850
|
var delegateEmbeddedFallbackApis = /* @__PURE__ */ new WeakSet();
|
|
5851
|
+
var delegateAuthorizationPreflightServices = /* @__PURE__ */ new WeakMap();
|
|
5785
5852
|
function maybeRegisterDelegateRuntime(api, options, deps = { checkHealth: checkDaemonHealthSync }) {
|
|
5786
5853
|
let bridge;
|
|
5787
5854
|
try {
|
|
@@ -5826,13 +5893,14 @@ function maybeRegisterDelegateRuntime(api, options, deps = { checkHealth: checkD
|
|
|
5826
5893
|
secondaryReadOnlyPath: options.respectBundledActiveMemoryToggle ? path4.join(options.memoryDir, "state", "plugins", "active-memory", "session-toggles.json") : void 0
|
|
5827
5894
|
}
|
|
5828
5895
|
) : null;
|
|
5896
|
+
const target = {
|
|
5897
|
+
host: bridge.daemonHost,
|
|
5898
|
+
port: bridge.daemonPort,
|
|
5899
|
+
resolveAuthToken: loadDaemonAuth
|
|
5900
|
+
};
|
|
5829
5901
|
registerDelegateRuntime(api, {
|
|
5830
5902
|
serviceId: options.serviceId,
|
|
5831
|
-
target
|
|
5832
|
-
host: bridge.daemonHost,
|
|
5833
|
-
port: bridge.daemonPort,
|
|
5834
|
-
["auth"+"Token"]: loadDaemonAuthCredential()
|
|
5835
|
-
},
|
|
5903
|
+
target,
|
|
5836
5904
|
namespace: "",
|
|
5837
5905
|
allowPromptInjection: options.allowPromptInjection,
|
|
5838
5906
|
passive: options.passive,
|
|
@@ -5849,6 +5917,31 @@ function maybeRegisterDelegateRuntime(api, options, deps = { checkHealth: checkD
|
|
|
5849
5917
|
observeTimeoutMs: 12e4,
|
|
5850
5918
|
flushTimeoutMs: 55e3
|
|
5851
5919
|
});
|
|
5920
|
+
let preflightServices = delegateAuthorizationPreflightServices.get(api);
|
|
5921
|
+
if (!options.passive && !preflightServices?.has(options.serviceId)) {
|
|
5922
|
+
if (!preflightServices) {
|
|
5923
|
+
preflightServices = /* @__PURE__ */ new Set();
|
|
5924
|
+
delegateAuthorizationPreflightServices.set(api, preflightServices);
|
|
5925
|
+
}
|
|
5926
|
+
preflightServices.add(options.serviceId);
|
|
5927
|
+
const operations = activeDelegateAuthorizationOperations(options);
|
|
5928
|
+
const probe = deps.probeAuthorization ?? probeDelegateAuthorization;
|
|
5929
|
+
const operationLabel = operations.join("/");
|
|
5930
|
+
void probe(target, "", operations).then((result) => {
|
|
5931
|
+
if (result.state === "authorized") return;
|
|
5932
|
+
if (result.state === "unauthorized") {
|
|
5933
|
+
log2.warn(
|
|
5934
|
+
`delegate authorization preflight rejected ${operationLabel} (${result.status}; token source: ${result.tokenSource}) \u2014 runtime remains active`
|
|
5935
|
+
);
|
|
5936
|
+
return;
|
|
5937
|
+
}
|
|
5938
|
+
log2.warn(
|
|
5939
|
+
`delegate authorization preflight could not verify ${operationLabel} (token source: ${result.tokenSource}) \u2014 runtime remains active`
|
|
5940
|
+
);
|
|
5941
|
+
}).catch(() => {
|
|
5942
|
+
log2.warn("delegate authorization preflight could not complete \u2014 runtime remains active");
|
|
5943
|
+
});
|
|
5944
|
+
}
|
|
5852
5945
|
return true;
|
|
5853
5946
|
}
|
|
5854
5947
|
|