@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.
Files changed (2) hide show
  1. package/dist/index.js +47 -158
  2. 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
- rawText = fs6.existsSync(configPath) ? fs6.readFileSync(configPath, "utf8") : "";
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(formatConfigKeyReport(reportConfigKeys(rawText)));
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
- rawText = fs7.existsSync(configPath) ? fs7.readFileSync(configPath, "utf8") : "";
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(formatConfigKeyReport(reportConfigKeys(rawText)));
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.8",
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/server": "^9.69.8",
30
- "@remnic/plugin-pi": "^9.69.8",
31
- "@remnic/core": "^9.69.8"
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.8",
35
- "@remnic/plugin-openclaw": "^9.69.8",
36
- "@remnic/export-weclone": "^9.69.8",
37
- "@remnic/import-weclone": "^9.69.8",
38
- "@remnic/import-chatgpt": "^9.69.8",
39
- "@remnic/import-claude": "^9.69.8",
40
- "@remnic/import-gemini": "^9.69.8",
41
- "@remnic/import-lossless-claw": "^9.69.8",
42
- "@remnic/import-mem0": "^9.69.8",
43
- "@remnic/import-supermemory": "^9.69.8",
44
- "@remnic/import-okf": "^9.69.8",
45
- "@remnic/connector-limitless": "^9.69.8",
46
- "@remnic/connector-bee": "^9.69.8",
47
- "@remnic/connector-omi": "^9.69.8",
48
- "@remnic/capture-audio": "^9.69.8"
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/plugin-openclaw": "9.69.8",
101
- "@remnic/bench": "9.69.8",
102
- "@remnic/import-weclone": "9.69.8",
103
- "@remnic/export-weclone": "9.69.8",
104
- "@remnic/import-gemini": "9.69.8",
105
- "@remnic/import-claude": "9.69.8",
106
- "@remnic/import-chatgpt": "9.69.8",
107
- "@remnic/import-lossless-claw": "9.69.8",
108
- "@remnic/import-mem0": "9.69.8",
109
- "@remnic/import-supermemory": "9.69.8",
110
- "@remnic/connector-limitless": "9.69.8",
111
- "@remnic/connector-bee": "9.69.8",
112
- "@remnic/connector-omi": "9.69.8"
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": {