@remnic/cli 9.69.56 → 9.69.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +657 -166
- package/package.json +32 -32
package/dist/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/enrichment-persist.ts
|
|
2
9
|
import { composeSalvagedEnvelope } from "@remnic/core/salvage-envelope";
|
|
3
10
|
async function persistEnrichmentCandidate(storage, entityName, candidate) {
|
|
@@ -480,8 +487,8 @@ function resetLegacyDatasetWarningState() {
|
|
|
480
487
|
|
|
481
488
|
// src/index.ts
|
|
482
489
|
import fs32 from "fs";
|
|
483
|
-
import
|
|
484
|
-
import
|
|
490
|
+
import os4 from "os";
|
|
491
|
+
import path23 from "path";
|
|
485
492
|
import { createHash as createHash6 } from "crypto";
|
|
486
493
|
import { writeFile as fsWriteFile } from "fs/promises";
|
|
487
494
|
import * as childProcess2 from "child_process";
|
|
@@ -569,6 +576,8 @@ import {
|
|
|
569
576
|
StorageManager as StorageManager4,
|
|
570
577
|
parseXrayCliOptions,
|
|
571
578
|
renderXray,
|
|
579
|
+
parseWhyCliOptions,
|
|
580
|
+
renderRecallWhy,
|
|
572
581
|
extractWhoKnowsRawArgs,
|
|
573
582
|
parseWhoKnowsCliOptions,
|
|
574
583
|
renderWhoKnows,
|
|
@@ -3296,13 +3305,13 @@ async function planLocalNamespaceCensus(args) {
|
|
|
3296
3305
|
citationTemplate: args.citationTemplate,
|
|
3297
3306
|
cachedFiles: identityCache.size > 0 ? [...identityCache.values()] : priorFiles,
|
|
3298
3307
|
readFile: async (file) => {
|
|
3299
|
-
const
|
|
3300
|
-
if (!
|
|
3308
|
+
const readFile5 = io.readFile;
|
|
3309
|
+
if (!readFile5) {
|
|
3301
3310
|
manifestReadFailed = true;
|
|
3302
3311
|
throw new Error("offline storage cannot read reconciliation manifest files");
|
|
3303
3312
|
}
|
|
3304
3313
|
try {
|
|
3305
|
-
return await
|
|
3314
|
+
return await readFile5({
|
|
3306
3315
|
root: rootDir,
|
|
3307
3316
|
path: file.path,
|
|
3308
3317
|
filePath: path6.join(rootDir, file.path)
|
|
@@ -7684,6 +7693,355 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
7684
7693
|
}
|
|
7685
7694
|
}
|
|
7686
7695
|
|
|
7696
|
+
// src/report.ts
|
|
7697
|
+
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync as statSync2, writeFileSync } from "fs";
|
|
7698
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
7699
|
+
import os2 from "os";
|
|
7700
|
+
import path16 from "path";
|
|
7701
|
+
var REPORT_ALLOWED_CONFIG_FIELDS = Object.freeze([
|
|
7702
|
+
"qmdEnabled",
|
|
7703
|
+
"qmdAutoEmbedEnabled",
|
|
7704
|
+
"qmdDaemonEnabled",
|
|
7705
|
+
"qmdColdTierEnabled",
|
|
7706
|
+
"qmdTierMigrationEnabled",
|
|
7707
|
+
"qmdTierAutoBackfillEnabled",
|
|
7708
|
+
"qmdMaintenanceEnabled",
|
|
7709
|
+
"debug",
|
|
7710
|
+
"identityEnabled",
|
|
7711
|
+
"injectQuestions",
|
|
7712
|
+
"consolidateEveryN",
|
|
7713
|
+
"maxMemoryTokens",
|
|
7714
|
+
"commitmentDecayDays"
|
|
7715
|
+
]);
|
|
7716
|
+
var SIZE_BUCKETS = Object.freeze([
|
|
7717
|
+
{ label: "< 1 KB", max: 1024 },
|
|
7718
|
+
{ label: "1 KB \u2013 10 KB", max: 10 * 1024 },
|
|
7719
|
+
{ label: "10 KB \u2013 100 KB", max: 100 * 1024 },
|
|
7720
|
+
{ label: "100 KB \u2013 1 MB", max: 1024 * 1024 },
|
|
7721
|
+
{ label: "1 MB \u2013 10 MB", max: 10 * 1024 * 1024 },
|
|
7722
|
+
{ label: "10 MB \u2013 100 MB", max: 100 * 1024 * 1024 },
|
|
7723
|
+
{ label: "100 MB \u2013 1 GB", max: 1024 * 1024 * 1024 },
|
|
7724
|
+
{ label: "> 1 GB", max: Infinity }
|
|
7725
|
+
]);
|
|
7726
|
+
function sizeBucket(bytes) {
|
|
7727
|
+
if (!Number.isFinite(bytes) || bytes < 0) return SIZE_BUCKETS[0].label;
|
|
7728
|
+
for (const bucket of SIZE_BUCKETS) {
|
|
7729
|
+
if (bytes <= bucket.max) return bucket.label;
|
|
7730
|
+
}
|
|
7731
|
+
return SIZE_BUCKETS[SIZE_BUCKETS.length - 1].label;
|
|
7732
|
+
}
|
|
7733
|
+
function sizeOfStore(dir) {
|
|
7734
|
+
try {
|
|
7735
|
+
const { execSync: execSync2 } = __require("child_process");
|
|
7736
|
+
const output = execSync2(`du -sb "${dir}" 2>/dev/null || echo 0`, {
|
|
7737
|
+
encoding: "utf-8",
|
|
7738
|
+
timeout: 5e3
|
|
7739
|
+
});
|
|
7740
|
+
const match = output.match(/^(\d+)/);
|
|
7741
|
+
return match ? Number(match[1]) : 0;
|
|
7742
|
+
} catch {
|
|
7743
|
+
return 0;
|
|
7744
|
+
}
|
|
7745
|
+
}
|
|
7746
|
+
function countMemories(dir) {
|
|
7747
|
+
try {
|
|
7748
|
+
let count = 0;
|
|
7749
|
+
const walk = (d) => {
|
|
7750
|
+
for (const entry of readdirSync2(d)) {
|
|
7751
|
+
const full = path16.join(d, entry);
|
|
7752
|
+
const st = statSync2(full);
|
|
7753
|
+
if (st.isDirectory()) walk(full);
|
|
7754
|
+
else if (entry.endsWith(".md")) count++;
|
|
7755
|
+
}
|
|
7756
|
+
};
|
|
7757
|
+
walk(dir);
|
|
7758
|
+
return count;
|
|
7759
|
+
} catch {
|
|
7760
|
+
return 0;
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7763
|
+
function findConfigPath() {
|
|
7764
|
+
const candidates = [
|
|
7765
|
+
path16.join(os2.homedir(), ".config", "remnic", "config.json"),
|
|
7766
|
+
path16.join(os2.homedir(), ".config", "openclaw", "openclaw.json"),
|
|
7767
|
+
path16.join(os2.homedir(), ".openclaw", "config.json")
|
|
7768
|
+
];
|
|
7769
|
+
for (const p of candidates) {
|
|
7770
|
+
if (existsSync4(p)) return p;
|
|
7771
|
+
}
|
|
7772
|
+
return void 0;
|
|
7773
|
+
}
|
|
7774
|
+
function findMemoryDir(configPath) {
|
|
7775
|
+
if (configPath) {
|
|
7776
|
+
try {
|
|
7777
|
+
const raw = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7778
|
+
const cfg = raw?.plugins?.["remnic"] ?? raw?.plugins?.["openclaw-engram"] ?? {};
|
|
7779
|
+
if (typeof cfg.memoryDir === "string") return cfg.memoryDir;
|
|
7780
|
+
} catch {
|
|
7781
|
+
}
|
|
7782
|
+
}
|
|
7783
|
+
return path16.join(os2.homedir(), ".remnic", "memory");
|
|
7784
|
+
}
|
|
7785
|
+
function extractConfigShape(rawConfig) {
|
|
7786
|
+
const result = {};
|
|
7787
|
+
for (const key of Object.getOwnPropertyNames(rawConfig)) {
|
|
7788
|
+
if (!Object.hasOwn(rawConfig, key)) continue;
|
|
7789
|
+
if (!REPORT_ALLOWED_CONFIG_FIELDS.includes(key)) continue;
|
|
7790
|
+
const value = rawConfig[key];
|
|
7791
|
+
if (typeof value === "boolean" || typeof value === "number") {
|
|
7792
|
+
result[key] = value;
|
|
7793
|
+
} else if (typeof value === "string" && ["alpha", "beta", "stable"].includes(value)) {
|
|
7794
|
+
result[key] = value;
|
|
7795
|
+
}
|
|
7796
|
+
}
|
|
7797
|
+
return result;
|
|
7798
|
+
}
|
|
7799
|
+
function runDoctorChecks() {
|
|
7800
|
+
const checks = [];
|
|
7801
|
+
const nodeMajor = Number.parseInt(process.version.slice(1).split(".")[0], 10);
|
|
7802
|
+
checks.push({ name: "Node.js version", ok: nodeMajor >= 22 });
|
|
7803
|
+
const configPath = findConfigPath();
|
|
7804
|
+
checks.push({ name: "Config file", ok: configPath !== void 0 });
|
|
7805
|
+
const memoryDir = findMemoryDir(configPath);
|
|
7806
|
+
try {
|
|
7807
|
+
mkdirSync(memoryDir, { recursive: true });
|
|
7808
|
+
checks.push({ name: "Memory directory", ok: true });
|
|
7809
|
+
} catch {
|
|
7810
|
+
checks.push({ name: "Memory directory", ok: false });
|
|
7811
|
+
}
|
|
7812
|
+
const openclawPath = path16.join(os2.homedir(), ".config", "openclaw", "openclaw.json");
|
|
7813
|
+
checks.push({ name: "OpenClaw config file", ok: existsSync4(openclawPath) });
|
|
7814
|
+
return checks;
|
|
7815
|
+
}
|
|
7816
|
+
var PUBLIC_BENCHMARK_IDS = Object.freeze([
|
|
7817
|
+
"ama-bench",
|
|
7818
|
+
"memory-arena",
|
|
7819
|
+
"amemgym",
|
|
7820
|
+
"longmemeval",
|
|
7821
|
+
"locomo",
|
|
7822
|
+
"beam",
|
|
7823
|
+
"personamem",
|
|
7824
|
+
"membench",
|
|
7825
|
+
"memoryagentbench",
|
|
7826
|
+
"taxonomy-accuracy",
|
|
7827
|
+
"extraction-judge-calibration",
|
|
7828
|
+
"extraction-span-mode",
|
|
7829
|
+
"enrichment-fidelity",
|
|
7830
|
+
"entity-consolidation",
|
|
7831
|
+
"page-versioning",
|
|
7832
|
+
"retrieval-personalization",
|
|
7833
|
+
"retrieval-temporal",
|
|
7834
|
+
"retrieval-direct-answer",
|
|
7835
|
+
"retrieval-graph",
|
|
7836
|
+
"retrieval-reasoning-trace",
|
|
7837
|
+
"coding-recall",
|
|
7838
|
+
"procedural-recall",
|
|
7839
|
+
"say-once",
|
|
7840
|
+
"ingestion-entity-recall",
|
|
7841
|
+
"ingestion-schema-completeness",
|
|
7842
|
+
"ingestion-backlink-f1",
|
|
7843
|
+
"ingestion-setup-friction",
|
|
7844
|
+
"ingestion-citation-accuracy",
|
|
7845
|
+
"assistant-morning-brief",
|
|
7846
|
+
"assistant-meeting-prep",
|
|
7847
|
+
"assistant-next-best-action",
|
|
7848
|
+
"assistant-synthesis",
|
|
7849
|
+
"buffer-surprise-trigger",
|
|
7850
|
+
"contradiction-detection",
|
|
7851
|
+
"retention-aged-dataset",
|
|
7852
|
+
"memcorrect-v1",
|
|
7853
|
+
"bounded-memory-contracts",
|
|
7854
|
+
"staged-memory-synthetic-v1"
|
|
7855
|
+
]);
|
|
7856
|
+
var PUBLIC_METRIC_KEYS = Object.freeze([
|
|
7857
|
+
"recall",
|
|
7858
|
+
"precision",
|
|
7859
|
+
"f1",
|
|
7860
|
+
"exact_match",
|
|
7861
|
+
"category_match",
|
|
7862
|
+
"keyword_overlap",
|
|
7863
|
+
"high_confidence",
|
|
7864
|
+
"latencyMs",
|
|
7865
|
+
"tokens",
|
|
7866
|
+
"cost",
|
|
7867
|
+
"qrel_at_1",
|
|
7868
|
+
"qrel_at_3",
|
|
7869
|
+
"qrel_at_5",
|
|
7870
|
+
"qrel_at_10",
|
|
7871
|
+
"bleu",
|
|
7872
|
+
"rouge",
|
|
7873
|
+
"support",
|
|
7874
|
+
"completeness"
|
|
7875
|
+
]);
|
|
7876
|
+
var METRIC_KEY_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
7877
|
+
function summarizeBenchScorecard(raw) {
|
|
7878
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
7879
|
+
const summary = {};
|
|
7880
|
+
const rawId = readBenchmarkId(raw);
|
|
7881
|
+
if (rawId !== void 0) {
|
|
7882
|
+
summary.benchmarkId = PUBLIC_BENCHMARK_IDS.includes(rawId) ? rawId : "custom";
|
|
7883
|
+
}
|
|
7884
|
+
const tasks = readNested(raw, "results", "tasks") ?? readOwn(raw, "tasks");
|
|
7885
|
+
if (Array.isArray(tasks)) summary.taskCount = tasks.length;
|
|
7886
|
+
const aggregates = readNested(raw, "results", "aggregates") ?? readOwn(raw, "scores");
|
|
7887
|
+
const scores = extractNumericScores(aggregates);
|
|
7888
|
+
if (scores !== void 0) summary.scores = scores;
|
|
7889
|
+
return Object.keys(summary).length > 0 ? summary : void 0;
|
|
7890
|
+
}
|
|
7891
|
+
function readOwn(source, key) {
|
|
7892
|
+
return Object.hasOwn(source, key) ? source[key] : void 0;
|
|
7893
|
+
}
|
|
7894
|
+
function readNested(source, ...path24) {
|
|
7895
|
+
let current = source;
|
|
7896
|
+
for (const key of path24) {
|
|
7897
|
+
if (typeof current !== "object" || current === null) return void 0;
|
|
7898
|
+
if (!Object.hasOwn(current, key)) return void 0;
|
|
7899
|
+
current = current[key];
|
|
7900
|
+
}
|
|
7901
|
+
return current;
|
|
7902
|
+
}
|
|
7903
|
+
function readBenchmarkId(raw) {
|
|
7904
|
+
const metaId = readNested(raw, "meta", "benchmark");
|
|
7905
|
+
if (typeof metaId === "string" && metaId.length > 0) return metaId;
|
|
7906
|
+
const bench = readOwn(raw, "benchmark");
|
|
7907
|
+
if (typeof bench === "object" && bench !== null) {
|
|
7908
|
+
const id = readOwn(bench, "id");
|
|
7909
|
+
if (typeof id === "string" && id.length > 0) return id;
|
|
7910
|
+
}
|
|
7911
|
+
return void 0;
|
|
7912
|
+
}
|
|
7913
|
+
function extractNumericScores(source) {
|
|
7914
|
+
if (typeof source !== "object" || source === null) return void 0;
|
|
7915
|
+
const scores = {};
|
|
7916
|
+
for (const key of Object.getOwnPropertyNames(source)) {
|
|
7917
|
+
if (!Object.hasOwn(source, key)) continue;
|
|
7918
|
+
if (!PUBLIC_METRIC_KEYS.includes(key)) continue;
|
|
7919
|
+
if (!METRIC_KEY_PATTERN.test(key)) continue;
|
|
7920
|
+
const value = readOwn(source, key);
|
|
7921
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
7922
|
+
scores[key] = value;
|
|
7923
|
+
continue;
|
|
7924
|
+
}
|
|
7925
|
+
if (typeof value === "object" && value !== null) {
|
|
7926
|
+
const mean = readOwn(value, "mean");
|
|
7927
|
+
if (typeof mean === "number" && Number.isFinite(mean)) scores[key] = mean;
|
|
7928
|
+
}
|
|
7929
|
+
}
|
|
7930
|
+
return Object.keys(scores).length > 0 ? scores : void 0;
|
|
7931
|
+
}
|
|
7932
|
+
async function buildReport(options = {}) {
|
|
7933
|
+
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7934
|
+
const platform = { os: os2.platform(), arch: os2.arch(), node: process.version };
|
|
7935
|
+
let remnicVersion = "unknown";
|
|
7936
|
+
try {
|
|
7937
|
+
const pkgPath = __require.resolve("@remnic/core/package.json");
|
|
7938
|
+
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
7939
|
+
remnicVersion = pkg.version ?? "unknown";
|
|
7940
|
+
} catch {
|
|
7941
|
+
}
|
|
7942
|
+
const doctor = runDoctorChecks();
|
|
7943
|
+
let configShape = {};
|
|
7944
|
+
try {
|
|
7945
|
+
const configPath = findConfigPath();
|
|
7946
|
+
if (configPath) {
|
|
7947
|
+
const raw = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
7948
|
+
const remnicCfg = raw?.plugins?.["remnic"] ?? raw?.plugins?.["openclaw-engram"] ?? {};
|
|
7949
|
+
configShape = extractConfigShape(remnicCfg);
|
|
7950
|
+
}
|
|
7951
|
+
} catch {
|
|
7952
|
+
}
|
|
7953
|
+
const memoryDir = findMemoryDir(findConfigPath());
|
|
7954
|
+
const totalMemories = countMemories(memoryDir);
|
|
7955
|
+
const storeBytes = sizeOfStore(memoryDir);
|
|
7956
|
+
const sizeBucketLabel = sizeBucket(storeBytes);
|
|
7957
|
+
let benchScorecard;
|
|
7958
|
+
if (options.includeBench) {
|
|
7959
|
+
const scorecardPath = path16.join(os2.homedir(), ".remnic", "reports", "bench-scorecard.json");
|
|
7960
|
+
try {
|
|
7961
|
+
const raw = JSON.parse(await readFile3(scorecardPath, "utf-8"));
|
|
7962
|
+
benchScorecard = summarizeBenchScorecard(raw);
|
|
7963
|
+
} catch {
|
|
7964
|
+
}
|
|
7965
|
+
}
|
|
7966
|
+
return {
|
|
7967
|
+
schemaVersion: "1",
|
|
7968
|
+
generatedAt,
|
|
7969
|
+
platform,
|
|
7970
|
+
remnicVersion,
|
|
7971
|
+
doctor,
|
|
7972
|
+
configShape,
|
|
7973
|
+
storeScale: { totalMemories, sizeBucket: sizeBucketLabel },
|
|
7974
|
+
...benchScorecard !== void 0 ? { benchScorecard } : {}
|
|
7975
|
+
};
|
|
7976
|
+
}
|
|
7977
|
+
function renderReportMarkdown(report) {
|
|
7978
|
+
const lines = [
|
|
7979
|
+
"## Remnic Diagnostic Report",
|
|
7980
|
+
"",
|
|
7981
|
+
`Generated: ${report.generatedAt}`,
|
|
7982
|
+
`Version: ${report.remnicVersion}`,
|
|
7983
|
+
`Platform: ${report.platform.os} ${report.platform.arch} (Node ${report.platform.node})`,
|
|
7984
|
+
"",
|
|
7985
|
+
"### Doctor Checks",
|
|
7986
|
+
"",
|
|
7987
|
+
"| Check | Status |",
|
|
7988
|
+
"| --- | --- |"
|
|
7989
|
+
];
|
|
7990
|
+
for (const check of report.doctor) {
|
|
7991
|
+
lines.push(`| ${check.name} | ${check.ok ? "Pass" : "Fail"} |`);
|
|
7992
|
+
}
|
|
7993
|
+
lines.push("", "### Config Shape (allow-list only)", "");
|
|
7994
|
+
const keys = Object.getOwnPropertyNames(report.configShape).sort();
|
|
7995
|
+
lines.push("| Field | Value |");
|
|
7996
|
+
lines.push("| --- | --- |");
|
|
7997
|
+
for (const key of keys) {
|
|
7998
|
+
lines.push(`| ${key} | ${JSON.stringify(report.configShape[key])} |`);
|
|
7999
|
+
}
|
|
8000
|
+
lines.push("", "### Store Scale", "");
|
|
8001
|
+
lines.push("| Metric | Value |");
|
|
8002
|
+
lines.push("| --- | --- |");
|
|
8003
|
+
lines.push(`| Total memories | ${report.storeScale.totalMemories} |`);
|
|
8004
|
+
lines.push(`| Store size | ${report.storeScale.sizeBucket} |`);
|
|
8005
|
+
if (report.benchScorecard !== void 0) {
|
|
8006
|
+
lines.push("", "### Bench Scorecard", "");
|
|
8007
|
+
lines.push("```json");
|
|
8008
|
+
lines.push(JSON.stringify(report.benchScorecard, null, 2));
|
|
8009
|
+
lines.push("```");
|
|
8010
|
+
}
|
|
8011
|
+
lines.push("", "---", "", "**Privacy:** This report contains only the fields listed above.");
|
|
8012
|
+
lines.push("No secrets, paths, hostnames, or personal data are included.");
|
|
8013
|
+
lines.push("", "To file an issue, paste the above into a new GitHub issue at:");
|
|
8014
|
+
lines.push("https://github.com/joshuaswarren/remnic/issues/new");
|
|
8015
|
+
return lines.join("\n");
|
|
8016
|
+
}
|
|
8017
|
+
function renderReportJson(report) {
|
|
8018
|
+
return JSON.stringify(report, null, 2);
|
|
8019
|
+
}
|
|
8020
|
+
async function cmdReport(options = {}) {
|
|
8021
|
+
const reportDir = path16.join(os2.homedir(), ".remnic", "reports");
|
|
8022
|
+
mkdirSync(reportDir, { recursive: true });
|
|
8023
|
+
const report = await buildReport({ includeBench: options.includeBench });
|
|
8024
|
+
const dateStr = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "");
|
|
8025
|
+
const mdPath = path16.join(reportDir, `report-${dateStr}.md`);
|
|
8026
|
+
const jsonPath = path16.join(reportDir, `report-${dateStr}.json`);
|
|
8027
|
+
const md = renderReportMarkdown(report);
|
|
8028
|
+
const json = renderReportJson(report);
|
|
8029
|
+
writeFileSync(mdPath, md, "utf-8");
|
|
8030
|
+
writeFileSync(jsonPath, json, "utf-8");
|
|
8031
|
+
if (options.json) {
|
|
8032
|
+
console.log(json);
|
|
8033
|
+
} else {
|
|
8034
|
+
console.log(md);
|
|
8035
|
+
}
|
|
8036
|
+
console.log(`
|
|
8037
|
+
Report saved to:
|
|
8038
|
+
${mdPath}
|
|
8039
|
+
${jsonPath}`);
|
|
8040
|
+
console.log("\nTo file an issue, run:");
|
|
8041
|
+
console.log(` gh issue create --title "Remnic diagnostic report ${dateStr}" --body-file "${mdPath}"`);
|
|
8042
|
+
console.log("\nOr paste the report at: https://github.com/joshuaswarren/remnic/issues/new");
|
|
8043
|
+
}
|
|
8044
|
+
|
|
7687
8045
|
// src/remote-daemon.ts
|
|
7688
8046
|
import fs28 from "fs";
|
|
7689
8047
|
import { readCompatEnv } from "@remnic/core";
|
|
@@ -7936,13 +8294,58 @@ async function remoteRecallXray(daemon, request) {
|
|
|
7936
8294
|
}
|
|
7937
8295
|
return { snapshotFound: false };
|
|
7938
8296
|
}
|
|
8297
|
+
async function remoteRecallWhy(daemon, request) {
|
|
8298
|
+
const params = new URLSearchParams({ q: request.query });
|
|
8299
|
+
if (request.expect !== void 0 && request.expect.length > 0) {
|
|
8300
|
+
params.set("expect", request.expect);
|
|
8301
|
+
}
|
|
8302
|
+
if (request.namespace !== void 0 && request.namespace.length > 0) {
|
|
8303
|
+
params.set("namespace", request.namespace);
|
|
8304
|
+
}
|
|
8305
|
+
if (request.sessionKey !== void 0 && request.sessionKey.length > 0) {
|
|
8306
|
+
params.set("session", request.sessionKey);
|
|
8307
|
+
}
|
|
8308
|
+
let response;
|
|
8309
|
+
try {
|
|
8310
|
+
response = await daemonFetch(
|
|
8311
|
+
daemon.baseUrl,
|
|
8312
|
+
`engram/v1/recall/why?${params.toString()}`,
|
|
8313
|
+
daemon.token,
|
|
8314
|
+
1e4
|
|
8315
|
+
);
|
|
8316
|
+
} catch (err) {
|
|
8317
|
+
if (isTransportError(err)) throw unreachableError(daemon.baseUrl);
|
|
8318
|
+
throw err;
|
|
8319
|
+
}
|
|
8320
|
+
if (response.status === 401) {
|
|
8321
|
+
throw new Error(
|
|
8322
|
+
`token rejected by remnic-server at ${daemon.baseUrl} (HTTP 401). Update server.authToken or REMNIC_AUTH_TOKEN to match the remote daemon.`
|
|
8323
|
+
);
|
|
8324
|
+
}
|
|
8325
|
+
if (!response.ok) {
|
|
8326
|
+
throw new Error(`remnic-server returned HTTP ${response.status} ${response.statusText}`);
|
|
8327
|
+
}
|
|
8328
|
+
let payload;
|
|
8329
|
+
try {
|
|
8330
|
+
payload = await response.json();
|
|
8331
|
+
} catch {
|
|
8332
|
+
throw new Error("remnic-server returned a non-JSON response");
|
|
8333
|
+
}
|
|
8334
|
+
if (payload !== null && typeof payload === "object" && !Array.isArray(payload)) {
|
|
8335
|
+
const record2 = payload;
|
|
8336
|
+
if (record2.reportFound === true && record2.report !== null && typeof record2.report === "object") {
|
|
8337
|
+
return { reportFound: true, report: record2.report };
|
|
8338
|
+
}
|
|
8339
|
+
}
|
|
8340
|
+
return { reportFound: false };
|
|
8341
|
+
}
|
|
7939
8342
|
|
|
7940
8343
|
// src/daemon-service.ts
|
|
7941
8344
|
import fs29 from "fs";
|
|
7942
|
-
import
|
|
8345
|
+
import path17 from "path";
|
|
7943
8346
|
import * as childProcess from "child_process";
|
|
7944
8347
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
7945
|
-
var thisModuleDir =
|
|
8348
|
+
var thisModuleDir = path17.dirname(fileURLToPath5(import.meta.url));
|
|
7946
8349
|
function launchdLoadPlist(plistPath, processApi = childProcess) {
|
|
7947
8350
|
processApi.execFileSync("launchctl", ["load", "-w", plistPath], { stdio: "pipe" });
|
|
7948
8351
|
}
|
|
@@ -7950,7 +8353,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
7950
8353
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
7951
8354
|
}
|
|
7952
8355
|
function resolveServerBinDetails(options = {}) {
|
|
7953
|
-
const
|
|
8356
|
+
const existsSync5 = options.existsSync ?? fs29.existsSync;
|
|
7954
8357
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
7955
8358
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
7956
8359
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -7964,8 +8367,8 @@ function resolveServerBinDetails(options = {}) {
|
|
|
7964
8367
|
});
|
|
7965
8368
|
} catch {
|
|
7966
8369
|
}
|
|
7967
|
-
const workspaceServerBin =
|
|
7968
|
-
const workspaceDistIndex =
|
|
8370
|
+
const workspaceServerBin = path17.resolve(moduleDir, "../../remnic-server/bin/remnic-server.js");
|
|
8371
|
+
const workspaceDistIndex = path17.resolve(moduleDir, "../../remnic-server/dist/index.js");
|
|
7969
8372
|
candidates.push(
|
|
7970
8373
|
{
|
|
7971
8374
|
path: workspaceServerBin,
|
|
@@ -7986,15 +8389,15 @@ function resolveServerBinDetails(options = {}) {
|
|
|
7986
8389
|
});
|
|
7987
8390
|
}
|
|
7988
8391
|
candidates.push({
|
|
7989
|
-
path:
|
|
8392
|
+
path: path17.resolve(moduleDir, "../../remnic-server/src/index.ts"),
|
|
7990
8393
|
source: "workspace-source"
|
|
7991
8394
|
});
|
|
7992
|
-
const selected = candidates.find((candidate) => isCandidateReady(candidate,
|
|
7993
|
-
path:
|
|
8395
|
+
const selected = candidates.find((candidate) => isCandidateReady(candidate, existsSync5)) ?? candidates.find((candidate) => existsSync5(candidate.path)) ?? candidates[0] ?? {
|
|
8396
|
+
path: path17.resolve(moduleDir, "../../remnic-server/dist/index.js"),
|
|
7994
8397
|
source: "workspace-dist"
|
|
7995
8398
|
};
|
|
7996
|
-
const exists =
|
|
7997
|
-
const requiredExists = selected.requiredPath ?
|
|
8399
|
+
const exists = existsSync5(selected.path);
|
|
8400
|
+
const requiredExists = selected.requiredPath ? existsSync5(selected.requiredPath) : true;
|
|
7998
8401
|
const { requiredPath: _requiredPath, ...publicSelected } = selected;
|
|
7999
8402
|
return {
|
|
8000
8403
|
...publicSelected,
|
|
@@ -8002,14 +8405,14 @@ function resolveServerBinDetails(options = {}) {
|
|
|
8002
8405
|
loadableByNode: exists && requiredExists && !selected.path.endsWith(".ts")
|
|
8003
8406
|
};
|
|
8004
8407
|
}
|
|
8005
|
-
function isCandidateReady(candidate,
|
|
8006
|
-
return
|
|
8408
|
+
function isCandidateReady(candidate, existsSync5) {
|
|
8409
|
+
return existsSync5(candidate.path) && (candidate.requiredPath ? existsSync5(candidate.requiredPath) : true);
|
|
8007
8410
|
}
|
|
8008
8411
|
function resolveServerBin(options = {}) {
|
|
8009
8412
|
return resolveServerBinDetails(options).path;
|
|
8010
8413
|
}
|
|
8011
8414
|
function readVerifiedDaemonPid(options) {
|
|
8012
|
-
const
|
|
8415
|
+
const readFileSync6 = options.readFileSync ?? fs29.readFileSync;
|
|
8013
8416
|
const unlinkSync = options.unlinkSync ?? fs29.unlinkSync;
|
|
8014
8417
|
const processKill = options.processKill ?? process.kill;
|
|
8015
8418
|
const platform = options.platform ?? process.platform;
|
|
@@ -8017,7 +8420,7 @@ function readVerifiedDaemonPid(options) {
|
|
|
8017
8420
|
for (const file of options.pidFiles) {
|
|
8018
8421
|
let pid;
|
|
8019
8422
|
try {
|
|
8020
|
-
pid = parseDaemonPid(
|
|
8423
|
+
pid = parseDaemonPid(readFileSync6(file, "utf8"));
|
|
8021
8424
|
} catch {
|
|
8022
8425
|
continue;
|
|
8023
8426
|
}
|
|
@@ -8045,7 +8448,7 @@ function readVerifiedDaemonPid(options) {
|
|
|
8045
8448
|
}
|
|
8046
8449
|
function doesProcessCommandLookLikeRemnicDaemon(command, expectedServerBin) {
|
|
8047
8450
|
const normalizedCommand = command.trim();
|
|
8048
|
-
const normalizedExpected =
|
|
8451
|
+
const normalizedExpected = path17.resolve(expandTilde(expectedServerBin));
|
|
8049
8452
|
return normalizedCommand.includes(normalizedExpected) || /(?:^|\s|[/\\])(?:remnic-server|engram-server)(?:\.js)?(?:\s|$)/.test(normalizedCommand) || /@remnic[/\\]server[/\\]/.test(normalizedCommand) || /packages[/\\]remnic-server[/\\](?:bin[/\\]remnic-server\.js|dist[/\\]index\.js|src[/\\]index\.ts)/.test(normalizedCommand);
|
|
8050
8453
|
}
|
|
8051
8454
|
function parseDaemonPid(raw) {
|
|
@@ -8110,9 +8513,9 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
8110
8513
|
}
|
|
8111
8514
|
}
|
|
8112
8515
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
8113
|
-
const
|
|
8114
|
-
const
|
|
8115
|
-
if (!
|
|
8516
|
+
const existsSync5 = options.existsSync ?? fs29.existsSync;
|
|
8517
|
+
const readFileSync6 = options.readFileSync ?? fs29.readFileSync;
|
|
8518
|
+
if (!existsSync5(plistPath)) {
|
|
8116
8519
|
return {
|
|
8117
8520
|
installed: false,
|
|
8118
8521
|
ok: true,
|
|
@@ -8122,7 +8525,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
8122
8525
|
}
|
|
8123
8526
|
let content;
|
|
8124
8527
|
try {
|
|
8125
|
-
content =
|
|
8528
|
+
content = readFileSync6(plistPath, "utf8");
|
|
8126
8529
|
} catch {
|
|
8127
8530
|
return {
|
|
8128
8531
|
installed: true,
|
|
@@ -8150,7 +8553,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
8150
8553
|
};
|
|
8151
8554
|
}
|
|
8152
8555
|
const expandedServerArg = expandTilde(serverArg);
|
|
8153
|
-
if (!
|
|
8556
|
+
if (!path17.isAbsolute(expandedServerArg)) {
|
|
8154
8557
|
return {
|
|
8155
8558
|
installed: true,
|
|
8156
8559
|
ok: false,
|
|
@@ -8158,7 +8561,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
8158
8561
|
remediation: "Run `remnic daemon install` so launchd uses an absolute Remnic server path."
|
|
8159
8562
|
};
|
|
8160
8563
|
}
|
|
8161
|
-
if (!
|
|
8564
|
+
if (!existsSync5(expandedServerArg)) {
|
|
8162
8565
|
return {
|
|
8163
8566
|
installed: true,
|
|
8164
8567
|
ok: false,
|
|
@@ -8222,8 +8625,8 @@ function normalizeResolvedPath(resolved) {
|
|
|
8222
8625
|
return resolved;
|
|
8223
8626
|
}
|
|
8224
8627
|
function packageServerBinFromEntry(packageEntry) {
|
|
8225
|
-
if (
|
|
8226
|
-
return
|
|
8628
|
+
if (path17.basename(packageEntry) === "index.js" && path17.basename(path17.dirname(packageEntry)) === "dist") {
|
|
8629
|
+
return path17.join(path17.dirname(path17.dirname(packageEntry)), "bin", "remnic-server.js");
|
|
8227
8630
|
}
|
|
8228
8631
|
return packageEntry;
|
|
8229
8632
|
}
|
|
@@ -8297,8 +8700,8 @@ import {
|
|
|
8297
8700
|
} from "@remnic/core";
|
|
8298
8701
|
|
|
8299
8702
|
// src/import-bundle-detect.ts
|
|
8300
|
-
import { lstatSync as lstatSync3, readdirSync as
|
|
8301
|
-
import
|
|
8703
|
+
import { lstatSync as lstatSync3, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "fs";
|
|
8704
|
+
import path18 from "path";
|
|
8302
8705
|
function detectBundleEntries(bundleDir, options = {}) {
|
|
8303
8706
|
const readdir4 = options.readdirImpl ?? defaultReaddir;
|
|
8304
8707
|
const readFileImpl = options.readFileImpl ?? defaultReadFile;
|
|
@@ -8329,7 +8732,7 @@ function detectBundleEntries(bundleDir, options = {}) {
|
|
|
8329
8732
|
for (const filePath of roots) {
|
|
8330
8733
|
if (seenFiles.has(filePath)) continue;
|
|
8331
8734
|
seenFiles.add(filePath);
|
|
8332
|
-
const name =
|
|
8735
|
+
const name = path18.basename(filePath);
|
|
8333
8736
|
const match = classifyFile(name, filePath, readFileImpl);
|
|
8334
8737
|
if (match) entries.push(match);
|
|
8335
8738
|
}
|
|
@@ -8367,7 +8770,7 @@ function collectCandidatePaths(root, readdir4, isDirectory2, isRegularFile) {
|
|
|
8367
8770
|
return;
|
|
8368
8771
|
}
|
|
8369
8772
|
for (const entry of entries) {
|
|
8370
|
-
const full =
|
|
8773
|
+
const full = path18.join(dir, entry);
|
|
8371
8774
|
if (isDirectory2(full)) {
|
|
8372
8775
|
walk(full, depth + 1);
|
|
8373
8776
|
} else if (isRegularFile(full)) {
|
|
@@ -8416,10 +8819,10 @@ function disambiguateConversations(filePath, readFileImpl) {
|
|
|
8416
8819
|
return "chatgpt";
|
|
8417
8820
|
}
|
|
8418
8821
|
function defaultReaddir(dir) {
|
|
8419
|
-
return
|
|
8822
|
+
return readdirSync3(dir);
|
|
8420
8823
|
}
|
|
8421
8824
|
function defaultReadFile(p) {
|
|
8422
|
-
return
|
|
8825
|
+
return readFileSync5(p, "utf-8");
|
|
8423
8826
|
}
|
|
8424
8827
|
function defaultIsDirectory(p) {
|
|
8425
8828
|
try {
|
|
@@ -8923,7 +9326,7 @@ async function cmdCapture(rest, io) {
|
|
|
8923
9326
|
|
|
8924
9327
|
// src/import-lossless-claw-cmd.ts
|
|
8925
9328
|
import fs31 from "fs";
|
|
8926
|
-
import
|
|
9329
|
+
import path19 from "path";
|
|
8927
9330
|
import {
|
|
8928
9331
|
applyLcmSchema,
|
|
8929
9332
|
ensureLcmStateDir,
|
|
@@ -9073,7 +9476,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
9073
9476
|
let destDb;
|
|
9074
9477
|
try {
|
|
9075
9478
|
if (parsed.dryRun) {
|
|
9076
|
-
const lcmPath =
|
|
9479
|
+
const lcmPath = path19.join(memoryDir, "state", "lcm.sqlite");
|
|
9077
9480
|
if (fs31.existsSync(lcmPath)) {
|
|
9078
9481
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
9079
9482
|
} else {
|
|
@@ -9193,9 +9596,9 @@ function printBenchComparisonSummary(comparison, baseline, candidate) {
|
|
|
9193
9596
|
}
|
|
9194
9597
|
|
|
9195
9598
|
// src/bench-coding-commands.ts
|
|
9196
|
-
import { lstat as lstat3, readFile as
|
|
9197
|
-
import
|
|
9198
|
-
import
|
|
9599
|
+
import { lstat as lstat3, readFile as readFile4, realpath as realpath2, stat as stat2 } from "fs/promises";
|
|
9600
|
+
import os3 from "os";
|
|
9601
|
+
import path20 from "path";
|
|
9199
9602
|
var UINT32_MAX = 4294967295;
|
|
9200
9603
|
var FROZEN_GENERATOR_SEED = 81;
|
|
9201
9604
|
var FROZEN_TASK_COUNT = 30;
|
|
@@ -9205,7 +9608,7 @@ var FROZEN_MAX_STEPS = 12;
|
|
|
9205
9608
|
var FROZEN_MAX_TOOL_CALLS = 8;
|
|
9206
9609
|
var FROZEN_MAX_OUTPUT_CHARS = 16384;
|
|
9207
9610
|
var MAX_OUTPUT_BYTES = 16384;
|
|
9208
|
-
var DEFAULT_REPEATED_FAILURE_OUTPUT_DIR =
|
|
9611
|
+
var DEFAULT_REPEATED_FAILURE_OUTPUT_DIR = path20.join(
|
|
9209
9612
|
resolveHomeDir(),
|
|
9210
9613
|
".remnic",
|
|
9211
9614
|
"bench",
|
|
@@ -9539,7 +9942,7 @@ function parseBenchCodingArgs(args) {
|
|
|
9539
9942
|
throw new Error(`unknown bench coding subcommand ${args[0]}`);
|
|
9540
9943
|
}
|
|
9541
9944
|
function normalizeCommandPaths(command) {
|
|
9542
|
-
const resolve3 = (value) =>
|
|
9945
|
+
const resolve3 = (value) => path20.resolve(expandTilde(value));
|
|
9543
9946
|
if (command.kind === "repo-generate") {
|
|
9544
9947
|
return { ...command, outputDir: resolve3(command.outputDir) };
|
|
9545
9948
|
}
|
|
@@ -9570,23 +9973,23 @@ function normalizeCommandPaths(command) {
|
|
|
9570
9973
|
return command;
|
|
9571
9974
|
}
|
|
9572
9975
|
async function canonicalProspectivePath(value) {
|
|
9573
|
-
let candidate =
|
|
9976
|
+
let candidate = path20.resolve(value);
|
|
9574
9977
|
const missingSegments = [];
|
|
9575
9978
|
while (true) {
|
|
9576
9979
|
try {
|
|
9577
|
-
return
|
|
9980
|
+
return path20.join(await realpath2(candidate), ...missingSegments.reverse());
|
|
9578
9981
|
} catch (error) {
|
|
9579
9982
|
if (error.code !== "ENOENT") throw error;
|
|
9580
|
-
const parent =
|
|
9983
|
+
const parent = path20.dirname(candidate);
|
|
9581
9984
|
if (parent === candidate) throw error;
|
|
9582
|
-
missingSegments.push(
|
|
9985
|
+
missingSegments.push(path20.basename(candidate));
|
|
9583
9986
|
candidate = parent;
|
|
9584
9987
|
}
|
|
9585
9988
|
}
|
|
9586
9989
|
}
|
|
9587
9990
|
function isSameOrDescendant(candidate, root) {
|
|
9588
|
-
const relative2 =
|
|
9589
|
-
return relative2 === "" || relative2 !== ".." && !relative2.startsWith(`..${
|
|
9991
|
+
const relative2 = path20.relative(root, candidate);
|
|
9992
|
+
return relative2 === "" || relative2 !== ".." && !relative2.startsWith(`..${path20.sep}`) && !path20.isAbsolute(relative2);
|
|
9590
9993
|
}
|
|
9591
9994
|
async function pathExists(value) {
|
|
9592
9995
|
try {
|
|
@@ -9605,7 +10008,7 @@ async function assertSafeBenchmarkOutput(outputDir) {
|
|
|
9605
10008
|
const configured = process.env[variable]?.trim();
|
|
9606
10009
|
if (!configured) continue;
|
|
9607
10010
|
const memoryRoot = await canonicalProspectivePath(
|
|
9608
|
-
|
|
10011
|
+
path20.resolve(expandTilde(configured))
|
|
9609
10012
|
);
|
|
9610
10013
|
if (isSameOrDescendant(canonicalOutput, memoryRoot)) {
|
|
9611
10014
|
throw new Error(refusal);
|
|
@@ -9613,10 +10016,10 @@ async function assertSafeBenchmarkOutput(outputDir) {
|
|
|
9613
10016
|
}
|
|
9614
10017
|
let candidate = canonicalOutput;
|
|
9615
10018
|
while (true) {
|
|
9616
|
-
const hasProfile = await pathExists(
|
|
9617
|
-
const hasMemoryData = await pathExists(
|
|
10019
|
+
const hasProfile = await pathExists(path20.join(candidate, "profile.md"));
|
|
10020
|
+
const hasMemoryData = await pathExists(path20.join(candidate, "facts")) || await pathExists(path20.join(candidate, "entities")) || await pathExists(path20.join(candidate, "state"));
|
|
9618
10021
|
if (hasProfile && hasMemoryData) throw new Error(refusal);
|
|
9619
|
-
const parent =
|
|
10022
|
+
const parent = path20.dirname(candidate);
|
|
9620
10023
|
if (parent === candidate) break;
|
|
9621
10024
|
candidate = parent;
|
|
9622
10025
|
}
|
|
@@ -9628,7 +10031,7 @@ async function assertSafeBenchmarkOutput(outputDir) {
|
|
|
9628
10031
|
async function assertH6StatsRunDirectory(runDir, commandName = "stats") {
|
|
9629
10032
|
try {
|
|
9630
10033
|
const parsed = JSON.parse(
|
|
9631
|
-
await
|
|
10034
|
+
await readFile4(path20.join(runDir, "run.json"), "utf8")
|
|
9632
10035
|
);
|
|
9633
10036
|
if (parsed.schemaVersion !== 1 || typeof parsed.runId !== "string" || parsed.runId.length === 0 || typeof parsed.suiteVersion !== "string" || !parsed.suiteVersion.startsWith("h6-failure-gate-v1-")) {
|
|
9634
10037
|
throw new Error("invalid H6 metadata");
|
|
@@ -9638,7 +10041,7 @@ async function assertH6StatsRunDirectory(runDir, commandName = "stats") {
|
|
|
9638
10041
|
}
|
|
9639
10042
|
}
|
|
9640
10043
|
function sanitizeOutput(output) {
|
|
9641
|
-
const home =
|
|
10044
|
+
const home = os3.homedir();
|
|
9642
10045
|
const safe = home.length > 1 ? output.replaceAll(home, "~") : output;
|
|
9643
10046
|
if (Buffer.byteLength(safe, "utf8") <= MAX_OUTPUT_BYTES) return safe.trimEnd();
|
|
9644
10047
|
const bounded = Buffer.from(safe, "utf8").subarray(0, MAX_OUTPUT_BYTES - 32).toString("utf8");
|
|
@@ -9687,7 +10090,7 @@ async function runRepoVerification(command, bench) {
|
|
|
9687
10090
|
if (command.directory === void 0) {
|
|
9688
10091
|
dataset = await requireFunction(bench, "loadCommittedH6BenchmarkDataset")();
|
|
9689
10092
|
} else {
|
|
9690
|
-
const serialized = await
|
|
10093
|
+
const serialized = await readFile4(path20.join(command.directory, "dataset.json"), "utf8").catch(
|
|
9691
10094
|
() => void 0
|
|
9692
10095
|
);
|
|
9693
10096
|
if (serialized === void 0) {
|
|
@@ -9815,8 +10218,8 @@ async function cmdBenchCoding(args) {
|
|
|
9815
10218
|
}
|
|
9816
10219
|
|
|
9817
10220
|
// src/bench-security-commands.ts
|
|
9818
|
-
import
|
|
9819
|
-
var DEFAULT_OUTPUT_DIR =
|
|
10221
|
+
import path21 from "path";
|
|
10222
|
+
var DEFAULT_OUTPUT_DIR = path21.join(
|
|
9820
10223
|
resolveHomeDir(),
|
|
9821
10224
|
".remnic",
|
|
9822
10225
|
"bench",
|
|
@@ -9969,7 +10372,7 @@ ${BENCH_SECURITY_USAGE}`);
|
|
|
9969
10372
|
}
|
|
9970
10373
|
|
|
9971
10374
|
// src/bench-research-commands.ts
|
|
9972
|
-
import
|
|
10375
|
+
import path22 from "path";
|
|
9973
10376
|
function emit(result) {
|
|
9974
10377
|
if (result.output) {
|
|
9975
10378
|
console.log(result.output);
|
|
@@ -9987,7 +10390,7 @@ async function runBenchResearchCommand(parsed) {
|
|
|
9987
10390
|
emit(
|
|
9988
10391
|
await runAttributeCliCommand({
|
|
9989
10392
|
runRef: parsed.runRef,
|
|
9990
|
-
resultsDir: parsed.resultsDir ??
|
|
10393
|
+
resultsDir: parsed.resultsDir ?? path22.join(resolveHomeDir(), ".remnic", "bench", "results"),
|
|
9991
10394
|
memoryDir: parsed.memoryDir,
|
|
9992
10395
|
qmdPath: parsed.qmdPath,
|
|
9993
10396
|
collection: parsed.collection,
|
|
@@ -10257,14 +10660,14 @@ registerPublisher("hermes", () => new HermesMemoryExtensionPublisher());
|
|
|
10257
10660
|
registerPublisher("pi", () => new LazyPluginPiPublisher("pi", (mod) => mod.PiMemoryExtensionPublisher));
|
|
10258
10661
|
registerPublisher("omp", () => new LazyPluginPiPublisher("omp", (mod) => mod.OmpMemoryExtensionPublisher));
|
|
10259
10662
|
registerPublisher("prime-agent", () => new LazyPluginPiPublisher("prime-agent", (mod) => mod.PrimeAgentMemoryExtensionPublisher));
|
|
10260
|
-
var PID_DIR =
|
|
10261
|
-
var LEGACY_PID_DIR =
|
|
10262
|
-
var PID_FILE =
|
|
10263
|
-
var LEGACY_PID_FILE =
|
|
10264
|
-
var LOG_FILE =
|
|
10265
|
-
var LEGACY_LOG_FILE =
|
|
10266
|
-
var CLI_MODULE_DIR =
|
|
10267
|
-
var CLI_REPO_ROOT2 =
|
|
10663
|
+
var PID_DIR = path23.join(resolveHomeDir(), ".remnic");
|
|
10664
|
+
var LEGACY_PID_DIR = path23.join(resolveHomeDir(), ".engram");
|
|
10665
|
+
var PID_FILE = path23.join(PID_DIR, "server.pid");
|
|
10666
|
+
var LEGACY_PID_FILE = path23.join(LEGACY_PID_DIR, "server.pid");
|
|
10667
|
+
var LOG_FILE = path23.join(PID_DIR, "server.log");
|
|
10668
|
+
var LEGACY_LOG_FILE = path23.join(LEGACY_PID_DIR, "server.log");
|
|
10669
|
+
var CLI_MODULE_DIR = path23.dirname(fileURLToPath6(import.meta.url));
|
|
10670
|
+
var CLI_REPO_ROOT2 = path23.resolve(CLI_MODULE_DIR, "../../..");
|
|
10268
10671
|
var OPENCLAW_GATEWAY_LABEL = "ai.openclaw.gateway";
|
|
10269
10672
|
var CLI_SUCCESS_EXIT_GRACE_MS = 5e3;
|
|
10270
10673
|
var CLI_OUTPUT_FLUSH_GRACE_MS = 250;
|
|
@@ -10443,12 +10846,12 @@ async function resolveKnownBenchmarkIds() {
|
|
|
10443
10846
|
return knownIds;
|
|
10444
10847
|
}
|
|
10445
10848
|
function resolveBenchOutputDir() {
|
|
10446
|
-
return
|
|
10849
|
+
return path23.join(resolveHomeDir(), ".remnic", "bench", "results");
|
|
10447
10850
|
}
|
|
10448
10851
|
async function launchBenchUi(resultsDir) {
|
|
10449
|
-
const benchUiDir =
|
|
10852
|
+
const benchUiDir = path23.join(CLI_REPO_ROOT2, "packages", "bench-ui");
|
|
10450
10853
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
10451
|
-
if (!fs32.existsSync(
|
|
10854
|
+
if (!fs32.existsSync(path23.join(benchUiDir, "package.json"))) {
|
|
10452
10855
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
10453
10856
|
process.exit(1);
|
|
10454
10857
|
}
|
|
@@ -10475,11 +10878,11 @@ async function launchBenchUi(resultsDir) {
|
|
|
10475
10878
|
});
|
|
10476
10879
|
}
|
|
10477
10880
|
function resolveDatasetDownloadScriptPath() {
|
|
10478
|
-
const bundled =
|
|
10881
|
+
const bundled = path23.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
10479
10882
|
if (fs32.existsSync(bundled)) {
|
|
10480
10883
|
return bundled;
|
|
10481
10884
|
}
|
|
10482
|
-
return
|
|
10885
|
+
return path23.join(CLI_REPO_ROOT2, "packages", "remnic-cli", "assets", "download-datasets.sh");
|
|
10483
10886
|
}
|
|
10484
10887
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
10485
10888
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -10785,12 +11188,12 @@ async function exportBenchPackageResult(parsed) {
|
|
|
10785
11188
|
process.exit(1);
|
|
10786
11189
|
}
|
|
10787
11190
|
const result = await loadBenchmarkResult(summary.path);
|
|
10788
|
-
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(
|
|
11191
|
+
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(path23.dirname(summary.path), result.meta.id) : void 0;
|
|
10789
11192
|
const rendered = renderBenchmarkResultExport(result, parsed.format, {
|
|
10790
11193
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
10791
11194
|
});
|
|
10792
11195
|
if (parsed.output) {
|
|
10793
|
-
fs32.mkdirSync(
|
|
11196
|
+
fs32.mkdirSync(path23.dirname(parsed.output), { recursive: true });
|
|
10794
11197
|
fs32.writeFileSync(parsed.output, rendered);
|
|
10795
11198
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
10796
11199
|
return;
|
|
@@ -10812,7 +11215,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
10812
11215
|
return {
|
|
10813
11216
|
benchmark: benchmarkId,
|
|
10814
11217
|
downloaded: discovered !== void 0,
|
|
10815
|
-
path: discovered ? discovered.dir :
|
|
11218
|
+
path: discovered ? discovered.dir : path23.join(datasetRoot, benchmarkId),
|
|
10816
11219
|
source: discovered?.source ?? "canonical"
|
|
10817
11220
|
};
|
|
10818
11221
|
});
|
|
@@ -10847,7 +11250,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
10847
11250
|
runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, parsed.json === true);
|
|
10848
11251
|
downloaded.push({
|
|
10849
11252
|
benchmark: benchmarkId,
|
|
10850
|
-
path:
|
|
11253
|
+
path: path23.join(datasetRoot, benchmarkId)
|
|
10851
11254
|
});
|
|
10852
11255
|
}
|
|
10853
11256
|
if (parsed.json) {
|
|
@@ -10986,10 +11389,10 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
10986
11389
|
}
|
|
10987
11390
|
const bench = await loadBenchModule();
|
|
10988
11391
|
const resultsDir = expandTilde(
|
|
10989
|
-
parsed.resultsDir ??
|
|
11392
|
+
parsed.resultsDir ?? path23.join(resolveHomeDir(), ".remnic", "bench", "results")
|
|
10990
11393
|
);
|
|
10991
11394
|
const calibrationDir = expandTilde(
|
|
10992
|
-
parsed.calibrationDir ??
|
|
11395
|
+
parsed.calibrationDir ?? path23.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
10993
11396
|
);
|
|
10994
11397
|
const stored = await bench.listBenchmarkResults(resultsDir);
|
|
10995
11398
|
const allForBenchmark = stored.filter((entry) => entry.benchmark === benchmarkId);
|
|
@@ -11548,9 +11951,9 @@ async function loadPublishedPromotionHelpers() {
|
|
|
11548
11951
|
const benchModule = await loadBenchModule();
|
|
11549
11952
|
return {
|
|
11550
11953
|
async promoteArtifactsToPublished(args) {
|
|
11551
|
-
const { mkdirSync, readFileSync:
|
|
11552
|
-
const
|
|
11553
|
-
|
|
11954
|
+
const { mkdirSync: mkdirSync2, readFileSync: readFileSync6, writeFileSync: writeFileSync2 } = await import("fs");
|
|
11955
|
+
const path24 = await import("path");
|
|
11956
|
+
mkdirSync2(args.publishedOutDir, { recursive: true });
|
|
11554
11957
|
if (args.artifactPaths.length === 0) {
|
|
11555
11958
|
console.warn(
|
|
11556
11959
|
`[bench published] No artifacts produced for ${args.benchmarkId}; nothing to promote.`
|
|
@@ -11558,7 +11961,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
11558
11961
|
return;
|
|
11559
11962
|
}
|
|
11560
11963
|
for (const artifactPath of args.artifactPaths) {
|
|
11561
|
-
const raw =
|
|
11964
|
+
const raw = readFileSync6(artifactPath, "utf8");
|
|
11562
11965
|
const parsedUnknown = JSON.parse(raw);
|
|
11563
11966
|
const parsedObj = parsedUnknown !== null && typeof parsedUnknown === "object" && !Array.isArray(parsedUnknown) ? parsedUnknown : {};
|
|
11564
11967
|
const gitShaShort = (parsedObj.meta?.gitSha ?? "unknown").slice(0, 7);
|
|
@@ -11566,13 +11969,13 @@ async function loadPublishedPromotionHelpers() {
|
|
|
11566
11969
|
const modelSlug = args.model.replace(/[^a-zA-Z0-9_.-]/g, "-");
|
|
11567
11970
|
const rawProfile = parsedObj.config?.runtimeProfile;
|
|
11568
11971
|
const profileSlug = typeof rawProfile === "string" && rawProfile.length > 0 ? `-${rawProfile.replace(/[^a-zA-Z0-9_.-]/g, "-")}` : "";
|
|
11569
|
-
const target =
|
|
11972
|
+
const target = path24.join(
|
|
11570
11973
|
args.publishedOutDir,
|
|
11571
11974
|
`${today}-${args.benchmarkId}-${modelSlug}${profileSlug}-${gitShaShort}.json`
|
|
11572
11975
|
);
|
|
11573
|
-
|
|
11976
|
+
writeFileSync2(target, raw, "utf8");
|
|
11574
11977
|
console.log(
|
|
11575
|
-
`[bench published] Promoted ${
|
|
11978
|
+
`[bench published] Promoted ${path24.basename(artifactPath)} \u2192 ${target}`
|
|
11576
11979
|
);
|
|
11577
11980
|
}
|
|
11578
11981
|
void benchModule;
|
|
@@ -11679,7 +12082,7 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
|
|
|
11679
12082
|
const previousCodexDiagnosticsDir = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV];
|
|
11680
12083
|
const previousCodexDiagnosticsMode = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_MODE_ENV];
|
|
11681
12084
|
if (!previousCodexDiagnosticsDir) {
|
|
11682
|
-
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] =
|
|
12085
|
+
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] = path23.join(
|
|
11683
12086
|
outputDir,
|
|
11684
12087
|
"codex-cli-diagnostics"
|
|
11685
12088
|
);
|
|
@@ -11829,7 +12232,7 @@ async function preparePersistedJudgeCalibrationAttachment(benchModule, benchmark
|
|
|
11829
12232
|
);
|
|
11830
12233
|
}
|
|
11831
12234
|
const calibrationDir = expandTilde(
|
|
11832
|
-
calibrationBinding.calibrationDir ??
|
|
12235
|
+
calibrationBinding.calibrationDir ?? path23.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
11833
12236
|
);
|
|
11834
12237
|
const state = await benchModule.loadJudgeCalibrationState?.(benchmarkId, calibrationDir);
|
|
11835
12238
|
if (!state) {
|
|
@@ -12311,7 +12714,7 @@ async function resolvePackageBenchRuntime(benchModule, parsed, runtimeProfile) {
|
|
|
12311
12714
|
);
|
|
12312
12715
|
}
|
|
12313
12716
|
function normalizeMemoryDirPath(memoryDir) {
|
|
12314
|
-
return
|
|
12717
|
+
return path23.resolve(expandTilde(memoryDir));
|
|
12315
12718
|
}
|
|
12316
12719
|
function resolveMemoryDir() {
|
|
12317
12720
|
const configMemoryDir = (() => {
|
|
@@ -12324,9 +12727,9 @@ function resolveMemoryDir() {
|
|
|
12324
12727
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
12325
12728
|
}
|
|
12326
12729
|
const home = resolveHomeDir();
|
|
12327
|
-
const standalonePath =
|
|
12328
|
-
const legacyStandalonePath =
|
|
12329
|
-
const openclawPath =
|
|
12730
|
+
const standalonePath = path23.join(home, ".remnic", "memory");
|
|
12731
|
+
const legacyStandalonePath = path23.join(home, ".engram", "memory");
|
|
12732
|
+
const openclawPath = path23.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
12330
12733
|
if (fs32.existsSync(standalonePath)) return standalonePath;
|
|
12331
12734
|
if (fs32.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
12332
12735
|
return openclawPath;
|
|
@@ -12375,21 +12778,21 @@ function resolveFlagStrict(args, flag) {
|
|
|
12375
12778
|
var REMNIC_OPENCLAW_LEGACY_PLUGIN_ID = "openclaw-engram";
|
|
12376
12779
|
function resolveOpenclawStateDir() {
|
|
12377
12780
|
const configuredStateDir = process.env.OPENCLAW_STATE_DIR?.trim();
|
|
12378
|
-
return configuredStateDir ?
|
|
12781
|
+
return configuredStateDir ? path23.resolve(expandTilde(configuredStateDir)) : path23.join(resolveHomeDir(), ".openclaw");
|
|
12379
12782
|
}
|
|
12380
12783
|
var DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR = [
|
|
12381
12784
|
process.env.OPENCLAW_CONFIG_PATH,
|
|
12382
12785
|
process.env.OPENCLAW_ENGRAM_CONFIG_PATH,
|
|
12383
|
-
|
|
12786
|
+
path23.join(resolveOpenclawStateDir(), "openclaw.json")
|
|
12384
12787
|
].filter(Boolean);
|
|
12385
12788
|
function resolveOpenclawConfigPath(cliPath) {
|
|
12386
|
-
if (cliPath) return
|
|
12789
|
+
if (cliPath) return path23.resolve(expandTilde(cliPath));
|
|
12387
12790
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
12388
|
-
if (envPath) return
|
|
12791
|
+
if (envPath) return path23.resolve(expandTilde(envPath));
|
|
12389
12792
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
12390
12793
|
if (fs32.existsSync(candidate)) return candidate;
|
|
12391
12794
|
}
|
|
12392
|
-
return
|
|
12795
|
+
return path23.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
12393
12796
|
}
|
|
12394
12797
|
function readOpenclawConfig(configPath) {
|
|
12395
12798
|
if (!fs32.existsSync(configPath)) return {};
|
|
@@ -12448,10 +12851,10 @@ function buildRemnicOpenclawHooksPolicy(legacyHooks, existingHooks) {
|
|
|
12448
12851
|
function resolveOpenclawInstallMemoryDir(args) {
|
|
12449
12852
|
const existingMemoryDir = (typeof args.existingNewEntryConfig.memoryDir === "string" ? args.existingNewEntryConfig.memoryDir : void 0) || (args.migrateLegacy && typeof args.legacyConfigToMerge.memoryDir === "string" ? args.legacyConfigToMerge.memoryDir : void 0);
|
|
12450
12853
|
if (args.requestedMemoryDir) {
|
|
12451
|
-
return
|
|
12854
|
+
return path23.resolve(expandTilde(args.requestedMemoryDir));
|
|
12452
12855
|
}
|
|
12453
12856
|
if (existingMemoryDir) {
|
|
12454
|
-
return
|
|
12857
|
+
return path23.resolve(expandTilde(existingMemoryDir));
|
|
12455
12858
|
}
|
|
12456
12859
|
return args.fallbackMemoryDir;
|
|
12457
12860
|
}
|
|
@@ -12469,21 +12872,21 @@ function resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir) {
|
|
|
12469
12872
|
if (!config || typeof config !== "object" || Array.isArray(config)) continue;
|
|
12470
12873
|
const memoryDir = config.memoryDir;
|
|
12471
12874
|
if (typeof memoryDir === "string" && memoryDir.trim().length > 0) {
|
|
12472
|
-
return
|
|
12875
|
+
return path23.resolve(expandTilde(memoryDir));
|
|
12473
12876
|
}
|
|
12474
12877
|
}
|
|
12475
12878
|
return fallbackMemoryDir;
|
|
12476
12879
|
}
|
|
12477
12880
|
function resolveOpenclawPluginDir(cliPath) {
|
|
12478
|
-
if (cliPath) return
|
|
12881
|
+
if (cliPath) return path23.resolve(expandTilde(cliPath));
|
|
12479
12882
|
return resolveOpenclawManagedPluginDir();
|
|
12480
12883
|
}
|
|
12481
12884
|
function resolveOpenclawManagedPluginDir() {
|
|
12482
|
-
return
|
|
12885
|
+
return path23.join(resolveOpenclawStateDir(), "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
12483
12886
|
}
|
|
12484
12887
|
function resolveOpenclawLegacyPluginDir(cliPath) {
|
|
12485
|
-
if (cliPath) return
|
|
12486
|
-
return
|
|
12888
|
+
if (cliPath) return path23.resolve(expandTilde(cliPath));
|
|
12889
|
+
return path23.join(resolveOpenclawStateDir(), "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID);
|
|
12487
12890
|
}
|
|
12488
12891
|
function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
12489
12892
|
const yyyy = now.getFullYear().toString();
|
|
@@ -12496,7 +12899,7 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
12496
12899
|
}
|
|
12497
12900
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
12498
12901
|
if (!fs32.existsSync(sourcePath)) return false;
|
|
12499
|
-
fs32.mkdirSync(
|
|
12902
|
+
fs32.mkdirSync(path23.dirname(backupPath), { recursive: true });
|
|
12500
12903
|
fs32.cpSync(sourcePath, backupPath, { recursive: true });
|
|
12501
12904
|
return true;
|
|
12502
12905
|
}
|
|
@@ -12515,7 +12918,7 @@ function restartOpenclawGateway() {
|
|
|
12515
12918
|
});
|
|
12516
12919
|
}
|
|
12517
12920
|
function cmdInit() {
|
|
12518
|
-
const configPath =
|
|
12921
|
+
const configPath = path23.join(process.cwd(), "remnic.config.json");
|
|
12519
12922
|
if (fs32.existsSync(configPath)) {
|
|
12520
12923
|
console.log(`Config already exists: ${configPath}`);
|
|
12521
12924
|
return;
|
|
@@ -12523,7 +12926,7 @@ function cmdInit() {
|
|
|
12523
12926
|
const template = {
|
|
12524
12927
|
remnic: {
|
|
12525
12928
|
openaiApiKey: "${OPENAI_API_KEY}",
|
|
12526
|
-
memoryDir:
|
|
12929
|
+
memoryDir: path23.join(process.cwd(), ".remnic", "memory"),
|
|
12527
12930
|
memoryOsPreset: "balanced"
|
|
12528
12931
|
},
|
|
12529
12932
|
server: {
|
|
@@ -12585,7 +12988,7 @@ async function cmdStatus(json) {
|
|
|
12585
12988
|
console.log(`Remnic server: running${pid ? ` (pid ${pid})` : ""}`);
|
|
12586
12989
|
await printHealthCheck(resolveDaemonBaseUrl(resolveConfigPath()), resolveStatusProbeToken());
|
|
12587
12990
|
}
|
|
12588
|
-
async function oauthFetch(method,
|
|
12991
|
+
async function oauthFetch(method, path24, token, body) {
|
|
12589
12992
|
const controller = new AbortController();
|
|
12590
12993
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
12591
12994
|
try {
|
|
@@ -12604,7 +13007,7 @@ async function oauthFetch(method, path23, token, body) {
|
|
|
12604
13007
|
if (body !== void 0) {
|
|
12605
13008
|
init.body = JSON.stringify(body);
|
|
12606
13009
|
}
|
|
12607
|
-
const response = await fetch(`${resolveDaemonBaseUrl(resolveConfigPath())}${
|
|
13010
|
+
const response = await fetch(`${resolveDaemonBaseUrl(resolveConfigPath())}${path24}`, init);
|
|
12608
13011
|
if (response.status === 401) {
|
|
12609
13012
|
throw new Error(
|
|
12610
13013
|
"operator token rejected by remnic-server (HTTP 401). Update `server.authToken` or `REMNIC_AUTH_TOKEN` to match the running daemon."
|
|
@@ -13154,6 +13557,82 @@ function xrayCliIo(recallXray) {
|
|
|
13154
13557
|
stdout: (line) => console.log(line)
|
|
13155
13558
|
};
|
|
13156
13559
|
}
|
|
13560
|
+
function extractWhyRawArgs(rest) {
|
|
13561
|
+
const VALUE_FLAGS = /* @__PURE__ */ new Set(["--format", "--expect", "--namespace", "--session", "--out"]);
|
|
13562
|
+
const positional = [];
|
|
13563
|
+
const options = {};
|
|
13564
|
+
for (let i = 0; i < rest.length; i++) {
|
|
13565
|
+
const token = rest[i];
|
|
13566
|
+
if (token.startsWith("--")) {
|
|
13567
|
+
if (!VALUE_FLAGS.has(token)) {
|
|
13568
|
+
throw new Error(
|
|
13569
|
+
`Unknown flag ${JSON.stringify(token)}. Supported flags: --format, --expect, --namespace, --session, --out.`
|
|
13570
|
+
);
|
|
13571
|
+
}
|
|
13572
|
+
const next = rest[i + 1];
|
|
13573
|
+
if (next === void 0 || next.startsWith("--")) {
|
|
13574
|
+
throw new Error(
|
|
13575
|
+
`${token} requires a value. Provide it as \`${token} <value>\`, not as a bare flag.`
|
|
13576
|
+
);
|
|
13577
|
+
}
|
|
13578
|
+
options[token.slice(2)] = next;
|
|
13579
|
+
i++;
|
|
13580
|
+
continue;
|
|
13581
|
+
}
|
|
13582
|
+
positional.push(token);
|
|
13583
|
+
}
|
|
13584
|
+
return { rawQuery: positional.join(" "), options };
|
|
13585
|
+
}
|
|
13586
|
+
async function runWhyCommand(rest, io) {
|
|
13587
|
+
const { rawQuery, options } = extractWhyRawArgs(rest);
|
|
13588
|
+
const parsed = parseWhyCliOptions(rawQuery, options);
|
|
13589
|
+
const response = await io.recallWhy({
|
|
13590
|
+
query: parsed.query,
|
|
13591
|
+
...parsed.expect !== void 0 ? { expect: parsed.expect } : {},
|
|
13592
|
+
...parsed.session !== void 0 ? { sessionKey: parsed.session } : {},
|
|
13593
|
+
...parsed.namespace !== void 0 ? { namespace: parsed.namespace } : {}
|
|
13594
|
+
});
|
|
13595
|
+
if (!response.reportFound || response.report === void 0) {
|
|
13596
|
+
throw new Error(
|
|
13597
|
+
"recall diagnosis unavailable: the requested namespace is not readable by this caller"
|
|
13598
|
+
);
|
|
13599
|
+
}
|
|
13600
|
+
const rendered = renderRecallWhy(response.report, parsed.format);
|
|
13601
|
+
if (parsed.outPath !== void 0) {
|
|
13602
|
+
await io.writeFile(expandTildePath(parsed.outPath), rendered);
|
|
13603
|
+
} else {
|
|
13604
|
+
io.stdout(rendered);
|
|
13605
|
+
}
|
|
13606
|
+
}
|
|
13607
|
+
async function cmdWhy(rest) {
|
|
13608
|
+
const { rawQuery, options } = extractWhyRawArgs(rest);
|
|
13609
|
+
parseWhyCliOptions(rawQuery, options);
|
|
13610
|
+
const remote = resolveRemoteDaemon(resolveConfigPath());
|
|
13611
|
+
if (remote) {
|
|
13612
|
+
await runWhyCommand(rest, whyCliIo((request) => remoteRecallWhy(remote, request)));
|
|
13613
|
+
return;
|
|
13614
|
+
}
|
|
13615
|
+
initLogger5();
|
|
13616
|
+
const configPath = resolveConfigPath();
|
|
13617
|
+
const raw = fs32.existsSync(configPath) ? JSON.parse(fs32.readFileSync(configPath, "utf8")) : {};
|
|
13618
|
+
const config = parseConfig17(resolveRemnicConfigRecord16(raw));
|
|
13619
|
+
const orchestrator = new Orchestrator11(config);
|
|
13620
|
+
await orchestrator.initialize();
|
|
13621
|
+
await orchestrator.deferredReady;
|
|
13622
|
+
const service = new EngramAccessService2(orchestrator);
|
|
13623
|
+
try {
|
|
13624
|
+
await runWhyCommand(rest, whyCliIo((request) => service.recallWhy(request)));
|
|
13625
|
+
} finally {
|
|
13626
|
+
orchestrator.abortDeferredInit();
|
|
13627
|
+
}
|
|
13628
|
+
}
|
|
13629
|
+
function whyCliIo(recallWhy) {
|
|
13630
|
+
return {
|
|
13631
|
+
recallWhy,
|
|
13632
|
+
writeFile: (filePath, data) => fsWriteFile(filePath, data, "utf8"),
|
|
13633
|
+
stdout: (line) => console.log(line)
|
|
13634
|
+
};
|
|
13635
|
+
}
|
|
13157
13636
|
async function runWhoKnowsCommand(rest, io) {
|
|
13158
13637
|
const { topic, options } = extractWhoKnowsRawArgs(rest);
|
|
13159
13638
|
const parsed = parseWhoKnowsCliOptions(topic, options);
|
|
@@ -13222,7 +13701,7 @@ async function cmdVersions(rest) {
|
|
|
13222
13701
|
console.error("Usage: remnic versions list <page-path>");
|
|
13223
13702
|
process.exit(1);
|
|
13224
13703
|
}
|
|
13225
|
-
const absPath =
|
|
13704
|
+
const absPath = path23.resolve(pagePath);
|
|
13226
13705
|
const history = await listVersions(absPath, versioningConfig, memDir);
|
|
13227
13706
|
if (json) {
|
|
13228
13707
|
console.log(JSON.stringify(history, null, 2));
|
|
@@ -13247,7 +13726,7 @@ async function cmdVersions(rest) {
|
|
|
13247
13726
|
console.error("Usage: remnic versions show <page-path> <version-id>");
|
|
13248
13727
|
process.exit(1);
|
|
13249
13728
|
}
|
|
13250
|
-
const absPath =
|
|
13729
|
+
const absPath = path23.resolve(pagePath);
|
|
13251
13730
|
try {
|
|
13252
13731
|
const content = await getVersion(absPath, versionId, versioningConfig, memDir);
|
|
13253
13732
|
console.log(content);
|
|
@@ -13265,7 +13744,7 @@ async function cmdVersions(rest) {
|
|
|
13265
13744
|
console.error("Usage: remnic versions diff <page-path> <v1> <v2>");
|
|
13266
13745
|
process.exit(1);
|
|
13267
13746
|
}
|
|
13268
|
-
const absPath =
|
|
13747
|
+
const absPath = path23.resolve(pagePath);
|
|
13269
13748
|
try {
|
|
13270
13749
|
const diffOutput = await diffVersions(absPath, v1, v2, versioningConfig, memDir);
|
|
13271
13750
|
console.log(diffOutput);
|
|
@@ -13282,7 +13761,7 @@ async function cmdVersions(rest) {
|
|
|
13282
13761
|
console.error("Usage: remnic versions revert <page-path> <version-id>");
|
|
13283
13762
|
process.exit(1);
|
|
13284
13763
|
}
|
|
13285
|
-
const absPath =
|
|
13764
|
+
const absPath = path23.resolve(pagePath);
|
|
13286
13765
|
try {
|
|
13287
13766
|
const version = await revertToVersion(absPath, versionId, versioningConfig, void 0, memDir);
|
|
13288
13767
|
if (json) {
|
|
@@ -13322,7 +13801,7 @@ async function cmdEnrich(rest) {
|
|
|
13322
13801
|
const subcommand = rest[0];
|
|
13323
13802
|
if (subcommand === "audit") {
|
|
13324
13803
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
13325
|
-
const auditDir2 =
|
|
13804
|
+
const auditDir2 = path23.join(memoryDir2, "enrichment");
|
|
13326
13805
|
const sinceFlag = resolveFlag(rest.slice(1), "--since");
|
|
13327
13806
|
const entries = await readAuditLog(auditDir2, sinceFlag ?? void 0);
|
|
13328
13807
|
if (entries.length === 0) {
|
|
@@ -13447,7 +13926,7 @@ Registered providers:`);
|
|
|
13447
13926
|
return;
|
|
13448
13927
|
}
|
|
13449
13928
|
const memoryDir = expandTilde(config.memoryDir);
|
|
13450
|
-
const auditDir =
|
|
13929
|
+
const auditDir = path23.join(memoryDir, "enrichment");
|
|
13451
13930
|
let totalPersisted = 0;
|
|
13452
13931
|
for (const result of results) {
|
|
13453
13932
|
for (const candidate of result.acceptedCandidates) {
|
|
@@ -13570,7 +14049,7 @@ Root: ${root}`);
|
|
|
13570
14049
|
const validNames = new Set(extensions.map((e) => e.name));
|
|
13571
14050
|
let errors = 0;
|
|
13572
14051
|
for (const entry of entries) {
|
|
13573
|
-
const entryPath =
|
|
14052
|
+
const entryPath = path23.join(root, entry);
|
|
13574
14053
|
try {
|
|
13575
14054
|
if (!fs32.statSync(entryPath).isDirectory()) continue;
|
|
13576
14055
|
} catch {
|
|
@@ -13701,7 +14180,7 @@ ${section}
|
|
|
13701
14180
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
13702
14181
|
fs32.mkdirSync(saveDir, { recursive: true });
|
|
13703
14182
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
13704
|
-
const filePath =
|
|
14183
|
+
const filePath = path23.join(saveDir, filename);
|
|
13705
14184
|
fs32.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
13706
14185
|
console.error(`Saved briefing: ${filePath}`);
|
|
13707
14186
|
} catch (err) {
|
|
@@ -13857,7 +14336,7 @@ async function cmdDoctor() {
|
|
|
13857
14336
|
const rawMemoryDir = entryConfig?.memoryDir;
|
|
13858
14337
|
const configuredMemoryDir = typeof rawMemoryDir === "string" ? rawMemoryDir : void 0;
|
|
13859
14338
|
if (configuredMemoryDir) {
|
|
13860
|
-
const resolvedMemDir =
|
|
14339
|
+
const resolvedMemDir = path23.resolve(expandTilde(configuredMemoryDir));
|
|
13861
14340
|
let memDirOk = false;
|
|
13862
14341
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
13863
14342
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
@@ -14070,7 +14549,7 @@ async function cmdMigrate(json, rollback) {
|
|
|
14070
14549
|
console.log(` Rollback: ${result.rollbackCommand}`);
|
|
14071
14550
|
}
|
|
14072
14551
|
function cmdOnboard(dirPath, json) {
|
|
14073
|
-
const directory =
|
|
14552
|
+
const directory = path23.resolve(dirPath || process.cwd());
|
|
14074
14553
|
const result = onboard({ directory });
|
|
14075
14554
|
if (json) {
|
|
14076
14555
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -14089,7 +14568,7 @@ Suggested namespace: ${result.plan.suggestedNamespace}`);
|
|
|
14089
14568
|
async function cmdCurate(targetPath, json) {
|
|
14090
14569
|
const memoryDir = resolveMemoryDir();
|
|
14091
14570
|
const result = await curate({
|
|
14092
|
-
targetPath:
|
|
14571
|
+
targetPath: path23.resolve(targetPath),
|
|
14093
14572
|
memoryDir,
|
|
14094
14573
|
source: "curation",
|
|
14095
14574
|
checkDuplicates: true,
|
|
@@ -14218,8 +14697,8 @@ async function cmdSync(action, rest, json) {
|
|
|
14218
14697
|
}
|
|
14219
14698
|
}
|
|
14220
14699
|
function localOfflineSourceId(memoryDir) {
|
|
14221
|
-
const host =
|
|
14222
|
-
const dirHash = createHash6("sha256").update(
|
|
14700
|
+
const host = os4.hostname() || "unknown-host";
|
|
14701
|
+
const dirHash = createHash6("sha256").update(path23.resolve(memoryDir)).digest("hex").slice(0, 16);
|
|
14223
14702
|
return `remnic-local:${host}:${dirHash}`;
|
|
14224
14703
|
}
|
|
14225
14704
|
function normalizeOfflineRemoteUrl(raw) {
|
|
@@ -14628,10 +15107,10 @@ var OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX = 3;
|
|
|
14628
15107
|
var OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS = 250;
|
|
14629
15108
|
var OfflineRemoteFileChangedError = class extends Error {
|
|
14630
15109
|
path;
|
|
14631
|
-
constructor(
|
|
14632
|
-
super(`remote file changed while fetching offline content: ${
|
|
15110
|
+
constructor(path24) {
|
|
15111
|
+
super(`remote file changed while fetching offline content: ${path24}`);
|
|
14633
15112
|
this.name = "OfflineRemoteFileChangedError";
|
|
14634
|
-
this.path =
|
|
15113
|
+
this.path = path24;
|
|
14635
15114
|
}
|
|
14636
15115
|
};
|
|
14637
15116
|
function isOfflineRemoteFileChangedError(error) {
|
|
@@ -14892,7 +15371,7 @@ async function pushOfflineFileContentFromChunkReader(args) {
|
|
|
14892
15371
|
}
|
|
14893
15372
|
const hash = createHash6("sha256");
|
|
14894
15373
|
const chunks = args.readFileChunks({
|
|
14895
|
-
root:
|
|
15374
|
+
root: path23.resolve(args.memoryDir),
|
|
14896
15375
|
path: args.file.path,
|
|
14897
15376
|
filePath,
|
|
14898
15377
|
chunkSize: OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES
|
|
@@ -16006,7 +16485,7 @@ Environment fallbacks:
|
|
|
16006
16485
|
REMNIC_OFFLINE_TOKEN > REMNIC_AUTH_TOKEN > ENGRAM_AUTH_TOKEN.`);
|
|
16007
16486
|
return;
|
|
16008
16487
|
}
|
|
16009
|
-
const memoryDir =
|
|
16488
|
+
const memoryDir = path23.resolve(expandTilde(resolveRequiredValueFlag(rest, "--memory-dir") ?? resolveMemoryDir()));
|
|
16010
16489
|
const namespace = resolveRequiredValueFlag(rest, "--namespace");
|
|
16011
16490
|
const includeTranscripts = !hasFlag(rest, "--no-transcripts");
|
|
16012
16491
|
const stateOverride = resolveRequiredValueFlag(rest, "--state");
|
|
@@ -16027,7 +16506,7 @@ Environment fallbacks:
|
|
|
16027
16506
|
const remoteUrl = needsRemote ? resolveOfflineRemoteUrl(rest) : resolveOptionalOfflineRemoteUrl(rest);
|
|
16028
16507
|
const knownAction = needsRemote || action === "status";
|
|
16029
16508
|
const token = knownAction ? resolveOfflineToken(rest) : void 0;
|
|
16030
|
-
const statePath = statePathExplicit ?
|
|
16509
|
+
const statePath = statePathExplicit ? path23.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
16031
16510
|
if (action === "prepare") {
|
|
16032
16511
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
16033
16512
|
fs32.mkdirSync(memoryDir, { recursive: true });
|
|
@@ -16209,11 +16688,11 @@ Environment fallbacks:
|
|
|
16209
16688
|
failures: result.largeFilePushFailures
|
|
16210
16689
|
});
|
|
16211
16690
|
largeFileFailureCounts = advanced.counts;
|
|
16212
|
-
for (const
|
|
16213
|
-
if (skippedLargeFiles.has(
|
|
16214
|
-
skippedLargeFiles.add(
|
|
16691
|
+
for (const path24 of advanced.newlySkipped) {
|
|
16692
|
+
if (skippedLargeFiles.has(path24)) continue;
|
|
16693
|
+
skippedLargeFiles.add(path24);
|
|
16215
16694
|
console.warn(
|
|
16216
|
-
`offline sync: permanently skipping ${
|
|
16695
|
+
`offline sync: permanently skipping ${path24} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
16217
16696
|
);
|
|
16218
16697
|
}
|
|
16219
16698
|
const pulled = result.pull ? result.pull.upserted + result.pull.deleted : 0;
|
|
@@ -16228,11 +16707,11 @@ Environment fallbacks:
|
|
|
16228
16707
|
failures: error.failures
|
|
16229
16708
|
});
|
|
16230
16709
|
largeFileFailureCounts = advanced.counts;
|
|
16231
|
-
for (const
|
|
16232
|
-
if (skippedLargeFiles.has(
|
|
16233
|
-
skippedLargeFiles.add(
|
|
16710
|
+
for (const path24 of advanced.newlySkipped) {
|
|
16711
|
+
if (skippedLargeFiles.has(path24)) continue;
|
|
16712
|
+
skippedLargeFiles.add(path24);
|
|
16234
16713
|
console.warn(
|
|
16235
|
-
`offline sync: permanently skipping ${
|
|
16714
|
+
`offline sync: permanently skipping ${path24} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
16236
16715
|
);
|
|
16237
16716
|
}
|
|
16238
16717
|
}
|
|
@@ -16373,7 +16852,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
16373
16852
|
const connectorDaemonUrl = typeof effectiveConnectorConfig.remnicDaemonUrl === "string" && effectiveConnectorConfig.remnicDaemonUrl.trim().length > 0 ? effectiveConnectorConfig.remnicDaemonUrl.trim() : void 0;
|
|
16374
16853
|
const pubResult = await pub.publish({
|
|
16375
16854
|
config: { memoryDir, namespace: connectorNamespace, daemonUrl: connectorDaemonUrl },
|
|
16376
|
-
skillsRoot:
|
|
16855
|
+
skillsRoot: path23.join(memoryDir, "skills"),
|
|
16377
16856
|
rollbackTokenEntry: preInstallTokenEntry,
|
|
16378
16857
|
log: { info: console.log, warn: console.warn, error: console.error }
|
|
16379
16858
|
});
|
|
@@ -16733,15 +17212,15 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
16733
17212
|
}
|
|
16734
17213
|
const manifest = generateMarketplaceManifest();
|
|
16735
17214
|
await writeMarketplaceManifest(outputDir, manifest);
|
|
16736
|
-
const outPath =
|
|
17215
|
+
const outPath = path23.join(outputDir, "marketplace.json");
|
|
16737
17216
|
if (json) {
|
|
16738
17217
|
console.log(JSON.stringify({ status: "generated", path: outPath }, null, 2));
|
|
16739
17218
|
} else {
|
|
16740
17219
|
console.log(`Generated marketplace.json at ${outPath}`);
|
|
16741
17220
|
}
|
|
16742
17221
|
} else if (subAction === "validate") {
|
|
16743
|
-
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ??
|
|
16744
|
-
const resolved =
|
|
17222
|
+
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path23.join(process.cwd(), "marketplace.json");
|
|
17223
|
+
const resolved = path23.resolve(targetPath);
|
|
16745
17224
|
if (!fs32.existsSync(resolved)) {
|
|
16746
17225
|
console.error(`File not found: ${resolved}`);
|
|
16747
17226
|
process.exit(1);
|
|
@@ -17157,7 +17636,7 @@ async function cmdBench(rest) {
|
|
|
17157
17636
|
}
|
|
17158
17637
|
const completeCount = prevStatus.benchmarks.filter((b) => b.status === "complete").length;
|
|
17159
17638
|
const failedCount = prevStatus.benchmarks.filter((b) => b.status === "failed").length;
|
|
17160
|
-
printBenchStatusLine(parsed.json, `Resuming from: ${
|
|
17639
|
+
printBenchStatusLine(parsed.json, `Resuming from: ${path23.basename(latestStatusPath)}`);
|
|
17161
17640
|
printBenchStatusLine(parsed.json, ` Previous run: ${prevStatus.startedAt}`);
|
|
17162
17641
|
printBenchStatusLine(parsed.json, ` Benchmarks: ${prevStatus.benchmarks.length} total, ${completeCount} complete, ${failedCount} failed`);
|
|
17163
17642
|
const before = selectedBenchmarks.length;
|
|
@@ -17322,9 +17801,9 @@ Options:
|
|
|
17322
17801
|
);
|
|
17323
17802
|
process.exit(1);
|
|
17324
17803
|
} else {
|
|
17325
|
-
fixturePath =
|
|
17804
|
+
fixturePath = path23.resolve(expandTilde(fixturePathRaw));
|
|
17326
17805
|
}
|
|
17327
|
-
const outPath =
|
|
17806
|
+
const outPath = path23.resolve(expandTilde(outPathRaw));
|
|
17328
17807
|
const benchModule = await loadBenchModule();
|
|
17329
17808
|
const runner = benchModule.runProceduralAblationCli;
|
|
17330
17809
|
if (typeof runner !== "function") {
|
|
@@ -17343,7 +17822,7 @@ Options:
|
|
|
17343
17822
|
);
|
|
17344
17823
|
console.log(`wrote ${outPath}`);
|
|
17345
17824
|
}
|
|
17346
|
-
var LOGS_DIR =
|
|
17825
|
+
var LOGS_DIR = path23.join(PID_DIR, "logs");
|
|
17347
17826
|
var LAUNCHD_PLIST_PATHS = launchdPlistPaths(resolveHomeDir());
|
|
17348
17827
|
var [LAUNCHD_PLIST_PATH] = LAUNCHD_PLIST_PATHS;
|
|
17349
17828
|
var SYSTEMD_UNIT_PATHS = systemdUnitPaths(resolveHomeDir());
|
|
@@ -17420,7 +17899,7 @@ function selectLaunchdInspection(openclawPluginModeConfigured) {
|
|
|
17420
17899
|
for (const plistPath of LAUNCHD_PLIST_PATHS.slice(1)) {
|
|
17421
17900
|
const legacy = inspectLaunchdPlist(plistPath);
|
|
17422
17901
|
if (!legacy.installed) continue;
|
|
17423
|
-
const label =
|
|
17902
|
+
const label = path23.basename(plistPath, ".plist");
|
|
17424
17903
|
return legacy.ok ? {
|
|
17425
17904
|
...legacy,
|
|
17426
17905
|
warn: true,
|
|
@@ -17454,10 +17933,10 @@ function daemonInstall() {
|
|
|
17454
17933
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
17455
17934
|
fs32.mkdirSync(LOGS_DIR, { recursive: true });
|
|
17456
17935
|
if (isMacOS()) {
|
|
17457
|
-
const templatePath =
|
|
17936
|
+
const templatePath = path23.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
17458
17937
|
const template = fs32.readFileSync(templatePath, "utf8");
|
|
17459
17938
|
const plist = renderTemplate(template, vars);
|
|
17460
|
-
fs32.mkdirSync(
|
|
17939
|
+
fs32.mkdirSync(path23.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
17461
17940
|
fs32.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
17462
17941
|
try {
|
|
17463
17942
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
@@ -17474,10 +17953,10 @@ function daemonInstall() {
|
|
|
17474
17953
|
console.log(` RunAtLoad: true, KeepAlive: true`);
|
|
17475
17954
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
17476
17955
|
} else if (isLinux()) {
|
|
17477
|
-
const templatePath =
|
|
17956
|
+
const templatePath = path23.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
17478
17957
|
const template = fs32.readFileSync(templatePath, "utf8");
|
|
17479
17958
|
const unit = renderTemplate(template, vars);
|
|
17480
|
-
fs32.mkdirSync(
|
|
17959
|
+
fs32.mkdirSync(path23.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
17481
17960
|
fs32.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
17482
17961
|
try {
|
|
17483
17962
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
@@ -17976,7 +18455,7 @@ Clean complete: cleaned=${result.cleaned}`
|
|
|
17976
18455
|
}
|
|
17977
18456
|
async function cmdOpenclawInstall(opts) {
|
|
17978
18457
|
const configPath = resolveOpenclawConfigPath(opts.configPath);
|
|
17979
|
-
const fallbackMemoryDir =
|
|
18458
|
+
const fallbackMemoryDir = path23.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
17980
18459
|
console.log(`OpenClaw config: ${configPath}`);
|
|
17981
18460
|
const existingConfig = readOpenclawConfig(configPath);
|
|
17982
18461
|
const { plugins, entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
@@ -18079,7 +18558,7 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
18079
18558
|
fs32.mkdirSync(memoryDir, { recursive: true });
|
|
18080
18559
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
18081
18560
|
}
|
|
18082
|
-
const configDir =
|
|
18561
|
+
const configDir = path23.dirname(configPath);
|
|
18083
18562
|
if (!fs32.existsSync(configDir)) {
|
|
18084
18563
|
fs32.mkdirSync(configDir, { recursive: true });
|
|
18085
18564
|
}
|
|
@@ -18108,12 +18587,12 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
18108
18587
|
const pluginDir = resolveOpenclawPluginDir(opts.pluginDir);
|
|
18109
18588
|
const managedTargetDir = resolveOpenclawManagedPluginDir();
|
|
18110
18589
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
18111
|
-
const fallbackMemoryDir =
|
|
18590
|
+
const fallbackMemoryDir = path23.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
18112
18591
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
18113
18592
|
const configExistedBefore = fs32.existsSync(configPath);
|
|
18114
18593
|
const existingConfig = readOpenclawConfig(configPath);
|
|
18115
18594
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
18116
|
-
const preservedMemoryDir = opts.memoryDir ?
|
|
18595
|
+
const preservedMemoryDir = opts.memoryDir ? path23.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
18117
18596
|
console.log(`OpenClaw config: ${configPath}`);
|
|
18118
18597
|
console.log(`Plugin dir: ${pluginDir}`);
|
|
18119
18598
|
if (legacyPluginDirForBackup) {
|
|
@@ -18121,7 +18600,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
18121
18600
|
}
|
|
18122
18601
|
console.log(`Memory dir: ${preservedMemoryDir}`);
|
|
18123
18602
|
console.log(`Package spec: ${packageSpec}`);
|
|
18124
|
-
console.log(`Backup root: ${
|
|
18603
|
+
console.log(`Backup root: ${path23.join(resolveOpenclawStateDir(), "backups")}`);
|
|
18125
18604
|
const plannedActions = [
|
|
18126
18605
|
`backup openclaw.json and the existing ${REMNIC_OPENCLAW_PLUGIN_ID} extension`,
|
|
18127
18606
|
...legacyPluginDirForBackup ? [`backup the existing ${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID} extension without modifying it`] : [],
|
|
@@ -18159,9 +18638,9 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
18159
18638
|
assertDirectoryPathOrMissing(legacyPluginDirForBackup, "Legacy OpenClaw plugin dir");
|
|
18160
18639
|
}
|
|
18161
18640
|
const backupDir = createOpenclawUpgradeBackupDir();
|
|
18162
|
-
const configBackupPath =
|
|
18163
|
-
const pluginBackupDir =
|
|
18164
|
-
const legacyPluginBackupDir = legacyPluginDirForBackup ?
|
|
18641
|
+
const configBackupPath = path23.join(backupDir, "openclaw.json");
|
|
18642
|
+
const pluginBackupDir = path23.join(backupDir, "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
18643
|
+
const legacyPluginBackupDir = legacyPluginDirForBackup ? path23.join(backupDir, "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID) : void 0;
|
|
18165
18644
|
const backupNotes = [];
|
|
18166
18645
|
if (backupPathIfPresent(configPath, configBackupPath)) {
|
|
18167
18646
|
backupNotes.push(`+ Backed up config to ${configBackupPath}`);
|
|
@@ -18211,7 +18690,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
18211
18690
|
const managedRollbackDir = publishedInstallError ? publishedInstallError.managedRollbackDir : installResult?.managedRollbackDir;
|
|
18212
18691
|
const managedRollbackTargetDir = publishedInstallError?.managedRollbackTargetDir ?? installResult?.managedRollbackTargetDir ?? managedTargetDir;
|
|
18213
18692
|
const requiresHostManagedRestore = publishedInstallError?.requiresHostManagedRestore ?? installResult?.requiresHostManagedRestore ?? false;
|
|
18214
|
-
const managedRollbackSharesPluginDir = managedRollbackDir &&
|
|
18693
|
+
const managedRollbackSharesPluginDir = managedRollbackDir && path23.resolve(managedRollbackTargetDir) === path23.resolve(pluginDir);
|
|
18215
18694
|
const pluginRollbackDir = managedRollbackSharesPluginDir ? requiresHostManagedRestore ? rollbackDir : rollbackDir ?? managedRollbackDir : rollbackDir;
|
|
18216
18695
|
const shouldRestorePlugin = Boolean(
|
|
18217
18696
|
installResult && !requiresHostManagedRestore || pluginRollbackDir || publishedInstallError?.shouldRestoreBackup
|
|
@@ -18268,7 +18747,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
18268
18747
|
rollbackErrors.push(error);
|
|
18269
18748
|
}
|
|
18270
18749
|
if (pendingConfigRestoreError) rollbackErrors.push(pendingConfigRestoreError);
|
|
18271
|
-
if (managedRollbackDir &&
|
|
18750
|
+
if (managedRollbackDir && path23.resolve(managedRollbackTargetDir) !== path23.resolve(pluginDir) && !requiresHostManagedRestore) {
|
|
18272
18751
|
try {
|
|
18273
18752
|
rollbackNotes.push(
|
|
18274
18753
|
...rollbackOpenclawUpgrade({
|
|
@@ -18334,9 +18813,9 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
18334
18813
|
console.log(" - Re-apply any local source patches to the new package only after verifying the published build.");
|
|
18335
18814
|
}
|
|
18336
18815
|
function createOpenclawUpgradeBackupDir() {
|
|
18337
|
-
const backupsRoot =
|
|
18816
|
+
const backupsRoot = path23.join(resolveOpenclawStateDir(), "backups");
|
|
18338
18817
|
fs32.mkdirSync(backupsRoot, { recursive: true });
|
|
18339
|
-
return fs32.mkdtempSync(
|
|
18818
|
+
return fs32.mkdtempSync(path23.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
18340
18819
|
}
|
|
18341
18820
|
async function cmdTaxonomy(rest) {
|
|
18342
18821
|
initLogger5();
|
|
@@ -18378,8 +18857,8 @@ async function cmdTaxonomy(rest) {
|
|
|
18378
18857
|
const doc = generateResolverDocument(taxonomy);
|
|
18379
18858
|
console.log(doc);
|
|
18380
18859
|
if (config.taxonomyAutoGenResolver) {
|
|
18381
|
-
const resolverPath =
|
|
18382
|
-
fs32.mkdirSync(
|
|
18860
|
+
const resolverPath = path23.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
18861
|
+
fs32.mkdirSync(path23.dirname(resolverPath), { recursive: true });
|
|
18383
18862
|
fs32.writeFileSync(resolverPath, doc);
|
|
18384
18863
|
console.error(`Written: ${resolverPath}`);
|
|
18385
18864
|
}
|
|
@@ -18425,7 +18904,7 @@ async function cmdTaxonomy(rest) {
|
|
|
18425
18904
|
console.log(`Added category "${id}" (${name}).`);
|
|
18426
18905
|
if (config.taxonomyAutoGenResolver) {
|
|
18427
18906
|
const doc = generateResolverDocument(taxonomy);
|
|
18428
|
-
const resolverPath =
|
|
18907
|
+
const resolverPath = path23.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
18429
18908
|
fs32.writeFileSync(resolverPath, doc);
|
|
18430
18909
|
console.error(`Regenerated: ${resolverPath}`);
|
|
18431
18910
|
}
|
|
@@ -18456,7 +18935,7 @@ async function cmdTaxonomy(rest) {
|
|
|
18456
18935
|
console.log(`Removed category "${id}".`);
|
|
18457
18936
|
if (config.taxonomyAutoGenResolver) {
|
|
18458
18937
|
const doc = generateResolverDocument(taxonomy);
|
|
18459
|
-
const resolverPath =
|
|
18938
|
+
const resolverPath = path23.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
18460
18939
|
fs32.writeFileSync(resolverPath, doc);
|
|
18461
18940
|
console.error(`Regenerated: ${resolverPath}`);
|
|
18462
18941
|
}
|
|
@@ -18738,7 +19217,7 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
18738
19217
|
);
|
|
18739
19218
|
}
|
|
18740
19219
|
const formatted = adapter.formatRecords(records);
|
|
18741
|
-
const outDir =
|
|
19220
|
+
const outDir = path23.dirname(args.output);
|
|
18742
19221
|
fs32.mkdirSync(outDir, { recursive: true });
|
|
18743
19222
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
18744
19223
|
fs32.writeFileSync(tmpPath, formatted, "utf-8");
|
|
@@ -18794,6 +19273,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
18794
19273
|
case "xray":
|
|
18795
19274
|
await cmdXray(rest);
|
|
18796
19275
|
break;
|
|
19276
|
+
case "why":
|
|
19277
|
+
await cmdWhy(rest);
|
|
19278
|
+
break;
|
|
18797
19279
|
case "who-knows":
|
|
18798
19280
|
await cmdWhoKnows(rest);
|
|
18799
19281
|
break;
|
|
@@ -18806,6 +19288,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
18806
19288
|
case "doctor":
|
|
18807
19289
|
await cmdDoctor();
|
|
18808
19290
|
break;
|
|
19291
|
+
case "report":
|
|
19292
|
+
await cmdReport({ json: rest.includes("--json"), includeBench: rest.includes("--include-bench") });
|
|
19293
|
+
break;
|
|
18809
19294
|
case "config":
|
|
18810
19295
|
cmdConfig();
|
|
18811
19296
|
break;
|
|
@@ -18861,7 +19346,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
18861
19346
|
case "tree": {
|
|
18862
19347
|
const subAction = rest[0];
|
|
18863
19348
|
const json = rest.includes("--json");
|
|
18864
|
-
const outputDir = resolveFlag(rest, "--output") ??
|
|
19349
|
+
const outputDir = resolveFlag(rest, "--output") ?? path23.join(process.cwd(), ".remnic", "context-tree");
|
|
18865
19350
|
const categoriesFlag = resolveFlag(rest, "--categories");
|
|
18866
19351
|
const categories = categoriesFlag ? categoriesFlag.split(",") : void 0;
|
|
18867
19352
|
const maxPerCategoryRaw = resolveFlag(rest, "--max-per-category");
|
|
@@ -18938,7 +19423,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
18938
19423
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
18939
19424
|
process.exit(1);
|
|
18940
19425
|
}
|
|
18941
|
-
const indexPath =
|
|
19426
|
+
const indexPath = path23.join(treeDir, "INDEX.md");
|
|
18942
19427
|
if (!fs32.existsSync(indexPath)) {
|
|
18943
19428
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
18944
19429
|
process.exit(1);
|
|
@@ -19365,6 +19850,10 @@ Usage:
|
|
|
19365
19850
|
remnic xray <query> [--format text|markdown|json] [--budget <chars>] [--namespace <ns>] [--out <path>]
|
|
19366
19851
|
Run a recall with X-ray capture and print the unified snapshot
|
|
19367
19852
|
(tier + audit + MMR + filters). Part of #570. Text output by default.
|
|
19853
|
+
remnic why <query> [--expect <id|substring>] [--format markdown|json] [--namespace <ns>] [--session <key>] [--out <path>]
|
|
19854
|
+
Diagnose why a query did NOT recall what you expected (#3033). Prints
|
|
19855
|
+
per-stage candidate counts and drop reasons; with --expect, names the
|
|
19856
|
+
exact stage that dropped that memory plus a remediation hint.
|
|
19368
19857
|
remnic who-knows <topic> [--limit N] [--json] [--namespace <ns>] Rank entities by topic expertise
|
|
19369
19858
|
remnic wearables <status|check|sync|transcript|search|memories|speakers|corrections>
|
|
19370
19859
|
Wearable transcript sources (Limitless / Bee / Omi): pull + clean +
|
|
@@ -19547,6 +20036,7 @@ export {
|
|
|
19547
20036
|
chunkOfflineChangesetApplyBatches,
|
|
19548
20037
|
chunkOfflineFileContentBatches,
|
|
19549
20038
|
directHydrateLargeOfflineFiles,
|
|
20039
|
+
extractWhyRawArgs,
|
|
19550
20040
|
extractXrayRawArgs,
|
|
19551
20041
|
fetchOfflineSnapshot,
|
|
19552
20042
|
formatOfflineLargeFilePushFailureMessage,
|
|
@@ -19581,6 +20071,7 @@ export {
|
|
|
19581
20071
|
runOfflineSyncOnce,
|
|
19582
20072
|
runTrainingExport,
|
|
19583
20073
|
runWhoKnowsCommand,
|
|
20074
|
+
runWhyCommand,
|
|
19584
20075
|
runXrayCommand,
|
|
19585
20076
|
shouldDirectHydrateOfflineFile,
|
|
19586
20077
|
stripConfigArgv,
|