@remnic/cli 9.65.2 → 9.65.4
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 +428 -288
- package/package.json +31 -31
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
|
-
import
|
|
21
|
+
import fs19 from "fs";
|
|
22
22
|
import os3 from "os";
|
|
23
23
|
import path18 from "path";
|
|
24
24
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -27,13 +27,13 @@ import * as childProcess2 from "child_process";
|
|
|
27
27
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
28
28
|
import { gzipSync } from "zlib";
|
|
29
29
|
import {
|
|
30
|
-
parseConfig as
|
|
30
|
+
parseConfig as parseConfig10,
|
|
31
31
|
isOpenaiApiKeyDisabled,
|
|
32
32
|
resolveEnvVars,
|
|
33
|
-
resolveRemnicConfigRecord as
|
|
34
|
-
Orchestrator as
|
|
33
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord9,
|
|
34
|
+
Orchestrator as Orchestrator6,
|
|
35
35
|
EngramAccessService as EngramAccessService2,
|
|
36
|
-
initLogger as
|
|
36
|
+
initLogger as initLogger5,
|
|
37
37
|
onboard,
|
|
38
38
|
curate,
|
|
39
39
|
listReviewItems,
|
|
@@ -452,6 +452,136 @@ function formatProcedureMaintenanceText(report) {
|
|
|
452
452
|
return lines.join("\n") + "\n";
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
+
// src/commands/drift.ts
|
|
456
|
+
import fs5 from "fs";
|
|
457
|
+
import {
|
|
458
|
+
Orchestrator as Orchestrator3,
|
|
459
|
+
initLogger as initLogger2,
|
|
460
|
+
parseConfig as parseConfig5,
|
|
461
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord5,
|
|
462
|
+
runPreferenceDriftScan
|
|
463
|
+
} from "@remnic/core";
|
|
464
|
+
async function runDriftBinaryCommand(rest) {
|
|
465
|
+
initLogger2();
|
|
466
|
+
const subcommand = rest[0];
|
|
467
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
468
|
+
console.log(`remnic drift \u2014 Preference drift detection (issue #2371)
|
|
469
|
+
|
|
470
|
+
Usage:
|
|
471
|
+
remnic drift scan [--apply] [--namespace <ns>] [--format json|text] [--memory-dir <path>]
|
|
472
|
+
|
|
473
|
+
Subcommands:
|
|
474
|
+
scan Classify aging preference memories as corroborated /
|
|
475
|
+
stale / drifted from recent evidence. Reports only by
|
|
476
|
+
default. --apply stamps lastCorroborated / driftState
|
|
477
|
+
and opens one review item per drifted preference
|
|
478
|
+
(requires driftDetection.enabled in config). Never
|
|
479
|
+
auto-deletes and never auto-supersedes.
|
|
480
|
+
|
|
481
|
+
Shared with:
|
|
482
|
+
MCP remnic.preference_drift_scan (alias engram.preference_drift_scan)
|
|
483
|
+
|
|
484
|
+
Resolve a drifted item with the existing review surface:
|
|
485
|
+
remnic.review_list / remnic.review_resolve, verbs: keep, supersede, archive`);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
if (subcommand !== "scan") {
|
|
489
|
+
console.error(`Unknown drift subcommand "${subcommand}". Run \`remnic drift --help\` for usage.`);
|
|
490
|
+
process.exit(1);
|
|
491
|
+
}
|
|
492
|
+
const args = rest.slice(1);
|
|
493
|
+
const formatPresent = hasFlag(args, "--format");
|
|
494
|
+
const formatRaw = resolveFlag(args, "--format");
|
|
495
|
+
if (formatPresent && (formatRaw === void 0 || formatRaw === null)) {
|
|
496
|
+
console.error("--format requires a value. Use `--format json` or `--format text`.");
|
|
497
|
+
process.exit(1);
|
|
498
|
+
}
|
|
499
|
+
const format = (() => {
|
|
500
|
+
if (!formatPresent || formatRaw === void 0 || formatRaw === null) return "text";
|
|
501
|
+
const normalized = String(formatRaw).trim().toLowerCase();
|
|
502
|
+
if (normalized !== "text" && normalized !== "json") {
|
|
503
|
+
console.error(`Invalid --format "${formatRaw}". Allowed: text, json.`);
|
|
504
|
+
process.exit(1);
|
|
505
|
+
}
|
|
506
|
+
return normalized;
|
|
507
|
+
})();
|
|
508
|
+
const memoryDirPresent = hasFlag(args, "--memory-dir");
|
|
509
|
+
const memoryDirOverride = resolveFlag(args, "--memory-dir");
|
|
510
|
+
if (memoryDirPresent && (memoryDirOverride === void 0 || memoryDirOverride === null)) {
|
|
511
|
+
console.error("--memory-dir requires a path. Omit the flag to use the resolved default.");
|
|
512
|
+
process.exit(1);
|
|
513
|
+
}
|
|
514
|
+
const namespacePresent = hasFlag(args, "--namespace");
|
|
515
|
+
const namespaceOverride = resolveFlag(args, "--namespace");
|
|
516
|
+
if (namespacePresent && (namespaceOverride === void 0 || namespaceOverride === null)) {
|
|
517
|
+
console.error("--namespace requires a value. Omit the flag to scan the default namespace.");
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
520
|
+
const configPath = resolveConfigPath();
|
|
521
|
+
const raw = fs5.existsSync(configPath) ? JSON.parse(fs5.readFileSync(configPath, "utf8")) : {};
|
|
522
|
+
const config = parseConfig5(resolveRemnicConfigRecord5(raw));
|
|
523
|
+
const memoryDirOverridden = typeof memoryDirOverride === "string" && memoryDirOverride.length > 0;
|
|
524
|
+
const memoryDir = expandTilde(
|
|
525
|
+
memoryDirOverridden ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
526
|
+
);
|
|
527
|
+
const orchestrator = new Orchestrator3(
|
|
528
|
+
memoryDirOverridden ? { ...config, memoryDir } : config
|
|
529
|
+
);
|
|
530
|
+
await orchestrator.initialize();
|
|
531
|
+
const storage = await orchestrator.getStorageForNamespace(
|
|
532
|
+
typeof namespaceOverride === "string" && namespaceOverride.length > 0 ? namespaceOverride : void 0
|
|
533
|
+
);
|
|
534
|
+
const report = await runPreferenceDriftScan({
|
|
535
|
+
storage,
|
|
536
|
+
config: orchestrator.config,
|
|
537
|
+
memoryDir,
|
|
538
|
+
// Deliberately NOT wrapped in a swallowing try/catch: the drift scan's
|
|
539
|
+
// §22 contract is that a thrown lookup means `backend_unavailable`, and
|
|
540
|
+
// returning `[]` on failure would misreport a live preference as stale.
|
|
541
|
+
embeddingLookupFactory: (scanStorage) => (content, limit) => orchestrator.semanticDedupLookup(content, limit, scanStorage),
|
|
542
|
+
storageForNamespace: async (namespace) => {
|
|
543
|
+
const resolvedNamespace = namespace?.trim() || void 0;
|
|
544
|
+
return {
|
|
545
|
+
storage: await orchestrator.getStorageForNamespace(resolvedNamespace),
|
|
546
|
+
namespace: resolvedNamespace
|
|
547
|
+
};
|
|
548
|
+
},
|
|
549
|
+
localLlm: orchestrator.localLlm ?? null,
|
|
550
|
+
fallbackLlm: orchestrator.fastGatewayLlm ?? null,
|
|
551
|
+
namespace: typeof namespaceOverride === "string" ? namespaceOverride : void 0,
|
|
552
|
+
apply: hasFlag(args, "--apply")
|
|
553
|
+
});
|
|
554
|
+
if (format === "json") {
|
|
555
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
process.stdout.write(formatPreferenceDriftText(report));
|
|
559
|
+
}
|
|
560
|
+
function formatPreferenceDriftText(report) {
|
|
561
|
+
const lines = [];
|
|
562
|
+
lines.push(`Preference drift \u2014 ${report.mode} run at ${report.generatedAt}`);
|
|
563
|
+
if (report.skippedReason) {
|
|
564
|
+
lines.push(
|
|
565
|
+
report.skippedReason === "drift_disabled" ? " skipped: driftDetection.enabled is false" : " skipped: driftDetection.maxCandidatesPerRun is 0"
|
|
566
|
+
);
|
|
567
|
+
return lines.join("\n") + "\n";
|
|
568
|
+
}
|
|
569
|
+
if (report.namespace) lines.push(` namespace: ${report.namespace}`);
|
|
570
|
+
lines.push(` eligible preferences: ${report.eligible} (classified ${report.scanned})`);
|
|
571
|
+
lines.push(
|
|
572
|
+
` corroborated=${report.counts.corroborated} stale=${report.counts.stale} drifted=${report.counts.drifted} skipped=${report.counts.skipped}`
|
|
573
|
+
);
|
|
574
|
+
lines.push(` applied writes: ${report.appliedCount} (review items opened: ${report.reviewItemsOpened})`);
|
|
575
|
+
for (const finding of report.findings) {
|
|
576
|
+
const skip = finding.skipped ? ` [${finding.skipped}]` : "";
|
|
577
|
+
lines.push(` - ${finding.memoryId}: ${finding.classification}${skip} (${finding.ageDays}d old)`);
|
|
578
|
+
lines.push(` ${finding.reason}`);
|
|
579
|
+
if (finding.reviewPairId) lines.push(` review item: ${finding.reviewPairId}`);
|
|
580
|
+
}
|
|
581
|
+
lines.push(` elapsed: ${report.elapsedMs}ms`);
|
|
582
|
+
return lines.join("\n") + "\n";
|
|
583
|
+
}
|
|
584
|
+
|
|
455
585
|
// src/optional-module-loader.ts
|
|
456
586
|
function isSpecifierNotFoundError(err, specifier) {
|
|
457
587
|
if (!err || typeof err !== "object") {
|
|
@@ -502,13 +632,13 @@ async function loadWecloneExportModule() {
|
|
|
502
632
|
}
|
|
503
633
|
|
|
504
634
|
// src/converge.ts
|
|
505
|
-
import * as
|
|
635
|
+
import * as fs7 from "fs";
|
|
506
636
|
import { createHash as createHash3 } from "crypto";
|
|
507
637
|
import * as path2 from "path";
|
|
508
638
|
import {
|
|
509
639
|
CONVERGE_CONFLICT_POLICIES,
|
|
510
640
|
DEFAULT_CONVERGE_CONFLICT_POLICY,
|
|
511
|
-
parseConfig as
|
|
641
|
+
parseConfig as parseConfig6,
|
|
512
642
|
buildOfflineSyncSnapshotFromBase,
|
|
513
643
|
applyOfflineSyncFileContentChunk,
|
|
514
644
|
isInternalRemnicStatePath as isInternalRemnicStatePath3,
|
|
@@ -534,7 +664,7 @@ import {
|
|
|
534
664
|
|
|
535
665
|
// src/offline-storage-io.ts
|
|
536
666
|
import { createDecipheriv, createHash } from "crypto";
|
|
537
|
-
import
|
|
667
|
+
import fs6 from "fs";
|
|
538
668
|
import { lstat, mkdtemp, readdir, rm } from "fs/promises";
|
|
539
669
|
import path from "path";
|
|
540
670
|
import {
|
|
@@ -696,7 +826,7 @@ async function* readOfflineSyncFileChunks(options) {
|
|
|
696
826
|
});
|
|
697
827
|
}
|
|
698
828
|
async function readFilePrefix(filePath, length) {
|
|
699
|
-
const handle = await
|
|
829
|
+
const handle = await fs6.promises.open(filePath, "r");
|
|
700
830
|
try {
|
|
701
831
|
const out = Buffer.alloc(length);
|
|
702
832
|
const { bytesRead } = await handle.read(out, 0, length, 0);
|
|
@@ -706,7 +836,7 @@ async function readFilePrefix(filePath, length) {
|
|
|
706
836
|
}
|
|
707
837
|
}
|
|
708
838
|
async function* readPlainOfflineFileChunks(filePath, chunkSize) {
|
|
709
|
-
const stream =
|
|
839
|
+
const stream = fs6.createReadStream(filePath, { highWaterMark: chunkSize });
|
|
710
840
|
for await (const chunk of stream) {
|
|
711
841
|
yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
712
842
|
}
|
|
@@ -743,9 +873,9 @@ async function* readEncryptedOfflineFileChunks(options) {
|
|
|
743
873
|
});
|
|
744
874
|
decipher.setAuthTag(authTag);
|
|
745
875
|
decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
|
|
746
|
-
const output =
|
|
876
|
+
const output = fs6.createWriteStream(tempPath, { mode: 384 });
|
|
747
877
|
try {
|
|
748
|
-
const stream =
|
|
878
|
+
const stream = fs6.createReadStream(options.filePath, {
|
|
749
879
|
start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
|
|
750
880
|
highWaterMark: options.chunkSize
|
|
751
881
|
});
|
|
@@ -1355,7 +1485,7 @@ async function readLocalTombstoneEvidence(rootDir) {
|
|
|
1355
1485
|
for (const relativePath of TOMBSTONE_PATHS) {
|
|
1356
1486
|
let content;
|
|
1357
1487
|
try {
|
|
1358
|
-
content = await
|
|
1488
|
+
content = await fs7.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
|
|
1359
1489
|
} catch (error) {
|
|
1360
1490
|
if (error.code === "ENOENT") continue;
|
|
1361
1491
|
throw error;
|
|
@@ -1370,7 +1500,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
|
|
|
1370
1500
|
const cursorDir = path2.join(path2.resolve(memoryDir), ".remnic", "state", "converge-cursors");
|
|
1371
1501
|
let entries;
|
|
1372
1502
|
try {
|
|
1373
|
-
entries = await
|
|
1503
|
+
entries = await fs7.promises.readdir(cursorDir, { withFileTypes: true });
|
|
1374
1504
|
} catch (error) {
|
|
1375
1505
|
if (error.code === "ENOENT") return [];
|
|
1376
1506
|
throw error;
|
|
@@ -1446,7 +1576,7 @@ async function computeConvergePlan(options = {}) {
|
|
|
1446
1576
|
let config = options.config;
|
|
1447
1577
|
if (!config) {
|
|
1448
1578
|
try {
|
|
1449
|
-
config =
|
|
1579
|
+
config = parseConfig6({});
|
|
1450
1580
|
} catch {
|
|
1451
1581
|
}
|
|
1452
1582
|
}
|
|
@@ -1697,7 +1827,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
1697
1827
|
let config = options.config;
|
|
1698
1828
|
if (!config) {
|
|
1699
1829
|
try {
|
|
1700
|
-
config =
|
|
1830
|
+
config = parseConfig6({});
|
|
1701
1831
|
} catch {
|
|
1702
1832
|
}
|
|
1703
1833
|
}
|
|
@@ -1860,7 +1990,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
1860
1990
|
if (current.sha256 !== entry.localSha256) {
|
|
1861
1991
|
throw new Error(`local file changed during push: ${localPath}`);
|
|
1862
1992
|
}
|
|
1863
|
-
const stat2 = await
|
|
1993
|
+
const stat2 = await fs7.promises.stat(filePath);
|
|
1864
1994
|
let chunks;
|
|
1865
1995
|
let chunkOffset = 0;
|
|
1866
1996
|
const resetChunks = async () => {
|
|
@@ -2137,7 +2267,7 @@ function formatConvergeApplyReport(result) {
|
|
|
2137
2267
|
lines.push(formatConvergeReport(result.plan));
|
|
2138
2268
|
return lines.join("\n");
|
|
2139
2269
|
}
|
|
2140
|
-
async function cmdConverge(action, rest, json, config =
|
|
2270
|
+
async function cmdConverge(action, rest, json, config = parseConfig6({})) {
|
|
2141
2271
|
if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
2142
2272
|
console.log(`Usage: remnic converge <plan|apply> [options]
|
|
2143
2273
|
|
|
@@ -2343,8 +2473,8 @@ function renderReplayResult(result, targetNamespace, format) {
|
|
|
2343
2473
|
}
|
|
2344
2474
|
|
|
2345
2475
|
// src/quarantine-replay.ts
|
|
2346
|
-
import * as
|
|
2347
|
-
import { EngramAccessService, Orchestrator as
|
|
2476
|
+
import * as fs8 from "fs";
|
|
2477
|
+
import { EngramAccessService, Orchestrator as Orchestrator4, initLogger as initLogger3, parseConfig as parseConfig7, resolveRemnicConfigRecord as resolveRemnicConfigRecord6 } from "@remnic/core";
|
|
2348
2478
|
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
2349
2479
|
function valueFlag(args, flag) {
|
|
2350
2480
|
const occurrences = args.filter((a) => a === flag).length;
|
|
@@ -2388,13 +2518,13 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
2388
2518
|
process.exitCode = 2;
|
|
2389
2519
|
return;
|
|
2390
2520
|
}
|
|
2391
|
-
|
|
2521
|
+
initLogger3();
|
|
2392
2522
|
let orchestrator;
|
|
2393
2523
|
try {
|
|
2394
2524
|
const configPath = resolveConfigPath2();
|
|
2395
|
-
const raw =
|
|
2396
|
-
const config =
|
|
2397
|
-
orchestrator = new
|
|
2525
|
+
const raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
|
|
2526
|
+
const config = parseConfig7(resolveRemnicConfigRecord6(raw));
|
|
2527
|
+
orchestrator = new Orchestrator4(config);
|
|
2398
2528
|
await orchestrator.initialize();
|
|
2399
2529
|
await orchestrator.deferredReady;
|
|
2400
2530
|
const service = new EngramAccessService(orchestrator);
|
|
@@ -2424,15 +2554,15 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
2424
2554
|
}
|
|
2425
2555
|
|
|
2426
2556
|
// src/offline-impression-rotation.ts
|
|
2427
|
-
import
|
|
2428
|
-
import { parseConfig as
|
|
2557
|
+
import fs9 from "fs";
|
|
2558
|
+
import { parseConfig as parseConfig8, resolveRemnicConfigRecord as resolveRemnicConfigRecord7, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
2429
2559
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
2430
2560
|
function parseConfigQuietly(raw) {
|
|
2431
2561
|
const originalWarn = console.warn;
|
|
2432
2562
|
console.warn = () => {
|
|
2433
2563
|
};
|
|
2434
2564
|
try {
|
|
2435
|
-
return
|
|
2565
|
+
return parseConfig8(resolveRemnicConfigRecord7(raw));
|
|
2436
2566
|
} finally {
|
|
2437
2567
|
console.warn = originalWarn;
|
|
2438
2568
|
}
|
|
@@ -2446,7 +2576,7 @@ var OFFLINE_CONFIG_KEYS = [
|
|
|
2446
2576
|
function pickOfflineConfigRecord(raw) {
|
|
2447
2577
|
let resolved;
|
|
2448
2578
|
try {
|
|
2449
|
-
resolved =
|
|
2579
|
+
resolved = resolveRemnicConfigRecord7(raw);
|
|
2450
2580
|
} catch {
|
|
2451
2581
|
resolved = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
2452
2582
|
}
|
|
@@ -2459,7 +2589,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
2459
2589
|
function resolveOfflineImpressionRotation(configPath) {
|
|
2460
2590
|
let raw;
|
|
2461
2591
|
try {
|
|
2462
|
-
raw =
|
|
2592
|
+
raw = fs9.existsSync(configPath) ? JSON.parse(fs9.readFileSync(configPath, "utf8")) : {};
|
|
2463
2593
|
} catch {
|
|
2464
2594
|
throw new Error(
|
|
2465
2595
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -2717,12 +2847,12 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
2717
2847
|
}
|
|
2718
2848
|
|
|
2719
2849
|
// src/cmd-security.ts
|
|
2720
|
-
import
|
|
2850
|
+
import fs10 from "fs";
|
|
2721
2851
|
import {
|
|
2722
|
-
Orchestrator as
|
|
2723
|
-
parseConfig as
|
|
2724
|
-
initLogger as
|
|
2725
|
-
resolveRemnicConfigRecord as
|
|
2852
|
+
Orchestrator as Orchestrator5,
|
|
2853
|
+
parseConfig as parseConfig9,
|
|
2854
|
+
initLogger as initLogger4,
|
|
2855
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord8,
|
|
2726
2856
|
runAuditMemoryCliCommand,
|
|
2727
2857
|
formatAuditMemoryReport
|
|
2728
2858
|
} from "@remnic/core";
|
|
@@ -2735,11 +2865,11 @@ async function cmdSecurity(rest) {
|
|
|
2735
2865
|
process.exitCode = 1;
|
|
2736
2866
|
return;
|
|
2737
2867
|
}
|
|
2738
|
-
|
|
2868
|
+
initLogger4();
|
|
2739
2869
|
const configPath = resolveConfigPath();
|
|
2740
|
-
const raw =
|
|
2741
|
-
const config =
|
|
2742
|
-
const orchestrator = new
|
|
2870
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
2871
|
+
const config = parseConfig9(resolveRemnicConfigRecord8(raw));
|
|
2872
|
+
const orchestrator = new Orchestrator5(config);
|
|
2743
2873
|
await orchestrator.initialize();
|
|
2744
2874
|
try {
|
|
2745
2875
|
const sinceFlag = rest.indexOf("--since");
|
|
@@ -2762,7 +2892,7 @@ async function cmdSecurity(rest) {
|
|
|
2762
2892
|
}
|
|
2763
2893
|
|
|
2764
2894
|
// src/daemon-service-candidates.ts
|
|
2765
|
-
import
|
|
2895
|
+
import fs11 from "fs";
|
|
2766
2896
|
import path5 from "path";
|
|
2767
2897
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
2768
2898
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -2784,7 +2914,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
2784
2914
|
function anyFileExists(paths) {
|
|
2785
2915
|
return paths.some((candidate) => {
|
|
2786
2916
|
try {
|
|
2787
|
-
return
|
|
2917
|
+
return fs11.statSync(candidate).isFile();
|
|
2788
2918
|
} catch {
|
|
2789
2919
|
return false;
|
|
2790
2920
|
}
|
|
@@ -2796,7 +2926,7 @@ function commandNames(command) {
|
|
|
2796
2926
|
}
|
|
2797
2927
|
function isRunnableNodeScript(filePath) {
|
|
2798
2928
|
try {
|
|
2799
|
-
const text =
|
|
2929
|
+
const text = fs11.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
2800
2930
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
2801
2931
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
2802
2932
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -2809,7 +2939,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
2809
2939
|
function resolveShimNodeScript(filePath) {
|
|
2810
2940
|
let text;
|
|
2811
2941
|
try {
|
|
2812
|
-
text =
|
|
2942
|
+
text = fs11.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
2813
2943
|
} catch {
|
|
2814
2944
|
return void 0;
|
|
2815
2945
|
}
|
|
@@ -2821,8 +2951,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
2821
2951
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
2822
2952
|
const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
|
|
2823
2953
|
try {
|
|
2824
|
-
if (
|
|
2825
|
-
return
|
|
2954
|
+
if (fs11.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
2955
|
+
return fs11.realpathSync(resolved);
|
|
2826
2956
|
}
|
|
2827
2957
|
} catch {
|
|
2828
2958
|
}
|
|
@@ -2830,7 +2960,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
2830
2960
|
return void 0;
|
|
2831
2961
|
}
|
|
2832
2962
|
function resolveRunnableNodeScript(filePath) {
|
|
2833
|
-
const realPath =
|
|
2963
|
+
const realPath = fs11.realpathSync(filePath);
|
|
2834
2964
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
2835
2965
|
return resolveShimNodeScript(realPath);
|
|
2836
2966
|
}
|
|
@@ -2840,9 +2970,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
2840
2970
|
for (const name of commandNames(command)) {
|
|
2841
2971
|
const candidate = path5.join(dir, name);
|
|
2842
2972
|
try {
|
|
2843
|
-
const stat2 =
|
|
2973
|
+
const stat2 = fs11.statSync(candidate);
|
|
2844
2974
|
if (!stat2.isFile()) continue;
|
|
2845
|
-
if (process.platform !== "win32")
|
|
2975
|
+
if (process.platform !== "win32") fs11.accessSync(candidate, fs11.constants.X_OK);
|
|
2846
2976
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
2847
2977
|
if (runnable) return runnable;
|
|
2848
2978
|
} catch {
|
|
@@ -4315,7 +4445,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
4315
4445
|
}
|
|
4316
4446
|
|
|
4317
4447
|
// src/bench-fallback.ts
|
|
4318
|
-
import
|
|
4448
|
+
import fs12 from "fs";
|
|
4319
4449
|
import path9 from "path";
|
|
4320
4450
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
4321
4451
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -4387,7 +4517,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
4387
4517
|
);
|
|
4388
4518
|
}
|
|
4389
4519
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
4390
|
-
const entries =
|
|
4520
|
+
const entries = fs12.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
4391
4521
|
if (entries.length === 0) {
|
|
4392
4522
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
4393
4523
|
}
|
|
@@ -4395,7 +4525,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
4395
4525
|
}
|
|
4396
4526
|
|
|
4397
4527
|
// src/openclaw-upgrade-swap.ts
|
|
4398
|
-
import
|
|
4528
|
+
import fs13 from "fs";
|
|
4399
4529
|
import path10 from "path";
|
|
4400
4530
|
function describeError(error) {
|
|
4401
4531
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4407,7 +4537,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
4407
4537
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
4408
4538
|
if (explicitMode !== void 0) return explicitMode;
|
|
4409
4539
|
try {
|
|
4410
|
-
return
|
|
4540
|
+
return fs13.statSync(targetPath).mode & 4095;
|
|
4411
4541
|
} catch (error) {
|
|
4412
4542
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
4413
4543
|
return 384;
|
|
@@ -4417,8 +4547,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
4417
4547
|
}
|
|
4418
4548
|
function resolveAtomicReplacementPath(targetPath) {
|
|
4419
4549
|
try {
|
|
4420
|
-
if (
|
|
4421
|
-
return
|
|
4550
|
+
if (fs13.lstatSync(targetPath).isSymbolicLink()) {
|
|
4551
|
+
return fs13.realpathSync(targetPath);
|
|
4422
4552
|
}
|
|
4423
4553
|
} catch (error) {
|
|
4424
4554
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -4435,7 +4565,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
4435
4565
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
4436
4566
|
if (!displacedDir) return void 0;
|
|
4437
4567
|
try {
|
|
4438
|
-
|
|
4568
|
+
fs13.rmSync(displacedDir, { recursive: true, force: true });
|
|
4439
4569
|
return void 0;
|
|
4440
4570
|
} catch (error) {
|
|
4441
4571
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -4443,43 +4573,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
4443
4573
|
}
|
|
4444
4574
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
4445
4575
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4446
|
-
|
|
4576
|
+
fs13.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
4447
4577
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
4448
4578
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
4449
4579
|
try {
|
|
4450
4580
|
if (options.hooks?.writeTempFileSync) {
|
|
4451
4581
|
options.hooks.writeTempFileSync(tempPath);
|
|
4452
4582
|
} else {
|
|
4453
|
-
|
|
4583
|
+
fs13.writeFileSync(tempPath, data, { mode });
|
|
4454
4584
|
}
|
|
4455
|
-
|
|
4456
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
4585
|
+
fs13.chmodSync(tempPath, mode);
|
|
4586
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs13.renameSync;
|
|
4457
4587
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4458
4588
|
} catch (error) {
|
|
4459
|
-
|
|
4589
|
+
fs13.rmSync(tempPath, { force: true });
|
|
4460
4590
|
throw error;
|
|
4461
4591
|
}
|
|
4462
4592
|
}
|
|
4463
4593
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
4464
|
-
if (!
|
|
4594
|
+
if (!fs13.existsSync(sourcePath)) return;
|
|
4465
4595
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4466
|
-
|
|
4596
|
+
fs13.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
4467
4597
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
4468
|
-
const mode =
|
|
4598
|
+
const mode = fs13.statSync(sourcePath).mode & 4095;
|
|
4469
4599
|
try {
|
|
4470
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
4600
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs13.copyFileSync;
|
|
4471
4601
|
copyTempFileSync(sourcePath, tempPath);
|
|
4472
|
-
|
|
4473
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
4602
|
+
fs13.chmodSync(tempPath, mode);
|
|
4603
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs13.renameSync;
|
|
4474
4604
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4475
4605
|
} catch (error) {
|
|
4476
|
-
|
|
4606
|
+
fs13.rmSync(tempPath, { force: true });
|
|
4477
4607
|
throw error;
|
|
4478
4608
|
}
|
|
4479
4609
|
}
|
|
4480
4610
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
4481
4611
|
if (!rollbackDir) return;
|
|
4482
|
-
|
|
4612
|
+
fs13.rmSync(rollbackDir, { recursive: true, force: true });
|
|
4483
4613
|
}
|
|
4484
4614
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
4485
4615
|
if (!rollbackDir) return void 0;
|
|
@@ -4491,20 +4621,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
4491
4621
|
}
|
|
4492
4622
|
}
|
|
4493
4623
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
4494
|
-
if (!
|
|
4624
|
+
if (!fs13.existsSync(rollbackDir)) {
|
|
4495
4625
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
4496
4626
|
}
|
|
4497
|
-
|
|
4498
|
-
const displacedDir =
|
|
4627
|
+
fs13.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
4628
|
+
const displacedDir = fs13.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
4499
4629
|
if (displacedDir) {
|
|
4500
|
-
|
|
4630
|
+
fs13.renameSync(targetDir, displacedDir);
|
|
4501
4631
|
}
|
|
4502
4632
|
try {
|
|
4503
|
-
|
|
4633
|
+
fs13.renameSync(rollbackDir, targetDir);
|
|
4504
4634
|
} catch (restoreError) {
|
|
4505
|
-
if (displacedDir &&
|
|
4635
|
+
if (displacedDir && fs13.existsSync(displacedDir)) {
|
|
4506
4636
|
try {
|
|
4507
|
-
|
|
4637
|
+
fs13.renameSync(displacedDir, targetDir);
|
|
4508
4638
|
} catch (revertError) {
|
|
4509
4639
|
throw new AggregateError(
|
|
4510
4640
|
[restoreError, revertError],
|
|
@@ -4520,23 +4650,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
4520
4650
|
return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
|
|
4521
4651
|
}
|
|
4522
4652
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
4523
|
-
if (!
|
|
4653
|
+
if (!fs13.existsSync(backupDir)) {
|
|
4524
4654
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
4525
4655
|
}
|
|
4526
|
-
|
|
4656
|
+
fs13.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
4527
4657
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
4528
|
-
const displacedDir =
|
|
4529
|
-
|
|
4658
|
+
const displacedDir = fs13.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
4659
|
+
fs13.cpSync(backupDir, stagedDir, { recursive: true });
|
|
4530
4660
|
if (displacedDir) {
|
|
4531
|
-
|
|
4661
|
+
fs13.renameSync(targetDir, displacedDir);
|
|
4532
4662
|
}
|
|
4533
4663
|
try {
|
|
4534
|
-
|
|
4664
|
+
fs13.renameSync(stagedDir, targetDir);
|
|
4535
4665
|
} catch (restoreError) {
|
|
4536
|
-
|
|
4537
|
-
if (displacedDir &&
|
|
4666
|
+
fs13.rmSync(targetDir, { recursive: true, force: true });
|
|
4667
|
+
if (displacedDir && fs13.existsSync(displacedDir)) {
|
|
4538
4668
|
try {
|
|
4539
|
-
|
|
4669
|
+
fs13.renameSync(displacedDir, targetDir);
|
|
4540
4670
|
} catch (revertError) {
|
|
4541
4671
|
throw new AggregateError(
|
|
4542
4672
|
[restoreError, revertError],
|
|
@@ -4544,7 +4674,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
4544
4674
|
);
|
|
4545
4675
|
}
|
|
4546
4676
|
}
|
|
4547
|
-
|
|
4677
|
+
fs13.rmSync(stagedDir, { recursive: true, force: true });
|
|
4548
4678
|
throw new Error(
|
|
4549
4679
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
4550
4680
|
{ cause: restoreError }
|
|
@@ -4569,7 +4699,7 @@ function rollbackOpenclawUpgrade({
|
|
|
4569
4699
|
let configRemovalAttempted = false;
|
|
4570
4700
|
let pluginRestored = false;
|
|
4571
4701
|
try {
|
|
4572
|
-
if (rollbackDir &&
|
|
4702
|
+
if (rollbackDir && fs13.existsSync(rollbackDir)) {
|
|
4573
4703
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
4574
4704
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
4575
4705
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -4579,7 +4709,7 @@ function rollbackOpenclawUpgrade({
|
|
|
4579
4709
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
4580
4710
|
}
|
|
4581
4711
|
try {
|
|
4582
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
4712
|
+
if (!pluginRestored && pluginBackupDir && fs13.existsSync(pluginBackupDir)) {
|
|
4583
4713
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
4584
4714
|
if (rollbackRestoreError) {
|
|
4585
4715
|
notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
|
|
@@ -4604,12 +4734,12 @@ function rollbackOpenclawUpgrade({
|
|
|
4604
4734
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
4605
4735
|
}
|
|
4606
4736
|
try {
|
|
4607
|
-
if (configBackupPath &&
|
|
4737
|
+
if (configBackupPath && fs13.existsSync(configBackupPath)) {
|
|
4608
4738
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
4609
4739
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
4610
|
-
} else if (removeConfigIfUnbacked &&
|
|
4740
|
+
} else if (removeConfigIfUnbacked && fs13.existsSync(configPath)) {
|
|
4611
4741
|
configRemovalAttempted = true;
|
|
4612
|
-
|
|
4742
|
+
fs13.rmSync(configPath, { force: true });
|
|
4613
4743
|
notes.push("Removed OpenClaw config created during the failed upgrade");
|
|
4614
4744
|
}
|
|
4615
4745
|
} catch (error) {
|
|
@@ -4662,7 +4792,7 @@ Run this manually when you're ready:
|
|
|
4662
4792
|
|
|
4663
4793
|
// src/openclaw-managed-upgrade-loader.ts
|
|
4664
4794
|
import { execFileSync } from "child_process";
|
|
4665
|
-
import
|
|
4795
|
+
import fs14 from "fs";
|
|
4666
4796
|
import os from "os";
|
|
4667
4797
|
import path11 from "path";
|
|
4668
4798
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -4738,7 +4868,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
|
|
|
4738
4868
|
function readCliAdapterRange() {
|
|
4739
4869
|
const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
|
|
4740
4870
|
const manifestPath = path11.resolve(moduleDir, "../package.json");
|
|
4741
|
-
const manifest = JSON.parse(
|
|
4871
|
+
const manifest = JSON.parse(fs14.readFileSync(manifestPath, "utf8"));
|
|
4742
4872
|
if (manifest.name !== "@remnic/cli") {
|
|
4743
4873
|
throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
|
|
4744
4874
|
}
|
|
@@ -4782,7 +4912,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
4782
4912
|
const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
|
|
4783
4913
|
if (!adapterMissing) throw error;
|
|
4784
4914
|
}
|
|
4785
|
-
const temporaryRoot =
|
|
4915
|
+
const temporaryRoot = fs14.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
4786
4916
|
try {
|
|
4787
4917
|
const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
|
|
4788
4918
|
const installArgs = [
|
|
@@ -4797,12 +4927,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
4797
4927
|
];
|
|
4798
4928
|
(hooks.runNpmInstall ?? runNpmInstall)(installArgs);
|
|
4799
4929
|
const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
|
|
4800
|
-
|
|
4930
|
+
fs14.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
|
|
4801
4931
|
`, "utf8");
|
|
4802
4932
|
return await importModule(pathToFileURL2(resolverPath).href);
|
|
4803
4933
|
} finally {
|
|
4804
4934
|
try {
|
|
4805
|
-
|
|
4935
|
+
fs14.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
4806
4936
|
} catch (error) {
|
|
4807
4937
|
const detail = error instanceof Error ? error.message : String(error);
|
|
4808
4938
|
console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
|
|
@@ -4811,13 +4941,13 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
4811
4941
|
}
|
|
4812
4942
|
|
|
4813
4943
|
// src/remote-daemon.ts
|
|
4814
|
-
import
|
|
4944
|
+
import fs15 from "fs";
|
|
4815
4945
|
function readCompatEnv(primary, legacy) {
|
|
4816
4946
|
return process.env[primary] ?? process.env[legacy];
|
|
4817
4947
|
}
|
|
4818
4948
|
function readRemnicConfigRecord(configPath) {
|
|
4819
4949
|
try {
|
|
4820
|
-
const parsed = JSON.parse(
|
|
4950
|
+
const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
|
|
4821
4951
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4822
4952
|
return parsed;
|
|
4823
4953
|
}
|
|
@@ -5046,7 +5176,7 @@ async function remoteRecallXray(daemon, request) {
|
|
|
5046
5176
|
}
|
|
5047
5177
|
|
|
5048
5178
|
// src/daemon-service.ts
|
|
5049
|
-
import
|
|
5179
|
+
import fs16 from "fs";
|
|
5050
5180
|
import path12 from "path";
|
|
5051
5181
|
import * as childProcess from "child_process";
|
|
5052
5182
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -5058,7 +5188,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
5058
5188
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
5059
5189
|
}
|
|
5060
5190
|
function resolveServerBinDetails(options = {}) {
|
|
5061
|
-
const existsSync4 = options.existsSync ??
|
|
5191
|
+
const existsSync4 = options.existsSync ?? fs16.existsSync;
|
|
5062
5192
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
5063
5193
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
5064
5194
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -5117,8 +5247,8 @@ function resolveServerBin(options = {}) {
|
|
|
5117
5247
|
return resolveServerBinDetails(options).path;
|
|
5118
5248
|
}
|
|
5119
5249
|
function readVerifiedDaemonPid(options) {
|
|
5120
|
-
const readFileSync4 = options.readFileSync ??
|
|
5121
|
-
const unlinkSync = options.unlinkSync ??
|
|
5250
|
+
const readFileSync4 = options.readFileSync ?? fs16.readFileSync;
|
|
5251
|
+
const unlinkSync = options.unlinkSync ?? fs16.unlinkSync;
|
|
5122
5252
|
const processKill = options.processKill ?? process.kill;
|
|
5123
5253
|
const platform = options.platform ?? process.platform;
|
|
5124
5254
|
const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
@@ -5218,8 +5348,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
5218
5348
|
}
|
|
5219
5349
|
}
|
|
5220
5350
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
5221
|
-
const existsSync4 = options.existsSync ??
|
|
5222
|
-
const readFileSync4 = options.readFileSync ??
|
|
5351
|
+
const existsSync4 = options.existsSync ?? fs16.existsSync;
|
|
5352
|
+
const readFileSync4 = options.readFileSync ?? fs16.readFileSync;
|
|
5223
5353
|
if (!existsSync4(plistPath)) {
|
|
5224
5354
|
return {
|
|
5225
5355
|
installed: false,
|
|
@@ -5397,7 +5527,7 @@ function stripConfigArgv(args) {
|
|
|
5397
5527
|
}
|
|
5398
5528
|
|
|
5399
5529
|
// src/import-dispatch.ts
|
|
5400
|
-
import
|
|
5530
|
+
import fs17 from "fs";
|
|
5401
5531
|
import {
|
|
5402
5532
|
runImporter,
|
|
5403
5533
|
validateImportBatchSize,
|
|
@@ -5911,7 +6041,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
5911
6041
|
let materializedTarget;
|
|
5912
6042
|
let materializePromise;
|
|
5913
6043
|
const io = {
|
|
5914
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
6044
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs17.promises.readFile(p, "utf-8")),
|
|
5915
6045
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
5916
6046
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
5917
6047
|
getWriteTarget: async () => {
|
|
@@ -6024,7 +6154,7 @@ async function cmdCapture(rest, io) {
|
|
|
6024
6154
|
}
|
|
6025
6155
|
|
|
6026
6156
|
// src/import-lossless-claw-cmd.ts
|
|
6027
|
-
import
|
|
6157
|
+
import fs18 from "fs";
|
|
6028
6158
|
import path14 from "path";
|
|
6029
6159
|
import {
|
|
6030
6160
|
applyLcmSchema,
|
|
@@ -6136,15 +6266,15 @@ async function loadImportLosslessClawModule() {
|
|
|
6136
6266
|
|
|
6137
6267
|
// src/import-lossless-claw-cmd.ts
|
|
6138
6268
|
function assertDirectoryOrAbsent(p, label) {
|
|
6139
|
-
if (
|
|
6269
|
+
if (fs18.existsSync(p) && !fs18.statSync(p).isDirectory()) {
|
|
6140
6270
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
6141
6271
|
}
|
|
6142
6272
|
}
|
|
6143
6273
|
function assertFile(p, label) {
|
|
6144
|
-
if (!
|
|
6274
|
+
if (!fs18.existsSync(p)) {
|
|
6145
6275
|
throw new Error(`${label} does not exist: ${p}`);
|
|
6146
6276
|
}
|
|
6147
|
-
if (!
|
|
6277
|
+
if (!fs18.statSync(p).isFile()) {
|
|
6148
6278
|
throw new Error(`${label} is not a file: ${p}`);
|
|
6149
6279
|
}
|
|
6150
6280
|
}
|
|
@@ -6176,7 +6306,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
6176
6306
|
try {
|
|
6177
6307
|
if (parsed.dryRun) {
|
|
6178
6308
|
const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
|
|
6179
|
-
if (
|
|
6309
|
+
if (fs18.existsSync(lcmPath)) {
|
|
6180
6310
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
6181
6311
|
} else {
|
|
6182
6312
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -7528,7 +7658,7 @@ async function resolveAllBenchmarks() {
|
|
|
7528
7658
|
if (packageBenchmarks) {
|
|
7529
7659
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
7530
7660
|
}
|
|
7531
|
-
if (!
|
|
7661
|
+
if (!fs19.existsSync(EVAL_RUNNER_PATH)) {
|
|
7532
7662
|
return [];
|
|
7533
7663
|
}
|
|
7534
7664
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -7576,7 +7706,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
7576
7706
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
7577
7707
|
);
|
|
7578
7708
|
}
|
|
7579
|
-
if (!
|
|
7709
|
+
if (!fs19.existsSync(EVAL_RUNNER_PATH)) {
|
|
7580
7710
|
console.error(
|
|
7581
7711
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
7582
7712
|
);
|
|
@@ -7586,7 +7716,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
7586
7716
|
path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
7587
7717
|
path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
7588
7718
|
];
|
|
7589
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
7719
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs19.existsSync(candidate)) ?? "tsx";
|
|
7590
7720
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
7591
7721
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
7592
7722
|
benchmarkId,
|
|
@@ -7731,9 +7861,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
|
|
|
7731
7861
|
);
|
|
7732
7862
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
7733
7863
|
try {
|
|
7734
|
-
const datasetRoot =
|
|
7864
|
+
const datasetRoot = fs19.realpathSync(datasetPath);
|
|
7735
7865
|
const candidatePath = path18.resolve(datasetRoot, relativePath);
|
|
7736
|
-
const candidateRealPath =
|
|
7866
|
+
const candidateRealPath = fs19.realpathSync(candidatePath);
|
|
7737
7867
|
const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
|
|
7738
7868
|
if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
|
|
7739
7869
|
return null;
|
|
@@ -7792,14 +7922,14 @@ function parseCsvRows(raw) {
|
|
|
7792
7922
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
7793
7923
|
try {
|
|
7794
7924
|
const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
7795
|
-
if (
|
|
7925
|
+
if (fs19.statSync(completionMarkerPath).isFile()) {
|
|
7796
7926
|
return true;
|
|
7797
7927
|
}
|
|
7798
7928
|
} catch {
|
|
7799
7929
|
}
|
|
7800
7930
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
7801
7931
|
try {
|
|
7802
|
-
return
|
|
7932
|
+
return fs19.statSync(path18.join(datasetPath, candidate)).isFile();
|
|
7803
7933
|
} catch {
|
|
7804
7934
|
return false;
|
|
7805
7935
|
}
|
|
@@ -7808,7 +7938,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
7808
7938
|
return false;
|
|
7809
7939
|
}
|
|
7810
7940
|
try {
|
|
7811
|
-
const rows = parseCsvRows(
|
|
7941
|
+
const rows = parseCsvRows(fs19.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
|
|
7812
7942
|
if (rows.length < 2) {
|
|
7813
7943
|
return false;
|
|
7814
7944
|
}
|
|
@@ -7823,7 +7953,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
7823
7953
|
}
|
|
7824
7954
|
return historyPaths.every((relativePath) => {
|
|
7825
7955
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
7826
|
-
return resolvedPath !== null &&
|
|
7956
|
+
return resolvedPath !== null && fs19.statSync(resolvedPath).isFile();
|
|
7827
7957
|
});
|
|
7828
7958
|
} catch {
|
|
7829
7959
|
return false;
|
|
@@ -7831,7 +7961,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
7831
7961
|
}
|
|
7832
7962
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
7833
7963
|
try {
|
|
7834
|
-
return
|
|
7964
|
+
return fs19.statSync(path18.join(datasetPath, relativePath)).isFile();
|
|
7835
7965
|
} catch {
|
|
7836
7966
|
return false;
|
|
7837
7967
|
}
|
|
@@ -7851,10 +7981,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
7851
7981
|
return candidateFilenames.some((filename) => {
|
|
7852
7982
|
const filePath = path18.join(datasetPath, filename);
|
|
7853
7983
|
try {
|
|
7854
|
-
if (!
|
|
7984
|
+
if (!fs19.statSync(filePath).isFile()) {
|
|
7855
7985
|
return false;
|
|
7856
7986
|
}
|
|
7857
|
-
const raw =
|
|
7987
|
+
const raw = fs19.readFileSync(filePath, "utf8");
|
|
7858
7988
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
7859
7989
|
} catch {
|
|
7860
7990
|
return false;
|
|
@@ -7870,7 +8000,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
7870
8000
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
7871
8001
|
let stats;
|
|
7872
8002
|
try {
|
|
7873
|
-
stats =
|
|
8003
|
+
stats = fs19.statSync(datasetPath);
|
|
7874
8004
|
} catch {
|
|
7875
8005
|
return false;
|
|
7876
8006
|
}
|
|
@@ -7880,7 +8010,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7880
8010
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
7881
8011
|
if (!marker) {
|
|
7882
8012
|
try {
|
|
7883
|
-
return
|
|
8013
|
+
return fs19.readdirSync(datasetPath).length > 0;
|
|
7884
8014
|
} catch {
|
|
7885
8015
|
return false;
|
|
7886
8016
|
}
|
|
@@ -7888,7 +8018,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7888
8018
|
if (marker.allOf) {
|
|
7889
8019
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
7890
8020
|
try {
|
|
7891
|
-
return
|
|
8021
|
+
return fs19.statSync(path18.join(datasetPath, name)).isFile();
|
|
7892
8022
|
} catch {
|
|
7893
8023
|
return false;
|
|
7894
8024
|
}
|
|
@@ -7900,7 +8030,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7900
8030
|
if (marker.anyOf) {
|
|
7901
8031
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
7902
8032
|
try {
|
|
7903
|
-
return
|
|
8033
|
+
return fs19.statSync(path18.join(datasetPath, name)).isFile();
|
|
7904
8034
|
} catch {
|
|
7905
8035
|
return false;
|
|
7906
8036
|
}
|
|
@@ -7918,7 +8048,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7918
8048
|
}
|
|
7919
8049
|
if (marker.ext) {
|
|
7920
8050
|
try {
|
|
7921
|
-
return
|
|
8051
|
+
return fs19.readdirSync(datasetPath).some(
|
|
7922
8052
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
7923
8053
|
);
|
|
7924
8054
|
} catch {
|
|
@@ -7930,7 +8060,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7930
8060
|
async function launchBenchUi(resultsDir) {
|
|
7931
8061
|
const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
7932
8062
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
7933
|
-
if (!
|
|
8063
|
+
if (!fs19.existsSync(path18.join(benchUiDir, "package.json"))) {
|
|
7934
8064
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
7935
8065
|
process.exit(1);
|
|
7936
8066
|
}
|
|
@@ -7968,13 +8098,13 @@ function listDownloadableBenchmarks() {
|
|
|
7968
8098
|
}
|
|
7969
8099
|
function resolveDatasetDownloadScriptPath() {
|
|
7970
8100
|
const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
7971
|
-
if (
|
|
8101
|
+
if (fs19.existsSync(bundled)) {
|
|
7972
8102
|
return bundled;
|
|
7973
8103
|
}
|
|
7974
8104
|
return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
7975
8105
|
}
|
|
7976
8106
|
function isRepoCheckout() {
|
|
7977
|
-
return
|
|
8107
|
+
return fs19.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs19.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
7978
8108
|
}
|
|
7979
8109
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
7980
8110
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -8287,8 +8417,8 @@ async function exportBenchPackageResult(parsed) {
|
|
|
8287
8417
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
8288
8418
|
});
|
|
8289
8419
|
if (parsed.output) {
|
|
8290
|
-
|
|
8291
|
-
|
|
8420
|
+
fs19.mkdirSync(path18.dirname(parsed.output), { recursive: true });
|
|
8421
|
+
fs19.writeFileSync(parsed.output, rendered);
|
|
8292
8422
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
8293
8423
|
return;
|
|
8294
8424
|
}
|
|
@@ -8333,7 +8463,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
8333
8463
|
process.exit(1);
|
|
8334
8464
|
}
|
|
8335
8465
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
8336
|
-
if (!
|
|
8466
|
+
if (!fs19.existsSync(scriptPath)) {
|
|
8337
8467
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
8338
8468
|
process.exit(1);
|
|
8339
8469
|
}
|
|
@@ -8533,7 +8663,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
8533
8663
|
);
|
|
8534
8664
|
process.exit(1);
|
|
8535
8665
|
}
|
|
8536
|
-
const sourceResultSha256 = createHash4("sha256").update(
|
|
8666
|
+
const sourceResultSha256 = createHash4("sha256").update(fs19.readFileSync(latest.path)).digest("hex");
|
|
8537
8667
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
8538
8668
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
8539
8669
|
console.error(
|
|
@@ -8948,7 +9078,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
8948
9078
|
}
|
|
8949
9079
|
let decoded;
|
|
8950
9080
|
try {
|
|
8951
|
-
decoded = JSON.parse(
|
|
9081
|
+
decoded = JSON.parse(fs19.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
8952
9082
|
} catch (error) {
|
|
8953
9083
|
throw new Error(
|
|
8954
9084
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -9623,7 +9753,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
9623
9753
|
return void 0;
|
|
9624
9754
|
}
|
|
9625
9755
|
try {
|
|
9626
|
-
return
|
|
9756
|
+
return fs19.realpathSync(datasetDir);
|
|
9627
9757
|
} catch {
|
|
9628
9758
|
return datasetDir;
|
|
9629
9759
|
}
|
|
@@ -9677,13 +9807,13 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
9677
9807
|
}
|
|
9678
9808
|
function loadStandaloneConvergeCommandConfig() {
|
|
9679
9809
|
const configPath = resolveConfigPath();
|
|
9680
|
-
const raw =
|
|
9681
|
-
return
|
|
9810
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
9811
|
+
return parseConfig10(resolveRemnicConfigRecord9(raw));
|
|
9682
9812
|
}
|
|
9683
9813
|
function parseConvergePluginConfig(value) {
|
|
9684
9814
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
9685
9815
|
if (Object.keys(value).length === 0) return void 0;
|
|
9686
|
-
return
|
|
9816
|
+
return parseConfig10(resolveRemnicConfigRecord9(value));
|
|
9687
9817
|
}
|
|
9688
9818
|
function loadConvergeCommandConfig() {
|
|
9689
9819
|
if (readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH")) {
|
|
@@ -9706,13 +9836,13 @@ function resolveConfigPath(cliPath) {
|
|
|
9706
9836
|
path18.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
9707
9837
|
];
|
|
9708
9838
|
for (const candidate of candidates) {
|
|
9709
|
-
if (
|
|
9839
|
+
if (fs19.existsSync(candidate)) return candidate;
|
|
9710
9840
|
}
|
|
9711
9841
|
return path18.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
9712
9842
|
}
|
|
9713
9843
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
9714
9844
|
const configPath = resolveConfigPath(cliPath);
|
|
9715
|
-
if (
|
|
9845
|
+
if (fs19.existsSync(configPath)) {
|
|
9716
9846
|
return configPath;
|
|
9717
9847
|
}
|
|
9718
9848
|
if (cliPath) {
|
|
@@ -9722,7 +9852,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
9722
9852
|
}
|
|
9723
9853
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
9724
9854
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
9725
|
-
if (
|
|
9855
|
+
if (fs19.existsSync(configPath)) {
|
|
9726
9856
|
return configPath;
|
|
9727
9857
|
}
|
|
9728
9858
|
if (cliPath) {
|
|
@@ -9829,8 +9959,8 @@ function resolveMemoryDir() {
|
|
|
9829
9959
|
const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
9830
9960
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
9831
9961
|
const configPath = resolveConfigPath();
|
|
9832
|
-
const raw =
|
|
9833
|
-
const remnicCfg =
|
|
9962
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
9963
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
9834
9964
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
9835
9965
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
9836
9966
|
}
|
|
@@ -9838,18 +9968,18 @@ function resolveMemoryDir() {
|
|
|
9838
9968
|
const standalonePath = path18.join(home, ".remnic", "memory");
|
|
9839
9969
|
const legacyStandalonePath = path18.join(home, ".engram", "memory");
|
|
9840
9970
|
const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
9841
|
-
if (
|
|
9842
|
-
if (
|
|
9971
|
+
if (fs19.existsSync(standalonePath)) return standalonePath;
|
|
9972
|
+
if (fs19.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
9843
9973
|
return openclawPath;
|
|
9844
9974
|
})();
|
|
9845
9975
|
const manifestPath = getManifestPath();
|
|
9846
|
-
if (
|
|
9976
|
+
if (fs19.existsSync(manifestPath)) {
|
|
9847
9977
|
try {
|
|
9848
9978
|
const active = getActiveSpace();
|
|
9849
9979
|
if (active?.memoryDir) {
|
|
9850
9980
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
9851
|
-
if (!
|
|
9852
|
-
|
|
9981
|
+
if (!fs19.existsSync(activeMemoryDir)) {
|
|
9982
|
+
fs19.mkdirSync(activeMemoryDir, { recursive: true });
|
|
9853
9983
|
}
|
|
9854
9984
|
return activeMemoryDir;
|
|
9855
9985
|
}
|
|
@@ -9898,13 +10028,13 @@ function resolveOpenclawConfigPath(cliPath) {
|
|
|
9898
10028
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
9899
10029
|
if (envPath) return path18.resolve(expandTilde(envPath));
|
|
9900
10030
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
9901
|
-
if (
|
|
10031
|
+
if (fs19.existsSync(candidate)) return candidate;
|
|
9902
10032
|
}
|
|
9903
10033
|
return path18.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
9904
10034
|
}
|
|
9905
10035
|
function readOpenclawConfig(configPath) {
|
|
9906
|
-
if (!
|
|
9907
|
-
const raw =
|
|
10036
|
+
if (!fs19.existsSync(configPath)) return {};
|
|
10037
|
+
const raw = fs19.readFileSync(configPath, "utf-8");
|
|
9908
10038
|
let parsed;
|
|
9909
10039
|
try {
|
|
9910
10040
|
parsed = JSON.parse(raw);
|
|
@@ -10006,9 +10136,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
10006
10136
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
10007
10137
|
}
|
|
10008
10138
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
10009
|
-
if (!
|
|
10010
|
-
|
|
10011
|
-
|
|
10139
|
+
if (!fs19.existsSync(sourcePath)) return false;
|
|
10140
|
+
fs19.mkdirSync(path18.dirname(backupPath), { recursive: true });
|
|
10141
|
+
fs19.cpSync(sourcePath, backupPath, { recursive: true });
|
|
10012
10142
|
return true;
|
|
10013
10143
|
}
|
|
10014
10144
|
function restartOpenclawGateway() {
|
|
@@ -10027,7 +10157,7 @@ function restartOpenclawGateway() {
|
|
|
10027
10157
|
}
|
|
10028
10158
|
function cmdInit() {
|
|
10029
10159
|
const configPath = path18.join(process.cwd(), "remnic.config.json");
|
|
10030
|
-
if (
|
|
10160
|
+
if (fs19.existsSync(configPath)) {
|
|
10031
10161
|
console.log(`Config already exists: ${configPath}`);
|
|
10032
10162
|
return;
|
|
10033
10163
|
}
|
|
@@ -10043,7 +10173,7 @@ function cmdInit() {
|
|
|
10043
10173
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
10044
10174
|
}
|
|
10045
10175
|
};
|
|
10046
|
-
|
|
10176
|
+
fs19.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
10047
10177
|
console.log(`Created ${configPath}`);
|
|
10048
10178
|
console.log("\nSet these environment variables:");
|
|
10049
10179
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -10463,12 +10593,12 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
10463
10593
|
printQueryResult(result, json);
|
|
10464
10594
|
return;
|
|
10465
10595
|
}
|
|
10466
|
-
|
|
10596
|
+
initLogger5();
|
|
10467
10597
|
const configPath = resolveConfigPath();
|
|
10468
|
-
const raw =
|
|
10469
|
-
const remnicCfg =
|
|
10470
|
-
const config =
|
|
10471
|
-
const orchestrator = new
|
|
10598
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
10599
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
10600
|
+
const config = parseConfig10(remnicCfg);
|
|
10601
|
+
const orchestrator = new Orchestrator6(config);
|
|
10472
10602
|
await orchestrator.initialize();
|
|
10473
10603
|
const service = new EngramAccessService2(orchestrator);
|
|
10474
10604
|
const recallRequest = buildQueryRecallRequest(queryText);
|
|
@@ -10643,12 +10773,12 @@ async function cmdXray(rest) {
|
|
|
10643
10773
|
await runXrayCommand(rest, xrayCliIo((request) => remoteRecallXray(remote, request)));
|
|
10644
10774
|
return;
|
|
10645
10775
|
}
|
|
10646
|
-
|
|
10776
|
+
initLogger5();
|
|
10647
10777
|
const configPath = resolveConfigPath();
|
|
10648
|
-
const raw =
|
|
10649
|
-
const remnicCfg =
|
|
10650
|
-
const config =
|
|
10651
|
-
const orchestrator = new
|
|
10778
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
10779
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
10780
|
+
const config = parseConfig10(remnicCfg);
|
|
10781
|
+
const orchestrator = new Orchestrator6(config);
|
|
10652
10782
|
await orchestrator.initialize();
|
|
10653
10783
|
await orchestrator.deferredReady;
|
|
10654
10784
|
const service = new EngramAccessService2(orchestrator);
|
|
@@ -10676,10 +10806,10 @@ async function runWhoKnowsCommand(rest, io) {
|
|
|
10676
10806
|
io.stdout(renderWhoKnows(result, parsed.json));
|
|
10677
10807
|
}
|
|
10678
10808
|
async function withLocalService(fn) {
|
|
10679
|
-
|
|
10809
|
+
initLogger5();
|
|
10680
10810
|
const configPath = resolveConfigPath();
|
|
10681
|
-
const raw =
|
|
10682
|
-
const orchestrator = new
|
|
10811
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
10812
|
+
const orchestrator = new Orchestrator6(parseConfig10(resolveRemnicConfigRecord9(raw)));
|
|
10683
10813
|
await orchestrator.initialize();
|
|
10684
10814
|
await orchestrator.deferredReady;
|
|
10685
10815
|
const service = new EngramAccessService2(orchestrator);
|
|
@@ -10709,11 +10839,11 @@ async function cmdPromotionCandidates(rest) {
|
|
|
10709
10839
|
}));
|
|
10710
10840
|
}
|
|
10711
10841
|
async function cmdVersions(rest) {
|
|
10712
|
-
|
|
10842
|
+
initLogger5();
|
|
10713
10843
|
const configPath = resolveConfigPath();
|
|
10714
|
-
const raw =
|
|
10715
|
-
const remnicCfg =
|
|
10716
|
-
const config =
|
|
10844
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
10845
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
10846
|
+
const config = parseConfig10(remnicCfg);
|
|
10717
10847
|
if (!config.versioningEnabled) {
|
|
10718
10848
|
console.error("Page versioning is disabled (versioningEnabled = false).");
|
|
10719
10849
|
process.exit(1);
|
|
@@ -10825,11 +10955,11 @@ Options:
|
|
|
10825
10955
|
}
|
|
10826
10956
|
}
|
|
10827
10957
|
async function cmdEnrich(rest) {
|
|
10828
|
-
|
|
10958
|
+
initLogger5();
|
|
10829
10959
|
const configPath = resolveConfigPath();
|
|
10830
|
-
const raw =
|
|
10831
|
-
const remnicCfg =
|
|
10832
|
-
const config =
|
|
10960
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
10961
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
10962
|
+
const config = parseConfig10(remnicCfg);
|
|
10833
10963
|
const subcommand = rest[0];
|
|
10834
10964
|
if (subcommand === "audit") {
|
|
10835
10965
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
@@ -10857,7 +10987,7 @@ async function cmdEnrich(rest) {
|
|
|
10857
10987
|
pipelineConfig2.providers = [
|
|
10858
10988
|
{ id: "web-search", enabled: true, costTier: "cheap" }
|
|
10859
10989
|
];
|
|
10860
|
-
const orchestrator2 = new
|
|
10990
|
+
const orchestrator2 = new Orchestrator6(config);
|
|
10861
10991
|
await orchestrator2.initialize();
|
|
10862
10992
|
await orchestrator2.deferredReady;
|
|
10863
10993
|
const searchBackend2 = orchestrator2.qmd;
|
|
@@ -10893,7 +11023,7 @@ Registered providers:`);
|
|
|
10893
11023
|
console.error("Usage: remnic enrich <entity-name> | --all | --dry-run | audit | providers");
|
|
10894
11024
|
process.exit(1);
|
|
10895
11025
|
}
|
|
10896
|
-
const orchestrator = new
|
|
11026
|
+
const orchestrator = new Orchestrator6(config);
|
|
10897
11027
|
await orchestrator.initialize();
|
|
10898
11028
|
await orchestrator.deferredReady;
|
|
10899
11029
|
const storage = await orchestrator.getStorage(config.defaultNamespace);
|
|
@@ -11019,11 +11149,11 @@ Registered providers:`);
|
|
|
11019
11149
|
}
|
|
11020
11150
|
}
|
|
11021
11151
|
async function cmdExtensions(action, rest) {
|
|
11022
|
-
|
|
11152
|
+
initLogger5();
|
|
11023
11153
|
const configPath = resolveConfigPath();
|
|
11024
|
-
const raw =
|
|
11025
|
-
const remnicCfg =
|
|
11026
|
-
const config =
|
|
11154
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
11155
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
11156
|
+
const config = parseConfig10(remnicCfg);
|
|
11027
11157
|
const root = resolveExtensionsRoot(config);
|
|
11028
11158
|
const noopLog = { warn: () => {
|
|
11029
11159
|
}, debug: () => {
|
|
@@ -11072,7 +11202,7 @@ Root: ${root}`);
|
|
|
11072
11202
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
11073
11203
|
let entries = [];
|
|
11074
11204
|
try {
|
|
11075
|
-
entries =
|
|
11205
|
+
entries = fs19.readdirSync(root);
|
|
11076
11206
|
} catch {
|
|
11077
11207
|
console.log(`Extensions root does not exist: ${root}`);
|
|
11078
11208
|
process.exitCode = 0;
|
|
@@ -11083,7 +11213,7 @@ Root: ${root}`);
|
|
|
11083
11213
|
for (const entry of entries) {
|
|
11084
11214
|
const entryPath = path18.join(root, entry);
|
|
11085
11215
|
try {
|
|
11086
|
-
if (!
|
|
11216
|
+
if (!fs19.statSync(entryPath).isDirectory()) continue;
|
|
11087
11217
|
} catch {
|
|
11088
11218
|
continue;
|
|
11089
11219
|
}
|
|
@@ -11113,11 +11243,11 @@ Root: ${root}`);
|
|
|
11113
11243
|
}
|
|
11114
11244
|
}
|
|
11115
11245
|
async function cmdBriefing(rest) {
|
|
11116
|
-
|
|
11246
|
+
initLogger5();
|
|
11117
11247
|
const configPath = resolveConfigPath();
|
|
11118
|
-
const raw =
|
|
11119
|
-
const remnicCfg =
|
|
11120
|
-
const config =
|
|
11248
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
11249
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
11250
|
+
const config = parseConfig10(remnicCfg);
|
|
11121
11251
|
if (!config.briefing.enabled) {
|
|
11122
11252
|
console.error("Briefing is disabled in config (briefing.enabled = false).");
|
|
11123
11253
|
process.exit(1);
|
|
@@ -11170,7 +11300,7 @@ async function cmdBriefing(rest) {
|
|
|
11170
11300
|
process.exit(1);
|
|
11171
11301
|
}
|
|
11172
11302
|
const format = effectiveFormatFlag === "json" ? "json" : effectiveFormatFlag === "markdown" ? "markdown" : config.briefing.defaultFormat;
|
|
11173
|
-
const orchestrator = new
|
|
11303
|
+
const orchestrator = new Orchestrator6(config);
|
|
11174
11304
|
await orchestrator.initialize();
|
|
11175
11305
|
const storage = await orchestrator.getStorage(config.defaultNamespace);
|
|
11176
11306
|
const calendarSource = config.briefing.calendarSource ? new FileCalendarSource(config.briefing.calendarSource) : void 0;
|
|
@@ -11195,10 +11325,10 @@ async function cmdBriefing(rest) {
|
|
|
11195
11325
|
if (save) {
|
|
11196
11326
|
try {
|
|
11197
11327
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
11198
|
-
|
|
11328
|
+
fs19.mkdirSync(saveDir, { recursive: true });
|
|
11199
11329
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
11200
11330
|
const filePath = path18.join(saveDir, filename);
|
|
11201
|
-
|
|
11331
|
+
fs19.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
11202
11332
|
console.error(`Saved briefing: ${filePath}`);
|
|
11203
11333
|
} catch (err) {
|
|
11204
11334
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -11216,7 +11346,7 @@ async function cmdDoctor() {
|
|
|
11216
11346
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
11217
11347
|
});
|
|
11218
11348
|
const configPath = resolveConfigPath();
|
|
11219
|
-
const configExists =
|
|
11349
|
+
const configExists = fs19.existsSync(configPath);
|
|
11220
11350
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
11221
11351
|
let standaloneConfig;
|
|
11222
11352
|
let standaloneConfigError;
|
|
@@ -11224,11 +11354,11 @@ async function cmdDoctor() {
|
|
|
11224
11354
|
let configuredNs = { invalid: false };
|
|
11225
11355
|
if (configExists) {
|
|
11226
11356
|
try {
|
|
11227
|
-
const raw = JSON.parse(
|
|
11228
|
-
const remnicCfg =
|
|
11357
|
+
const raw = JSON.parse(fs19.readFileSync(configPath, "utf8"));
|
|
11358
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
11229
11359
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
11230
11360
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
11231
|
-
standaloneConfig =
|
|
11361
|
+
standaloneConfig = parseConfig10(remnicCfg);
|
|
11232
11362
|
} catch (err) {
|
|
11233
11363
|
standaloneConfigError = err instanceof Error ? err.message : String(err);
|
|
11234
11364
|
}
|
|
@@ -11237,10 +11367,10 @@ async function cmdDoctor() {
|
|
|
11237
11367
|
try {
|
|
11238
11368
|
memoryDir = resolveMemoryDir();
|
|
11239
11369
|
} catch {
|
|
11240
|
-
memoryDir =
|
|
11370
|
+
memoryDir = parseConfig10({}).memoryDir;
|
|
11241
11371
|
}
|
|
11242
11372
|
try {
|
|
11243
|
-
|
|
11373
|
+
fs19.mkdirSync(memoryDir, { recursive: true });
|
|
11244
11374
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
11245
11375
|
} catch {
|
|
11246
11376
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -11269,7 +11399,7 @@ async function cmdDoctor() {
|
|
|
11269
11399
|
});
|
|
11270
11400
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
11271
11401
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
11272
|
-
const openclawConfigExists =
|
|
11402
|
+
const openclawConfigExists = fs19.existsSync(openclawConfigPath);
|
|
11273
11403
|
let openclawConfig = {};
|
|
11274
11404
|
let openclawConfigValid = false;
|
|
11275
11405
|
let openclawPluginModeConfigured = false;
|
|
@@ -11277,7 +11407,7 @@ async function cmdDoctor() {
|
|
|
11277
11407
|
let activeOpenclawEntryConfig = null;
|
|
11278
11408
|
if (openclawConfigExists) {
|
|
11279
11409
|
try {
|
|
11280
|
-
const parsed = JSON.parse(
|
|
11410
|
+
const parsed = JSON.parse(fs19.readFileSync(openclawConfigPath, "utf-8"));
|
|
11281
11411
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
11282
11412
|
openclawConfig = parsed;
|
|
11283
11413
|
openclawConfigValid = true;
|
|
@@ -11357,9 +11487,9 @@ async function cmdDoctor() {
|
|
|
11357
11487
|
let memDirOk = false;
|
|
11358
11488
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
11359
11489
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
11360
|
-
if (
|
|
11490
|
+
if (fs19.existsSync(resolvedMemDir)) {
|
|
11361
11491
|
try {
|
|
11362
|
-
const stat2 =
|
|
11492
|
+
const stat2 = fs19.statSync(resolvedMemDir);
|
|
11363
11493
|
if (stat2.isDirectory()) {
|
|
11364
11494
|
memDirOk = true;
|
|
11365
11495
|
memDirDetail = resolvedMemDir;
|
|
@@ -11514,12 +11644,12 @@ async function cmdDoctor() {
|
|
|
11514
11644
|
}
|
|
11515
11645
|
function cmdConfig() {
|
|
11516
11646
|
const configPath = resolveConfigPath();
|
|
11517
|
-
if (!
|
|
11647
|
+
if (!fs19.existsSync(configPath)) {
|
|
11518
11648
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
11519
11649
|
return;
|
|
11520
11650
|
}
|
|
11521
11651
|
console.log(`Config: ${configPath}`);
|
|
11522
|
-
const rawConfig =
|
|
11652
|
+
const rawConfig = fs19.readFileSync(configPath, "utf8");
|
|
11523
11653
|
const redacted = rawConfig.replace(
|
|
11524
11654
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
11525
11655
|
"$1[REDACTED]$3"
|
|
@@ -11627,9 +11757,9 @@ async function cmdReview(action, rest) {
|
|
|
11627
11757
|
const configPath = resolveConfigPath();
|
|
11628
11758
|
let tombstonesConfig = null;
|
|
11629
11759
|
try {
|
|
11630
|
-
const rawCfg =
|
|
11631
|
-
const remnicCfg =
|
|
11632
|
-
const config =
|
|
11760
|
+
const rawCfg = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
11761
|
+
const remnicCfg = resolveRemnicConfigRecord9(rawCfg);
|
|
11762
|
+
const config = parseConfig10(remnicCfg);
|
|
11633
11763
|
tombstonesConfig = {
|
|
11634
11764
|
enabled: config.tombstonesEnabled,
|
|
11635
11765
|
semanticMatch: config.tombstonesSemanticMatch,
|
|
@@ -12371,7 +12501,7 @@ async function pushOfflineFileContent(args) {
|
|
|
12371
12501
|
}
|
|
12372
12502
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
12373
12503
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
12374
|
-
const stat2 =
|
|
12504
|
+
const stat2 = fs19.statSync(filePath);
|
|
12375
12505
|
if (stat2.mtimeMs !== args.file.mtimeMs) {
|
|
12376
12506
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
12377
12507
|
}
|
|
@@ -12862,7 +12992,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
12862
12992
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
12863
12993
|
}
|
|
12864
12994
|
async function runOfflineSyncOnce(options) {
|
|
12865
|
-
|
|
12995
|
+
fs19.mkdirSync(options.memoryDir, { recursive: true });
|
|
12866
12996
|
let activeStatePath = options.statePath;
|
|
12867
12997
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
12868
12998
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -13495,7 +13625,7 @@ Environment fallbacks:
|
|
|
13495
13625
|
const configPath = resolveConfigPath();
|
|
13496
13626
|
let config;
|
|
13497
13627
|
try {
|
|
13498
|
-
const rawConfig =
|
|
13628
|
+
const rawConfig = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
13499
13629
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
13500
13630
|
} catch {
|
|
13501
13631
|
throw new Error(
|
|
@@ -13510,7 +13640,7 @@ Environment fallbacks:
|
|
|
13510
13640
|
const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
13511
13641
|
if (action === "prepare") {
|
|
13512
13642
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
13513
|
-
|
|
13643
|
+
fs19.mkdirSync(memoryDir, { recursive: true });
|
|
13514
13644
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
13515
13645
|
remoteUrl,
|
|
13516
13646
|
token,
|
|
@@ -13609,7 +13739,7 @@ Environment fallbacks:
|
|
|
13609
13739
|
return;
|
|
13610
13740
|
}
|
|
13611
13741
|
if (action === "status") {
|
|
13612
|
-
|
|
13742
|
+
fs19.mkdirSync(memoryDir, { recursive: true });
|
|
13613
13743
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
13614
13744
|
if (state && remoteUrl && statePath) {
|
|
13615
13745
|
assertOfflineStateMatches({
|
|
@@ -13747,7 +13877,7 @@ function cmdDedup(json) {
|
|
|
13747
13877
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
13748
13878
|
if (!configPath) return fallback;
|
|
13749
13879
|
try {
|
|
13750
|
-
const parsed = JSON.parse(
|
|
13880
|
+
const parsed = JSON.parse(fs19.readFileSync(configPath, "utf8"));
|
|
13751
13881
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
13752
13882
|
const { token: _token, ...config } = parsed;
|
|
13753
13883
|
return config;
|
|
@@ -13925,7 +14055,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
13925
14055
|
const pub = factory();
|
|
13926
14056
|
const available = await pub.isHostAvailable();
|
|
13927
14057
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
13928
|
-
const extensionExists = available && extRoot ?
|
|
14058
|
+
const extensionExists = available && extRoot ? fs19.existsSync(extRoot) : false;
|
|
13929
14059
|
publisherChecks.push({
|
|
13930
14060
|
name: `Publisher: ${targetHostId}`,
|
|
13931
14061
|
ok: !available || extensionExists,
|
|
@@ -13999,7 +14129,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
13999
14129
|
let connectorsCfg;
|
|
14000
14130
|
const configPath = resolveConfigPath();
|
|
14001
14131
|
try {
|
|
14002
|
-
const raw =
|
|
14132
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
14003
14133
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
14004
14134
|
} catch {
|
|
14005
14135
|
process.stderr.write(
|
|
@@ -14073,12 +14203,12 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14073
14203
|
process.exitCode = 2;
|
|
14074
14204
|
return;
|
|
14075
14205
|
}
|
|
14076
|
-
|
|
14206
|
+
initLogger5();
|
|
14077
14207
|
const configPath = resolveConfigPath();
|
|
14078
|
-
const raw =
|
|
14079
|
-
const remnicCfg =
|
|
14080
|
-
const config =
|
|
14081
|
-
const orchestrator = new
|
|
14208
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
14209
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
14210
|
+
const config = parseConfig10(remnicCfg);
|
|
14211
|
+
const orchestrator = new Orchestrator6(config);
|
|
14082
14212
|
try {
|
|
14083
14213
|
await orchestrator.initialize();
|
|
14084
14214
|
await orchestrator.deferredReady;
|
|
@@ -14200,9 +14330,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
14200
14330
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
14201
14331
|
process.exit(1);
|
|
14202
14332
|
}
|
|
14203
|
-
const rawConfig =
|
|
14204
|
-
const pluginConfig =
|
|
14205
|
-
const config =
|
|
14333
|
+
const rawConfig = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
14334
|
+
const pluginConfig = resolveRemnicConfigRecord9(rawConfig);
|
|
14335
|
+
const config = parseConfig10(pluginConfig);
|
|
14206
14336
|
if (subAction === "generate") {
|
|
14207
14337
|
let outputDir;
|
|
14208
14338
|
try {
|
|
@@ -14222,13 +14352,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
14222
14352
|
} else if (subAction === "validate") {
|
|
14223
14353
|
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
|
|
14224
14354
|
const resolved = path18.resolve(targetPath);
|
|
14225
|
-
if (!
|
|
14355
|
+
if (!fs19.existsSync(resolved)) {
|
|
14226
14356
|
console.error(`File not found: ${resolved}`);
|
|
14227
14357
|
process.exit(1);
|
|
14228
14358
|
}
|
|
14229
14359
|
let parsed;
|
|
14230
14360
|
try {
|
|
14231
|
-
parsed = JSON.parse(
|
|
14361
|
+
parsed = JSON.parse(fs19.readFileSync(resolved, "utf8"));
|
|
14232
14362
|
} catch {
|
|
14233
14363
|
console.error(`Invalid JSON in ${resolved}`);
|
|
14234
14364
|
process.exit(1);
|
|
@@ -14429,12 +14559,12 @@ async function cmdSpace(action, rest, json) {
|
|
|
14429
14559
|
}
|
|
14430
14560
|
}
|
|
14431
14561
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
14432
|
-
|
|
14562
|
+
initLogger5();
|
|
14433
14563
|
const configPath = resolveConfigPath();
|
|
14434
|
-
const raw =
|
|
14435
|
-
const remnicCfg =
|
|
14436
|
-
const config =
|
|
14437
|
-
const orchestrator = new
|
|
14564
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
14565
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
14566
|
+
const config = parseConfig10(remnicCfg);
|
|
14567
|
+
const orchestrator = new Orchestrator6(config);
|
|
14438
14568
|
const service = new EngramAccessService2(orchestrator);
|
|
14439
14569
|
const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
|
|
14440
14570
|
const benchConfig = {
|
|
@@ -14836,7 +14966,7 @@ function readPid() {
|
|
|
14836
14966
|
function inferPort() {
|
|
14837
14967
|
try {
|
|
14838
14968
|
const configPath = resolveConfigPath();
|
|
14839
|
-
const raw = JSON.parse(
|
|
14969
|
+
const raw = JSON.parse(fs19.readFileSync(configPath, "utf8"));
|
|
14840
14970
|
return raw.server?.port ?? 4318;
|
|
14841
14971
|
} catch {
|
|
14842
14972
|
return 4318;
|
|
@@ -14931,13 +15061,13 @@ function daemonInstall() {
|
|
|
14931
15061
|
process.exit(1);
|
|
14932
15062
|
}
|
|
14933
15063
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
14934
|
-
|
|
15064
|
+
fs19.mkdirSync(LOGS_DIR, { recursive: true });
|
|
14935
15065
|
if (isMacOS()) {
|
|
14936
15066
|
const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
14937
|
-
const template =
|
|
15067
|
+
const template = fs19.readFileSync(templatePath, "utf8");
|
|
14938
15068
|
const plist = renderTemplate(template, vars);
|
|
14939
|
-
|
|
14940
|
-
|
|
15069
|
+
fs19.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
15070
|
+
fs19.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
14941
15071
|
try {
|
|
14942
15072
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
14943
15073
|
} catch (err) {
|
|
@@ -14954,10 +15084,10 @@ function daemonInstall() {
|
|
|
14954
15084
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
14955
15085
|
} else if (isLinux()) {
|
|
14956
15086
|
const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
14957
|
-
const template =
|
|
15087
|
+
const template = fs19.readFileSync(templatePath, "utf8");
|
|
14958
15088
|
const unit = renderTemplate(template, vars);
|
|
14959
|
-
|
|
14960
|
-
|
|
15089
|
+
fs19.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
15090
|
+
fs19.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
14961
15091
|
try {
|
|
14962
15092
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
14963
15093
|
} catch (err) {
|
|
@@ -14993,7 +15123,7 @@ function daemonUninstall() {
|
|
|
14993
15123
|
} catch {
|
|
14994
15124
|
}
|
|
14995
15125
|
try {
|
|
14996
|
-
|
|
15126
|
+
fs19.unlinkSync(plistPath);
|
|
14997
15127
|
removed = true;
|
|
14998
15128
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
14999
15129
|
} catch {
|
|
@@ -15013,7 +15143,7 @@ function daemonUninstall() {
|
|
|
15013
15143
|
let removed = false;
|
|
15014
15144
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
15015
15145
|
try {
|
|
15016
|
-
|
|
15146
|
+
fs19.unlinkSync(unitPath);
|
|
15017
15147
|
removed = true;
|
|
15018
15148
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
15019
15149
|
} catch {
|
|
@@ -15080,13 +15210,13 @@ async function daemonStatus() {
|
|
|
15080
15210
|
console.log(` Port: ${port}`);
|
|
15081
15211
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
15082
15212
|
console.log(` Platform: ${process.platform}`);
|
|
15083
|
-
console.log(` PID file: ${
|
|
15084
|
-
console.log(` Log file: ${
|
|
15213
|
+
console.log(` PID file: ${fs19.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
15214
|
+
console.log(` Log file: ${fs19.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
15085
15215
|
try {
|
|
15086
15216
|
const configPath = resolveConfigPath();
|
|
15087
|
-
const raw =
|
|
15088
|
-
const remnicCfg =
|
|
15089
|
-
const config =
|
|
15217
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
15218
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
15219
|
+
const config = parseConfig10(remnicCfg);
|
|
15090
15220
|
const extRoot = resolveExtensionsRoot(config);
|
|
15091
15221
|
const noopLog = { warn: () => {
|
|
15092
15222
|
}, debug: () => {
|
|
@@ -15125,9 +15255,9 @@ function daemonStart() {
|
|
|
15125
15255
|
return;
|
|
15126
15256
|
}
|
|
15127
15257
|
}
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
const logStream =
|
|
15258
|
+
fs19.mkdirSync(PID_DIR, { recursive: true });
|
|
15259
|
+
fs19.mkdirSync(LOGS_DIR, { recursive: true });
|
|
15260
|
+
const logStream = fs19.openSync(LOG_FILE, "a");
|
|
15131
15261
|
const serverBin = resolveServerBin();
|
|
15132
15262
|
const isSource = serverBin.endsWith(".ts");
|
|
15133
15263
|
let cmd;
|
|
@@ -15149,7 +15279,7 @@ function daemonStart() {
|
|
|
15149
15279
|
}
|
|
15150
15280
|
});
|
|
15151
15281
|
child.unref();
|
|
15152
|
-
|
|
15282
|
+
fs19.writeFileSync(PID_FILE, String(child.pid));
|
|
15153
15283
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
15154
15284
|
console.log(` Log: ${LOG_FILE}`);
|
|
15155
15285
|
}
|
|
@@ -15183,11 +15313,11 @@ function daemonStop() {
|
|
|
15183
15313
|
console.log("Process not found (cleaning up PID file)");
|
|
15184
15314
|
}
|
|
15185
15315
|
try {
|
|
15186
|
-
|
|
15316
|
+
fs19.unlinkSync(PID_FILE);
|
|
15187
15317
|
} catch {
|
|
15188
15318
|
}
|
|
15189
15319
|
try {
|
|
15190
|
-
|
|
15320
|
+
fs19.unlinkSync(LEGACY_PID_FILE);
|
|
15191
15321
|
} catch {
|
|
15192
15322
|
}
|
|
15193
15323
|
}
|
|
@@ -15313,11 +15443,11 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
15313
15443
|
});
|
|
15314
15444
|
}
|
|
15315
15445
|
async function cmdBinary(rest) {
|
|
15316
|
-
|
|
15446
|
+
initLogger5();
|
|
15317
15447
|
const configPath = resolveConfigPath();
|
|
15318
|
-
const raw =
|
|
15319
|
-
const remnicCfg =
|
|
15320
|
-
const config =
|
|
15448
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
15449
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
15450
|
+
const config = parseConfig10(remnicCfg);
|
|
15321
15451
|
const memoryDir = resolveMemoryDir();
|
|
15322
15452
|
const blConfig = {
|
|
15323
15453
|
enabled: config.binaryLifecycleEnabled,
|
|
@@ -15506,7 +15636,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
15506
15636
|
} else if (slotIsActiveLegacy) {
|
|
15507
15637
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
15508
15638
|
}
|
|
15509
|
-
if (!
|
|
15639
|
+
if (!fs19.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
15510
15640
|
if (hasLegacy && migrateLegacy) {
|
|
15511
15641
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
15512
15642
|
}
|
|
@@ -15526,8 +15656,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
15526
15656
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
15527
15657
|
return;
|
|
15528
15658
|
}
|
|
15529
|
-
if (
|
|
15530
|
-
const st =
|
|
15659
|
+
if (fs19.existsSync(memoryDir)) {
|
|
15660
|
+
const st = fs19.statSync(memoryDir);
|
|
15531
15661
|
if (!st.isDirectory()) {
|
|
15532
15662
|
throw new Error(
|
|
15533
15663
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -15535,12 +15665,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
15535
15665
|
);
|
|
15536
15666
|
}
|
|
15537
15667
|
} else {
|
|
15538
|
-
|
|
15668
|
+
fs19.mkdirSync(memoryDir, { recursive: true });
|
|
15539
15669
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
15540
15670
|
}
|
|
15541
15671
|
const configDir = path18.dirname(configPath);
|
|
15542
|
-
if (!
|
|
15543
|
-
|
|
15672
|
+
if (!fs19.existsSync(configDir)) {
|
|
15673
|
+
fs19.mkdirSync(configDir, { recursive: true });
|
|
15544
15674
|
}
|
|
15545
15675
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
15546
15676
|
console.log("\nDone! Summary of changes:");
|
|
@@ -15569,7 +15699,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15569
15699
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
15570
15700
|
const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
15571
15701
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
15572
|
-
const configExistedBefore =
|
|
15702
|
+
const configExistedBefore = fs19.existsSync(configPath);
|
|
15573
15703
|
const existingConfig = readOpenclawConfig(configPath);
|
|
15574
15704
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
15575
15705
|
const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
@@ -15794,15 +15924,15 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
15794
15924
|
}
|
|
15795
15925
|
function createOpenclawUpgradeBackupDir() {
|
|
15796
15926
|
const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
|
|
15797
|
-
|
|
15798
|
-
return
|
|
15927
|
+
fs19.mkdirSync(backupsRoot, { recursive: true });
|
|
15928
|
+
return fs19.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
15799
15929
|
}
|
|
15800
15930
|
async function cmdTaxonomy(rest) {
|
|
15801
|
-
|
|
15931
|
+
initLogger5();
|
|
15802
15932
|
const configPath = resolveConfigPath();
|
|
15803
|
-
const raw =
|
|
15804
|
-
const remnicCfg =
|
|
15805
|
-
const config =
|
|
15933
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
15934
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
15935
|
+
const config = parseConfig10(remnicCfg);
|
|
15806
15936
|
if (!config.taxonomyEnabled) {
|
|
15807
15937
|
console.error(
|
|
15808
15938
|
"Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
|
|
@@ -15838,8 +15968,8 @@ async function cmdTaxonomy(rest) {
|
|
|
15838
15968
|
console.log(doc);
|
|
15839
15969
|
if (config.taxonomyAutoGenResolver) {
|
|
15840
15970
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
15841
|
-
|
|
15842
|
-
|
|
15971
|
+
fs19.mkdirSync(path18.dirname(resolverPath), { recursive: true });
|
|
15972
|
+
fs19.writeFileSync(resolverPath, doc);
|
|
15843
15973
|
console.error(`Written: ${resolverPath}`);
|
|
15844
15974
|
}
|
|
15845
15975
|
break;
|
|
@@ -15885,7 +16015,7 @@ async function cmdTaxonomy(rest) {
|
|
|
15885
16015
|
if (config.taxonomyAutoGenResolver) {
|
|
15886
16016
|
const doc = generateResolverDocument(taxonomy);
|
|
15887
16017
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
15888
|
-
|
|
16018
|
+
fs19.writeFileSync(resolverPath, doc);
|
|
15889
16019
|
console.error(`Regenerated: ${resolverPath}`);
|
|
15890
16020
|
}
|
|
15891
16021
|
break;
|
|
@@ -15916,7 +16046,7 @@ async function cmdTaxonomy(rest) {
|
|
|
15916
16046
|
if (config.taxonomyAutoGenResolver) {
|
|
15917
16047
|
const doc = generateResolverDocument(taxonomy);
|
|
15918
16048
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
15919
|
-
|
|
16049
|
+
fs19.writeFileSync(resolverPath, doc);
|
|
15920
16050
|
console.error(`Regenerated: ${resolverPath}`);
|
|
15921
16051
|
}
|
|
15922
16052
|
break;
|
|
@@ -16107,12 +16237,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
16107
16237
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
16108
16238
|
);
|
|
16109
16239
|
}
|
|
16110
|
-
if (!
|
|
16240
|
+
if (!fs19.existsSync(args.memoryDir)) {
|
|
16111
16241
|
throw new Error(
|
|
16112
16242
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
16113
16243
|
);
|
|
16114
16244
|
}
|
|
16115
|
-
if (!
|
|
16245
|
+
if (!fs19.statSync(args.memoryDir).isDirectory()) {
|
|
16116
16246
|
throw new Error(
|
|
16117
16247
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
16118
16248
|
);
|
|
@@ -16198,10 +16328,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
16198
16328
|
}
|
|
16199
16329
|
const formatted = adapter.formatRecords(records);
|
|
16200
16330
|
const outDir = path18.dirname(args.output);
|
|
16201
|
-
|
|
16331
|
+
fs19.mkdirSync(outDir, { recursive: true });
|
|
16202
16332
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
16203
|
-
|
|
16204
|
-
|
|
16333
|
+
fs19.writeFileSync(tmpPath, formatted, "utf-8");
|
|
16334
|
+
fs19.renameSync(tmpPath, args.output);
|
|
16205
16335
|
stdout.write(
|
|
16206
16336
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
16207
16337
|
`
|
|
@@ -16379,7 +16509,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16379
16509
|
}
|
|
16380
16510
|
}, 500);
|
|
16381
16511
|
};
|
|
16382
|
-
|
|
16512
|
+
fs19.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
16383
16513
|
if (filename && filename.startsWith(".")) return;
|
|
16384
16514
|
rebuild();
|
|
16385
16515
|
});
|
|
@@ -16387,12 +16517,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16387
16517
|
});
|
|
16388
16518
|
} else if (subAction === "validate") {
|
|
16389
16519
|
const treeDir = outputDir;
|
|
16390
|
-
if (!
|
|
16520
|
+
if (!fs19.existsSync(treeDir)) {
|
|
16391
16521
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
16392
16522
|
process.exit(1);
|
|
16393
16523
|
}
|
|
16394
16524
|
const indexPath = path18.join(treeDir, "INDEX.md");
|
|
16395
|
-
if (!
|
|
16525
|
+
if (!fs19.existsSync(indexPath)) {
|
|
16396
16526
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
16397
16527
|
process.exit(1);
|
|
16398
16528
|
}
|
|
@@ -16517,6 +16647,10 @@ Options:
|
|
|
16517
16647
|
await runProceduralBinaryCommand(rest);
|
|
16518
16648
|
break;
|
|
16519
16649
|
}
|
|
16650
|
+
case "drift": {
|
|
16651
|
+
await runDriftBinaryCommand(rest);
|
|
16652
|
+
break;
|
|
16653
|
+
}
|
|
16520
16654
|
case "extensions": {
|
|
16521
16655
|
const action = rest[0] ?? "help";
|
|
16522
16656
|
await cmdExtensions(action, rest.slice(1));
|
|
@@ -16574,10 +16708,10 @@ Other:
|
|
|
16574
16708
|
let wearablesService;
|
|
16575
16709
|
try {
|
|
16576
16710
|
const configPath = resolveConfigPath();
|
|
16577
|
-
const raw =
|
|
16578
|
-
const remnicCfg =
|
|
16579
|
-
const config =
|
|
16580
|
-
wearablesOrchestrator = new
|
|
16711
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
16712
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
16713
|
+
const config = parseConfig10(remnicCfg);
|
|
16714
|
+
wearablesOrchestrator = new Orchestrator6(config);
|
|
16581
16715
|
await wearablesOrchestrator.initialize();
|
|
16582
16716
|
await wearablesOrchestrator.deferredReady;
|
|
16583
16717
|
wearablesService = wearablesOrchestrator.getWearablesService();
|
|
@@ -16632,10 +16766,10 @@ Other:
|
|
|
16632
16766
|
const targetFactory = async () => {
|
|
16633
16767
|
if (!orchestratorSingleton) {
|
|
16634
16768
|
const configPath = resolveConfigPath();
|
|
16635
|
-
const raw =
|
|
16636
|
-
const remnicCfg =
|
|
16637
|
-
const config =
|
|
16638
|
-
orchestratorSingleton = new
|
|
16769
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
16770
|
+
const remnicCfg = resolveRemnicConfigRecord9(raw);
|
|
16771
|
+
const config = parseConfig10(remnicCfg);
|
|
16772
|
+
orchestratorSingleton = new Orchestrator6(config);
|
|
16639
16773
|
await orchestratorSingleton.initialize();
|
|
16640
16774
|
await orchestratorSingleton.deferredReady;
|
|
16641
16775
|
}
|
|
@@ -16891,6 +17025,12 @@ Usage:
|
|
|
16891
17025
|
merge / repair-flag / retire proposals from outcome telemetry; --apply
|
|
16892
17026
|
executes them (requires procedural.maintenance.enabled). Mirrors the
|
|
16893
17027
|
remnic.procedure_library_maintenance MCP tool.
|
|
17028
|
+
remnic drift scan [--apply] [--namespace <ns>] [--format json|text] [--memory-dir <path>]
|
|
17029
|
+
Run preference drift detection (issue #2371): classify aging preference
|
|
17030
|
+
memories as corroborated / stale / drifted from recent evidence; --apply
|
|
17031
|
+
stamps lastCorroborated / driftState and opens a review item per drifted
|
|
17032
|
+
preference (requires driftDetection.enabled). Mirrors the
|
|
17033
|
+
remnic.preference_drift_scan MCP tool.
|
|
16894
17034
|
remnic training:export --format <name> --output <path> [options]
|
|
16895
17035
|
Export memories as a fine-tuning dataset (issue #459). Run
|
|
16896
17036
|
'remnic training:export --help' for the full option list.
|