@remnic/cli 9.69.8 → 9.69.10
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 +47 -158
- package/package.json +32 -32
package/dist/index.js
CHANGED
|
@@ -358,154 +358,6 @@ async function runOkfBinaryCommand(rest) {
|
|
|
358
358
|
import fs6 from "fs";
|
|
359
359
|
import { Orchestrator as Orchestrator4, parseConfig as parseConfig6, resolveRemnicConfigRecord as resolveRemnicConfigRecord6 } from "@remnic/core";
|
|
360
360
|
import { exportOkfBundle, parseIncludeStatus } from "@remnic/core/export-okf";
|
|
361
|
-
|
|
362
|
-
// src/config-key-report.ts
|
|
363
|
-
var REPORTABLE_KEY = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
364
|
-
function readString(text, i) {
|
|
365
|
-
let out = "";
|
|
366
|
-
let index = i + 1;
|
|
367
|
-
while (index < text.length) {
|
|
368
|
-
const ch = text[index];
|
|
369
|
-
if (ch === "\\") {
|
|
370
|
-
const next = text[index + 1];
|
|
371
|
-
if (next === void 0) return null;
|
|
372
|
-
index += next === "u" ? 6 : 2;
|
|
373
|
-
out += "\0";
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
if (ch === '"') return { value: out, next: index + 1 };
|
|
377
|
-
if (ch === "\n") return null;
|
|
378
|
-
out += ch;
|
|
379
|
-
index += 1;
|
|
380
|
-
}
|
|
381
|
-
return null;
|
|
382
|
-
}
|
|
383
|
-
var JSON_SCALAR = /^(?:-?(?:0|[1-9][0-9]{0,19})(?:\.[0-9]{1,20})?(?:[eE][+-]?[0-9]{1,3})?|true|false|null)$/;
|
|
384
|
-
function readScalar(text, i) {
|
|
385
|
-
let end = i;
|
|
386
|
-
while (end < text.length && !",}] \n\r".includes(text[end])) end += 1;
|
|
387
|
-
const token = text.slice(i, end);
|
|
388
|
-
if (token === "" || !JSON_SCALAR.test(token)) return null;
|
|
389
|
-
return { next: end };
|
|
390
|
-
}
|
|
391
|
-
function skipWs(text, i) {
|
|
392
|
-
let index = i;
|
|
393
|
-
while (index < text.length && (text[index] === " " || text[index] === " " || text[index] === "\n" || text[index] === "\r")) {
|
|
394
|
-
index += 1;
|
|
395
|
-
}
|
|
396
|
-
return index;
|
|
397
|
-
}
|
|
398
|
-
function reportConfigKeys(rawText, maxKeys = 200) {
|
|
399
|
-
const empty = { keys: [], unresolved: [], truncated: false };
|
|
400
|
-
if (typeof rawText !== "string" || rawText.trim() === "") return empty;
|
|
401
|
-
const keys = /* @__PURE__ */ new Set();
|
|
402
|
-
const unresolved = /* @__PURE__ */ new Set();
|
|
403
|
-
const inObject = [];
|
|
404
|
-
let truncated = false;
|
|
405
|
-
let i = skipWs(rawText, 0);
|
|
406
|
-
let expectKey = false;
|
|
407
|
-
scan: while (i < rawText.length) {
|
|
408
|
-
const ch = rawText[i];
|
|
409
|
-
if (ch === "{") {
|
|
410
|
-
inObject.push(true);
|
|
411
|
-
expectKey = true;
|
|
412
|
-
i = skipWs(rawText, i + 1);
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
if (ch === "[") {
|
|
416
|
-
inObject.push(false);
|
|
417
|
-
expectKey = false;
|
|
418
|
-
i = skipWs(rawText, i + 1);
|
|
419
|
-
continue;
|
|
420
|
-
}
|
|
421
|
-
if (ch === "}" || ch === "]") {
|
|
422
|
-
const expected = ch === "}";
|
|
423
|
-
if (inObject.length === 0 || inObject[inObject.length - 1] !== expected) {
|
|
424
|
-
truncated = true;
|
|
425
|
-
break scan;
|
|
426
|
-
}
|
|
427
|
-
inObject.pop();
|
|
428
|
-
expectKey = false;
|
|
429
|
-
i = skipWs(rawText, i + 1);
|
|
430
|
-
continue;
|
|
431
|
-
}
|
|
432
|
-
if (ch === ",") {
|
|
433
|
-
if (expectKey || inObject.length === 0) {
|
|
434
|
-
truncated = true;
|
|
435
|
-
break scan;
|
|
436
|
-
}
|
|
437
|
-
expectKey = inObject[inObject.length - 1] === true;
|
|
438
|
-
i = skipWs(rawText, i + 1);
|
|
439
|
-
continue;
|
|
440
|
-
}
|
|
441
|
-
if (ch === '"') {
|
|
442
|
-
const read = readString(rawText, i);
|
|
443
|
-
if (!read) {
|
|
444
|
-
truncated = true;
|
|
445
|
-
break scan;
|
|
446
|
-
}
|
|
447
|
-
const after = skipWs(rawText, read.next);
|
|
448
|
-
const isKeySlot = expectKey && inObject[inObject.length - 1] === true && rawText[after] === ":";
|
|
449
|
-
if (isKeySlot) {
|
|
450
|
-
if (keys.size >= maxKeys) {
|
|
451
|
-
truncated = true;
|
|
452
|
-
break scan;
|
|
453
|
-
}
|
|
454
|
-
if (REPORTABLE_KEY.test(read.value)) keys.add(read.value);
|
|
455
|
-
const valueStart = skipWs(rawText, after + 1);
|
|
456
|
-
if (valueStart >= rawText.length) {
|
|
457
|
-
truncated = true;
|
|
458
|
-
break scan;
|
|
459
|
-
}
|
|
460
|
-
if (rawText[valueStart] === '"') {
|
|
461
|
-
const value = readString(rawText, valueStart);
|
|
462
|
-
if (value && value.value.startsWith("${") && value.value.endsWith("}")) {
|
|
463
|
-
if (REPORTABLE_KEY.test(read.value)) unresolved.add(read.value);
|
|
464
|
-
}
|
|
465
|
-
i = value ? value.next : valueStart;
|
|
466
|
-
if (!value) {
|
|
467
|
-
truncated = true;
|
|
468
|
-
break scan;
|
|
469
|
-
}
|
|
470
|
-
expectKey = false;
|
|
471
|
-
i = skipWs(rawText, i);
|
|
472
|
-
continue;
|
|
473
|
-
}
|
|
474
|
-
expectKey = false;
|
|
475
|
-
i = valueStart;
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
expectKey = false;
|
|
479
|
-
i = after;
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
if (expectKey) {
|
|
483
|
-
truncated = true;
|
|
484
|
-
break scan;
|
|
485
|
-
}
|
|
486
|
-
const token = readScalar(rawText, i);
|
|
487
|
-
if (!token) {
|
|
488
|
-
truncated = true;
|
|
489
|
-
break scan;
|
|
490
|
-
}
|
|
491
|
-
i = skipWs(rawText, token.next);
|
|
492
|
-
}
|
|
493
|
-
const sort = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
494
|
-
return { keys: [...keys].sort(sort), unresolved: [...unresolved].sort(sort), truncated };
|
|
495
|
-
}
|
|
496
|
-
function formatConfigKeyReport(report) {
|
|
497
|
-
if (report.keys.length === 0) {
|
|
498
|
-
return report.truncated ? " (config could not be scanned)" : " (no config keys found)";
|
|
499
|
-
}
|
|
500
|
-
const unresolved = new Set(report.unresolved);
|
|
501
|
-
const lines = report.keys.map(
|
|
502
|
-
(key) => ` ${key}${unresolved.has(key) ? " (unresolved ${...} placeholder)" : ""}`
|
|
503
|
-
);
|
|
504
|
-
if (report.truncated) lines.push(" (scan stopped early: malformed config or key cap reached)");
|
|
505
|
-
return lines.join("\n");
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// src/commands/export-okf.ts
|
|
509
361
|
function takeFlag(rest, name) {
|
|
510
362
|
const index = rest.indexOf(name);
|
|
511
363
|
if (index < 0) return void 0;
|
|
@@ -532,18 +384,15 @@ async function runExportOkfBinaryCommand(rest) {
|
|
|
532
384
|
if (!out) throw new Error("Missing --out");
|
|
533
385
|
const namespace = takeFlag(args, "--namespace") ?? "";
|
|
534
386
|
const configPath = resolveConfigPath();
|
|
535
|
-
let rawConfig = {};
|
|
536
|
-
let rawText = "";
|
|
537
387
|
let config;
|
|
538
388
|
try {
|
|
539
|
-
|
|
540
|
-
rawConfig = rawText === "" ? {} : JSON.parse(rawText);
|
|
389
|
+
const rawConfig = fs6.existsSync(configPath) ? JSON.parse(fs6.readFileSync(configPath, "utf8")) : {};
|
|
541
390
|
config = parseConfig6(resolveRemnicConfigRecord6(rawConfig));
|
|
542
391
|
} catch (err) {
|
|
543
392
|
console.error(
|
|
544
393
|
`export-okf: failed to load config at ${configPath} (${err instanceof Error ? err.name : "unknown error"})`
|
|
545
394
|
);
|
|
546
|
-
console.error(
|
|
395
|
+
console.error(" config values are never printed; inspect the file directly");
|
|
547
396
|
process.exitCode = 1;
|
|
548
397
|
return;
|
|
549
398
|
}
|
|
@@ -609,18 +458,15 @@ async function runCodegraphBinaryCommand(rest) {
|
|
|
609
458
|
if (!project) throw new Error("Missing --project");
|
|
610
459
|
if (!out) throw new Error("Missing --out");
|
|
611
460
|
const configPath = resolveConfigPath();
|
|
612
|
-
let rawConfig = {};
|
|
613
|
-
let rawText = "";
|
|
614
461
|
let config;
|
|
615
462
|
try {
|
|
616
|
-
|
|
617
|
-
rawConfig = rawText === "" ? {} : JSON.parse(rawText);
|
|
463
|
+
const rawConfig = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
|
|
618
464
|
config = parseConfig7(resolveRemnicConfigRecord7(rawConfig));
|
|
619
465
|
} catch (err) {
|
|
620
466
|
console.error(
|
|
621
467
|
`codegraph export-okf: failed to load config at ${configPath} (${err instanceof Error ? err.name : "unknown error"})`
|
|
622
468
|
);
|
|
623
|
-
console.error(
|
|
469
|
+
console.error(" config values are never printed; inspect the file directly");
|
|
624
470
|
process.exitCode = 1;
|
|
625
471
|
return;
|
|
626
472
|
}
|
|
@@ -5861,6 +5707,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5861
5707
|
|
|
5862
5708
|
// src/remote-daemon.ts
|
|
5863
5709
|
import fs24 from "fs";
|
|
5710
|
+
import { isLoopbackHost } from "@remnic/core/runtime/http-transport.js";
|
|
5864
5711
|
function readCompatEnv(primary, legacy) {
|
|
5865
5712
|
return process.env[primary] ?? process.env[legacy];
|
|
5866
5713
|
}
|
|
@@ -5960,6 +5807,25 @@ function resolveRemoteDaemon(configPath) {
|
|
|
5960
5807
|
const token = resolveOperatorToken(configPath);
|
|
5961
5808
|
return token ? { baseUrl, token } : { baseUrl };
|
|
5962
5809
|
}
|
|
5810
|
+
function resolveHostedOnlyDaemonRefusal(configPath) {
|
|
5811
|
+
const remoteUrl = resolveRemoteDaemonUrl(configPath);
|
|
5812
|
+
if (!remoteUrl) return void 0;
|
|
5813
|
+
let hostname;
|
|
5814
|
+
try {
|
|
5815
|
+
hostname = new URL(remoteUrl).hostname;
|
|
5816
|
+
} catch {
|
|
5817
|
+
return void 0;
|
|
5818
|
+
}
|
|
5819
|
+
if (isLoopbackHost(hostname)) return void 0;
|
|
5820
|
+
return { remoteUrl };
|
|
5821
|
+
}
|
|
5822
|
+
function hostedOnlyDaemonRefusalMessage(remoteUrl, action) {
|
|
5823
|
+
return [
|
|
5824
|
+
`Error: refusing to ${action} a local remnic-server: REMNIC_DAEMON_URL / server.url is set to the remote origin ${remoteUrl} (hosted-only mode).`,
|
|
5825
|
+
" Check the hosted daemon instead: remnic status",
|
|
5826
|
+
" To manage a local daemon, unset REMNIC_DAEMON_URL / ENGRAM_DAEMON_URL and remove server.url from the config."
|
|
5827
|
+
].join("\n");
|
|
5828
|
+
}
|
|
5963
5829
|
function isTransportError(err) {
|
|
5964
5830
|
return err instanceof Error && (err.message.includes("ECONNREFUSED") || err.message.includes("ECONNRESET") || err.message.includes("fetch failed") || err.message.includes("aborted") || err.message.includes("ENOTFOUND"));
|
|
5965
5831
|
}
|
|
@@ -16127,6 +15993,19 @@ function isServiceRunning() {
|
|
|
16127
15993
|
return { running: false };
|
|
16128
15994
|
}
|
|
16129
15995
|
async function daemonStatus() {
|
|
15996
|
+
const hostedOnly = resolveHostedOnlyDaemonRefusal(resolveConfigPath());
|
|
15997
|
+
if (hostedOnly) {
|
|
15998
|
+
const probe = await probeDaemonHealth(
|
|
15999
|
+
hostedOnly.remoteUrl,
|
|
16000
|
+
resolveOperatorToken(resolveConfigPath())
|
|
16001
|
+
);
|
|
16002
|
+
const remoteState = probe.ok ? "reachable" : `unreachable${probe.status ? ` (HTTP ${probe.status})` : probe.error ? ` (${probe.error})` : ""}`;
|
|
16003
|
+
console.log(`Remnic daemon status:`);
|
|
16004
|
+
console.log(` Mode: hosted-only (remote origin ${hostedOnly.remoteUrl})`);
|
|
16005
|
+
console.log(` Remote: ${remoteState}`);
|
|
16006
|
+
console.log(` Local: disabled \u2014 \`daemon start|install\` refuse while the remote origin is set`);
|
|
16007
|
+
return;
|
|
16008
|
+
}
|
|
16130
16009
|
const { running, pid } = isServiceRunning();
|
|
16131
16010
|
const port = inferPort();
|
|
16132
16011
|
const serviceInstalled = isMacOS() ? anyFileExists(LAUNCHD_PLIST_PATHS) : isLinux() ? anyFileExists(SYSTEMD_UNIT_PATHS) : false;
|
|
@@ -16157,6 +16036,13 @@ async function daemonStatus() {
|
|
|
16157
16036
|
console.log(` Memory extensions: unknown (config error)`);
|
|
16158
16037
|
}
|
|
16159
16038
|
}
|
|
16039
|
+
function refuseLocalDaemonIfHostedOnly(action) {
|
|
16040
|
+
const refusal = resolveHostedOnlyDaemonRefusal(resolveConfigPath());
|
|
16041
|
+
if (refusal) {
|
|
16042
|
+
console.error(hostedOnlyDaemonRefusalMessage(refusal.remoteUrl, action));
|
|
16043
|
+
process.exit(1);
|
|
16044
|
+
}
|
|
16045
|
+
}
|
|
16160
16046
|
function daemonStart() {
|
|
16161
16047
|
const svc = isServiceRunning();
|
|
16162
16048
|
if (svc.running) {
|
|
@@ -17325,6 +17211,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
17325
17211
|
break;
|
|
17326
17212
|
case "daemon": {
|
|
17327
17213
|
const action = rest[0];
|
|
17214
|
+
if (action === "start" || action === "install" || action === "restart") {
|
|
17215
|
+
refuseLocalDaemonIfHostedOnly(action);
|
|
17216
|
+
}
|
|
17328
17217
|
switch (action) {
|
|
17329
17218
|
case "start":
|
|
17330
17219
|
daemonStart();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/cli",
|
|
3
|
-
"version": "9.69.
|
|
3
|
+
"version": "9.69.10",
|
|
4
4
|
"description": "CLI for Remnic memory — init, query, doctor, daemon management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,26 +26,26 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"yaml": "^2.4.2",
|
|
29
|
-
"@remnic/
|
|
30
|
-
"@remnic/plugin-pi": "^9.69.
|
|
31
|
-
"@remnic/
|
|
29
|
+
"@remnic/core": "^9.69.10",
|
|
30
|
+
"@remnic/plugin-pi": "^9.69.10",
|
|
31
|
+
"@remnic/server": "^9.69.10"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@remnic/bench": "^9.69.
|
|
35
|
-
"@remnic/plugin-openclaw": "^9.69.
|
|
36
|
-
"@remnic/export-weclone": "^9.69.
|
|
37
|
-
"@remnic/import-weclone": "^9.69.
|
|
38
|
-
"@remnic/import-chatgpt": "^9.69.
|
|
39
|
-
"@remnic/import-claude": "^9.69.
|
|
40
|
-
"@remnic/import-gemini": "^9.69.
|
|
41
|
-
"@remnic/import-lossless-claw": "^9.69.
|
|
42
|
-
"@remnic/import-mem0": "^9.69.
|
|
43
|
-
"@remnic/import-supermemory": "^9.69.
|
|
44
|
-
"@remnic/import-okf": "^9.69.
|
|
45
|
-
"@remnic/connector-limitless": "^9.69.
|
|
46
|
-
"@remnic/connector-bee": "^9.69.
|
|
47
|
-
"@remnic/connector-omi": "^9.69.
|
|
48
|
-
"@remnic/capture-audio": "^9.69.
|
|
34
|
+
"@remnic/bench": "^9.69.10",
|
|
35
|
+
"@remnic/plugin-openclaw": "^9.69.10",
|
|
36
|
+
"@remnic/export-weclone": "^9.69.10",
|
|
37
|
+
"@remnic/import-weclone": "^9.69.10",
|
|
38
|
+
"@remnic/import-chatgpt": "^9.69.10",
|
|
39
|
+
"@remnic/import-claude": "^9.69.10",
|
|
40
|
+
"@remnic/import-gemini": "^9.69.10",
|
|
41
|
+
"@remnic/import-lossless-claw": "^9.69.10",
|
|
42
|
+
"@remnic/import-mem0": "^9.69.10",
|
|
43
|
+
"@remnic/import-supermemory": "^9.69.10",
|
|
44
|
+
"@remnic/import-okf": "^9.69.10",
|
|
45
|
+
"@remnic/connector-limitless": "^9.69.10",
|
|
46
|
+
"@remnic/connector-bee": "^9.69.10",
|
|
47
|
+
"@remnic/connector-omi": "^9.69.10",
|
|
48
|
+
"@remnic/capture-audio": "^9.69.10"
|
|
49
49
|
},
|
|
50
50
|
"peerDependenciesMeta": {
|
|
51
51
|
"@remnic/bench": {
|
|
@@ -97,19 +97,19 @@
|
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"tsup": "^8.5.1",
|
|
99
99
|
"typescript": "^5.9.3",
|
|
100
|
-
"@remnic/
|
|
101
|
-
"@remnic/
|
|
102
|
-
"@remnic/
|
|
103
|
-
"@remnic/
|
|
104
|
-
"@remnic/import-
|
|
105
|
-
"@remnic/import-claude": "9.69.
|
|
106
|
-
"@remnic/import-
|
|
107
|
-
"@remnic/import-lossless-claw": "9.69.
|
|
108
|
-
"@remnic/import-mem0": "9.69.
|
|
109
|
-
"@remnic/import-supermemory": "9.69.
|
|
110
|
-
"@remnic/connector-limitless": "9.69.
|
|
111
|
-
"@remnic/connector-bee": "9.69.
|
|
112
|
-
"@remnic/connector-omi": "9.69.
|
|
100
|
+
"@remnic/bench": "9.69.10",
|
|
101
|
+
"@remnic/plugin-openclaw": "9.69.10",
|
|
102
|
+
"@remnic/export-weclone": "9.69.10",
|
|
103
|
+
"@remnic/import-weclone": "9.69.10",
|
|
104
|
+
"@remnic/import-chatgpt": "9.69.10",
|
|
105
|
+
"@remnic/import-claude": "9.69.10",
|
|
106
|
+
"@remnic/import-gemini": "9.69.10",
|
|
107
|
+
"@remnic/import-lossless-claw": "9.69.10",
|
|
108
|
+
"@remnic/import-mem0": "9.69.10",
|
|
109
|
+
"@remnic/import-supermemory": "9.69.10",
|
|
110
|
+
"@remnic/connector-limitless": "9.69.10",
|
|
111
|
+
"@remnic/connector-bee": "9.69.10",
|
|
112
|
+
"@remnic/connector-omi": "9.69.10"
|
|
113
113
|
},
|
|
114
114
|
"license": "MIT",
|
|
115
115
|
"repository": {
|