@remnic/cli 9.63.0 → 9.63.2

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 +482 -291
  2. package/package.json +31 -31
package/dist/index.js CHANGED
@@ -18,10 +18,11 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
18
18
  }
19
19
 
20
20
  // src/index.ts
21
- import fs15 from "fs";
21
+ import fs16 from "fs";
22
22
  import os3 from "os";
23
23
  import path18 from "path";
24
24
  import { createHash as createHash4 } from "crypto";
25
+ import { writeFile as fsWriteFile } from "fs/promises";
25
26
  import * as childProcess2 from "child_process";
26
27
  import { fileURLToPath as fileURLToPath5 } from "url";
27
28
  import { gzipSync } from "zlib";
@@ -4594,8 +4595,243 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
4594
4595
  }
4595
4596
  }
4596
4597
 
4597
- // src/daemon-service.ts
4598
+ // src/remote-daemon.ts
4598
4599
  import fs12 from "fs";
4600
+ function readCompatEnv(primary, legacy) {
4601
+ return process.env[primary] ?? process.env[legacy];
4602
+ }
4603
+ function readRemnicConfigRecord(configPath) {
4604
+ try {
4605
+ const parsed = JSON.parse(fs12.readFileSync(configPath, "utf8"));
4606
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
4607
+ return parsed;
4608
+ }
4609
+ return void 0;
4610
+ } catch {
4611
+ return void 0;
4612
+ }
4613
+ }
4614
+ function normalizeRemoteDaemonUrl(raw, source) {
4615
+ let parsed;
4616
+ try {
4617
+ parsed = new URL(raw.trim());
4618
+ } catch {
4619
+ throw new Error(`Invalid ${source} "${raw}": expected an http:// or https:// URL.`);
4620
+ }
4621
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
4622
+ throw new Error(`Invalid ${source} "${raw}": scheme must be http:// or https://.`);
4623
+ }
4624
+ return `${parsed.origin}${parsed.pathname.replace(/\/+$/, "")}`;
4625
+ }
4626
+ function resolveRemoteDaemonUrl(configPath) {
4627
+ const envUrl = readCompatEnv("REMNIC_DAEMON_URL", "ENGRAM_DAEMON_URL");
4628
+ if (typeof envUrl === "string" && envUrl.trim().length > 0) {
4629
+ return normalizeRemoteDaemonUrl(envUrl, "REMNIC_DAEMON_URL/ENGRAM_DAEMON_URL");
4630
+ }
4631
+ const raw = readRemnicConfigRecord(configPath);
4632
+ if (raw && "server" in raw) {
4633
+ const server = raw.server;
4634
+ if (server && typeof server === "object") {
4635
+ const candidate = server.url;
4636
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
4637
+ return normalizeRemoteDaemonUrl(candidate, "server.url");
4638
+ }
4639
+ }
4640
+ }
4641
+ return void 0;
4642
+ }
4643
+ function resolveDaemonBaseUrl(configPath) {
4644
+ const remoteUrl = resolveRemoteDaemonUrl(configPath);
4645
+ if (remoteUrl) return remoteUrl;
4646
+ let port = 4318;
4647
+ let host = "127.0.0.1";
4648
+ const raw = readRemnicConfigRecord(configPath);
4649
+ if (raw && "server" in raw) {
4650
+ const server = raw.server;
4651
+ if (server && typeof server === "object") {
4652
+ const hostCandidate = server.host;
4653
+ if (typeof hostCandidate === "string" && hostCandidate.length > 0) {
4654
+ host = hostCandidate;
4655
+ }
4656
+ const portCandidate = server.port;
4657
+ if (typeof portCandidate === "number" && Number.isInteger(portCandidate)) {
4658
+ port = portCandidate;
4659
+ }
4660
+ }
4661
+ }
4662
+ const envHost = readCompatEnv("REMNIC_HOST", "ENGRAM_HOST");
4663
+ if (typeof envHost === "string" && envHost.length > 0) {
4664
+ host = envHost;
4665
+ }
4666
+ const envPortRaw = readCompatEnv("REMNIC_PORT", "ENGRAM_PORT");
4667
+ if (typeof envPortRaw === "string" && envPortRaw.length > 0) {
4668
+ const envPort = Number(envPortRaw);
4669
+ if (!Number.isInteger(envPort) || envPort < 1 || envPort > 65535) {
4670
+ throw new Error(
4671
+ `Invalid REMNIC_PORT/ENGRAM_PORT "${envPortRaw}": expected an integer in [1, 65535].`
4672
+ );
4673
+ }
4674
+ port = envPort;
4675
+ }
4676
+ return `http://${host}:${port}`;
4677
+ }
4678
+ function resolveOperatorToken(configPath) {
4679
+ const envToken = readCompatEnv("REMNIC_AUTH_TOKEN", "ENGRAM_AUTH_TOKEN");
4680
+ if (typeof envToken === "string" && envToken.length > 0) return envToken;
4681
+ const raw = readRemnicConfigRecord(configPath);
4682
+ if (raw && "server" in raw) {
4683
+ const server = raw.server;
4684
+ if (server && typeof server === "object" && "authToken" in server) {
4685
+ const candidate = server.authToken;
4686
+ if (typeof candidate === "string" && candidate.length > 0 && !candidate.includes("${")) {
4687
+ return candidate;
4688
+ }
4689
+ }
4690
+ }
4691
+ return void 0;
4692
+ }
4693
+ function resolveRemoteDaemon(configPath) {
4694
+ const baseUrl = resolveRemoteDaemonUrl(configPath);
4695
+ if (!baseUrl) return void 0;
4696
+ const token = resolveOperatorToken(configPath);
4697
+ return token ? { baseUrl, token } : { baseUrl };
4698
+ }
4699
+ function isTransportError(err) {
4700
+ 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"));
4701
+ }
4702
+ function unreachableError(baseUrl) {
4703
+ return new Error(
4704
+ `cannot reach remnic-server at ${baseUrl} \u2014 check REMNIC_DAEMON_URL / server.url and the remote server's availability.`
4705
+ );
4706
+ }
4707
+ async function daemonFetch(baseUrl, relativePath, token, timeoutMs, init) {
4708
+ const url = new URL(relativePath, `${baseUrl}/`);
4709
+ if (baseUrl.startsWith("https:") && url.protocol !== "https:") {
4710
+ throw new Error(
4711
+ `refusing to downgrade https daemon URL ${baseUrl} to ${url.protocol}// \u2014 fix REMNIC_DAEMON_URL / server.url.`
4712
+ );
4713
+ }
4714
+ const controller = new AbortController();
4715
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
4716
+ try {
4717
+ const headers = { accept: "application/json" };
4718
+ if (token) headers.authorization = `Bearer ${token}`;
4719
+ return await fetch(url, {
4720
+ ...init,
4721
+ headers: { ...headers, ...init?.headers },
4722
+ signal: controller.signal
4723
+ });
4724
+ } finally {
4725
+ clearTimeout(timeoutId);
4726
+ }
4727
+ }
4728
+ async function probeDaemonHealth(baseUrl, token, timeoutMs = 3e3) {
4729
+ try {
4730
+ const response = await daemonFetch(baseUrl, "engram/v1/health", token, timeoutMs);
4731
+ return response.ok ? { ok: true, status: response.status } : { ok: false, status: response.status };
4732
+ } catch (err) {
4733
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
4734
+ }
4735
+ }
4736
+ async function printHealthCheck(baseUrl, token, timeoutMs = 3e3) {
4737
+ try {
4738
+ const response = await daemonFetch(baseUrl, "engram/v1/health", token, timeoutMs);
4739
+ if (!response.ok) {
4740
+ const hint = response.status === 401 && !token ? " (daemon requires auth and no token was found \u2014 set REMNIC_AUTH_TOKEN or configure server.authToken)" : response.status === 401 ? " (token rejected by the daemon)" : "";
4741
+ console.log(`Health: server responded with ${response.status} ${response.statusText}${hint}`);
4742
+ return;
4743
+ }
4744
+ const health = await response.json();
4745
+ const status = typeof health.status === "string" ? health.status : "ok";
4746
+ console.log(`Health: ${status}`);
4747
+ const qmd = health.qmd;
4748
+ if (qmd?.pendingEmbeddings != null) {
4749
+ console.log(` Pending embeddings: ${qmd.pendingEmbeddings}`);
4750
+ if (qmd.oldestPendingAgeMs != null) {
4751
+ console.log(` Oldest pending: ${Math.round(qmd.oldestPendingAgeMs / 6e4)}m`);
4752
+ }
4753
+ if (qmd.embeddingBacklogThreshold != null) {
4754
+ console.log(` Backlog threshold: ${qmd.embeddingBacklogThreshold}`);
4755
+ }
4756
+ }
4757
+ if (qmd?.degradedReason) {
4758
+ console.log(` Degraded: ${qmd.degradedReason}`);
4759
+ }
4760
+ } catch {
4761
+ console.log("Health: unable to reach server");
4762
+ }
4763
+ }
4764
+ async function remoteRecall(daemon, request) {
4765
+ let response;
4766
+ try {
4767
+ response = await daemonFetch(daemon.baseUrl, "engram/v1/recall", daemon.token, 1e4, {
4768
+ method: "POST",
4769
+ headers: { "content-type": "application/json" },
4770
+ body: JSON.stringify(request)
4771
+ });
4772
+ } catch (err) {
4773
+ if (isTransportError(err)) throw unreachableError(daemon.baseUrl);
4774
+ throw err;
4775
+ }
4776
+ if (response.status === 401) {
4777
+ throw new Error(
4778
+ `token rejected by remnic-server at ${daemon.baseUrl} (HTTP 401). Update server.authToken or REMNIC_AUTH_TOKEN to match the remote daemon.`
4779
+ );
4780
+ }
4781
+ if (!response.ok) {
4782
+ throw new Error(`remnic-server returned HTTP ${response.status} ${response.statusText}`);
4783
+ }
4784
+ try {
4785
+ return await response.json();
4786
+ } catch {
4787
+ throw new Error("remnic-server returned a non-JSON response");
4788
+ }
4789
+ }
4790
+ async function remoteRecallXray(daemon, request) {
4791
+ const params = new URLSearchParams({ q: request.query });
4792
+ if (request.namespace && request.namespace.length > 0) {
4793
+ params.set("namespace", request.namespace);
4794
+ }
4795
+ if (request.budget !== void 0) {
4796
+ params.set("budget", String(request.budget));
4797
+ }
4798
+ let response;
4799
+ try {
4800
+ response = await daemonFetch(
4801
+ daemon.baseUrl,
4802
+ `engram/v1/recall/xray?${params.toString()}`,
4803
+ daemon.token,
4804
+ 1e4
4805
+ );
4806
+ } catch (err) {
4807
+ if (isTransportError(err)) throw unreachableError(daemon.baseUrl);
4808
+ throw err;
4809
+ }
4810
+ if (response.status === 401) {
4811
+ throw new Error(
4812
+ `token rejected by remnic-server at ${daemon.baseUrl} (HTTP 401). Update server.authToken or REMNIC_AUTH_TOKEN to match the remote daemon.`
4813
+ );
4814
+ }
4815
+ if (!response.ok) {
4816
+ throw new Error(`remnic-server returned HTTP ${response.status} ${response.statusText}`);
4817
+ }
4818
+ let payload;
4819
+ try {
4820
+ payload = await response.json();
4821
+ } catch {
4822
+ throw new Error("remnic-server returned a non-JSON response");
4823
+ }
4824
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
4825
+ const record2 = payload;
4826
+ if (record2.snapshotFound === true && record2.snapshot && typeof record2.snapshot === "object") {
4827
+ return { snapshotFound: true, snapshot: record2.snapshot };
4828
+ }
4829
+ }
4830
+ return { snapshotFound: false };
4831
+ }
4832
+
4833
+ // src/daemon-service.ts
4834
+ import fs13 from "fs";
4599
4835
  import path12 from "path";
4600
4836
  import * as childProcess from "child_process";
4601
4837
  import { fileURLToPath as fileURLToPath4 } from "url";
@@ -4607,7 +4843,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
4607
4843
  processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
4608
4844
  }
4609
4845
  function resolveServerBinDetails(options = {}) {
4610
- const existsSync4 = options.existsSync ?? fs12.existsSync;
4846
+ const existsSync4 = options.existsSync ?? fs13.existsSync;
4611
4847
  const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
4612
4848
  const moduleDir = options.moduleDir ?? thisModuleDir;
4613
4849
  const packageResolve = options.packageResolve ?? resolveImportSpecifier;
@@ -4666,8 +4902,8 @@ function resolveServerBin(options = {}) {
4666
4902
  return resolveServerBinDetails(options).path;
4667
4903
  }
4668
4904
  function readVerifiedDaemonPid(options) {
4669
- const readFileSync4 = options.readFileSync ?? fs12.readFileSync;
4670
- const unlinkSync = options.unlinkSync ?? fs12.unlinkSync;
4905
+ const readFileSync4 = options.readFileSync ?? fs13.readFileSync;
4906
+ const unlinkSync = options.unlinkSync ?? fs13.unlinkSync;
4671
4907
  const processKill = options.processKill ?? process.kill;
4672
4908
  const platform = options.platform ?? process.platform;
4673
4909
  const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
@@ -4767,8 +5003,8 @@ function removePidFileBestEffort(file, unlinkSync) {
4767
5003
  }
4768
5004
  }
4769
5005
  function inspectLaunchdPlist(plistPath, options = {}) {
4770
- const existsSync4 = options.existsSync ?? fs12.existsSync;
4771
- const readFileSync4 = options.readFileSync ?? fs12.readFileSync;
5006
+ const existsSync4 = options.existsSync ?? fs13.existsSync;
5007
+ const readFileSync4 = options.readFileSync ?? fs13.readFileSync;
4772
5008
  if (!existsSync4(plistPath)) {
4773
5009
  return {
4774
5010
  installed: false,
@@ -5002,7 +5238,7 @@ function stripConfigArgv(args) {
5002
5238
  }
5003
5239
 
5004
5240
  // src/import-dispatch.ts
5005
- import fs13 from "fs";
5241
+ import fs14 from "fs";
5006
5242
  import {
5007
5243
  runImporter,
5008
5244
  validateImportBatchSize,
@@ -5516,7 +5752,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
5516
5752
  let materializedTarget;
5517
5753
  let materializePromise;
5518
5754
  const io = {
5519
- readFile: ioOverrides.readFile ?? (async (p) => fs13.promises.readFile(p, "utf-8")),
5755
+ readFile: ioOverrides.readFile ?? (async (p) => fs14.promises.readFile(p, "utf-8")),
5520
5756
  loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
5521
5757
  runImporter: ioOverrides.runImporter ?? runImporter,
5522
5758
  getWriteTarget: async () => {
@@ -5629,7 +5865,7 @@ async function cmdCapture(rest, io) {
5629
5865
  }
5630
5866
 
5631
5867
  // src/import-lossless-claw-cmd.ts
5632
- import fs14 from "fs";
5868
+ import fs15 from "fs";
5633
5869
  import path14 from "path";
5634
5870
  import {
5635
5871
  applyLcmSchema,
@@ -5741,15 +5977,15 @@ async function loadImportLosslessClawModule() {
5741
5977
 
5742
5978
  // src/import-lossless-claw-cmd.ts
5743
5979
  function assertDirectoryOrAbsent(p, label) {
5744
- if (fs14.existsSync(p) && !fs14.statSync(p).isDirectory()) {
5980
+ if (fs15.existsSync(p) && !fs15.statSync(p).isDirectory()) {
5745
5981
  throw new Error(`${label} is not a directory: ${p}`);
5746
5982
  }
5747
5983
  }
5748
5984
  function assertFile(p, label) {
5749
- if (!fs14.existsSync(p)) {
5985
+ if (!fs15.existsSync(p)) {
5750
5986
  throw new Error(`${label} does not exist: ${p}`);
5751
5987
  }
5752
- if (!fs14.statSync(p).isFile()) {
5988
+ if (!fs15.statSync(p).isFile()) {
5753
5989
  throw new Error(`${label} is not a file: ${p}`);
5754
5990
  }
5755
5991
  }
@@ -5781,7 +6017,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
5781
6017
  try {
5782
6018
  if (parsed.dryRun) {
5783
6019
  const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
5784
- if (fs14.existsSync(lcmPath)) {
6020
+ if (fs15.existsSync(lcmPath)) {
5785
6021
  destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
5786
6022
  } else {
5787
6023
  destDb = mod.openInMemoryDestinationDatabase();
@@ -6959,9 +7195,6 @@ registerPublisher("claude-code", () => new ClaudeCodeMemoryExtensionPublisher())
6959
7195
  registerPublisher("hermes", () => new HermesMemoryExtensionPublisher());
6960
7196
  registerPublisher("pi", () => new LazyPluginPiPublisher("pi", (mod) => mod.PiMemoryExtensionPublisher));
6961
7197
  registerPublisher("omp", () => new LazyPluginPiPublisher("omp", (mod) => mod.OmpMemoryExtensionPublisher));
6962
- function readCompatEnv(primary, legacy) {
6963
- return process.env[primary] ?? process.env[legacy];
6964
- }
6965
7198
  var PID_DIR = path18.join(resolveHomeDir(), ".remnic");
6966
7199
  var LEGACY_PID_DIR = path18.join(resolveHomeDir(), ".engram");
6967
7200
  var PID_FILE = path18.join(PID_DIR, "server.pid");
@@ -7135,7 +7368,7 @@ async function resolveAllBenchmarks() {
7135
7368
  if (packageBenchmarks) {
7136
7369
  return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
7137
7370
  }
7138
- if (!fs15.existsSync(EVAL_RUNNER_PATH)) {
7371
+ if (!fs16.existsSync(EVAL_RUNNER_PATH)) {
7139
7372
  return [];
7140
7373
  }
7141
7374
  return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
@@ -7183,7 +7416,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7183
7416
  `Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
7184
7417
  );
7185
7418
  }
7186
- if (!fs15.existsSync(EVAL_RUNNER_PATH)) {
7419
+ if (!fs16.existsSync(EVAL_RUNNER_PATH)) {
7187
7420
  console.error(
7188
7421
  "Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
7189
7422
  );
@@ -7193,7 +7426,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
7193
7426
  path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
7194
7427
  path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
7195
7428
  ];
7196
- const tsxCmd = tsxCandidates.find((candidate) => fs15.existsSync(candidate)) ?? "tsx";
7429
+ const tsxCmd = tsxCandidates.find((candidate) => fs16.existsSync(candidate)) ?? "tsx";
7197
7430
  const fallbackOutputDir = createFallbackBenchOutputDir(
7198
7431
  parsed.resultsDir ?? resolveBenchOutputDir(),
7199
7432
  benchmarkId,
@@ -7338,9 +7571,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
7338
7571
  );
7339
7572
  function resolveRealpathWithinDataset(datasetPath, relativePath) {
7340
7573
  try {
7341
- const datasetRoot = fs15.realpathSync(datasetPath);
7574
+ const datasetRoot = fs16.realpathSync(datasetPath);
7342
7575
  const candidatePath = path18.resolve(datasetRoot, relativePath);
7343
- const candidateRealPath = fs15.realpathSync(candidatePath);
7576
+ const candidateRealPath = fs16.realpathSync(candidatePath);
7344
7577
  const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
7345
7578
  if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
7346
7579
  return null;
@@ -7399,14 +7632,14 @@ function parseCsvRows(raw) {
7399
7632
  function isPersonaMemDatasetComplete(datasetPath) {
7400
7633
  try {
7401
7634
  const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
7402
- if (fs15.statSync(completionMarkerPath).isFile()) {
7635
+ if (fs16.statSync(completionMarkerPath).isFile()) {
7403
7636
  return true;
7404
7637
  }
7405
7638
  } catch {
7406
7639
  }
7407
7640
  const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
7408
7641
  try {
7409
- return fs15.statSync(path18.join(datasetPath, candidate)).isFile();
7642
+ return fs16.statSync(path18.join(datasetPath, candidate)).isFile();
7410
7643
  } catch {
7411
7644
  return false;
7412
7645
  }
@@ -7415,7 +7648,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7415
7648
  return false;
7416
7649
  }
7417
7650
  try {
7418
- const rows = parseCsvRows(fs15.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7651
+ const rows = parseCsvRows(fs16.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
7419
7652
  if (rows.length < 2) {
7420
7653
  return false;
7421
7654
  }
@@ -7430,7 +7663,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7430
7663
  }
7431
7664
  return historyPaths.every((relativePath) => {
7432
7665
  const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
7433
- return resolvedPath !== null && fs15.statSync(resolvedPath).isFile();
7666
+ return resolvedPath !== null && fs16.statSync(resolvedPath).isFile();
7434
7667
  });
7435
7668
  } catch {
7436
7669
  return false;
@@ -7438,7 +7671,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
7438
7671
  }
7439
7672
  function hasDatasetFile(datasetPath, relativePath) {
7440
7673
  try {
7441
- return fs15.statSync(path18.join(datasetPath, relativePath)).isFile();
7674
+ return fs16.statSync(path18.join(datasetPath, relativePath)).isFile();
7442
7675
  } catch {
7443
7676
  return false;
7444
7677
  }
@@ -7458,10 +7691,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
7458
7691
  return candidateFilenames.some((filename) => {
7459
7692
  const filePath = path18.join(datasetPath, filename);
7460
7693
  try {
7461
- if (!fs15.statSync(filePath).isFile()) {
7694
+ if (!fs16.statSync(filePath).isFile()) {
7462
7695
  return false;
7463
7696
  }
7464
- const raw = fs15.readFileSync(filePath, "utf8");
7697
+ const raw = fs16.readFileSync(filePath, "utf8");
7465
7698
  return /"source"\s*:\s*"recsys[_-]/i.test(raw);
7466
7699
  } catch {
7467
7700
  return false;
@@ -7477,7 +7710,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
7477
7710
  function isDatasetDownloaded(datasetPath, benchmarkId) {
7478
7711
  let stats;
7479
7712
  try {
7480
- stats = fs15.statSync(datasetPath);
7713
+ stats = fs16.statSync(datasetPath);
7481
7714
  } catch {
7482
7715
  return false;
7483
7716
  }
@@ -7487,7 +7720,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7487
7720
  const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
7488
7721
  if (!marker) {
7489
7722
  try {
7490
- return fs15.readdirSync(datasetPath).length > 0;
7723
+ return fs16.readdirSync(datasetPath).length > 0;
7491
7724
  } catch {
7492
7725
  return false;
7493
7726
  }
@@ -7495,7 +7728,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7495
7728
  if (marker.allOf) {
7496
7729
  const hasAllRequiredFiles = marker.allOf.every((name) => {
7497
7730
  try {
7498
- return fs15.statSync(path18.join(datasetPath, name)).isFile();
7731
+ return fs16.statSync(path18.join(datasetPath, name)).isFile();
7499
7732
  } catch {
7500
7733
  return false;
7501
7734
  }
@@ -7507,7 +7740,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7507
7740
  if (marker.anyOf) {
7508
7741
  const hasMarkerFile = marker.anyOf.some((name) => {
7509
7742
  try {
7510
- return fs15.statSync(path18.join(datasetPath, name)).isFile();
7743
+ return fs16.statSync(path18.join(datasetPath, name)).isFile();
7511
7744
  } catch {
7512
7745
  return false;
7513
7746
  }
@@ -7525,7 +7758,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7525
7758
  }
7526
7759
  if (marker.ext) {
7527
7760
  try {
7528
- return fs15.readdirSync(datasetPath).some(
7761
+ return fs16.readdirSync(datasetPath).some(
7529
7762
  (name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
7530
7763
  );
7531
7764
  } catch {
@@ -7537,7 +7770,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
7537
7770
  async function launchBenchUi(resultsDir) {
7538
7771
  const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
7539
7772
  const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
7540
- if (!fs15.existsSync(path18.join(benchUiDir, "package.json"))) {
7773
+ if (!fs16.existsSync(path18.join(benchUiDir, "package.json"))) {
7541
7774
  console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
7542
7775
  process.exit(1);
7543
7776
  }
@@ -7575,13 +7808,13 @@ function listDownloadableBenchmarks() {
7575
7808
  }
7576
7809
  function resolveDatasetDownloadScriptPath() {
7577
7810
  const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
7578
- if (fs15.existsSync(bundled)) {
7811
+ if (fs16.existsSync(bundled)) {
7579
7812
  return bundled;
7580
7813
  }
7581
7814
  return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
7582
7815
  }
7583
7816
  function isRepoCheckout() {
7584
- return fs15.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs15.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
7817
+ return fs16.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs16.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
7585
7818
  }
7586
7819
  function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
7587
7820
  const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
@@ -7894,8 +8127,8 @@ async function exportBenchPackageResult(parsed) {
7894
8127
  ...reportCardProvenance ? { reportCardProvenance } : {}
7895
8128
  });
7896
8129
  if (parsed.output) {
7897
- fs15.mkdirSync(path18.dirname(parsed.output), { recursive: true });
7898
- fs15.writeFileSync(parsed.output, rendered);
8130
+ fs16.mkdirSync(path18.dirname(parsed.output), { recursive: true });
8131
+ fs16.writeFileSync(parsed.output, rendered);
7899
8132
  console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
7900
8133
  return;
7901
8134
  }
@@ -7940,7 +8173,7 @@ async function manageBenchDatasets(parsed) {
7940
8173
  process.exit(1);
7941
8174
  }
7942
8175
  const scriptPath = resolveDatasetDownloadScriptPath();
7943
- if (!fs15.existsSync(scriptPath)) {
8176
+ if (!fs16.existsSync(scriptPath)) {
7944
8177
  console.error(`ERROR: dataset download script not found: ${scriptPath}`);
7945
8178
  process.exit(1);
7946
8179
  }
@@ -8140,7 +8373,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
8140
8373
  );
8141
8374
  process.exit(1);
8142
8375
  }
8143
- const sourceResultSha256 = createHash4("sha256").update(fs15.readFileSync(latest.path)).digest("hex");
8376
+ const sourceResultSha256 = createHash4("sha256").update(fs16.readFileSync(latest.path)).digest("hex");
8144
8377
  const expandedManifestPath = expandTilde(manifestPath);
8145
8378
  if (!bench.resolveLocalLabJudgeProviderConfig) {
8146
8379
  console.error(
@@ -8555,7 +8788,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
8555
8788
  }
8556
8789
  let decoded;
8557
8790
  try {
8558
- decoded = JSON.parse(fs15.readFileSync(parsed.taskIdsFile, "utf8"));
8791
+ decoded = JSON.parse(fs16.readFileSync(parsed.taskIdsFile, "utf8"));
8559
8792
  } catch (error) {
8560
8793
  throw new Error(
8561
8794
  `Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
@@ -9230,7 +9463,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
9230
9463
  return void 0;
9231
9464
  }
9232
9465
  try {
9233
- return fs15.realpathSync(datasetDir);
9466
+ return fs16.realpathSync(datasetDir);
9234
9467
  } catch {
9235
9468
  return datasetDir;
9236
9469
  }
@@ -9284,7 +9517,7 @@ async function writeBenchReproManifestForPackageRun(args) {
9284
9517
  }
9285
9518
  function loadStandaloneConvergeCommandConfig() {
9286
9519
  const configPath = resolveConfigPath();
9287
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
9520
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
9288
9521
  return parseConfig7(resolveRemnicConfigRecord6(raw));
9289
9522
  }
9290
9523
  function parseConvergePluginConfig(value) {
@@ -9313,13 +9546,13 @@ function resolveConfigPath(cliPath) {
9313
9546
  path18.join(resolveHomeDir(), ".config", "engram", "config.json")
9314
9547
  ];
9315
9548
  for (const candidate of candidates) {
9316
- if (fs15.existsSync(candidate)) return candidate;
9549
+ if (fs16.existsSync(candidate)) return candidate;
9317
9550
  }
9318
9551
  return path18.join(resolveHomeDir(), ".config", "remnic", "config.json");
9319
9552
  }
9320
9553
  function resolveExistingBenchRemnicConfigPath(cliPath) {
9321
9554
  const configPath = resolveConfigPath(cliPath);
9322
- if (fs15.existsSync(configPath)) {
9555
+ if (fs16.existsSync(configPath)) {
9323
9556
  return configPath;
9324
9557
  }
9325
9558
  if (cliPath) {
@@ -9329,7 +9562,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
9329
9562
  }
9330
9563
  function resolveExistingBenchOpenclawConfigPath(cliPath) {
9331
9564
  const configPath = resolveOpenclawConfigPath(cliPath);
9332
- if (fs15.existsSync(configPath)) {
9565
+ if (fs16.existsSync(configPath)) {
9333
9566
  return configPath;
9334
9567
  }
9335
9568
  if (cliPath) {
@@ -9436,7 +9669,7 @@ function resolveMemoryDir() {
9436
9669
  const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
9437
9670
  if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
9438
9671
  const configPath = resolveConfigPath();
9439
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
9672
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
9440
9673
  const remnicCfg = resolveRemnicConfigRecord6(raw);
9441
9674
  if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
9442
9675
  return normalizeMemoryDirPath(remnicCfg.memoryDir);
@@ -9445,18 +9678,18 @@ function resolveMemoryDir() {
9445
9678
  const standalonePath = path18.join(home, ".remnic", "memory");
9446
9679
  const legacyStandalonePath = path18.join(home, ".engram", "memory");
9447
9680
  const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
9448
- if (fs15.existsSync(standalonePath)) return standalonePath;
9449
- if (fs15.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9681
+ if (fs16.existsSync(standalonePath)) return standalonePath;
9682
+ if (fs16.existsSync(legacyStandalonePath)) return legacyStandalonePath;
9450
9683
  return openclawPath;
9451
9684
  })();
9452
9685
  const manifestPath = getManifestPath();
9453
- if (fs15.existsSync(manifestPath)) {
9686
+ if (fs16.existsSync(manifestPath)) {
9454
9687
  try {
9455
9688
  const active = getActiveSpace();
9456
9689
  if (active?.memoryDir) {
9457
9690
  const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
9458
- if (!fs15.existsSync(activeMemoryDir)) {
9459
- fs15.mkdirSync(activeMemoryDir, { recursive: true });
9691
+ if (!fs16.existsSync(activeMemoryDir)) {
9692
+ fs16.mkdirSync(activeMemoryDir, { recursive: true });
9460
9693
  }
9461
9694
  return activeMemoryDir;
9462
9695
  }
@@ -9505,13 +9738,13 @@ function resolveOpenclawConfigPath(cliPath) {
9505
9738
  const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
9506
9739
  if (envPath) return path18.resolve(expandTilde(envPath));
9507
9740
  for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
9508
- if (fs15.existsSync(candidate)) return candidate;
9741
+ if (fs16.existsSync(candidate)) return candidate;
9509
9742
  }
9510
9743
  return path18.join(resolveOpenclawStateDir(), "openclaw.json");
9511
9744
  }
9512
9745
  function readOpenclawConfig(configPath) {
9513
- if (!fs15.existsSync(configPath)) return {};
9514
- const raw = fs15.readFileSync(configPath, "utf-8");
9746
+ if (!fs16.existsSync(configPath)) return {};
9747
+ const raw = fs16.readFileSync(configPath, "utf-8");
9515
9748
  let parsed;
9516
9749
  try {
9517
9750
  parsed = JSON.parse(raw);
@@ -9613,9 +9846,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
9613
9846
  return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
9614
9847
  }
9615
9848
  function backupPathIfPresent(sourcePath, backupPath) {
9616
- if (!fs15.existsSync(sourcePath)) return false;
9617
- fs15.mkdirSync(path18.dirname(backupPath), { recursive: true });
9618
- fs15.cpSync(sourcePath, backupPath, { recursive: true });
9849
+ if (!fs16.existsSync(sourcePath)) return false;
9850
+ fs16.mkdirSync(path18.dirname(backupPath), { recursive: true });
9851
+ fs16.cpSync(sourcePath, backupPath, { recursive: true });
9619
9852
  return true;
9620
9853
  }
9621
9854
  function restartOpenclawGateway() {
@@ -9634,7 +9867,7 @@ function restartOpenclawGateway() {
9634
9867
  }
9635
9868
  function cmdInit() {
9636
9869
  const configPath = path18.join(process.cwd(), "remnic.config.json");
9637
- if (fs15.existsSync(configPath)) {
9870
+ if (fs16.existsSync(configPath)) {
9638
9871
  console.log(`Config already exists: ${configPath}`);
9639
9872
  return;
9640
9873
  }
@@ -9650,7 +9883,7 @@ function cmdInit() {
9650
9883
  authToken: "${REMNIC_AUTH_TOKEN}"
9651
9884
  }
9652
9885
  };
9653
- fs15.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
9886
+ fs16.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
9654
9887
  console.log(`Created ${configPath}`);
9655
9888
  console.log("\nSet these environment variables:");
9656
9889
  console.log(" export OPENAI_API_KEY=sk-...");
@@ -9660,7 +9893,7 @@ function cmdInit() {
9660
9893
  console.log(" npx --package @remnic/server remnic-server");
9661
9894
  }
9662
9895
  function resolveStatusProbeToken() {
9663
- const operatorToken = oauthResolveOperatorToken();
9896
+ const operatorToken = resolveOperatorToken(resolveConfigPath());
9664
9897
  if (operatorToken) return operatorToken;
9665
9898
  try {
9666
9899
  const usable = listTokens().find(
@@ -9672,6 +9905,25 @@ function resolveStatusProbeToken() {
9672
9905
  }
9673
9906
  var __statusHealthTestHooks = { resolveStatusProbeToken };
9674
9907
  async function cmdStatus(json) {
9908
+ const remote = resolveRemoteDaemon(resolveConfigPath());
9909
+ if (remote) {
9910
+ if (json) {
9911
+ const probe = await probeDaemonHealth(remote.baseUrl, remote.token);
9912
+ console.log(
9913
+ JSON.stringify({
9914
+ running: probe.ok,
9915
+ pid: null,
9916
+ pidFile: null,
9917
+ logFile: null,
9918
+ remote: remote.baseUrl
9919
+ })
9920
+ );
9921
+ return;
9922
+ }
9923
+ console.log(`Remnic server: remote (${remote.baseUrl})`);
9924
+ await printHealthCheck(remote.baseUrl, remote.token);
9925
+ return;
9926
+ }
9675
9927
  const { running, pid } = isServiceRunning();
9676
9928
  if (json) {
9677
9929
  console.log(JSON.stringify({ running, pid: pid ?? null, pidFile: PID_FILE, logFile: LOG_FILE }));
@@ -9682,101 +9934,7 @@ async function cmdStatus(json) {
9682
9934
  return;
9683
9935
  }
9684
9936
  console.log(`Remnic server: running${pid ? ` (pid ${pid})` : ""}`);
9685
- const port = inferPort();
9686
- const probeToken = resolveStatusProbeToken();
9687
- const controller = new AbortController();
9688
- const timeoutId = setTimeout(() => controller.abort(), 3e3);
9689
- try {
9690
- const response = await fetch(`http://127.0.0.1:${port}/engram/v1/health`, {
9691
- signal: controller.signal,
9692
- ...probeToken ? { headers: { Authorization: `Bearer ${probeToken}` } } : {}
9693
- });
9694
- if (!response.ok) {
9695
- const hint = response.status === 401 && !probeToken ? " (daemon requires auth and no local token was found \u2014 set REMNIC_AUTH_TOKEN, configure server.authToken, or run 'remnic token generate')" : response.status === 401 ? " (local token rejected by the daemon)" : "";
9696
- console.log(`Health: server responded with ${response.status} ${response.statusText}${hint}`);
9697
- } else {
9698
- const health = await response.json();
9699
- const status = typeof health.status === "string" ? health.status : "ok";
9700
- console.log(`Health: ${status}`);
9701
- const qmd = health.qmd;
9702
- if (qmd?.pendingEmbeddings != null) {
9703
- console.log(` Pending embeddings: ${qmd.pendingEmbeddings}`);
9704
- if (qmd.oldestPendingAgeMs != null) {
9705
- console.log(` Oldest pending: ${Math.round(qmd.oldestPendingAgeMs / 6e4)}m`);
9706
- }
9707
- if (qmd.embeddingBacklogThreshold != null) {
9708
- console.log(` Backlog threshold: ${qmd.embeddingBacklogThreshold}`);
9709
- }
9710
- }
9711
- if (qmd?.degradedReason) {
9712
- console.log(` Degraded: ${qmd.degradedReason}`);
9713
- }
9714
- }
9715
- } catch {
9716
- console.log("Health: unable to reach server");
9717
- } finally {
9718
- clearTimeout(timeoutId);
9719
- }
9720
- }
9721
- function oauthReadConfigRecord(configPath) {
9722
- try {
9723
- const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
9724
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
9725
- return parsed;
9726
- }
9727
- return void 0;
9728
- } catch {
9729
- return void 0;
9730
- }
9731
- }
9732
- function oauthResolveBaseUrl() {
9733
- const configPath = resolveConfigPath();
9734
- let port = 4318;
9735
- let host = "127.0.0.1";
9736
- const raw = oauthReadConfigRecord(configPath);
9737
- if (raw && "server" in raw) {
9738
- const server = raw.server;
9739
- if (server && typeof server === "object") {
9740
- const hostCandidate = server.host;
9741
- if (typeof hostCandidate === "string" && hostCandidate.length > 0) {
9742
- host = hostCandidate;
9743
- }
9744
- const portCandidate = server.port;
9745
- if (typeof portCandidate === "number" && Number.isInteger(portCandidate)) {
9746
- port = portCandidate;
9747
- }
9748
- }
9749
- }
9750
- const envHost = readCompatEnv("REMNIC_HOST", "ENGRAM_HOST");
9751
- if (typeof envHost === "string" && envHost.length > 0) {
9752
- host = envHost;
9753
- }
9754
- const envPortRaw = readCompatEnv("REMNIC_PORT", "ENGRAM_PORT");
9755
- if (typeof envPortRaw === "string" && envPortRaw.length > 0) {
9756
- const envPort = Number(envPortRaw);
9757
- if (!Number.isInteger(envPort) || envPort < 1 || envPort > 65535) {
9758
- throw new Error(
9759
- `Invalid REMNIC_PORT/ENGRAM_PORT "${envPortRaw}": expected an integer in [1, 65535].`
9760
- );
9761
- }
9762
- port = envPort;
9763
- }
9764
- return `http://${host}:${port}`;
9765
- }
9766
- function oauthResolveOperatorToken() {
9767
- const envToken = readCompatEnv("REMNIC_AUTH_TOKEN", "ENGRAM_AUTH_TOKEN");
9768
- if (typeof envToken === "string" && envToken.length > 0) return envToken;
9769
- const raw = oauthReadConfigRecord(resolveConfigPath());
9770
- if (raw && "server" in raw) {
9771
- const server = raw.server;
9772
- if (server && typeof server === "object" && "authToken" in server) {
9773
- const candidate = server.authToken;
9774
- if (typeof candidate === "string" && candidate.length > 0 && !candidate.includes("${")) {
9775
- return candidate;
9776
- }
9777
- }
9778
- }
9779
- return void 0;
9937
+ await printHealthCheck(resolveDaemonBaseUrl(resolveConfigPath()), resolveStatusProbeToken());
9780
9938
  }
9781
9939
  async function oauthFetch(method, path19, token, body) {
9782
9940
  const controller = new AbortController();
@@ -9797,7 +9955,7 @@ async function oauthFetch(method, path19, token, body) {
9797
9955
  if (body !== void 0) {
9798
9956
  init.body = JSON.stringify(body);
9799
9957
  }
9800
- const response = await fetch(`${oauthResolveBaseUrl()}${path19}`, init);
9958
+ const response = await fetch(`${resolveDaemonBaseUrl(resolveConfigPath())}${path19}`, init);
9801
9959
  if (response.status === 401) {
9802
9960
  throw new Error(
9803
9961
  "operator token rejected by remnic-server (HTTP 401). Update `server.authToken` or `REMNIC_AUTH_TOKEN` to match the running daemon."
@@ -9835,7 +9993,7 @@ async function oauthFetch(method, path19, token, body) {
9835
9993
  const msg = err.message;
9836
9994
  if (msg.includes("ECONNREFUSED") || msg.includes("ECONNRESET") || msg.includes("fetch failed") || msg.includes("aborted") || msg.includes("ENOTFOUND")) {
9837
9995
  throw new Error(
9838
- `cannot reach remnic-server at ${oauthResolveBaseUrl()} \u2014 is remnic-server running? Start it with \`remnic daemon start\`.`
9996
+ `cannot reach remnic-server at ${resolveDaemonBaseUrl(resolveConfigPath())} \u2014 is remnic-server running? Start it with \`remnic daemon start\` (or point REMNIC_DAEMON_URL at a remote daemon).`
9839
9997
  );
9840
9998
  }
9841
9999
  throw err;
@@ -9914,7 +10072,7 @@ Server endpoints (operator bearer auth):
9914
10072
  POST /oauth/pending/<ref>/approve
9915
10073
  POST /oauth/pending/<ref>/deny`;
9916
10074
  function oauthRequireOperatorToken() {
9917
- const token = oauthResolveOperatorToken();
10075
+ const token = resolveOperatorToken(resolveConfigPath());
9918
10076
  if (!token) {
9919
10077
  console.error(
9920
10078
  "remnic oauth: no operator token configured. Set `server.authToken` in remnic.config.json or export REMNIC_AUTH_TOKEN."
@@ -10134,9 +10292,20 @@ async function cmdQuery(queryText, json, explain) {
10134
10292
  console.error("Usage: remnic query <text>");
10135
10293
  process.exit(1);
10136
10294
  }
10295
+ const remote = resolveRemoteDaemon(resolveConfigPath());
10296
+ if (remote) {
10297
+ const started = Date.now();
10298
+ const result = await remoteRecall(remote, buildQueryRecallRequest(queryText));
10299
+ if (explain) {
10300
+ printMinimalQueryExplain(queryText, result, Date.now() - started, json);
10301
+ return;
10302
+ }
10303
+ printQueryResult(result, json);
10304
+ return;
10305
+ }
10137
10306
  initLogger3();
10138
10307
  const configPath = resolveConfigPath();
10139
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10308
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10140
10309
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10141
10310
  const config = parseConfig7(remnicCfg);
10142
10311
  const orchestrator = new Orchestrator4(config);
@@ -10147,14 +10316,14 @@ async function cmdQuery(queryText, json, explain) {
10147
10316
  if (explain) {
10148
10317
  const bench = await tryLoadBenchModule();
10149
10318
  if (bench?.runExplain) {
10150
- const result2 = await bench.runExplain(service, queryText);
10319
+ const result = await bench.runExplain(service, queryText);
10151
10320
  if (json) {
10152
- console.log(JSON.stringify(result2, null, 2));
10321
+ console.log(JSON.stringify(result, null, 2));
10153
10322
  } else {
10154
- console.log(`Query: ${result2.query}`);
10155
- console.log(`Tiers used: ${result2.tiersUsed.join(" \u2192 ")}`);
10156
- console.log(`Total duration: ${result2.totalDurationMs}ms`);
10157
- for (const t of result2.tierResults) {
10323
+ console.log(`Query: ${result.query}`);
10324
+ console.log(`Tiers used: ${result.tiersUsed.join(" \u2192 ")}`);
10325
+ console.log(`Total duration: ${result.totalDurationMs}ms`);
10326
+ for (const t of result.tierResults) {
10158
10327
  console.log(` ${t.tier}: ${t.latencyMs}ms (${t.resultsCount} results)`);
10159
10328
  }
10160
10329
  }
@@ -10162,42 +10331,46 @@ async function cmdQuery(queryText, json, explain) {
10162
10331
  }
10163
10332
  const explainStart = Date.now();
10164
10333
  const recallResult = await service.recall(recallRequest);
10165
- const totalDurationMs = Date.now() - explainStart;
10166
- const resultsCount = typeof recallResult.count === "number" ? recallResult.count : Array.isArray(recallResult.results) ? recallResult.results.length : 0;
10167
- const minimalExplain = {
10168
- query: queryText,
10169
- totalDurationMs,
10170
- resultsCount,
10171
- results: summarizeQueryExplainFallbackResults(recallResult),
10172
- note: "Install @remnic/bench for a full tier-level explain breakdown."
10173
- };
10174
- if (json) {
10175
- console.log(JSON.stringify(minimalExplain, null, 2));
10176
- } else {
10177
- console.log(`Query: ${minimalExplain.query}`);
10178
- console.log(`Total duration: ${minimalExplain.totalDurationMs}ms`);
10179
- console.log(`Results: ${minimalExplain.resultsCount}`);
10180
- for (const result2 of minimalExplain.results) {
10181
- const suffix = result2.source ? ` (${result2.source})` : "";
10182
- console.log(` ${result2.index}. ${result2.text}${suffix}`);
10183
- }
10184
- console.log(`Note: ${minimalExplain.note}`);
10185
- }
10334
+ printMinimalQueryExplain(queryText, recallResult, Date.now() - explainStart, json);
10186
10335
  return;
10187
10336
  }
10188
- const result = await service.recall(recallRequest);
10189
- if (json) {
10190
- console.log(JSON.stringify(result, null, 2));
10191
- } else {
10192
- for (const line of renderQueryTextLines(result)) {
10193
- console.log(line);
10194
- }
10195
- }
10337
+ printQueryResult(await service.recall(recallRequest), json);
10196
10338
  } finally {
10197
10339
  orchestrator.abortDeferredInit();
10198
10340
  await orchestrator.destroy();
10199
10341
  }
10200
10342
  }
10343
+ function printQueryResult(result, json) {
10344
+ if (json) {
10345
+ console.log(JSON.stringify(result, null, 2));
10346
+ return;
10347
+ }
10348
+ for (const line of renderQueryTextLines(result)) {
10349
+ console.log(line);
10350
+ }
10351
+ }
10352
+ function printMinimalQueryExplain(queryText, result, totalDurationMs, json) {
10353
+ const resultsCount = typeof result.count === "number" ? result.count : Array.isArray(result.results) ? result.results.length : 0;
10354
+ const minimalExplain = {
10355
+ query: queryText,
10356
+ totalDurationMs,
10357
+ resultsCount,
10358
+ results: summarizeQueryExplainFallbackResults(result),
10359
+ note: "Install @remnic/bench for a full tier-level explain breakdown."
10360
+ };
10361
+ if (json) {
10362
+ console.log(JSON.stringify(minimalExplain, null, 2));
10363
+ return;
10364
+ }
10365
+ console.log(`Query: ${minimalExplain.query}`);
10366
+ console.log(`Total duration: ${minimalExplain.totalDurationMs}ms`);
10367
+ console.log(`Results: ${minimalExplain.resultsCount}`);
10368
+ for (const resultLine of minimalExplain.results) {
10369
+ const suffix = resultLine.source ? ` (${resultLine.source})` : "";
10370
+ console.log(` ${resultLine.index}. ${resultLine.text}${suffix}`);
10371
+ }
10372
+ console.log(`Note: ${minimalExplain.note}`);
10373
+ }
10201
10374
  function parseActionConfidenceRest(rest) {
10202
10375
  const valueFlags = /* @__PURE__ */ new Set([
10203
10376
  "--action",
@@ -10305,9 +10478,14 @@ async function runXrayCommand(rest, io) {
10305
10478
  async function cmdXray(rest) {
10306
10479
  const { rawQuery, options } = extractXrayRawArgs(rest);
10307
10480
  parseXrayCliOptions(rawQuery, options);
10481
+ const remote = resolveRemoteDaemon(resolveConfigPath());
10482
+ if (remote) {
10483
+ await runXrayCommand(rest, xrayCliIo((request) => remoteRecallXray(remote, request)));
10484
+ return;
10485
+ }
10308
10486
  initLogger3();
10309
10487
  const configPath = resolveConfigPath();
10310
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10488
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10311
10489
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10312
10490
  const config = parseConfig7(remnicCfg);
10313
10491
  const orchestrator = new Orchestrator4(config);
@@ -10315,22 +10493,22 @@ async function cmdXray(rest) {
10315
10493
  await orchestrator.deferredReady;
10316
10494
  const service = new EngramAccessService2(orchestrator);
10317
10495
  try {
10318
- await runXrayCommand(rest, {
10319
- recallXray: (request) => service.recallXray(request),
10320
- writeFile: async (filePath, data) => {
10321
- const { writeFile: fsWriteFile } = await import("fs/promises");
10322
- await fsWriteFile(filePath, data, "utf8");
10323
- },
10324
- stdout: (line) => console.log(line)
10325
- });
10496
+ await runXrayCommand(rest, xrayCliIo((request) => service.recallXray(request)));
10326
10497
  } finally {
10327
10498
  orchestrator.abortDeferredInit();
10328
10499
  }
10329
10500
  }
10501
+ function xrayCliIo(recallXray) {
10502
+ return {
10503
+ recallXray,
10504
+ writeFile: (filePath, data) => fsWriteFile(filePath, data, "utf8"),
10505
+ stdout: (line) => console.log(line)
10506
+ };
10507
+ }
10330
10508
  async function cmdVersions(rest) {
10331
10509
  initLogger3();
10332
10510
  const configPath = resolveConfigPath();
10333
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10511
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10334
10512
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10335
10513
  const config = parseConfig7(remnicCfg);
10336
10514
  if (!config.versioningEnabled) {
@@ -10446,7 +10624,7 @@ Options:
10446
10624
  async function cmdEnrich(rest) {
10447
10625
  initLogger3();
10448
10626
  const configPath = resolveConfigPath();
10449
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10627
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10450
10628
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10451
10629
  const config = parseConfig7(remnicCfg);
10452
10630
  const subcommand = rest[0];
@@ -10691,7 +10869,7 @@ Shared with:
10691
10869
  process.exit(1);
10692
10870
  }
10693
10871
  const configPath = resolveConfigPath();
10694
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10872
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10695
10873
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10696
10874
  const config = parseConfig7(remnicCfg);
10697
10875
  const memoryDir = expandTilde(
@@ -10708,7 +10886,7 @@ Shared with:
10708
10886
  async function cmdExtensions(action, rest) {
10709
10887
  initLogger3();
10710
10888
  const configPath = resolveConfigPath();
10711
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10889
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10712
10890
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10713
10891
  const config = parseConfig7(remnicCfg);
10714
10892
  const root = resolveExtensionsRoot(config);
@@ -10759,7 +10937,7 @@ Root: ${root}`);
10759
10937
  const extensions = await discoverMemoryExtensions(root, warnLog);
10760
10938
  let entries = [];
10761
10939
  try {
10762
- entries = fs15.readdirSync(root);
10940
+ entries = fs16.readdirSync(root);
10763
10941
  } catch {
10764
10942
  console.log(`Extensions root does not exist: ${root}`);
10765
10943
  process.exitCode = 0;
@@ -10770,7 +10948,7 @@ Root: ${root}`);
10770
10948
  for (const entry of entries) {
10771
10949
  const entryPath = path18.join(root, entry);
10772
10950
  try {
10773
- if (!fs15.statSync(entryPath).isDirectory()) continue;
10951
+ if (!fs16.statSync(entryPath).isDirectory()) continue;
10774
10952
  } catch {
10775
10953
  continue;
10776
10954
  }
@@ -10802,7 +10980,7 @@ Root: ${root}`);
10802
10980
  async function cmdBriefing(rest) {
10803
10981
  initLogger3();
10804
10982
  const configPath = resolveConfigPath();
10805
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
10983
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
10806
10984
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10807
10985
  const config = parseConfig7(remnicCfg);
10808
10986
  if (!config.briefing.enabled) {
@@ -10882,10 +11060,10 @@ async function cmdBriefing(rest) {
10882
11060
  if (save) {
10883
11061
  try {
10884
11062
  const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
10885
- fs15.mkdirSync(saveDir, { recursive: true });
11063
+ fs16.mkdirSync(saveDir, { recursive: true });
10886
11064
  const filename = briefingFilename(new Date(result.window.to), format);
10887
11065
  const filePath = path18.join(saveDir, filename);
10888
- fs15.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
11066
+ fs16.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
10889
11067
  console.error(`Saved briefing: ${filePath}`);
10890
11068
  } catch (err) {
10891
11069
  console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
@@ -10903,7 +11081,7 @@ async function cmdDoctor() {
10903
11081
  detail: `${nodeVersion} (requires >= 22.12.0)`
10904
11082
  });
10905
11083
  const configPath = resolveConfigPath();
10906
- const configExists = fs15.existsSync(configPath);
11084
+ const configExists = fs16.existsSync(configPath);
10907
11085
  checks.push({ name: "Config file", ok: configExists, detail: configPath });
10908
11086
  let standaloneConfig;
10909
11087
  let standaloneConfigError;
@@ -10911,7 +11089,7 @@ async function cmdDoctor() {
10911
11089
  let configuredNs = { invalid: false };
10912
11090
  if (configExists) {
10913
11091
  try {
10914
- const raw = JSON.parse(fs15.readFileSync(configPath, "utf8"));
11092
+ const raw = JSON.parse(fs16.readFileSync(configPath, "utf8"));
10915
11093
  const remnicCfg = resolveRemnicConfigRecord6(raw);
10916
11094
  standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
10917
11095
  configuredNs = readConfiguredNamespace(remnicCfg);
@@ -10927,7 +11105,7 @@ async function cmdDoctor() {
10927
11105
  memoryDir = parseConfig7({}).memoryDir;
10928
11106
  }
10929
11107
  try {
10930
- fs15.mkdirSync(memoryDir, { recursive: true });
11108
+ fs16.mkdirSync(memoryDir, { recursive: true });
10931
11109
  checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
10932
11110
  } catch {
10933
11111
  checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
@@ -10956,7 +11134,7 @@ async function cmdDoctor() {
10956
11134
  });
10957
11135
  if (nsPolicyCheck) checks.push(nsPolicyCheck);
10958
11136
  const openclawConfigPath = resolveOpenclawConfigPath();
10959
- const openclawConfigExists = fs15.existsSync(openclawConfigPath);
11137
+ const openclawConfigExists = fs16.existsSync(openclawConfigPath);
10960
11138
  let openclawConfig = {};
10961
11139
  let openclawConfigValid = false;
10962
11140
  let openclawPluginModeConfigured = false;
@@ -10964,7 +11142,7 @@ async function cmdDoctor() {
10964
11142
  let activeOpenclawEntryConfig = null;
10965
11143
  if (openclawConfigExists) {
10966
11144
  try {
10967
- const parsed = JSON.parse(fs15.readFileSync(openclawConfigPath, "utf-8"));
11145
+ const parsed = JSON.parse(fs16.readFileSync(openclawConfigPath, "utf-8"));
10968
11146
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
10969
11147
  openclawConfig = parsed;
10970
11148
  openclawConfigValid = true;
@@ -11044,9 +11222,9 @@ async function cmdDoctor() {
11044
11222
  let memDirOk = false;
11045
11223
  let memDirDetail = `${resolvedMemDir} (not found)`;
11046
11224
  let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
11047
- if (fs15.existsSync(resolvedMemDir)) {
11225
+ if (fs16.existsSync(resolvedMemDir)) {
11048
11226
  try {
11049
- const stat2 = fs15.statSync(resolvedMemDir);
11227
+ const stat2 = fs16.statSync(resolvedMemDir);
11050
11228
  if (stat2.isDirectory()) {
11051
11229
  memDirOk = true;
11052
11230
  memDirDetail = resolvedMemDir;
@@ -11097,16 +11275,29 @@ async function cmdDoctor() {
11097
11275
  warn: openclawKeyErrorBlocksOk || standaloneConfigErrorBlocksOk || !hasApiKey && !openaiKeyOptionalForOpenclaw && !openaiKeyOptionalForStandalone,
11098
11276
  detail: standaloneConfigErrorBlocksOk ? "config parse failed" : openclawKeyErrorBlocksOk ? "OpenClaw openaiApiKey placeholder failed" : hasApiKey ? "configured" : !diagnosingOpenclawPluginMode && standaloneOpenaiApiKeyExplicitlyFalse && localLlmConfigured ? "disabled by config (local LLM enabled)" : !diagnosingOpenclawPluginMode && standaloneOpenaiApiKeyExplicitlyFalse && standaloneConfig?.modelSource === "gateway" ? "disabled by config (gateway modelSource)" : activeOpenclawOpenaiApiKeyExplicitlyFalse ? "disabled by OpenClaw config" : openaiKeyOptionalForOpenclaw ? activeOpenclawModelSource === "gateway" ? "not set (not required for OpenClaw gateway modelSource)" : "not set (not required for OpenClaw local LLM)" : openaiKeyOptionalForStandalone ? "not set (standalone local/gateway model path configured)" : "not set (required for direct OpenAI-backed extraction)"
11099
11277
  });
11100
- const svcState = isServiceRunning();
11101
- const standaloneServiceInstalled = isStandaloneServiceInstalled();
11102
- const daemonOptionalForOpenclaw = openclawPluginModeConfigured && !standaloneServiceInstalled;
11103
- checks.push({
11104
- name: "Server daemon",
11105
- ok: svcState.running || daemonOptionalForOpenclaw,
11106
- warn: !svcState.running,
11107
- detail: svcState.running ? `running${svcState.pid ? ` (pid ${svcState.pid})` : ""}` : daemonOptionalForOpenclaw ? "stopped (not required for OpenClaw plugin mode)" : "stopped",
11108
- remediation: !svcState.running && standaloneServiceInstalled ? "Run `remnic daemon start`, or `remnic daemon uninstall` if you only use the OpenClaw plugin." : void 0
11109
- });
11278
+ const remoteDaemon = resolveRemoteDaemon(configPath);
11279
+ if (remoteDaemon) {
11280
+ const probe = await probeDaemonHealth(remoteDaemon.baseUrl, remoteDaemon.token);
11281
+ const detail = probe.ok ? `remote ${remoteDaemon.baseUrl} (reachable)` : `remote ${remoteDaemon.baseUrl} (unreachable${probe.status ? `, HTTP ${probe.status}` : probe.error ? `, ${probe.error}` : ""})`;
11282
+ checks.push({
11283
+ name: "Server daemon",
11284
+ ok: probe.ok,
11285
+ warn: !probe.ok,
11286
+ detail,
11287
+ remediation: probe.ok ? void 0 : "Check REMNIC_DAEMON_URL / server.url and the remote server's availability."
11288
+ });
11289
+ } else {
11290
+ const svcState = isServiceRunning();
11291
+ const standaloneServiceInstalled = isStandaloneServiceInstalled();
11292
+ const daemonOptionalForOpenclaw = openclawPluginModeConfigured && !standaloneServiceInstalled;
11293
+ checks.push({
11294
+ name: "Server daemon",
11295
+ ok: svcState.running || daemonOptionalForOpenclaw,
11296
+ warn: !svcState.running,
11297
+ detail: svcState.running ? `running${svcState.pid ? ` (pid ${svcState.pid})` : ""}` : daemonOptionalForOpenclaw ? "stopped (not required for OpenClaw plugin mode)" : "stopped",
11298
+ remediation: !svcState.running && standaloneServiceInstalled ? "Run `remnic daemon start`, or `remnic daemon uninstall` if you only use the OpenClaw plugin." : void 0
11299
+ });
11300
+ }
11110
11301
  if (isMacOS()) {
11111
11302
  const launchdInspection = selectLaunchdInspection(openclawPluginModeConfigured);
11112
11303
  checks.push({
@@ -11188,12 +11379,12 @@ async function cmdDoctor() {
11188
11379
  }
11189
11380
  function cmdConfig() {
11190
11381
  const configPath = resolveConfigPath();
11191
- if (!fs15.existsSync(configPath)) {
11382
+ if (!fs16.existsSync(configPath)) {
11192
11383
  console.log("No config file found. Run `remnic init` to create one.");
11193
11384
  return;
11194
11385
  }
11195
11386
  console.log(`Config: ${configPath}`);
11196
- const rawConfig = fs15.readFileSync(configPath, "utf8");
11387
+ const rawConfig = fs16.readFileSync(configPath, "utf8");
11197
11388
  const redacted = rawConfig.replace(
11198
11389
  /("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
11199
11390
  "$1[REDACTED]$3"
@@ -11301,7 +11492,7 @@ async function cmdReview(action, rest) {
11301
11492
  const configPath = resolveConfigPath();
11302
11493
  let tombstonesConfig = null;
11303
11494
  try {
11304
- const rawCfg = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
11495
+ const rawCfg = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
11305
11496
  const remnicCfg = resolveRemnicConfigRecord6(rawCfg);
11306
11497
  const config = parseConfig7(remnicCfg);
11307
11498
  tombstonesConfig = {
@@ -12045,7 +12236,7 @@ async function pushOfflineFileContent(args) {
12045
12236
  }
12046
12237
  async function pushOfflineFileContentFromChunkReader(args) {
12047
12238
  const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
12048
- const stat2 = fs15.statSync(filePath);
12239
+ const stat2 = fs16.statSync(filePath);
12049
12240
  if (stat2.mtimeMs !== args.file.mtimeMs) {
12050
12241
  throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
12051
12242
  }
@@ -12536,7 +12727,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
12536
12727
  return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
12537
12728
  }
12538
12729
  async function runOfflineSyncOnce(options) {
12539
- fs15.mkdirSync(options.memoryDir, { recursive: true });
12730
+ fs16.mkdirSync(options.memoryDir, { recursive: true });
12540
12731
  let activeStatePath = options.statePath;
12541
12732
  let priorState = await readOfflineSyncState(activeStatePath);
12542
12733
  let syncNamespace = options.namespace ?? priorState?.namespace;
@@ -13169,7 +13360,7 @@ Environment fallbacks:
13169
13360
  const configPath = resolveConfigPath();
13170
13361
  let config;
13171
13362
  try {
13172
- const rawConfig = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
13363
+ const rawConfig = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
13173
13364
  config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
13174
13365
  } catch {
13175
13366
  throw new Error(
@@ -13184,7 +13375,7 @@ Environment fallbacks:
13184
13375
  const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
13185
13376
  if (action === "prepare") {
13186
13377
  if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
13187
- fs15.mkdirSync(memoryDir, { recursive: true });
13378
+ fs16.mkdirSync(memoryDir, { recursive: true });
13188
13379
  const remoteSnapshot = await fetchOfflineSnapshot({
13189
13380
  remoteUrl,
13190
13381
  token,
@@ -13283,7 +13474,7 @@ Environment fallbacks:
13283
13474
  return;
13284
13475
  }
13285
13476
  if (action === "status") {
13286
- fs15.mkdirSync(memoryDir, { recursive: true });
13477
+ fs16.mkdirSync(memoryDir, { recursive: true });
13287
13478
  const state = statePath ? await readOfflineSyncState(statePath) : null;
13288
13479
  if (state && remoteUrl && statePath) {
13289
13480
  assertOfflineStateMatches({
@@ -13421,7 +13612,7 @@ function cmdDedup(json) {
13421
13612
  function readInstalledConnectorConfig(configPath, fallback) {
13422
13613
  if (!configPath) return fallback;
13423
13614
  try {
13424
- const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
13615
+ const parsed = JSON.parse(fs16.readFileSync(configPath, "utf8"));
13425
13616
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
13426
13617
  const { token: _token, ...config } = parsed;
13427
13618
  return config;
@@ -13599,7 +13790,7 @@ async function cmdConnectors(action, rest, json) {
13599
13790
  const pub = factory();
13600
13791
  const available = await pub.isHostAvailable();
13601
13792
  const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
13602
- const extensionExists = available && extRoot ? fs15.existsSync(extRoot) : false;
13793
+ const extensionExists = available && extRoot ? fs16.existsSync(extRoot) : false;
13603
13794
  publisherChecks.push({
13604
13795
  name: `Publisher: ${targetHostId}`,
13605
13796
  ok: !available || extensionExists,
@@ -13673,7 +13864,7 @@ async function cmdConnectors(action, rest, json) {
13673
13864
  let connectorsCfg;
13674
13865
  const configPath = resolveConfigPath();
13675
13866
  try {
13676
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
13867
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
13677
13868
  connectorsCfg = parseConfigQuietly(raw).connectors;
13678
13869
  } catch {
13679
13870
  process.stderr.write(
@@ -13749,7 +13940,7 @@ async function cmdConnectors(action, rest, json) {
13749
13940
  }
13750
13941
  initLogger3();
13751
13942
  const configPath = resolveConfigPath();
13752
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
13943
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
13753
13944
  const remnicCfg = resolveRemnicConfigRecord6(raw);
13754
13945
  const config = parseConfig7(remnicCfg);
13755
13946
  const orchestrator = new Orchestrator4(config);
@@ -13874,7 +14065,7 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
13874
14065
  console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
13875
14066
  process.exit(1);
13876
14067
  }
13877
- const rawConfig = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
14068
+ const rawConfig = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
13878
14069
  const pluginConfig = resolveRemnicConfigRecord6(rawConfig);
13879
14070
  const config = parseConfig7(pluginConfig);
13880
14071
  if (subAction === "generate") {
@@ -13896,13 +14087,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
13896
14087
  } else if (subAction === "validate") {
13897
14088
  const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
13898
14089
  const resolved = path18.resolve(targetPath);
13899
- if (!fs15.existsSync(resolved)) {
14090
+ if (!fs16.existsSync(resolved)) {
13900
14091
  console.error(`File not found: ${resolved}`);
13901
14092
  process.exit(1);
13902
14093
  }
13903
14094
  let parsed;
13904
14095
  try {
13905
- parsed = JSON.parse(fs15.readFileSync(resolved, "utf8"));
14096
+ parsed = JSON.parse(fs16.readFileSync(resolved, "utf8"));
13906
14097
  } catch {
13907
14098
  console.error(`Invalid JSON in ${resolved}`);
13908
14099
  process.exit(1);
@@ -14103,7 +14294,7 @@ async function cmdSpace(action, rest, json) {
14103
14294
  async function cmdLegacyBenchmark(action, rest, json) {
14104
14295
  initLogger3();
14105
14296
  const configPath = resolveConfigPath();
14106
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
14297
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
14107
14298
  const remnicCfg = resolveRemnicConfigRecord6(raw);
14108
14299
  const config = parseConfig7(remnicCfg);
14109
14300
  const orchestrator = new Orchestrator4(config);
@@ -14508,7 +14699,7 @@ function readPid() {
14508
14699
  function inferPort() {
14509
14700
  try {
14510
14701
  const configPath = resolveConfigPath();
14511
- const raw = JSON.parse(fs15.readFileSync(configPath, "utf8"));
14702
+ const raw = JSON.parse(fs16.readFileSync(configPath, "utf8"));
14512
14703
  return raw.server?.port ?? 4318;
14513
14704
  } catch {
14514
14705
  return 4318;
@@ -14603,13 +14794,13 @@ function daemonInstall() {
14603
14794
  process.exit(1);
14604
14795
  }
14605
14796
  const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
14606
- fs15.mkdirSync(LOGS_DIR, { recursive: true });
14797
+ fs16.mkdirSync(LOGS_DIR, { recursive: true });
14607
14798
  if (isMacOS()) {
14608
14799
  const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
14609
- const template = fs15.readFileSync(templatePath, "utf8");
14800
+ const template = fs16.readFileSync(templatePath, "utf8");
14610
14801
  const plist = renderTemplate(template, vars);
14611
- fs15.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
14612
- fs15.writeFileSync(LAUNCHD_PLIST_PATH, plist);
14802
+ fs16.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
14803
+ fs16.writeFileSync(LAUNCHD_PLIST_PATH, plist);
14613
14804
  try {
14614
14805
  launchdLoadPlist(LAUNCHD_PLIST_PATH);
14615
14806
  } catch (err) {
@@ -14626,10 +14817,10 @@ function daemonInstall() {
14626
14817
  console.log(` Logs: ${LOGS_DIR}/daemon.log`);
14627
14818
  } else if (isLinux()) {
14628
14819
  const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
14629
- const template = fs15.readFileSync(templatePath, "utf8");
14820
+ const template = fs16.readFileSync(templatePath, "utf8");
14630
14821
  const unit = renderTemplate(template, vars);
14631
- fs15.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
14632
- fs15.writeFileSync(SYSTEMD_UNIT_PATH, unit);
14822
+ fs16.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
14823
+ fs16.writeFileSync(SYSTEMD_UNIT_PATH, unit);
14633
14824
  try {
14634
14825
  childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
14635
14826
  } catch (err) {
@@ -14665,7 +14856,7 @@ function daemonUninstall() {
14665
14856
  } catch {
14666
14857
  }
14667
14858
  try {
14668
- fs15.unlinkSync(plistPath);
14859
+ fs16.unlinkSync(plistPath);
14669
14860
  removed = true;
14670
14861
  console.log(`Removed launchd service: ${plistPath}`);
14671
14862
  } catch {
@@ -14685,7 +14876,7 @@ function daemonUninstall() {
14685
14876
  let removed = false;
14686
14877
  for (const unitPath of SYSTEMD_UNIT_PATHS) {
14687
14878
  try {
14688
- fs15.unlinkSync(unitPath);
14879
+ fs16.unlinkSync(unitPath);
14689
14880
  removed = true;
14690
14881
  console.log(`Removed systemd service: ${unitPath}`);
14691
14882
  } catch {
@@ -14752,11 +14943,11 @@ async function daemonStatus() {
14752
14943
  console.log(` Port: ${port}`);
14753
14944
  console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
14754
14945
  console.log(` Platform: ${process.platform}`);
14755
- console.log(` PID file: ${fs15.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
14756
- console.log(` Log file: ${fs15.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
14946
+ console.log(` PID file: ${fs16.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
14947
+ console.log(` Log file: ${fs16.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
14757
14948
  try {
14758
14949
  const configPath = resolveConfigPath();
14759
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
14950
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
14760
14951
  const remnicCfg = resolveRemnicConfigRecord6(raw);
14761
14952
  const config = parseConfig7(remnicCfg);
14762
14953
  const extRoot = resolveExtensionsRoot(config);
@@ -14797,9 +14988,9 @@ function daemonStart() {
14797
14988
  return;
14798
14989
  }
14799
14990
  }
14800
- fs15.mkdirSync(PID_DIR, { recursive: true });
14801
- fs15.mkdirSync(LOGS_DIR, { recursive: true });
14802
- const logStream = fs15.openSync(LOG_FILE, "a");
14991
+ fs16.mkdirSync(PID_DIR, { recursive: true });
14992
+ fs16.mkdirSync(LOGS_DIR, { recursive: true });
14993
+ const logStream = fs16.openSync(LOG_FILE, "a");
14803
14994
  const serverBin = resolveServerBin();
14804
14995
  const isSource = serverBin.endsWith(".ts");
14805
14996
  let cmd;
@@ -14821,7 +15012,7 @@ function daemonStart() {
14821
15012
  }
14822
15013
  });
14823
15014
  child.unref();
14824
- fs15.writeFileSync(PID_FILE, String(child.pid));
15015
+ fs16.writeFileSync(PID_FILE, String(child.pid));
14825
15016
  console.log(`Started remnic server (pid ${child.pid})`);
14826
15017
  console.log(` Log: ${LOG_FILE}`);
14827
15018
  }
@@ -14855,11 +15046,11 @@ function daemonStop() {
14855
15046
  console.log("Process not found (cleaning up PID file)");
14856
15047
  }
14857
15048
  try {
14858
- fs15.unlinkSync(PID_FILE);
15049
+ fs16.unlinkSync(PID_FILE);
14859
15050
  } catch {
14860
15051
  }
14861
15052
  try {
14862
- fs15.unlinkSync(LEGACY_PID_FILE);
15053
+ fs16.unlinkSync(LEGACY_PID_FILE);
14863
15054
  } catch {
14864
15055
  }
14865
15056
  }
@@ -14987,7 +15178,7 @@ async function promptYesNo(question, defaultYes = true) {
14987
15178
  async function cmdBinary(rest) {
14988
15179
  initLogger3();
14989
15180
  const configPath = resolveConfigPath();
14990
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
15181
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
14991
15182
  const remnicCfg = resolveRemnicConfigRecord6(raw);
14992
15183
  const config = parseConfig7(remnicCfg);
14993
15184
  const memoryDir = resolveMemoryDir();
@@ -15178,7 +15369,7 @@ async function cmdOpenclawInstall(opts) {
15178
15369
  } else if (slotIsActiveLegacy) {
15179
15370
  changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
15180
15371
  }
15181
- if (!fs15.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15372
+ if (!fs16.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
15182
15373
  if (hasLegacy && migrateLegacy) {
15183
15374
  changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
15184
15375
  }
@@ -15198,8 +15389,8 @@ async function cmdOpenclawInstall(opts) {
15198
15389
  Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
15199
15390
  return;
15200
15391
  }
15201
- if (fs15.existsSync(memoryDir)) {
15202
- const st = fs15.statSync(memoryDir);
15392
+ if (fs16.existsSync(memoryDir)) {
15393
+ const st = fs16.statSync(memoryDir);
15203
15394
  if (!st.isDirectory()) {
15204
15395
  throw new Error(
15205
15396
  `Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
@@ -15207,12 +15398,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
15207
15398
  );
15208
15399
  }
15209
15400
  } else {
15210
- fs15.mkdirSync(memoryDir, { recursive: true });
15401
+ fs16.mkdirSync(memoryDir, { recursive: true });
15211
15402
  console.log(`Created memory directory: ${memoryDir}`);
15212
15403
  }
15213
15404
  const configDir = path18.dirname(configPath);
15214
- if (!fs15.existsSync(configDir)) {
15215
- fs15.mkdirSync(configDir, { recursive: true });
15405
+ if (!fs16.existsSync(configDir)) {
15406
+ fs16.mkdirSync(configDir, { recursive: true });
15216
15407
  }
15217
15408
  atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
15218
15409
  console.log("\nDone! Summary of changes:");
@@ -15241,7 +15432,7 @@ async function cmdOpenclawUpgrade(opts) {
15241
15432
  const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
15242
15433
  const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
15243
15434
  const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
15244
- const configExistedBefore = fs15.existsSync(configPath);
15435
+ const configExistedBefore = fs16.existsSync(configPath);
15245
15436
  const existingConfig = readOpenclawConfig(configPath);
15246
15437
  const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
15247
15438
  const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
@@ -15466,13 +15657,13 @@ async function cmdOpenclawMigrateEngram(opts) {
15466
15657
  }
15467
15658
  function createOpenclawUpgradeBackupDir() {
15468
15659
  const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
15469
- fs15.mkdirSync(backupsRoot, { recursive: true });
15470
- return fs15.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
15660
+ fs16.mkdirSync(backupsRoot, { recursive: true });
15661
+ return fs16.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
15471
15662
  }
15472
15663
  async function cmdTaxonomy(rest) {
15473
15664
  initLogger3();
15474
15665
  const configPath = resolveConfigPath();
15475
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
15666
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
15476
15667
  const remnicCfg = resolveRemnicConfigRecord6(raw);
15477
15668
  const config = parseConfig7(remnicCfg);
15478
15669
  if (!config.taxonomyEnabled) {
@@ -15510,8 +15701,8 @@ async function cmdTaxonomy(rest) {
15510
15701
  console.log(doc);
15511
15702
  if (config.taxonomyAutoGenResolver) {
15512
15703
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15513
- fs15.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15514
- fs15.writeFileSync(resolverPath, doc);
15704
+ fs16.mkdirSync(path18.dirname(resolverPath), { recursive: true });
15705
+ fs16.writeFileSync(resolverPath, doc);
15515
15706
  console.error(`Written: ${resolverPath}`);
15516
15707
  }
15517
15708
  break;
@@ -15557,7 +15748,7 @@ async function cmdTaxonomy(rest) {
15557
15748
  if (config.taxonomyAutoGenResolver) {
15558
15749
  const doc = generateResolverDocument(taxonomy);
15559
15750
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15560
- fs15.writeFileSync(resolverPath, doc);
15751
+ fs16.writeFileSync(resolverPath, doc);
15561
15752
  console.error(`Regenerated: ${resolverPath}`);
15562
15753
  }
15563
15754
  break;
@@ -15588,7 +15779,7 @@ async function cmdTaxonomy(rest) {
15588
15779
  if (config.taxonomyAutoGenResolver) {
15589
15780
  const doc = generateResolverDocument(taxonomy);
15590
15781
  const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
15591
- fs15.writeFileSync(resolverPath, doc);
15782
+ fs16.writeFileSync(resolverPath, doc);
15592
15783
  console.error(`Regenerated: ${resolverPath}`);
15593
15784
  }
15594
15785
  break;
@@ -15779,12 +15970,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
15779
15970
  `Unknown training-export format "${args.format}". ${validList}`
15780
15971
  );
15781
15972
  }
15782
- if (!fs15.existsSync(args.memoryDir)) {
15973
+ if (!fs16.existsSync(args.memoryDir)) {
15783
15974
  throw new Error(
15784
15975
  `--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
15785
15976
  );
15786
15977
  }
15787
- if (!fs15.statSync(args.memoryDir).isDirectory()) {
15978
+ if (!fs16.statSync(args.memoryDir).isDirectory()) {
15788
15979
  throw new Error(
15789
15980
  `--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
15790
15981
  );
@@ -15870,10 +16061,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
15870
16061
  }
15871
16062
  const formatted = adapter.formatRecords(records);
15872
16063
  const outDir = path18.dirname(args.output);
15873
- fs15.mkdirSync(outDir, { recursive: true });
16064
+ fs16.mkdirSync(outDir, { recursive: true });
15874
16065
  const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
15875
- fs15.writeFileSync(tmpPath, formatted, "utf-8");
15876
- fs15.renameSync(tmpPath, args.output);
16066
+ fs16.writeFileSync(tmpPath, formatted, "utf-8");
16067
+ fs16.renameSync(tmpPath, args.output);
15877
16068
  stdout.write(
15878
16069
  `Exported ${records.length} records to ${args.output} (${adapter.name} format)
15879
16070
  `
@@ -16045,7 +16236,7 @@ async function main(argv = process.argv.slice(2)) {
16045
16236
  }
16046
16237
  }, 500);
16047
16238
  };
16048
- fs15.watch(memoryDir, { recursive: true }, (_event, filename) => {
16239
+ fs16.watch(memoryDir, { recursive: true }, (_event, filename) => {
16049
16240
  if (filename && filename.startsWith(".")) return;
16050
16241
  rebuild();
16051
16242
  });
@@ -16053,12 +16244,12 @@ async function main(argv = process.argv.slice(2)) {
16053
16244
  });
16054
16245
  } else if (subAction === "validate") {
16055
16246
  const treeDir = outputDir;
16056
- if (!fs15.existsSync(treeDir)) {
16247
+ if (!fs16.existsSync(treeDir)) {
16057
16248
  console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
16058
16249
  process.exit(1);
16059
16250
  }
16060
16251
  const indexPath = path18.join(treeDir, "INDEX.md");
16061
- if (!fs15.existsSync(indexPath)) {
16252
+ if (!fs16.existsSync(indexPath)) {
16062
16253
  console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
16063
16254
  process.exit(1);
16064
16255
  }
@@ -16240,7 +16431,7 @@ Other:
16240
16431
  let wearablesService;
16241
16432
  try {
16242
16433
  const configPath = resolveConfigPath();
16243
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
16434
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
16244
16435
  const remnicCfg = resolveRemnicConfigRecord6(raw);
16245
16436
  const config = parseConfig7(remnicCfg);
16246
16437
  wearablesOrchestrator = new Orchestrator4(config);
@@ -16295,7 +16486,7 @@ Other:
16295
16486
  const targetFactory = async () => {
16296
16487
  if (!orchestratorSingleton) {
16297
16488
  const configPath = resolveConfigPath();
16298
- const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
16489
+ const raw = fs16.existsSync(configPath) ? JSON.parse(fs16.readFileSync(configPath, "utf8")) : {};
16299
16490
  const remnicCfg = resolveRemnicConfigRecord6(raw);
16300
16491
  const config = parseConfig7(remnicCfg);
16301
16492
  orchestratorSingleton = new Orchestrator4(config);