@remnic/cli 9.66.0 → 9.66.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +739 -315
- package/package.json +32 -32
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 fs28 from "fs";
|
|
22
22
|
import os3 from "os";
|
|
23
23
|
import path19 from "path";
|
|
24
24
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -27,10 +27,10 @@ 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 parseConfig17,
|
|
31
31
|
isOpenaiApiKeyDisabled,
|
|
32
32
|
resolveEnvVars,
|
|
33
|
-
resolveRemnicConfigRecord as
|
|
33
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord16,
|
|
34
34
|
Orchestrator as Orchestrator10,
|
|
35
35
|
EngramAccessService as EngramAccessService2,
|
|
36
36
|
initLogger as initLogger5,
|
|
@@ -192,12 +192,49 @@ async function runMeetingsBinaryCommand(rest) {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
// src/commands/
|
|
195
|
+
// src/commands/timeline.ts
|
|
196
196
|
import fs2 from "fs";
|
|
197
197
|
import {
|
|
198
|
-
Orchestrator as Orchestrator2,
|
|
199
198
|
parseConfig as parseConfig2,
|
|
200
199
|
resolveRemnicConfigRecord as resolveRemnicConfigRecord2,
|
|
200
|
+
runTimelineCliCommand
|
|
201
|
+
} from "@remnic/core";
|
|
202
|
+
async function runTimelineBinaryCommand(rest) {
|
|
203
|
+
const timelineArgs = rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" ? ["help"] : rest;
|
|
204
|
+
try {
|
|
205
|
+
let qa = { enabled: false, maxRangeDays: 31 };
|
|
206
|
+
let timelineEnabled = false;
|
|
207
|
+
try {
|
|
208
|
+
const configPath = resolveConfigPath();
|
|
209
|
+
const raw = fs2.existsSync(configPath) ? JSON.parse(fs2.readFileSync(configPath, "utf8")) : {};
|
|
210
|
+
const config = parseConfig2(resolveRemnicConfigRecord2(raw));
|
|
211
|
+
timelineEnabled = config.activity.timeline.enabled;
|
|
212
|
+
qa = config.activity.timeline.qa;
|
|
213
|
+
} catch {
|
|
214
|
+
console.error(
|
|
215
|
+
"timeline: failed to load the Remnic config \u2014 run `remnic doctor` and check the config file for errors"
|
|
216
|
+
);
|
|
217
|
+
process.exitCode = 1;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const code = await runTimelineCliCommand(
|
|
221
|
+
{ cards: null, qa, timelineEnabled },
|
|
222
|
+
timelineArgs,
|
|
223
|
+
{ stdout: process.stdout, stderr: process.stderr }
|
|
224
|
+
);
|
|
225
|
+
if (code !== 0) process.exitCode = code;
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
228
|
+
process.exitCode = 1;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/commands/wearables.ts
|
|
233
|
+
import fs3 from "fs";
|
|
234
|
+
import {
|
|
235
|
+
Orchestrator as Orchestrator2,
|
|
236
|
+
parseConfig as parseConfig3,
|
|
237
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord3,
|
|
201
238
|
runWearablesCliCommand
|
|
202
239
|
} from "@remnic/core";
|
|
203
240
|
async function runWearablesBinaryCommand(rest) {
|
|
@@ -207,8 +244,8 @@ async function runWearablesBinaryCommand(rest) {
|
|
|
207
244
|
let wearablesService;
|
|
208
245
|
try {
|
|
209
246
|
const configPath = resolveConfigPath();
|
|
210
|
-
const raw =
|
|
211
|
-
const config =
|
|
247
|
+
const raw = fs3.existsSync(configPath) ? JSON.parse(fs3.readFileSync(configPath, "utf8")) : {};
|
|
248
|
+
const config = parseConfig3(resolveRemnicConfigRecord3(raw));
|
|
212
249
|
wearablesOrchestrator = new Orchestrator2(config);
|
|
213
250
|
await wearablesOrchestrator.initialize();
|
|
214
251
|
await wearablesOrchestrator.deferredReady;
|
|
@@ -245,8 +282,8 @@ async function runWearablesBinaryCommand(rest) {
|
|
|
245
282
|
}
|
|
246
283
|
|
|
247
284
|
// src/commands/location.ts
|
|
248
|
-
import
|
|
249
|
-
import { parseConfig as
|
|
285
|
+
import fs4 from "fs";
|
|
286
|
+
import { parseConfig as parseConfig4, resolveRemnicConfigRecord as resolveRemnicConfigRecord4 } from "@remnic/core";
|
|
250
287
|
import { backfillMemoryStorage, runLocationCliCommand } from "@remnic/core/location";
|
|
251
288
|
async function runLocationBinaryCommand(rest) {
|
|
252
289
|
const locationArgs = rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" ? ["help"] : rest;
|
|
@@ -254,8 +291,8 @@ async function runLocationBinaryCommand(rest) {
|
|
|
254
291
|
let config;
|
|
255
292
|
try {
|
|
256
293
|
const configPath = resolveConfigPath();
|
|
257
|
-
const raw =
|
|
258
|
-
config =
|
|
294
|
+
const raw = fs4.existsSync(configPath) ? JSON.parse(fs4.readFileSync(configPath, "utf8")) : {};
|
|
295
|
+
config = parseConfig4(resolveRemnicConfigRecord4(raw));
|
|
259
296
|
} catch {
|
|
260
297
|
console.error(
|
|
261
298
|
"location: failed to load the Remnic config \u2014 run `remnic doctor` and check the config file for errors"
|
|
@@ -280,16 +317,16 @@ async function runLocationBinaryCommand(rest) {
|
|
|
280
317
|
}
|
|
281
318
|
|
|
282
319
|
// src/commands/okf.ts
|
|
283
|
-
import
|
|
284
|
-
import { Orchestrator as Orchestrator3, parseConfig as
|
|
320
|
+
import fs5 from "fs";
|
|
321
|
+
import { Orchestrator as Orchestrator3, parseConfig as parseConfig5, resolveRemnicConfigRecord as resolveRemnicConfigRecord5, runOkfCliCommand } from "@remnic/core";
|
|
285
322
|
async function runOkfBinaryCommand(rest) {
|
|
286
323
|
const argv = rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" ? ["help"] : rest;
|
|
287
324
|
let orchestrator;
|
|
288
325
|
try {
|
|
289
326
|
try {
|
|
290
327
|
const configPath = resolveConfigPath();
|
|
291
|
-
const raw =
|
|
292
|
-
const config2 =
|
|
328
|
+
const raw = fs5.existsSync(configPath) ? JSON.parse(fs5.readFileSync(configPath, "utf8")) : {};
|
|
329
|
+
const config2 = parseConfig5(resolveRemnicConfigRecord5(raw));
|
|
293
330
|
orchestrator = new Orchestrator3(config2);
|
|
294
331
|
await orchestrator.initialize();
|
|
295
332
|
await orchestrator.deferredReady;
|
|
@@ -318,9 +355,9 @@ async function runOkfBinaryCommand(rest) {
|
|
|
318
355
|
}
|
|
319
356
|
|
|
320
357
|
// src/commands/export-okf.ts
|
|
321
|
-
import
|
|
358
|
+
import fs6 from "fs";
|
|
322
359
|
import path from "path";
|
|
323
|
-
import { Orchestrator as Orchestrator4, parseConfig as
|
|
360
|
+
import { Orchestrator as Orchestrator4, parseConfig as parseConfig6, resolveRemnicConfigRecord as resolveRemnicConfigRecord6 } from "@remnic/core";
|
|
324
361
|
import { exportOkfBundle, parseIncludeStatus } from "@remnic/core/export-okf";
|
|
325
362
|
function takeFlag(rest, name) {
|
|
326
363
|
const index = rest.indexOf(name);
|
|
@@ -348,8 +385,8 @@ async function runExportOkfBinaryCommand(rest) {
|
|
|
348
385
|
if (!out) throw new Error("Missing --out");
|
|
349
386
|
const namespace = takeFlag(args, "--namespace") ?? "";
|
|
350
387
|
const configPath = resolveConfigPath();
|
|
351
|
-
const raw =
|
|
352
|
-
const config =
|
|
388
|
+
const raw = fs6.existsSync(configPath) ? JSON.parse(fs6.readFileSync(configPath, "utf8")) : {};
|
|
389
|
+
const config = parseConfig6(resolveRemnicConfigRecord6(raw));
|
|
353
390
|
orchestrator = new Orchestrator4(config);
|
|
354
391
|
await orchestrator.initialize();
|
|
355
392
|
await orchestrator.deferredReady;
|
|
@@ -377,8 +414,8 @@ async function runExportOkfBinaryCommand(rest) {
|
|
|
377
414
|
}
|
|
378
415
|
|
|
379
416
|
// src/commands/codegraph.ts
|
|
380
|
-
import
|
|
381
|
-
import { Orchestrator as Orchestrator5, parseConfig as
|
|
417
|
+
import fs7 from "fs";
|
|
418
|
+
import { Orchestrator as Orchestrator5, parseConfig as parseConfig7, resolveRemnicConfigRecord as resolveRemnicConfigRecord7 } from "@remnic/core";
|
|
382
419
|
import {
|
|
383
420
|
exportCodegraphOkfBundle,
|
|
384
421
|
parseOkfCodegraphSymbolFilter
|
|
@@ -412,8 +449,8 @@ async function runCodegraphBinaryCommand(rest) {
|
|
|
412
449
|
if (!project) throw new Error("Missing --project");
|
|
413
450
|
if (!out) throw new Error("Missing --out");
|
|
414
451
|
const configPath = resolveConfigPath();
|
|
415
|
-
const raw =
|
|
416
|
-
const config =
|
|
452
|
+
const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
|
|
453
|
+
const config = parseConfig7(resolveRemnicConfigRecord7(raw));
|
|
417
454
|
orchestrator = new Orchestrator5(config);
|
|
418
455
|
await orchestrator.initialize();
|
|
419
456
|
await orchestrator.deferredReady;
|
|
@@ -441,8 +478,8 @@ async function runCodegraphBinaryCommand(rest) {
|
|
|
441
478
|
}
|
|
442
479
|
|
|
443
480
|
// src/commands/standup.ts
|
|
444
|
-
import
|
|
445
|
-
import { Orchestrator as Orchestrator6, parseConfig as
|
|
481
|
+
import fs8 from "fs";
|
|
482
|
+
import { Orchestrator as Orchestrator6, parseConfig as parseConfig8, resolveRemnicConfigRecord as resolveRemnicConfigRecord8 } from "@remnic/core";
|
|
446
483
|
import { buildStandup, parseStandupDate, standupHelp } from "@remnic/core/standup";
|
|
447
484
|
function takeFlag3(rest, name) {
|
|
448
485
|
const index = rest.indexOf(name);
|
|
@@ -459,8 +496,8 @@ async function runStandupBinaryCommand(rest) {
|
|
|
459
496
|
let orchestrator;
|
|
460
497
|
try {
|
|
461
498
|
const configPath = resolveConfigPath();
|
|
462
|
-
const raw =
|
|
463
|
-
const config =
|
|
499
|
+
const raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
|
|
500
|
+
const config = parseConfig8(resolveRemnicConfigRecord8(raw));
|
|
464
501
|
orchestrator = new Orchestrator6(config);
|
|
465
502
|
await orchestrator.initialize();
|
|
466
503
|
await orchestrator.deferredReady;
|
|
@@ -475,45 +512,85 @@ async function runStandupBinaryCommand(rest) {
|
|
|
475
512
|
}
|
|
476
513
|
}
|
|
477
514
|
|
|
478
|
-
// src/commands/
|
|
479
|
-
import
|
|
480
|
-
import {
|
|
481
|
-
|
|
482
|
-
|
|
515
|
+
// src/commands/journal.ts
|
|
516
|
+
import fs9 from "fs";
|
|
517
|
+
import {
|
|
518
|
+
journalPath,
|
|
519
|
+
parseConfig as parseConfig9,
|
|
520
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord9,
|
|
521
|
+
seedJournal,
|
|
522
|
+
todayJournalDate
|
|
523
|
+
} from "@remnic/core";
|
|
524
|
+
function takeFlag4(rest, name) {
|
|
525
|
+
const index = rest.indexOf(name);
|
|
526
|
+
if (index < 0) return void 0;
|
|
527
|
+
const value = rest[index + 1];
|
|
528
|
+
if (value === void 0 || value.startsWith("-")) throw new Error(`${name} requires a value`);
|
|
529
|
+
return value;
|
|
530
|
+
}
|
|
531
|
+
function journalHelp() {
|
|
532
|
+
return `Usage: remnic journal <show|edit-path|seed> [--date YYYY-MM-DD] [--force]
|
|
533
|
+
|
|
534
|
+
show Print the journal file for the date (default: today).
|
|
535
|
+
edit-path Print the journal file path.
|
|
536
|
+
seed Write the file only if it is absent. --force overwrites.
|
|
537
|
+
`;
|
|
538
|
+
}
|
|
539
|
+
function loadMemoryDir() {
|
|
540
|
+
const configPath = resolveConfigPath();
|
|
541
|
+
const raw = fs9.existsSync(configPath) ? JSON.parse(fs9.readFileSync(configPath, "utf8")) : {};
|
|
542
|
+
return parseConfig9(resolveRemnicConfigRecord9(raw)).memoryDir;
|
|
543
|
+
}
|
|
544
|
+
async function runJournalBinaryCommand(rest) {
|
|
545
|
+
if (rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" || rest[0] === "help") {
|
|
546
|
+
console.log(journalHelp());
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
let memoryDir;
|
|
483
550
|
try {
|
|
484
|
-
|
|
485
|
-
const raw = fs8.existsSync(configPath) ? JSON.parse(fs8.readFileSync(configPath, "utf8")) : {};
|
|
486
|
-
roots = parseConfig8(resolveRemnicConfigRecord8(raw)).externalWikis;
|
|
551
|
+
memoryDir = loadMemoryDir();
|
|
487
552
|
} catch {
|
|
488
553
|
console.error(
|
|
489
|
-
"
|
|
554
|
+
"journal: failed to load the Remnic config \u2014 run `remnic doctor` and check the config file for errors"
|
|
490
555
|
);
|
|
491
556
|
process.exitCode = 1;
|
|
492
557
|
return;
|
|
493
558
|
}
|
|
494
559
|
try {
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (
|
|
500
|
-
|
|
501
|
-
|
|
560
|
+
const action = rest[0];
|
|
561
|
+
const date = takeFlag4(rest, "--date") ?? todayJournalDate();
|
|
562
|
+
const force = rest.includes("--force");
|
|
563
|
+
const filePath = journalPath(memoryDir, date);
|
|
564
|
+
if (action === "edit-path") {
|
|
565
|
+
console.log(filePath);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (action === "show") {
|
|
569
|
+
if (!fs9.existsSync(filePath)) {
|
|
570
|
+
console.error(`journal: no file at ${filePath}. Run remnic journal seed --date ${date}.`);
|
|
571
|
+
process.exitCode = 1;
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
process.stdout.write(fs9.readFileSync(filePath, "utf8"));
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
if (action === "seed") {
|
|
578
|
+
const result = seedJournal({ memoryDir, date, force });
|
|
579
|
+
console.log(result.wrote ? `wrote ${result.path}` : `unchanged ${result.path}`);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
console.error(`journal: unknown action "${action}".`);
|
|
583
|
+
console.error(journalHelp());
|
|
584
|
+
process.exitCode = 1;
|
|
585
|
+
} catch (err) {
|
|
586
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
502
587
|
process.exitCode = 1;
|
|
503
588
|
}
|
|
504
589
|
}
|
|
505
590
|
|
|
506
|
-
// src/commands/
|
|
507
|
-
import
|
|
508
|
-
import {
|
|
509
|
-
StorageManager,
|
|
510
|
-
computeProcedureStats,
|
|
511
|
-
formatProcedureStatsText,
|
|
512
|
-
initLogger,
|
|
513
|
-
parseConfig as parseConfig9,
|
|
514
|
-
resolveRemnicConfigRecord as resolveRemnicConfigRecord9,
|
|
515
|
-
runProcedureLibraryMaintenance
|
|
516
|
-
} from "@remnic/core";
|
|
591
|
+
// src/commands/journal-vault.ts
|
|
592
|
+
import fs10 from "fs";
|
|
593
|
+
import { readVaultJournal } from "@remnic/core";
|
|
517
594
|
|
|
518
595
|
// src/cli-args.ts
|
|
519
596
|
function resolveFlag(args, flag) {
|
|
@@ -571,6 +648,236 @@ function parseTaxonomyResolveArgs(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_
|
|
|
571
648
|
return { textParts, values, booleans };
|
|
572
649
|
}
|
|
573
650
|
|
|
651
|
+
// src/commands/journal-vault.ts
|
|
652
|
+
var defaultIo = {
|
|
653
|
+
stdout: (line) => {
|
|
654
|
+
process.stdout.write(`${line}
|
|
655
|
+
`);
|
|
656
|
+
},
|
|
657
|
+
stderr: (line) => {
|
|
658
|
+
process.stderr.write(`${line}
|
|
659
|
+
`);
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
function journalVaultHelp() {
|
|
663
|
+
return `Usage: remnic journal-vault show --file <path> --section <heading>
|
|
664
|
+
|
|
665
|
+
show Print the stripped journal section. Missing file or heading prints exists:false.
|
|
666
|
+
`;
|
|
667
|
+
}
|
|
668
|
+
function runJournalVaultCommand(rest, io = defaultIo) {
|
|
669
|
+
if (rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" || rest[0] === "help") {
|
|
670
|
+
io.stdout(journalVaultHelp().trimEnd());
|
|
671
|
+
return 0;
|
|
672
|
+
}
|
|
673
|
+
if (rest[0] !== "show") {
|
|
674
|
+
io.stderr(`journal-vault: unknown action "${rest[0]}".`);
|
|
675
|
+
io.stderr(journalVaultHelp().trimEnd());
|
|
676
|
+
return 1;
|
|
677
|
+
}
|
|
678
|
+
const filePath = resolveFlag(rest, "--file");
|
|
679
|
+
const section = resolveFlag(rest, "--section");
|
|
680
|
+
if (filePath === void 0 || section === void 0) {
|
|
681
|
+
io.stderr("journal-vault: show requires --file <path> and --section <heading>");
|
|
682
|
+
return 1;
|
|
683
|
+
}
|
|
684
|
+
let fileText = null;
|
|
685
|
+
try {
|
|
686
|
+
fileText = fs10.readFileSync(filePath, "utf8");
|
|
687
|
+
} catch (err) {
|
|
688
|
+
if (err.code !== "ENOENT") {
|
|
689
|
+
io.stderr(err instanceof Error ? err.message : String(err));
|
|
690
|
+
return 1;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
const result = readVaultJournal({ fileText, journalSection: section });
|
|
694
|
+
if (!result.ok) {
|
|
695
|
+
io.stderr(`journal-vault: duplicate heading at lines ${result.lines.join(", ")}`);
|
|
696
|
+
return 1;
|
|
697
|
+
}
|
|
698
|
+
if (!result.exists) {
|
|
699
|
+
io.stdout("exists:false");
|
|
700
|
+
return 0;
|
|
701
|
+
}
|
|
702
|
+
io.stdout(result.text);
|
|
703
|
+
return 0;
|
|
704
|
+
}
|
|
705
|
+
async function runJournalVaultBinaryCommand(rest) {
|
|
706
|
+
const code = runJournalVaultCommand(rest);
|
|
707
|
+
if (code !== 0) process.exitCode = code;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// src/commands/activity-privacy.ts
|
|
711
|
+
import { parseFlexibleIsoTimestamp, shouldRetain } from "@remnic/core";
|
|
712
|
+
var defaultIo2 = {
|
|
713
|
+
stdout: (line) => {
|
|
714
|
+
process.stdout.write(`${line}
|
|
715
|
+
`);
|
|
716
|
+
},
|
|
717
|
+
stderr: (line) => {
|
|
718
|
+
process.stderr.write(`${line}
|
|
719
|
+
`);
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
function activityPrivacyHelp() {
|
|
723
|
+
return `Usage: remnic activity-privacy retain --captured <iso> --now <iso> --days <n> [--enabled <true|false>]
|
|
724
|
+
|
|
725
|
+
retain Print retain=true or retain=false. --days 0 keeps forever.
|
|
726
|
+
`;
|
|
727
|
+
}
|
|
728
|
+
function parseEnabled(rest, io) {
|
|
729
|
+
const raw = resolveFlag(rest, "--enabled");
|
|
730
|
+
if (raw === void 0) {
|
|
731
|
+
if (hasFlag(rest, "--enabled")) {
|
|
732
|
+
io.stderr("activity-privacy: --enabled requires true or false");
|
|
733
|
+
return void 0;
|
|
734
|
+
}
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
if (raw === "true") return true;
|
|
738
|
+
if (raw === "false") return false;
|
|
739
|
+
io.stderr("activity-privacy: --enabled must be true or false");
|
|
740
|
+
return void 0;
|
|
741
|
+
}
|
|
742
|
+
function runActivityPrivacyCommand(rest, io = defaultIo2) {
|
|
743
|
+
if (rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" || rest[0] === "help") {
|
|
744
|
+
io.stdout(activityPrivacyHelp().trimEnd());
|
|
745
|
+
return 0;
|
|
746
|
+
}
|
|
747
|
+
if (rest[0] !== "retain") {
|
|
748
|
+
io.stderr(`activity-privacy: unknown action "${rest[0]}".`);
|
|
749
|
+
io.stderr(activityPrivacyHelp().trimEnd());
|
|
750
|
+
return 1;
|
|
751
|
+
}
|
|
752
|
+
const capturedRaw = resolveFlag(rest, "--captured");
|
|
753
|
+
const nowRaw = resolveFlag(rest, "--now");
|
|
754
|
+
const daysRaw = resolveFlag(rest, "--days");
|
|
755
|
+
if (capturedRaw === void 0 || nowRaw === void 0 || daysRaw === void 0) {
|
|
756
|
+
io.stderr("activity-privacy: retain requires --captured <iso>, --now <iso>, and --days <n>");
|
|
757
|
+
return 1;
|
|
758
|
+
}
|
|
759
|
+
const capturedAtMs = parseFlexibleIsoTimestamp(capturedRaw);
|
|
760
|
+
const nowMs = parseFlexibleIsoTimestamp(nowRaw);
|
|
761
|
+
if (capturedAtMs === null || nowMs === null) {
|
|
762
|
+
io.stderr("activity-privacy: --captured and --now must be ISO timestamps");
|
|
763
|
+
return 1;
|
|
764
|
+
}
|
|
765
|
+
const days = Number(daysRaw);
|
|
766
|
+
if (!Number.isInteger(days) || days < 0) {
|
|
767
|
+
io.stderr("activity-privacy: --days must be a non-negative integer");
|
|
768
|
+
return 1;
|
|
769
|
+
}
|
|
770
|
+
const enabled = parseEnabled(rest, io);
|
|
771
|
+
if (enabled === void 0) return 1;
|
|
772
|
+
io.stdout(`retain=${shouldRetain(capturedAtMs, nowMs, days, enabled)}`);
|
|
773
|
+
return 0;
|
|
774
|
+
}
|
|
775
|
+
async function runActivityPrivacyBinaryCommand(rest) {
|
|
776
|
+
const code = runActivityPrivacyCommand(rest);
|
|
777
|
+
if (code !== 0) process.exitCode = code;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// src/commands/vault-publish.ts
|
|
781
|
+
import fs11 from "fs";
|
|
782
|
+
import { applyManagedRegion } from "@remnic/core";
|
|
783
|
+
var defaultIo3 = {
|
|
784
|
+
stdout: (line) => {
|
|
785
|
+
process.stdout.write(`${line}
|
|
786
|
+
`);
|
|
787
|
+
},
|
|
788
|
+
stderr: (line) => {
|
|
789
|
+
process.stderr.write(`${line}
|
|
790
|
+
`);
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
function vaultPublishHelp() {
|
|
794
|
+
return `Usage: remnic vault-publish apply --file <path> --name <region> --content <text>
|
|
795
|
+
|
|
796
|
+
apply Replace the marked region. Missing markers print no_marker.
|
|
797
|
+
`;
|
|
798
|
+
}
|
|
799
|
+
function runVaultPublishCommand(rest, io = defaultIo3) {
|
|
800
|
+
if (rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" || rest[0] === "help") {
|
|
801
|
+
io.stdout(vaultPublishHelp().trimEnd());
|
|
802
|
+
return 0;
|
|
803
|
+
}
|
|
804
|
+
if (rest[0] !== "apply") {
|
|
805
|
+
io.stderr(`vault-publish: unknown action "${rest[0]}".`);
|
|
806
|
+
io.stderr(vaultPublishHelp().trimEnd());
|
|
807
|
+
return 1;
|
|
808
|
+
}
|
|
809
|
+
const filePath = resolveFlag(rest, "--file");
|
|
810
|
+
const name = resolveFlag(rest, "--name");
|
|
811
|
+
const content = resolveFlag(rest, "--content");
|
|
812
|
+
if (filePath === void 0 || name === void 0 || content === void 0) {
|
|
813
|
+
io.stderr("vault-publish: apply requires --file <path>, --name <region>, and --content <text>");
|
|
814
|
+
return 1;
|
|
815
|
+
}
|
|
816
|
+
let fileText;
|
|
817
|
+
try {
|
|
818
|
+
fileText = fs11.readFileSync(filePath, "utf8");
|
|
819
|
+
} catch (err) {
|
|
820
|
+
if (err.code === "ENOENT") {
|
|
821
|
+
io.stderr("missing_file");
|
|
822
|
+
return 1;
|
|
823
|
+
}
|
|
824
|
+
io.stderr(err instanceof Error ? err.message : String(err));
|
|
825
|
+
return 1;
|
|
826
|
+
}
|
|
827
|
+
const applied = applyManagedRegion(fileText, { strategy: "markers", name, content });
|
|
828
|
+
if (!applied.ok) {
|
|
829
|
+
io.stderr(applied.reason);
|
|
830
|
+
return 1;
|
|
831
|
+
}
|
|
832
|
+
if (applied.text !== fileText) fs11.writeFileSync(filePath, applied.text);
|
|
833
|
+
io.stdout("ok");
|
|
834
|
+
return 0;
|
|
835
|
+
}
|
|
836
|
+
async function runVaultPublishBinaryCommand(rest) {
|
|
837
|
+
const code = runVaultPublishCommand(rest);
|
|
838
|
+
if (code !== 0) process.exitCode = code;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// src/commands/external-wiki.ts
|
|
842
|
+
import fs12 from "fs";
|
|
843
|
+
import { parseConfig as parseConfig10, resolveRemnicConfigRecord as resolveRemnicConfigRecord10, runExternalWikiCliCommand } from "@remnic/core";
|
|
844
|
+
async function runExternalWikiBinaryCommand(rest) {
|
|
845
|
+
let roots;
|
|
846
|
+
try {
|
|
847
|
+
const configPath = resolveConfigPath();
|
|
848
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
849
|
+
roots = parseConfig10(resolveRemnicConfigRecord10(raw)).externalWikis;
|
|
850
|
+
} catch {
|
|
851
|
+
console.error(
|
|
852
|
+
"external-wiki: failed to load the Remnic config - run `remnic doctor` and check the config file for errors"
|
|
853
|
+
);
|
|
854
|
+
process.exitCode = 1;
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
try {
|
|
858
|
+
const code = await runExternalWikiCliCommand(roots, rest, {
|
|
859
|
+
stdout: process.stdout,
|
|
860
|
+
stderr: process.stderr
|
|
861
|
+
});
|
|
862
|
+
if (code !== 0) process.exitCode = code;
|
|
863
|
+
} catch {
|
|
864
|
+
console.error("external-wiki: search failed");
|
|
865
|
+
process.exitCode = 1;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// src/commands/procedural.ts
|
|
870
|
+
import fs13 from "fs";
|
|
871
|
+
import {
|
|
872
|
+
StorageManager,
|
|
873
|
+
computeProcedureStats,
|
|
874
|
+
formatProcedureStatsText,
|
|
875
|
+
initLogger,
|
|
876
|
+
parseConfig as parseConfig11,
|
|
877
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord11,
|
|
878
|
+
runProcedureLibraryMaintenance
|
|
879
|
+
} from "@remnic/core";
|
|
880
|
+
|
|
574
881
|
// src/path-utils.ts
|
|
575
882
|
function resolveHomeDir() {
|
|
576
883
|
return process.env.HOME ?? process.env.USERPROFILE ?? "~";
|
|
@@ -642,8 +949,8 @@ Shared with:
|
|
|
642
949
|
process.exit(1);
|
|
643
950
|
}
|
|
644
951
|
const configPath = resolveConfigPath();
|
|
645
|
-
const raw =
|
|
646
|
-
const config =
|
|
952
|
+
const raw = fs13.existsSync(configPath) ? JSON.parse(fs13.readFileSync(configPath, "utf8")) : {};
|
|
953
|
+
const config = parseConfig11(resolveRemnicConfigRecord11(raw));
|
|
647
954
|
const memoryDir = expandTilde(
|
|
648
955
|
typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
649
956
|
);
|
|
@@ -698,12 +1005,12 @@ function formatProcedureMaintenanceText(report) {
|
|
|
698
1005
|
}
|
|
699
1006
|
|
|
700
1007
|
// src/commands/drift.ts
|
|
701
|
-
import
|
|
1008
|
+
import fs14 from "fs";
|
|
702
1009
|
import {
|
|
703
1010
|
Orchestrator as Orchestrator7,
|
|
704
1011
|
initLogger as initLogger2,
|
|
705
|
-
parseConfig as
|
|
706
|
-
resolveRemnicConfigRecord as
|
|
1012
|
+
parseConfig as parseConfig12,
|
|
1013
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord12,
|
|
707
1014
|
runPreferenceDriftScan
|
|
708
1015
|
} from "@remnic/core";
|
|
709
1016
|
async function runDriftBinaryCommand(rest) {
|
|
@@ -763,8 +1070,8 @@ Resolve a drifted item with the existing review surface:
|
|
|
763
1070
|
process.exit(1);
|
|
764
1071
|
}
|
|
765
1072
|
const configPath = resolveConfigPath();
|
|
766
|
-
const raw =
|
|
767
|
-
const config =
|
|
1073
|
+
const raw = fs14.existsSync(configPath) ? JSON.parse(fs14.readFileSync(configPath, "utf8")) : {};
|
|
1074
|
+
const config = parseConfig12(resolveRemnicConfigRecord12(raw));
|
|
768
1075
|
const memoryDirOverridden = typeof memoryDirOverride === "string" && memoryDirOverride.length > 0;
|
|
769
1076
|
const memoryDir = expandTilde(
|
|
770
1077
|
memoryDirOverridden ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
@@ -827,6 +1134,104 @@ function formatPreferenceDriftText(report) {
|
|
|
827
1134
|
return lines.join("\n") + "\n";
|
|
828
1135
|
}
|
|
829
1136
|
|
|
1137
|
+
// src/commands/recall-navigate.ts
|
|
1138
|
+
import {
|
|
1139
|
+
expandRecallNode,
|
|
1140
|
+
traverseRecallLink
|
|
1141
|
+
} from "@remnic/core";
|
|
1142
|
+
var RECALL_NAV_UNAVAILABLE_TAG = "[unavailable] budget_off";
|
|
1143
|
+
function recallNavigateHelp() {
|
|
1144
|
+
return `Usage: remnic recall <expand|traverse> --node <json> [--budget <n>] [--type <linkType>]
|
|
1145
|
+
|
|
1146
|
+
expand Re-render one node at the next disclosure level
|
|
1147
|
+
traverse Follow typed links from a node
|
|
1148
|
+
|
|
1149
|
+
--budget 0 turns navigation off and prints ${RECALL_NAV_UNAVAILABLE_TAG}
|
|
1150
|
+
--type required for traverse: supports, contradicts, elaborates, supersedes, causes
|
|
1151
|
+
`;
|
|
1152
|
+
}
|
|
1153
|
+
function takeFlag5(rest, name) {
|
|
1154
|
+
const index = rest.indexOf(name);
|
|
1155
|
+
if (index < 0) return void 0;
|
|
1156
|
+
const value = rest[index + 1];
|
|
1157
|
+
if (value === void 0 || value.startsWith("-")) {
|
|
1158
|
+
throw new Error(`${name} requires a value`);
|
|
1159
|
+
}
|
|
1160
|
+
return value;
|
|
1161
|
+
}
|
|
1162
|
+
function parseBudget(rest) {
|
|
1163
|
+
if (!rest.includes("--budget")) return 1;
|
|
1164
|
+
const raw = takeFlag5(rest, "--budget");
|
|
1165
|
+
const budget = Number(raw);
|
|
1166
|
+
if (!Number.isFinite(budget)) {
|
|
1167
|
+
throw new Error(`--budget must be a number (got ${JSON.stringify(raw)})`);
|
|
1168
|
+
}
|
|
1169
|
+
return budget;
|
|
1170
|
+
}
|
|
1171
|
+
function parseNode(raw) {
|
|
1172
|
+
let value;
|
|
1173
|
+
try {
|
|
1174
|
+
value = JSON.parse(raw);
|
|
1175
|
+
} catch {
|
|
1176
|
+
throw new Error("--node must be JSON");
|
|
1177
|
+
}
|
|
1178
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1179
|
+
throw new Error("--node must be a JSON object");
|
|
1180
|
+
}
|
|
1181
|
+
const node = value;
|
|
1182
|
+
if (typeof node.id !== "string" || node.id.length === 0) {
|
|
1183
|
+
throw new Error("--node.id must be a non-empty string");
|
|
1184
|
+
}
|
|
1185
|
+
if (typeof node.disclosure !== "string") {
|
|
1186
|
+
throw new Error("--node.disclosure is required");
|
|
1187
|
+
}
|
|
1188
|
+
return node;
|
|
1189
|
+
}
|
|
1190
|
+
function emitUnavailable(io) {
|
|
1191
|
+
io.stdout(RECALL_NAV_UNAVAILABLE_TAG);
|
|
1192
|
+
return 0;
|
|
1193
|
+
}
|
|
1194
|
+
function runRecallNavigate(rest, io) {
|
|
1195
|
+
const action = rest[0];
|
|
1196
|
+
if (rest.length === 0 || action === "--help" || action === "-h" || action === "help") {
|
|
1197
|
+
io.stdout(recallNavigateHelp());
|
|
1198
|
+
return 0;
|
|
1199
|
+
}
|
|
1200
|
+
try {
|
|
1201
|
+
const budget = parseBudget(rest);
|
|
1202
|
+
const nodeRaw = takeFlag5(rest, "--node");
|
|
1203
|
+
if (nodeRaw === void 0) throw new Error("--node is required");
|
|
1204
|
+
const node = parseNode(nodeRaw);
|
|
1205
|
+
if (action === "expand") {
|
|
1206
|
+
const result = expandRecallNode(node, { budget });
|
|
1207
|
+
if (result.status === "unavailable") return emitUnavailable(io);
|
|
1208
|
+
io.stdout(JSON.stringify(result));
|
|
1209
|
+
return 0;
|
|
1210
|
+
}
|
|
1211
|
+
if (action === "traverse") {
|
|
1212
|
+
const linkType = takeFlag5(rest, "--type");
|
|
1213
|
+
if (linkType === void 0) throw new Error("traverse requires --type");
|
|
1214
|
+
const result = traverseRecallLink(node, linkType, { budget });
|
|
1215
|
+
if (result.status === "unavailable") return emitUnavailable(io);
|
|
1216
|
+
io.stdout(JSON.stringify(result));
|
|
1217
|
+
return 0;
|
|
1218
|
+
}
|
|
1219
|
+
io.stderr(`recall: unknown action "${action}".`);
|
|
1220
|
+
io.stderr(recallNavigateHelp());
|
|
1221
|
+
return 1;
|
|
1222
|
+
} catch (err) {
|
|
1223
|
+
io.stderr(err instanceof Error ? err.message : String(err));
|
|
1224
|
+
return 1;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
async function runRecallNavigateCommand(rest) {
|
|
1228
|
+
const code = runRecallNavigate(rest, {
|
|
1229
|
+
stdout: (line) => console.log(line),
|
|
1230
|
+
stderr: (line) => console.error(line)
|
|
1231
|
+
});
|
|
1232
|
+
if (code !== 0) process.exitCode = code;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
830
1235
|
// src/optional-module-loader.ts
|
|
831
1236
|
function isSpecifierNotFoundError(err, specifier) {
|
|
832
1237
|
if (!err || typeof err !== "object") {
|
|
@@ -877,13 +1282,13 @@ async function loadWecloneExportModule() {
|
|
|
877
1282
|
}
|
|
878
1283
|
|
|
879
1284
|
// src/converge.ts
|
|
880
|
-
import * as
|
|
1285
|
+
import * as fs16 from "fs";
|
|
881
1286
|
import { createHash as createHash3 } from "crypto";
|
|
882
1287
|
import * as path3 from "path";
|
|
883
1288
|
import {
|
|
884
1289
|
CONVERGE_CONFLICT_POLICIES,
|
|
885
1290
|
DEFAULT_CONVERGE_CONFLICT_POLICY,
|
|
886
|
-
parseConfig as
|
|
1291
|
+
parseConfig as parseConfig13,
|
|
887
1292
|
buildOfflineSyncSnapshotFromBase,
|
|
888
1293
|
applyOfflineSyncFileContentChunk,
|
|
889
1294
|
isInternalRemnicStatePath as isInternalRemnicStatePath3,
|
|
@@ -909,7 +1314,7 @@ import {
|
|
|
909
1314
|
|
|
910
1315
|
// src/offline-storage-io.ts
|
|
911
1316
|
import { createDecipheriv, createHash } from "crypto";
|
|
912
|
-
import
|
|
1317
|
+
import fs15 from "fs";
|
|
913
1318
|
import { lstat, mkdtemp, readdir, rm } from "fs/promises";
|
|
914
1319
|
import path2 from "path";
|
|
915
1320
|
import {
|
|
@@ -1071,7 +1476,7 @@ async function* readOfflineSyncFileChunks(options) {
|
|
|
1071
1476
|
});
|
|
1072
1477
|
}
|
|
1073
1478
|
async function readFilePrefix(filePath, length) {
|
|
1074
|
-
const handle = await
|
|
1479
|
+
const handle = await fs15.promises.open(filePath, "r");
|
|
1075
1480
|
try {
|
|
1076
1481
|
const out = Buffer.alloc(length);
|
|
1077
1482
|
const { bytesRead } = await handle.read(out, 0, length, 0);
|
|
@@ -1081,7 +1486,7 @@ async function readFilePrefix(filePath, length) {
|
|
|
1081
1486
|
}
|
|
1082
1487
|
}
|
|
1083
1488
|
async function* readPlainOfflineFileChunks(filePath, chunkSize) {
|
|
1084
|
-
const stream =
|
|
1489
|
+
const stream = fs15.createReadStream(filePath, { highWaterMark: chunkSize });
|
|
1085
1490
|
for await (const chunk of stream) {
|
|
1086
1491
|
yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
1087
1492
|
}
|
|
@@ -1118,9 +1523,9 @@ async function* readEncryptedOfflineFileChunks(options) {
|
|
|
1118
1523
|
});
|
|
1119
1524
|
decipher.setAuthTag(authTag);
|
|
1120
1525
|
decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
|
|
1121
|
-
const output =
|
|
1526
|
+
const output = fs15.createWriteStream(tempPath, { mode: 384 });
|
|
1122
1527
|
try {
|
|
1123
|
-
const stream =
|
|
1528
|
+
const stream = fs15.createReadStream(options.filePath, {
|
|
1124
1529
|
start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
|
|
1125
1530
|
highWaterMark: options.chunkSize
|
|
1126
1531
|
});
|
|
@@ -1730,7 +2135,7 @@ async function readLocalTombstoneEvidence(rootDir) {
|
|
|
1730
2135
|
for (const relativePath of TOMBSTONE_PATHS) {
|
|
1731
2136
|
let content;
|
|
1732
2137
|
try {
|
|
1733
|
-
content = await
|
|
2138
|
+
content = await fs16.promises.readFile(path3.join(rootDir, relativePath), "utf-8");
|
|
1734
2139
|
} catch (error) {
|
|
1735
2140
|
if (error.code === "ENOENT") continue;
|
|
1736
2141
|
throw error;
|
|
@@ -1745,7 +2150,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
|
|
|
1745
2150
|
const cursorDir = path3.join(path3.resolve(memoryDir), ".remnic", "state", "converge-cursors");
|
|
1746
2151
|
let entries;
|
|
1747
2152
|
try {
|
|
1748
|
-
entries = await
|
|
2153
|
+
entries = await fs16.promises.readdir(cursorDir, { withFileTypes: true });
|
|
1749
2154
|
} catch (error) {
|
|
1750
2155
|
if (error.code === "ENOENT") return [];
|
|
1751
2156
|
throw error;
|
|
@@ -1821,7 +2226,7 @@ async function computeConvergePlan(options = {}) {
|
|
|
1821
2226
|
let config = options.config;
|
|
1822
2227
|
if (!config) {
|
|
1823
2228
|
try {
|
|
1824
|
-
config =
|
|
2229
|
+
config = parseConfig13({});
|
|
1825
2230
|
} catch {
|
|
1826
2231
|
}
|
|
1827
2232
|
}
|
|
@@ -2072,7 +2477,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2072
2477
|
let config = options.config;
|
|
2073
2478
|
if (!config) {
|
|
2074
2479
|
try {
|
|
2075
|
-
config =
|
|
2480
|
+
config = parseConfig13({});
|
|
2076
2481
|
} catch {
|
|
2077
2482
|
}
|
|
2078
2483
|
}
|
|
@@ -2235,7 +2640,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2235
2640
|
if (current.sha256 !== entry.localSha256) {
|
|
2236
2641
|
throw new Error(`local file changed during push: ${localPath}`);
|
|
2237
2642
|
}
|
|
2238
|
-
const stat2 = await
|
|
2643
|
+
const stat2 = await fs16.promises.stat(filePath);
|
|
2239
2644
|
let chunks;
|
|
2240
2645
|
let chunkOffset = 0;
|
|
2241
2646
|
const resetChunks = async () => {
|
|
@@ -2512,7 +2917,7 @@ function formatConvergeApplyReport(result) {
|
|
|
2512
2917
|
lines.push(formatConvergeReport(result.plan));
|
|
2513
2918
|
return lines.join("\n");
|
|
2514
2919
|
}
|
|
2515
|
-
async function cmdConverge(action, rest, json, config =
|
|
2920
|
+
async function cmdConverge(action, rest, json, config = parseConfig13({})) {
|
|
2516
2921
|
if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
2517
2922
|
console.log(`Usage: remnic converge <plan|apply> [options]
|
|
2518
2923
|
|
|
@@ -2718,8 +3123,8 @@ function renderReplayResult(result, targetNamespace, format) {
|
|
|
2718
3123
|
}
|
|
2719
3124
|
|
|
2720
3125
|
// src/quarantine-replay.ts
|
|
2721
|
-
import * as
|
|
2722
|
-
import { EngramAccessService, Orchestrator as Orchestrator8, initLogger as initLogger3, parseConfig as
|
|
3126
|
+
import * as fs17 from "fs";
|
|
3127
|
+
import { EngramAccessService, Orchestrator as Orchestrator8, initLogger as initLogger3, parseConfig as parseConfig14, resolveRemnicConfigRecord as resolveRemnicConfigRecord13 } from "@remnic/core";
|
|
2723
3128
|
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
2724
3129
|
function valueFlag(args, flag) {
|
|
2725
3130
|
const occurrences = args.filter((a) => a === flag).length;
|
|
@@ -2767,8 +3172,8 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
2767
3172
|
let orchestrator;
|
|
2768
3173
|
try {
|
|
2769
3174
|
const configPath = resolveConfigPath2();
|
|
2770
|
-
const raw =
|
|
2771
|
-
const config =
|
|
3175
|
+
const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
|
|
3176
|
+
const config = parseConfig14(resolveRemnicConfigRecord13(raw));
|
|
2772
3177
|
orchestrator = new Orchestrator8(config);
|
|
2773
3178
|
await orchestrator.initialize();
|
|
2774
3179
|
await orchestrator.deferredReady;
|
|
@@ -2799,15 +3204,15 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
2799
3204
|
}
|
|
2800
3205
|
|
|
2801
3206
|
// src/offline-impression-rotation.ts
|
|
2802
|
-
import
|
|
2803
|
-
import { parseConfig as
|
|
3207
|
+
import fs18 from "fs";
|
|
3208
|
+
import { parseConfig as parseConfig15, resolveRemnicConfigRecord as resolveRemnicConfigRecord14, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
2804
3209
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
2805
3210
|
function parseConfigQuietly(raw) {
|
|
2806
3211
|
const originalWarn = console.warn;
|
|
2807
3212
|
console.warn = () => {
|
|
2808
3213
|
};
|
|
2809
3214
|
try {
|
|
2810
|
-
return
|
|
3215
|
+
return parseConfig15(resolveRemnicConfigRecord14(raw));
|
|
2811
3216
|
} finally {
|
|
2812
3217
|
console.warn = originalWarn;
|
|
2813
3218
|
}
|
|
@@ -2821,7 +3226,7 @@ var OFFLINE_CONFIG_KEYS = [
|
|
|
2821
3226
|
function pickOfflineConfigRecord(raw) {
|
|
2822
3227
|
let resolved;
|
|
2823
3228
|
try {
|
|
2824
|
-
resolved =
|
|
3229
|
+
resolved = resolveRemnicConfigRecord14(raw);
|
|
2825
3230
|
} catch {
|
|
2826
3231
|
resolved = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
2827
3232
|
}
|
|
@@ -2834,7 +3239,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
2834
3239
|
function resolveOfflineImpressionRotation(configPath) {
|
|
2835
3240
|
let raw;
|
|
2836
3241
|
try {
|
|
2837
|
-
raw =
|
|
3242
|
+
raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
|
|
2838
3243
|
} catch {
|
|
2839
3244
|
throw new Error(
|
|
2840
3245
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -3092,12 +3497,12 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
3092
3497
|
}
|
|
3093
3498
|
|
|
3094
3499
|
// src/cmd-security.ts
|
|
3095
|
-
import
|
|
3500
|
+
import fs19 from "fs";
|
|
3096
3501
|
import {
|
|
3097
3502
|
Orchestrator as Orchestrator9,
|
|
3098
|
-
parseConfig as
|
|
3503
|
+
parseConfig as parseConfig16,
|
|
3099
3504
|
initLogger as initLogger4,
|
|
3100
|
-
resolveRemnicConfigRecord as
|
|
3505
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord15,
|
|
3101
3506
|
runAuditMemoryCliCommand,
|
|
3102
3507
|
formatAuditMemoryReport
|
|
3103
3508
|
} from "@remnic/core";
|
|
@@ -3112,8 +3517,8 @@ async function cmdSecurity(rest) {
|
|
|
3112
3517
|
}
|
|
3113
3518
|
initLogger4();
|
|
3114
3519
|
const configPath = resolveConfigPath();
|
|
3115
|
-
const raw =
|
|
3116
|
-
const config =
|
|
3520
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
3521
|
+
const config = parseConfig16(resolveRemnicConfigRecord15(raw));
|
|
3117
3522
|
const orchestrator = new Orchestrator9(config);
|
|
3118
3523
|
await orchestrator.initialize();
|
|
3119
3524
|
try {
|
|
@@ -3137,7 +3542,7 @@ async function cmdSecurity(rest) {
|
|
|
3137
3542
|
}
|
|
3138
3543
|
|
|
3139
3544
|
// src/daemon-service-candidates.ts
|
|
3140
|
-
import
|
|
3545
|
+
import fs20 from "fs";
|
|
3141
3546
|
import path6 from "path";
|
|
3142
3547
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
3143
3548
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -3159,7 +3564,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
3159
3564
|
function anyFileExists(paths) {
|
|
3160
3565
|
return paths.some((candidate) => {
|
|
3161
3566
|
try {
|
|
3162
|
-
return
|
|
3567
|
+
return fs20.statSync(candidate).isFile();
|
|
3163
3568
|
} catch {
|
|
3164
3569
|
return false;
|
|
3165
3570
|
}
|
|
@@ -3171,7 +3576,7 @@ function commandNames(command) {
|
|
|
3171
3576
|
}
|
|
3172
3577
|
function isRunnableNodeScript(filePath) {
|
|
3173
3578
|
try {
|
|
3174
|
-
const text =
|
|
3579
|
+
const text = fs20.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
3175
3580
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
3176
3581
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
3177
3582
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -3184,7 +3589,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
3184
3589
|
function resolveShimNodeScript(filePath) {
|
|
3185
3590
|
let text;
|
|
3186
3591
|
try {
|
|
3187
|
-
text =
|
|
3592
|
+
text = fs20.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
3188
3593
|
} catch {
|
|
3189
3594
|
return void 0;
|
|
3190
3595
|
}
|
|
@@ -3196,8 +3601,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
3196
3601
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
3197
3602
|
const resolved = path6.isAbsolute(candidate) ? candidate : path6.resolve(basedir, candidate);
|
|
3198
3603
|
try {
|
|
3199
|
-
if (
|
|
3200
|
-
return
|
|
3604
|
+
if (fs20.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
3605
|
+
return fs20.realpathSync(resolved);
|
|
3201
3606
|
}
|
|
3202
3607
|
} catch {
|
|
3203
3608
|
}
|
|
@@ -3205,7 +3610,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
3205
3610
|
return void 0;
|
|
3206
3611
|
}
|
|
3207
3612
|
function resolveRunnableNodeScript(filePath) {
|
|
3208
|
-
const realPath =
|
|
3613
|
+
const realPath = fs20.realpathSync(filePath);
|
|
3209
3614
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
3210
3615
|
return resolveShimNodeScript(realPath);
|
|
3211
3616
|
}
|
|
@@ -3215,9 +3620,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
3215
3620
|
for (const name of commandNames(command)) {
|
|
3216
3621
|
const candidate = path6.join(dir, name);
|
|
3217
3622
|
try {
|
|
3218
|
-
const stat2 =
|
|
3623
|
+
const stat2 = fs20.statSync(candidate);
|
|
3219
3624
|
if (!stat2.isFile()) continue;
|
|
3220
|
-
if (process.platform !== "win32")
|
|
3625
|
+
if (process.platform !== "win32") fs20.accessSync(candidate, fs20.constants.X_OK);
|
|
3221
3626
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
3222
3627
|
if (runnable) return runnable;
|
|
3223
3628
|
} catch {
|
|
@@ -4690,7 +5095,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
4690
5095
|
}
|
|
4691
5096
|
|
|
4692
5097
|
// src/bench-fallback.ts
|
|
4693
|
-
import
|
|
5098
|
+
import fs21 from "fs";
|
|
4694
5099
|
import path10 from "path";
|
|
4695
5100
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
4696
5101
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -4762,7 +5167,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
4762
5167
|
);
|
|
4763
5168
|
}
|
|
4764
5169
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
4765
|
-
const entries =
|
|
5170
|
+
const entries = fs21.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
4766
5171
|
if (entries.length === 0) {
|
|
4767
5172
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
4768
5173
|
}
|
|
@@ -4770,7 +5175,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
4770
5175
|
}
|
|
4771
5176
|
|
|
4772
5177
|
// src/openclaw-upgrade-swap.ts
|
|
4773
|
-
import
|
|
5178
|
+
import fs22 from "fs";
|
|
4774
5179
|
import path11 from "path";
|
|
4775
5180
|
function describeError(error) {
|
|
4776
5181
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4782,7 +5187,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
4782
5187
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
4783
5188
|
if (explicitMode !== void 0) return explicitMode;
|
|
4784
5189
|
try {
|
|
4785
|
-
return
|
|
5190
|
+
return fs22.statSync(targetPath).mode & 4095;
|
|
4786
5191
|
} catch (error) {
|
|
4787
5192
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
4788
5193
|
return 384;
|
|
@@ -4792,8 +5197,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
4792
5197
|
}
|
|
4793
5198
|
function resolveAtomicReplacementPath(targetPath) {
|
|
4794
5199
|
try {
|
|
4795
|
-
if (
|
|
4796
|
-
return
|
|
5200
|
+
if (fs22.lstatSync(targetPath).isSymbolicLink()) {
|
|
5201
|
+
return fs22.realpathSync(targetPath);
|
|
4797
5202
|
}
|
|
4798
5203
|
} catch (error) {
|
|
4799
5204
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -4810,7 +5215,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
4810
5215
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
4811
5216
|
if (!displacedDir) return void 0;
|
|
4812
5217
|
try {
|
|
4813
|
-
|
|
5218
|
+
fs22.rmSync(displacedDir, { recursive: true, force: true });
|
|
4814
5219
|
return void 0;
|
|
4815
5220
|
} catch (error) {
|
|
4816
5221
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -4818,43 +5223,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
4818
5223
|
}
|
|
4819
5224
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
4820
5225
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4821
|
-
|
|
5226
|
+
fs22.mkdirSync(path11.dirname(resolvedTargetPath), { recursive: true });
|
|
4822
5227
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
4823
5228
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
4824
5229
|
try {
|
|
4825
5230
|
if (options.hooks?.writeTempFileSync) {
|
|
4826
5231
|
options.hooks.writeTempFileSync(tempPath);
|
|
4827
5232
|
} else {
|
|
4828
|
-
|
|
5233
|
+
fs22.writeFileSync(tempPath, data, { mode });
|
|
4829
5234
|
}
|
|
4830
|
-
|
|
4831
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5235
|
+
fs22.chmodSync(tempPath, mode);
|
|
5236
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs22.renameSync;
|
|
4832
5237
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4833
5238
|
} catch (error) {
|
|
4834
|
-
|
|
5239
|
+
fs22.rmSync(tempPath, { force: true });
|
|
4835
5240
|
throw error;
|
|
4836
5241
|
}
|
|
4837
5242
|
}
|
|
4838
5243
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
4839
|
-
if (!
|
|
5244
|
+
if (!fs22.existsSync(sourcePath)) return;
|
|
4840
5245
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4841
|
-
|
|
5246
|
+
fs22.mkdirSync(path11.dirname(resolvedTargetPath), { recursive: true });
|
|
4842
5247
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
4843
|
-
const mode =
|
|
5248
|
+
const mode = fs22.statSync(sourcePath).mode & 4095;
|
|
4844
5249
|
try {
|
|
4845
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
5250
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs22.copyFileSync;
|
|
4846
5251
|
copyTempFileSync(sourcePath, tempPath);
|
|
4847
|
-
|
|
4848
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5252
|
+
fs22.chmodSync(tempPath, mode);
|
|
5253
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs22.renameSync;
|
|
4849
5254
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4850
5255
|
} catch (error) {
|
|
4851
|
-
|
|
5256
|
+
fs22.rmSync(tempPath, { force: true });
|
|
4852
5257
|
throw error;
|
|
4853
5258
|
}
|
|
4854
5259
|
}
|
|
4855
5260
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
4856
5261
|
if (!rollbackDir) return;
|
|
4857
|
-
|
|
5262
|
+
fs22.rmSync(rollbackDir, { recursive: true, force: true });
|
|
4858
5263
|
}
|
|
4859
5264
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
4860
5265
|
if (!rollbackDir) return void 0;
|
|
@@ -4866,20 +5271,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
4866
5271
|
}
|
|
4867
5272
|
}
|
|
4868
5273
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
4869
|
-
if (!
|
|
5274
|
+
if (!fs22.existsSync(rollbackDir)) {
|
|
4870
5275
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
4871
5276
|
}
|
|
4872
|
-
|
|
4873
|
-
const displacedDir =
|
|
5277
|
+
fs22.mkdirSync(path11.dirname(targetDir), { recursive: true });
|
|
5278
|
+
const displacedDir = fs22.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
4874
5279
|
if (displacedDir) {
|
|
4875
|
-
|
|
5280
|
+
fs22.renameSync(targetDir, displacedDir);
|
|
4876
5281
|
}
|
|
4877
5282
|
try {
|
|
4878
|
-
|
|
5283
|
+
fs22.renameSync(rollbackDir, targetDir);
|
|
4879
5284
|
} catch (restoreError) {
|
|
4880
|
-
if (displacedDir &&
|
|
5285
|
+
if (displacedDir && fs22.existsSync(displacedDir)) {
|
|
4881
5286
|
try {
|
|
4882
|
-
|
|
5287
|
+
fs22.renameSync(displacedDir, targetDir);
|
|
4883
5288
|
} catch (revertError) {
|
|
4884
5289
|
throw new AggregateError(
|
|
4885
5290
|
[restoreError, revertError],
|
|
@@ -4895,23 +5300,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
4895
5300
|
return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
|
|
4896
5301
|
}
|
|
4897
5302
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
4898
|
-
if (!
|
|
5303
|
+
if (!fs22.existsSync(backupDir)) {
|
|
4899
5304
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
4900
5305
|
}
|
|
4901
|
-
|
|
5306
|
+
fs22.mkdirSync(path11.dirname(targetDir), { recursive: true });
|
|
4902
5307
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
4903
|
-
const displacedDir =
|
|
4904
|
-
|
|
5308
|
+
const displacedDir = fs22.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
5309
|
+
fs22.cpSync(backupDir, stagedDir, { recursive: true });
|
|
4905
5310
|
if (displacedDir) {
|
|
4906
|
-
|
|
5311
|
+
fs22.renameSync(targetDir, displacedDir);
|
|
4907
5312
|
}
|
|
4908
5313
|
try {
|
|
4909
|
-
|
|
5314
|
+
fs22.renameSync(stagedDir, targetDir);
|
|
4910
5315
|
} catch (restoreError) {
|
|
4911
|
-
|
|
4912
|
-
if (displacedDir &&
|
|
5316
|
+
fs22.rmSync(targetDir, { recursive: true, force: true });
|
|
5317
|
+
if (displacedDir && fs22.existsSync(displacedDir)) {
|
|
4913
5318
|
try {
|
|
4914
|
-
|
|
5319
|
+
fs22.renameSync(displacedDir, targetDir);
|
|
4915
5320
|
} catch (revertError) {
|
|
4916
5321
|
throw new AggregateError(
|
|
4917
5322
|
[restoreError, revertError],
|
|
@@ -4919,7 +5324,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
4919
5324
|
);
|
|
4920
5325
|
}
|
|
4921
5326
|
}
|
|
4922
|
-
|
|
5327
|
+
fs22.rmSync(stagedDir, { recursive: true, force: true });
|
|
4923
5328
|
throw new Error(
|
|
4924
5329
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
4925
5330
|
{ cause: restoreError }
|
|
@@ -4944,7 +5349,7 @@ function rollbackOpenclawUpgrade({
|
|
|
4944
5349
|
let configRemovalAttempted = false;
|
|
4945
5350
|
let pluginRestored = false;
|
|
4946
5351
|
try {
|
|
4947
|
-
if (rollbackDir &&
|
|
5352
|
+
if (rollbackDir && fs22.existsSync(rollbackDir)) {
|
|
4948
5353
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
4949
5354
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
4950
5355
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -4954,7 +5359,7 @@ function rollbackOpenclawUpgrade({
|
|
|
4954
5359
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
4955
5360
|
}
|
|
4956
5361
|
try {
|
|
4957
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
5362
|
+
if (!pluginRestored && pluginBackupDir && fs22.existsSync(pluginBackupDir)) {
|
|
4958
5363
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
4959
5364
|
if (rollbackRestoreError) {
|
|
4960
5365
|
notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
|
|
@@ -4979,12 +5384,12 @@ function rollbackOpenclawUpgrade({
|
|
|
4979
5384
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
4980
5385
|
}
|
|
4981
5386
|
try {
|
|
4982
|
-
if (configBackupPath &&
|
|
5387
|
+
if (configBackupPath && fs22.existsSync(configBackupPath)) {
|
|
4983
5388
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
4984
5389
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
4985
|
-
} else if (removeConfigIfUnbacked &&
|
|
5390
|
+
} else if (removeConfigIfUnbacked && fs22.existsSync(configPath)) {
|
|
4986
5391
|
configRemovalAttempted = true;
|
|
4987
|
-
|
|
5392
|
+
fs22.rmSync(configPath, { force: true });
|
|
4988
5393
|
notes.push("Removed OpenClaw config created during the failed upgrade");
|
|
4989
5394
|
}
|
|
4990
5395
|
} catch (error) {
|
|
@@ -5037,7 +5442,7 @@ Run this manually when you're ready:
|
|
|
5037
5442
|
|
|
5038
5443
|
// src/openclaw-managed-upgrade-loader.ts
|
|
5039
5444
|
import { execFileSync } from "child_process";
|
|
5040
|
-
import
|
|
5445
|
+
import fs23 from "fs";
|
|
5041
5446
|
import os from "os";
|
|
5042
5447
|
import path12 from "path";
|
|
5043
5448
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -5113,7 +5518,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
|
|
|
5113
5518
|
function readCliAdapterRange() {
|
|
5114
5519
|
const moduleDir = path12.dirname(fileURLToPath3(import.meta.url));
|
|
5115
5520
|
const manifestPath = path12.resolve(moduleDir, "../package.json");
|
|
5116
|
-
const manifest = JSON.parse(
|
|
5521
|
+
const manifest = JSON.parse(fs23.readFileSync(manifestPath, "utf8"));
|
|
5117
5522
|
if (manifest.name !== "@remnic/cli") {
|
|
5118
5523
|
throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
|
|
5119
5524
|
}
|
|
@@ -5157,7 +5562,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5157
5562
|
const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
|
|
5158
5563
|
if (!adapterMissing) throw error;
|
|
5159
5564
|
}
|
|
5160
|
-
const temporaryRoot =
|
|
5565
|
+
const temporaryRoot = fs23.mkdtempSync(path12.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
5161
5566
|
try {
|
|
5162
5567
|
const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
|
|
5163
5568
|
const installArgs = [
|
|
@@ -5172,12 +5577,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5172
5577
|
];
|
|
5173
5578
|
(hooks.runNpmInstall ?? runNpmInstall)(installArgs);
|
|
5174
5579
|
const resolverPath = path12.join(temporaryRoot, "load-managed-upgrade.mjs");
|
|
5175
|
-
|
|
5580
|
+
fs23.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
|
|
5176
5581
|
`, "utf8");
|
|
5177
5582
|
return await importModule(pathToFileURL2(resolverPath).href);
|
|
5178
5583
|
} finally {
|
|
5179
5584
|
try {
|
|
5180
|
-
|
|
5585
|
+
fs23.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
5181
5586
|
} catch (error) {
|
|
5182
5587
|
const detail = error instanceof Error ? error.message : String(error);
|
|
5183
5588
|
console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
|
|
@@ -5186,13 +5591,13 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5186
5591
|
}
|
|
5187
5592
|
|
|
5188
5593
|
// src/remote-daemon.ts
|
|
5189
|
-
import
|
|
5594
|
+
import fs24 from "fs";
|
|
5190
5595
|
function readCompatEnv(primary, legacy) {
|
|
5191
5596
|
return process.env[primary] ?? process.env[legacy];
|
|
5192
5597
|
}
|
|
5193
5598
|
function readRemnicConfigRecord(configPath) {
|
|
5194
5599
|
try {
|
|
5195
|
-
const parsed = JSON.parse(
|
|
5600
|
+
const parsed = JSON.parse(fs24.readFileSync(configPath, "utf8"));
|
|
5196
5601
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5197
5602
|
return parsed;
|
|
5198
5603
|
}
|
|
@@ -5421,7 +5826,7 @@ async function remoteRecallXray(daemon, request) {
|
|
|
5421
5826
|
}
|
|
5422
5827
|
|
|
5423
5828
|
// src/daemon-service.ts
|
|
5424
|
-
import
|
|
5829
|
+
import fs25 from "fs";
|
|
5425
5830
|
import path13 from "path";
|
|
5426
5831
|
import * as childProcess from "child_process";
|
|
5427
5832
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -5433,7 +5838,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
5433
5838
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
5434
5839
|
}
|
|
5435
5840
|
function resolveServerBinDetails(options = {}) {
|
|
5436
|
-
const existsSync4 = options.existsSync ??
|
|
5841
|
+
const existsSync4 = options.existsSync ?? fs25.existsSync;
|
|
5437
5842
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
5438
5843
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
5439
5844
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -5492,8 +5897,8 @@ function resolveServerBin(options = {}) {
|
|
|
5492
5897
|
return resolveServerBinDetails(options).path;
|
|
5493
5898
|
}
|
|
5494
5899
|
function readVerifiedDaemonPid(options) {
|
|
5495
|
-
const readFileSync4 = options.readFileSync ??
|
|
5496
|
-
const unlinkSync = options.unlinkSync ??
|
|
5900
|
+
const readFileSync4 = options.readFileSync ?? fs25.readFileSync;
|
|
5901
|
+
const unlinkSync = options.unlinkSync ?? fs25.unlinkSync;
|
|
5497
5902
|
const processKill = options.processKill ?? process.kill;
|
|
5498
5903
|
const platform = options.platform ?? process.platform;
|
|
5499
5904
|
const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
@@ -5593,8 +5998,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
5593
5998
|
}
|
|
5594
5999
|
}
|
|
5595
6000
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
5596
|
-
const existsSync4 = options.existsSync ??
|
|
5597
|
-
const readFileSync4 = options.readFileSync ??
|
|
6001
|
+
const existsSync4 = options.existsSync ?? fs25.existsSync;
|
|
6002
|
+
const readFileSync4 = options.readFileSync ?? fs25.readFileSync;
|
|
5598
6003
|
if (!existsSync4(plistPath)) {
|
|
5599
6004
|
return {
|
|
5600
6005
|
installed: false,
|
|
@@ -5772,7 +6177,7 @@ function stripConfigArgv(args) {
|
|
|
5772
6177
|
}
|
|
5773
6178
|
|
|
5774
6179
|
// src/import-dispatch.ts
|
|
5775
|
-
import
|
|
6180
|
+
import fs26 from "fs";
|
|
5776
6181
|
import {
|
|
5777
6182
|
runImporter,
|
|
5778
6183
|
validateImportBatchSize,
|
|
@@ -6292,7 +6697,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
6292
6697
|
let materializedTarget;
|
|
6293
6698
|
let materializePromise;
|
|
6294
6699
|
const io = {
|
|
6295
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
6700
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs26.promises.readFile(p, "utf-8")),
|
|
6296
6701
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
6297
6702
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
6298
6703
|
getWriteTarget: async () => {
|
|
@@ -6405,7 +6810,7 @@ async function cmdCapture(rest, io) {
|
|
|
6405
6810
|
}
|
|
6406
6811
|
|
|
6407
6812
|
// src/import-lossless-claw-cmd.ts
|
|
6408
|
-
import
|
|
6813
|
+
import fs27 from "fs";
|
|
6409
6814
|
import path15 from "path";
|
|
6410
6815
|
import {
|
|
6411
6816
|
applyLcmSchema,
|
|
@@ -6517,15 +6922,15 @@ async function loadImportLosslessClawModule() {
|
|
|
6517
6922
|
|
|
6518
6923
|
// src/import-lossless-claw-cmd.ts
|
|
6519
6924
|
function assertDirectoryOrAbsent(p, label) {
|
|
6520
|
-
if (
|
|
6925
|
+
if (fs27.existsSync(p) && !fs27.statSync(p).isDirectory()) {
|
|
6521
6926
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
6522
6927
|
}
|
|
6523
6928
|
}
|
|
6524
6929
|
function assertFile(p, label) {
|
|
6525
|
-
if (!
|
|
6930
|
+
if (!fs27.existsSync(p)) {
|
|
6526
6931
|
throw new Error(`${label} does not exist: ${p}`);
|
|
6527
6932
|
}
|
|
6528
|
-
if (!
|
|
6933
|
+
if (!fs27.statSync(p).isFile()) {
|
|
6529
6934
|
throw new Error(`${label} is not a file: ${p}`);
|
|
6530
6935
|
}
|
|
6531
6936
|
}
|
|
@@ -6557,7 +6962,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
6557
6962
|
try {
|
|
6558
6963
|
if (parsed.dryRun) {
|
|
6559
6964
|
const lcmPath = path15.join(memoryDir, "state", "lcm.sqlite");
|
|
6560
|
-
if (
|
|
6965
|
+
if (fs27.existsSync(lcmPath)) {
|
|
6561
6966
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
6562
6967
|
} else {
|
|
6563
6968
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -7909,7 +8314,7 @@ async function resolveAllBenchmarks() {
|
|
|
7909
8314
|
if (packageBenchmarks) {
|
|
7910
8315
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
7911
8316
|
}
|
|
7912
|
-
if (!
|
|
8317
|
+
if (!fs28.existsSync(EVAL_RUNNER_PATH)) {
|
|
7913
8318
|
return [];
|
|
7914
8319
|
}
|
|
7915
8320
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -7957,7 +8362,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
7957
8362
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
7958
8363
|
);
|
|
7959
8364
|
}
|
|
7960
|
-
if (!
|
|
8365
|
+
if (!fs28.existsSync(EVAL_RUNNER_PATH)) {
|
|
7961
8366
|
console.error(
|
|
7962
8367
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
7963
8368
|
);
|
|
@@ -7967,7 +8372,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
7967
8372
|
path19.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
7968
8373
|
path19.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
7969
8374
|
];
|
|
7970
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
8375
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs28.existsSync(candidate)) ?? "tsx";
|
|
7971
8376
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
7972
8377
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
7973
8378
|
benchmarkId,
|
|
@@ -8112,9 +8517,9 @@ var PERSONAMEM_COMPLETION_MARKER = path19.join(
|
|
|
8112
8517
|
);
|
|
8113
8518
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
8114
8519
|
try {
|
|
8115
|
-
const datasetRoot =
|
|
8520
|
+
const datasetRoot = fs28.realpathSync(datasetPath);
|
|
8116
8521
|
const candidatePath = path19.resolve(datasetRoot, relativePath);
|
|
8117
|
-
const candidateRealPath =
|
|
8522
|
+
const candidateRealPath = fs28.realpathSync(candidatePath);
|
|
8118
8523
|
const relativeToRoot = path19.relative(datasetRoot, candidateRealPath);
|
|
8119
8524
|
if (relativeToRoot.startsWith("..") || path19.isAbsolute(relativeToRoot)) {
|
|
8120
8525
|
return null;
|
|
@@ -8173,14 +8578,14 @@ function parseCsvRows(raw) {
|
|
|
8173
8578
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
8174
8579
|
try {
|
|
8175
8580
|
const completionMarkerPath = path19.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
8176
|
-
if (
|
|
8581
|
+
if (fs28.statSync(completionMarkerPath).isFile()) {
|
|
8177
8582
|
return true;
|
|
8178
8583
|
}
|
|
8179
8584
|
} catch {
|
|
8180
8585
|
}
|
|
8181
8586
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
8182
8587
|
try {
|
|
8183
|
-
return
|
|
8588
|
+
return fs28.statSync(path19.join(datasetPath, candidate)).isFile();
|
|
8184
8589
|
} catch {
|
|
8185
8590
|
return false;
|
|
8186
8591
|
}
|
|
@@ -8189,7 +8594,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8189
8594
|
return false;
|
|
8190
8595
|
}
|
|
8191
8596
|
try {
|
|
8192
|
-
const rows = parseCsvRows(
|
|
8597
|
+
const rows = parseCsvRows(fs28.readFileSync(path19.join(datasetPath, datasetFile), "utf8"));
|
|
8193
8598
|
if (rows.length < 2) {
|
|
8194
8599
|
return false;
|
|
8195
8600
|
}
|
|
@@ -8204,7 +8609,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8204
8609
|
}
|
|
8205
8610
|
return historyPaths.every((relativePath) => {
|
|
8206
8611
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
8207
|
-
return resolvedPath !== null &&
|
|
8612
|
+
return resolvedPath !== null && fs28.statSync(resolvedPath).isFile();
|
|
8208
8613
|
});
|
|
8209
8614
|
} catch {
|
|
8210
8615
|
return false;
|
|
@@ -8212,7 +8617,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8212
8617
|
}
|
|
8213
8618
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
8214
8619
|
try {
|
|
8215
|
-
return
|
|
8620
|
+
return fs28.statSync(path19.join(datasetPath, relativePath)).isFile();
|
|
8216
8621
|
} catch {
|
|
8217
8622
|
return false;
|
|
8218
8623
|
}
|
|
@@ -8232,10 +8637,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
8232
8637
|
return candidateFilenames.some((filename) => {
|
|
8233
8638
|
const filePath = path19.join(datasetPath, filename);
|
|
8234
8639
|
try {
|
|
8235
|
-
if (!
|
|
8640
|
+
if (!fs28.statSync(filePath).isFile()) {
|
|
8236
8641
|
return false;
|
|
8237
8642
|
}
|
|
8238
|
-
const raw =
|
|
8643
|
+
const raw = fs28.readFileSync(filePath, "utf8");
|
|
8239
8644
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
8240
8645
|
} catch {
|
|
8241
8646
|
return false;
|
|
@@ -8251,7 +8656,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
8251
8656
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
8252
8657
|
let stats;
|
|
8253
8658
|
try {
|
|
8254
|
-
stats =
|
|
8659
|
+
stats = fs28.statSync(datasetPath);
|
|
8255
8660
|
} catch {
|
|
8256
8661
|
return false;
|
|
8257
8662
|
}
|
|
@@ -8261,7 +8666,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8261
8666
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
8262
8667
|
if (!marker) {
|
|
8263
8668
|
try {
|
|
8264
|
-
return
|
|
8669
|
+
return fs28.readdirSync(datasetPath).length > 0;
|
|
8265
8670
|
} catch {
|
|
8266
8671
|
return false;
|
|
8267
8672
|
}
|
|
@@ -8269,7 +8674,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8269
8674
|
if (marker.allOf) {
|
|
8270
8675
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
8271
8676
|
try {
|
|
8272
|
-
return
|
|
8677
|
+
return fs28.statSync(path19.join(datasetPath, name)).isFile();
|
|
8273
8678
|
} catch {
|
|
8274
8679
|
return false;
|
|
8275
8680
|
}
|
|
@@ -8281,7 +8686,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8281
8686
|
if (marker.anyOf) {
|
|
8282
8687
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
8283
8688
|
try {
|
|
8284
|
-
return
|
|
8689
|
+
return fs28.statSync(path19.join(datasetPath, name)).isFile();
|
|
8285
8690
|
} catch {
|
|
8286
8691
|
return false;
|
|
8287
8692
|
}
|
|
@@ -8299,7 +8704,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8299
8704
|
}
|
|
8300
8705
|
if (marker.ext) {
|
|
8301
8706
|
try {
|
|
8302
|
-
return
|
|
8707
|
+
return fs28.readdirSync(datasetPath).some(
|
|
8303
8708
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
8304
8709
|
);
|
|
8305
8710
|
} catch {
|
|
@@ -8311,7 +8716,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8311
8716
|
async function launchBenchUi(resultsDir) {
|
|
8312
8717
|
const benchUiDir = path19.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
8313
8718
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
8314
|
-
if (!
|
|
8719
|
+
if (!fs28.existsSync(path19.join(benchUiDir, "package.json"))) {
|
|
8315
8720
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
8316
8721
|
process.exit(1);
|
|
8317
8722
|
}
|
|
@@ -8349,13 +8754,13 @@ function listDownloadableBenchmarks() {
|
|
|
8349
8754
|
}
|
|
8350
8755
|
function resolveDatasetDownloadScriptPath() {
|
|
8351
8756
|
const bundled = path19.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
8352
|
-
if (
|
|
8757
|
+
if (fs28.existsSync(bundled)) {
|
|
8353
8758
|
return bundled;
|
|
8354
8759
|
}
|
|
8355
8760
|
return path19.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
8356
8761
|
}
|
|
8357
8762
|
function isRepoCheckout() {
|
|
8358
|
-
return
|
|
8763
|
+
return fs28.existsSync(path19.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs28.existsSync(path19.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
8359
8764
|
}
|
|
8360
8765
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
8361
8766
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -8668,8 +9073,8 @@ async function exportBenchPackageResult(parsed) {
|
|
|
8668
9073
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
8669
9074
|
});
|
|
8670
9075
|
if (parsed.output) {
|
|
8671
|
-
|
|
8672
|
-
|
|
9076
|
+
fs28.mkdirSync(path19.dirname(parsed.output), { recursive: true });
|
|
9077
|
+
fs28.writeFileSync(parsed.output, rendered);
|
|
8673
9078
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
8674
9079
|
return;
|
|
8675
9080
|
}
|
|
@@ -8714,7 +9119,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
8714
9119
|
process.exit(1);
|
|
8715
9120
|
}
|
|
8716
9121
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
8717
|
-
if (!
|
|
9122
|
+
if (!fs28.existsSync(scriptPath)) {
|
|
8718
9123
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
8719
9124
|
process.exit(1);
|
|
8720
9125
|
}
|
|
@@ -8914,7 +9319,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
8914
9319
|
);
|
|
8915
9320
|
process.exit(1);
|
|
8916
9321
|
}
|
|
8917
|
-
const sourceResultSha256 = createHash4("sha256").update(
|
|
9322
|
+
const sourceResultSha256 = createHash4("sha256").update(fs28.readFileSync(latest.path)).digest("hex");
|
|
8918
9323
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
8919
9324
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
8920
9325
|
console.error(
|
|
@@ -9329,7 +9734,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
9329
9734
|
}
|
|
9330
9735
|
let decoded;
|
|
9331
9736
|
try {
|
|
9332
|
-
decoded = JSON.parse(
|
|
9737
|
+
decoded = JSON.parse(fs28.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
9333
9738
|
} catch (error) {
|
|
9334
9739
|
throw new Error(
|
|
9335
9740
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -10004,7 +10409,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
10004
10409
|
return void 0;
|
|
10005
10410
|
}
|
|
10006
10411
|
try {
|
|
10007
|
-
return
|
|
10412
|
+
return fs28.realpathSync(datasetDir);
|
|
10008
10413
|
} catch {
|
|
10009
10414
|
return datasetDir;
|
|
10010
10415
|
}
|
|
@@ -10058,13 +10463,13 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
10058
10463
|
}
|
|
10059
10464
|
function loadStandaloneConvergeCommandConfig() {
|
|
10060
10465
|
const configPath = resolveConfigPath();
|
|
10061
|
-
const raw =
|
|
10062
|
-
return
|
|
10466
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
10467
|
+
return parseConfig17(resolveRemnicConfigRecord16(raw));
|
|
10063
10468
|
}
|
|
10064
10469
|
function parseConvergePluginConfig(value) {
|
|
10065
10470
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
10066
10471
|
if (Object.keys(value).length === 0) return void 0;
|
|
10067
|
-
return
|
|
10472
|
+
return parseConfig17(resolveRemnicConfigRecord16(value));
|
|
10068
10473
|
}
|
|
10069
10474
|
function loadConvergeCommandConfig() {
|
|
10070
10475
|
if (readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH")) {
|
|
@@ -10087,13 +10492,13 @@ function resolveConfigPath(cliPath) {
|
|
|
10087
10492
|
path19.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
10088
10493
|
];
|
|
10089
10494
|
for (const candidate of candidates) {
|
|
10090
|
-
if (
|
|
10495
|
+
if (fs28.existsSync(candidate)) return candidate;
|
|
10091
10496
|
}
|
|
10092
10497
|
return path19.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
10093
10498
|
}
|
|
10094
10499
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
10095
10500
|
const configPath = resolveConfigPath(cliPath);
|
|
10096
|
-
if (
|
|
10501
|
+
if (fs28.existsSync(configPath)) {
|
|
10097
10502
|
return configPath;
|
|
10098
10503
|
}
|
|
10099
10504
|
if (cliPath) {
|
|
@@ -10103,7 +10508,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
10103
10508
|
}
|
|
10104
10509
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
10105
10510
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
10106
|
-
if (
|
|
10511
|
+
if (fs28.existsSync(configPath)) {
|
|
10107
10512
|
return configPath;
|
|
10108
10513
|
}
|
|
10109
10514
|
if (cliPath) {
|
|
@@ -10210,8 +10615,8 @@ function resolveMemoryDir() {
|
|
|
10210
10615
|
const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
10211
10616
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
10212
10617
|
const configPath = resolveConfigPath();
|
|
10213
|
-
const raw =
|
|
10214
|
-
const remnicCfg =
|
|
10618
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
10619
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
10215
10620
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
10216
10621
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
10217
10622
|
}
|
|
@@ -10219,18 +10624,18 @@ function resolveMemoryDir() {
|
|
|
10219
10624
|
const standalonePath = path19.join(home, ".remnic", "memory");
|
|
10220
10625
|
const legacyStandalonePath = path19.join(home, ".engram", "memory");
|
|
10221
10626
|
const openclawPath = path19.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
10222
|
-
if (
|
|
10223
|
-
if (
|
|
10627
|
+
if (fs28.existsSync(standalonePath)) return standalonePath;
|
|
10628
|
+
if (fs28.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
10224
10629
|
return openclawPath;
|
|
10225
10630
|
})();
|
|
10226
10631
|
const manifestPath = getManifestPath();
|
|
10227
|
-
if (
|
|
10632
|
+
if (fs28.existsSync(manifestPath)) {
|
|
10228
10633
|
try {
|
|
10229
10634
|
const active = getActiveSpace();
|
|
10230
10635
|
if (active?.memoryDir) {
|
|
10231
10636
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
10232
|
-
if (!
|
|
10233
|
-
|
|
10637
|
+
if (!fs28.existsSync(activeMemoryDir)) {
|
|
10638
|
+
fs28.mkdirSync(activeMemoryDir, { recursive: true });
|
|
10234
10639
|
}
|
|
10235
10640
|
return activeMemoryDir;
|
|
10236
10641
|
}
|
|
@@ -10279,13 +10684,13 @@ function resolveOpenclawConfigPath(cliPath) {
|
|
|
10279
10684
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
10280
10685
|
if (envPath) return path19.resolve(expandTilde(envPath));
|
|
10281
10686
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
10282
|
-
if (
|
|
10687
|
+
if (fs28.existsSync(candidate)) return candidate;
|
|
10283
10688
|
}
|
|
10284
10689
|
return path19.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
10285
10690
|
}
|
|
10286
10691
|
function readOpenclawConfig(configPath) {
|
|
10287
|
-
if (!
|
|
10288
|
-
const raw =
|
|
10692
|
+
if (!fs28.existsSync(configPath)) return {};
|
|
10693
|
+
const raw = fs28.readFileSync(configPath, "utf-8");
|
|
10289
10694
|
let parsed;
|
|
10290
10695
|
try {
|
|
10291
10696
|
parsed = JSON.parse(raw);
|
|
@@ -10387,9 +10792,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
10387
10792
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
10388
10793
|
}
|
|
10389
10794
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
10390
|
-
if (!
|
|
10391
|
-
|
|
10392
|
-
|
|
10795
|
+
if (!fs28.existsSync(sourcePath)) return false;
|
|
10796
|
+
fs28.mkdirSync(path19.dirname(backupPath), { recursive: true });
|
|
10797
|
+
fs28.cpSync(sourcePath, backupPath, { recursive: true });
|
|
10393
10798
|
return true;
|
|
10394
10799
|
}
|
|
10395
10800
|
function restartOpenclawGateway() {
|
|
@@ -10408,7 +10813,7 @@ function restartOpenclawGateway() {
|
|
|
10408
10813
|
}
|
|
10409
10814
|
function cmdInit() {
|
|
10410
10815
|
const configPath = path19.join(process.cwd(), "remnic.config.json");
|
|
10411
|
-
if (
|
|
10816
|
+
if (fs28.existsSync(configPath)) {
|
|
10412
10817
|
console.log(`Config already exists: ${configPath}`);
|
|
10413
10818
|
return;
|
|
10414
10819
|
}
|
|
@@ -10424,7 +10829,7 @@ function cmdInit() {
|
|
|
10424
10829
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
10425
10830
|
}
|
|
10426
10831
|
};
|
|
10427
|
-
|
|
10832
|
+
fs28.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
10428
10833
|
console.log(`Created ${configPath}`);
|
|
10429
10834
|
console.log("\nSet these environment variables:");
|
|
10430
10835
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -10846,9 +11251,9 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
10846
11251
|
}
|
|
10847
11252
|
initLogger5();
|
|
10848
11253
|
const configPath = resolveConfigPath();
|
|
10849
|
-
const raw =
|
|
10850
|
-
const remnicCfg =
|
|
10851
|
-
const config =
|
|
11254
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11255
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11256
|
+
const config = parseConfig17(remnicCfg);
|
|
10852
11257
|
const orchestrator = new Orchestrator10(config);
|
|
10853
11258
|
await orchestrator.initialize();
|
|
10854
11259
|
const service = new EngramAccessService2(orchestrator);
|
|
@@ -11026,9 +11431,9 @@ async function cmdXray(rest) {
|
|
|
11026
11431
|
}
|
|
11027
11432
|
initLogger5();
|
|
11028
11433
|
const configPath = resolveConfigPath();
|
|
11029
|
-
const raw =
|
|
11030
|
-
const remnicCfg =
|
|
11031
|
-
const config =
|
|
11434
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11435
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11436
|
+
const config = parseConfig17(remnicCfg);
|
|
11032
11437
|
const orchestrator = new Orchestrator10(config);
|
|
11033
11438
|
await orchestrator.initialize();
|
|
11034
11439
|
await orchestrator.deferredReady;
|
|
@@ -11059,8 +11464,8 @@ async function runWhoKnowsCommand(rest, io) {
|
|
|
11059
11464
|
async function withLocalService(fn) {
|
|
11060
11465
|
initLogger5();
|
|
11061
11466
|
const configPath = resolveConfigPath();
|
|
11062
|
-
const raw =
|
|
11063
|
-
const orchestrator = new Orchestrator10(
|
|
11467
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11468
|
+
const orchestrator = new Orchestrator10(parseConfig17(resolveRemnicConfigRecord16(raw)));
|
|
11064
11469
|
await orchestrator.initialize();
|
|
11065
11470
|
await orchestrator.deferredReady;
|
|
11066
11471
|
const service = new EngramAccessService2(orchestrator);
|
|
@@ -11092,9 +11497,9 @@ async function cmdPromotionCandidates(rest) {
|
|
|
11092
11497
|
async function cmdVersions(rest) {
|
|
11093
11498
|
initLogger5();
|
|
11094
11499
|
const configPath = resolveConfigPath();
|
|
11095
|
-
const raw =
|
|
11096
|
-
const remnicCfg =
|
|
11097
|
-
const config =
|
|
11500
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11501
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11502
|
+
const config = parseConfig17(remnicCfg);
|
|
11098
11503
|
if (!config.versioningEnabled) {
|
|
11099
11504
|
console.error("Page versioning is disabled (versioningEnabled = false).");
|
|
11100
11505
|
process.exit(1);
|
|
@@ -11208,9 +11613,9 @@ Options:
|
|
|
11208
11613
|
async function cmdEnrich(rest) {
|
|
11209
11614
|
initLogger5();
|
|
11210
11615
|
const configPath = resolveConfigPath();
|
|
11211
|
-
const raw =
|
|
11212
|
-
const remnicCfg =
|
|
11213
|
-
const config =
|
|
11616
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11617
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11618
|
+
const config = parseConfig17(remnicCfg);
|
|
11214
11619
|
const subcommand = rest[0];
|
|
11215
11620
|
if (subcommand === "audit") {
|
|
11216
11621
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
@@ -11402,9 +11807,9 @@ Registered providers:`);
|
|
|
11402
11807
|
async function cmdExtensions(action, rest) {
|
|
11403
11808
|
initLogger5();
|
|
11404
11809
|
const configPath = resolveConfigPath();
|
|
11405
|
-
const raw =
|
|
11406
|
-
const remnicCfg =
|
|
11407
|
-
const config =
|
|
11810
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11811
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11812
|
+
const config = parseConfig17(remnicCfg);
|
|
11408
11813
|
const root = resolveExtensionsRoot(config);
|
|
11409
11814
|
const noopLog = { warn: () => {
|
|
11410
11815
|
}, debug: () => {
|
|
@@ -11453,7 +11858,7 @@ Root: ${root}`);
|
|
|
11453
11858
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
11454
11859
|
let entries = [];
|
|
11455
11860
|
try {
|
|
11456
|
-
entries =
|
|
11861
|
+
entries = fs28.readdirSync(root);
|
|
11457
11862
|
} catch {
|
|
11458
11863
|
console.log(`Extensions root does not exist: ${root}`);
|
|
11459
11864
|
process.exitCode = 0;
|
|
@@ -11464,7 +11869,7 @@ Root: ${root}`);
|
|
|
11464
11869
|
for (const entry of entries) {
|
|
11465
11870
|
const entryPath = path19.join(root, entry);
|
|
11466
11871
|
try {
|
|
11467
|
-
if (!
|
|
11872
|
+
if (!fs28.statSync(entryPath).isDirectory()) continue;
|
|
11468
11873
|
} catch {
|
|
11469
11874
|
continue;
|
|
11470
11875
|
}
|
|
@@ -11496,9 +11901,9 @@ Root: ${root}`);
|
|
|
11496
11901
|
async function cmdBriefing(rest) {
|
|
11497
11902
|
initLogger5();
|
|
11498
11903
|
const configPath = resolveConfigPath();
|
|
11499
|
-
const raw =
|
|
11500
|
-
const remnicCfg =
|
|
11501
|
-
const config =
|
|
11904
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11905
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11906
|
+
const config = parseConfig17(remnicCfg);
|
|
11502
11907
|
if (!config.briefing.enabled) {
|
|
11503
11908
|
console.error("Briefing is disabled in config (briefing.enabled = false).");
|
|
11504
11909
|
process.exit(1);
|
|
@@ -11576,10 +11981,10 @@ async function cmdBriefing(rest) {
|
|
|
11576
11981
|
if (save) {
|
|
11577
11982
|
try {
|
|
11578
11983
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
11579
|
-
|
|
11984
|
+
fs28.mkdirSync(saveDir, { recursive: true });
|
|
11580
11985
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
11581
11986
|
const filePath = path19.join(saveDir, filename);
|
|
11582
|
-
|
|
11987
|
+
fs28.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
11583
11988
|
console.error(`Saved briefing: ${filePath}`);
|
|
11584
11989
|
} catch (err) {
|
|
11585
11990
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -11597,7 +12002,7 @@ async function cmdDoctor() {
|
|
|
11597
12002
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
11598
12003
|
});
|
|
11599
12004
|
const configPath = resolveConfigPath();
|
|
11600
|
-
const configExists =
|
|
12005
|
+
const configExists = fs28.existsSync(configPath);
|
|
11601
12006
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
11602
12007
|
let standaloneConfig;
|
|
11603
12008
|
let standaloneConfigError;
|
|
@@ -11605,11 +12010,11 @@ async function cmdDoctor() {
|
|
|
11605
12010
|
let configuredNs = { invalid: false };
|
|
11606
12011
|
if (configExists) {
|
|
11607
12012
|
try {
|
|
11608
|
-
const raw = JSON.parse(
|
|
11609
|
-
const remnicCfg =
|
|
12013
|
+
const raw = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
12014
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11610
12015
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
11611
12016
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
11612
|
-
standaloneConfig =
|
|
12017
|
+
standaloneConfig = parseConfig17(remnicCfg);
|
|
11613
12018
|
} catch (err) {
|
|
11614
12019
|
standaloneConfigError = err instanceof Error ? err.message : String(err);
|
|
11615
12020
|
}
|
|
@@ -11618,10 +12023,10 @@ async function cmdDoctor() {
|
|
|
11618
12023
|
try {
|
|
11619
12024
|
memoryDir = resolveMemoryDir();
|
|
11620
12025
|
} catch {
|
|
11621
|
-
memoryDir =
|
|
12026
|
+
memoryDir = parseConfig17({}).memoryDir;
|
|
11622
12027
|
}
|
|
11623
12028
|
try {
|
|
11624
|
-
|
|
12029
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
11625
12030
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
11626
12031
|
} catch {
|
|
11627
12032
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -11650,7 +12055,7 @@ async function cmdDoctor() {
|
|
|
11650
12055
|
});
|
|
11651
12056
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
11652
12057
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
11653
|
-
const openclawConfigExists =
|
|
12058
|
+
const openclawConfigExists = fs28.existsSync(openclawConfigPath);
|
|
11654
12059
|
let openclawConfig = {};
|
|
11655
12060
|
let openclawConfigValid = false;
|
|
11656
12061
|
let openclawPluginModeConfigured = false;
|
|
@@ -11658,7 +12063,7 @@ async function cmdDoctor() {
|
|
|
11658
12063
|
let activeOpenclawEntryConfig = null;
|
|
11659
12064
|
if (openclawConfigExists) {
|
|
11660
12065
|
try {
|
|
11661
|
-
const parsed = JSON.parse(
|
|
12066
|
+
const parsed = JSON.parse(fs28.readFileSync(openclawConfigPath, "utf-8"));
|
|
11662
12067
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
11663
12068
|
openclawConfig = parsed;
|
|
11664
12069
|
openclawConfigValid = true;
|
|
@@ -11738,9 +12143,9 @@ async function cmdDoctor() {
|
|
|
11738
12143
|
let memDirOk = false;
|
|
11739
12144
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
11740
12145
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
11741
|
-
if (
|
|
12146
|
+
if (fs28.existsSync(resolvedMemDir)) {
|
|
11742
12147
|
try {
|
|
11743
|
-
const stat2 =
|
|
12148
|
+
const stat2 = fs28.statSync(resolvedMemDir);
|
|
11744
12149
|
if (stat2.isDirectory()) {
|
|
11745
12150
|
memDirOk = true;
|
|
11746
12151
|
memDirDetail = resolvedMemDir;
|
|
@@ -11895,12 +12300,12 @@ async function cmdDoctor() {
|
|
|
11895
12300
|
}
|
|
11896
12301
|
function cmdConfig() {
|
|
11897
12302
|
const configPath = resolveConfigPath();
|
|
11898
|
-
if (!
|
|
12303
|
+
if (!fs28.existsSync(configPath)) {
|
|
11899
12304
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
11900
12305
|
return;
|
|
11901
12306
|
}
|
|
11902
12307
|
console.log(`Config: ${configPath}`);
|
|
11903
|
-
const rawConfig =
|
|
12308
|
+
const rawConfig = fs28.readFileSync(configPath, "utf8");
|
|
11904
12309
|
const redacted = rawConfig.replace(
|
|
11905
12310
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
11906
12311
|
"$1[REDACTED]$3"
|
|
@@ -12008,9 +12413,9 @@ async function cmdReview(action, rest) {
|
|
|
12008
12413
|
const configPath = resolveConfigPath();
|
|
12009
12414
|
let tombstonesConfig = null;
|
|
12010
12415
|
try {
|
|
12011
|
-
const rawCfg =
|
|
12012
|
-
const remnicCfg =
|
|
12013
|
-
const config =
|
|
12416
|
+
const rawCfg = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
12417
|
+
const remnicCfg = resolveRemnicConfigRecord16(rawCfg);
|
|
12418
|
+
const config = parseConfig17(remnicCfg);
|
|
12014
12419
|
tombstonesConfig = {
|
|
12015
12420
|
enabled: config.tombstonesEnabled,
|
|
12016
12421
|
semanticMatch: config.tombstonesSemanticMatch,
|
|
@@ -12752,7 +13157,7 @@ async function pushOfflineFileContent(args) {
|
|
|
12752
13157
|
}
|
|
12753
13158
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
12754
13159
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
12755
|
-
const stat2 =
|
|
13160
|
+
const stat2 = fs28.statSync(filePath);
|
|
12756
13161
|
if (stat2.mtimeMs !== args.file.mtimeMs) {
|
|
12757
13162
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
12758
13163
|
}
|
|
@@ -13243,7 +13648,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
13243
13648
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
13244
13649
|
}
|
|
13245
13650
|
async function runOfflineSyncOnce(options) {
|
|
13246
|
-
|
|
13651
|
+
fs28.mkdirSync(options.memoryDir, { recursive: true });
|
|
13247
13652
|
let activeStatePath = options.statePath;
|
|
13248
13653
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
13249
13654
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -13876,7 +14281,7 @@ Environment fallbacks:
|
|
|
13876
14281
|
const configPath = resolveConfigPath();
|
|
13877
14282
|
let config;
|
|
13878
14283
|
try {
|
|
13879
|
-
const rawConfig =
|
|
14284
|
+
const rawConfig = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
13880
14285
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
13881
14286
|
} catch {
|
|
13882
14287
|
throw new Error(
|
|
@@ -13891,7 +14296,7 @@ Environment fallbacks:
|
|
|
13891
14296
|
const statePath = statePathExplicit ? path19.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
13892
14297
|
if (action === "prepare") {
|
|
13893
14298
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
13894
|
-
|
|
14299
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
13895
14300
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
13896
14301
|
remoteUrl,
|
|
13897
14302
|
token,
|
|
@@ -13990,7 +14395,7 @@ Environment fallbacks:
|
|
|
13990
14395
|
return;
|
|
13991
14396
|
}
|
|
13992
14397
|
if (action === "status") {
|
|
13993
|
-
|
|
14398
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
13994
14399
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
13995
14400
|
if (state && remoteUrl && statePath) {
|
|
13996
14401
|
assertOfflineStateMatches({
|
|
@@ -14128,7 +14533,7 @@ function cmdDedup(json) {
|
|
|
14128
14533
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
14129
14534
|
if (!configPath) return fallback;
|
|
14130
14535
|
try {
|
|
14131
|
-
const parsed = JSON.parse(
|
|
14536
|
+
const parsed = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
14132
14537
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
14133
14538
|
const { token: _token, ...config } = parsed;
|
|
14134
14539
|
return config;
|
|
@@ -14306,7 +14711,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14306
14711
|
const pub = factory();
|
|
14307
14712
|
const available = await pub.isHostAvailable();
|
|
14308
14713
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
14309
|
-
const extensionExists = available && extRoot ?
|
|
14714
|
+
const extensionExists = available && extRoot ? fs28.existsSync(extRoot) : false;
|
|
14310
14715
|
publisherChecks.push({
|
|
14311
14716
|
name: `Publisher: ${targetHostId}`,
|
|
14312
14717
|
ok: !available || extensionExists,
|
|
@@ -14380,7 +14785,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14380
14785
|
let connectorsCfg;
|
|
14381
14786
|
const configPath = resolveConfigPath();
|
|
14382
14787
|
try {
|
|
14383
|
-
const raw =
|
|
14788
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14384
14789
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
14385
14790
|
} catch {
|
|
14386
14791
|
process.stderr.write(
|
|
@@ -14456,9 +14861,9 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14456
14861
|
}
|
|
14457
14862
|
initLogger5();
|
|
14458
14863
|
const configPath = resolveConfigPath();
|
|
14459
|
-
const raw =
|
|
14460
|
-
const remnicCfg =
|
|
14461
|
-
const config =
|
|
14864
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14865
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
14866
|
+
const config = parseConfig17(remnicCfg);
|
|
14462
14867
|
const orchestrator = new Orchestrator10(config);
|
|
14463
14868
|
try {
|
|
14464
14869
|
await orchestrator.initialize();
|
|
@@ -14581,9 +14986,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
14581
14986
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
14582
14987
|
process.exit(1);
|
|
14583
14988
|
}
|
|
14584
|
-
const rawConfig =
|
|
14585
|
-
const pluginConfig =
|
|
14586
|
-
const config =
|
|
14989
|
+
const rawConfig = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14990
|
+
const pluginConfig = resolveRemnicConfigRecord16(rawConfig);
|
|
14991
|
+
const config = parseConfig17(pluginConfig);
|
|
14587
14992
|
if (subAction === "generate") {
|
|
14588
14993
|
let outputDir;
|
|
14589
14994
|
try {
|
|
@@ -14603,13 +15008,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
14603
15008
|
} else if (subAction === "validate") {
|
|
14604
15009
|
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path19.join(process.cwd(), "marketplace.json");
|
|
14605
15010
|
const resolved = path19.resolve(targetPath);
|
|
14606
|
-
if (!
|
|
15011
|
+
if (!fs28.existsSync(resolved)) {
|
|
14607
15012
|
console.error(`File not found: ${resolved}`);
|
|
14608
15013
|
process.exit(1);
|
|
14609
15014
|
}
|
|
14610
15015
|
let parsed;
|
|
14611
15016
|
try {
|
|
14612
|
-
parsed = JSON.parse(
|
|
15017
|
+
parsed = JSON.parse(fs28.readFileSync(resolved, "utf8"));
|
|
14613
15018
|
} catch {
|
|
14614
15019
|
console.error(`Invalid JSON in ${resolved}`);
|
|
14615
15020
|
process.exit(1);
|
|
@@ -14812,9 +15217,9 @@ async function cmdSpace(action, rest, json) {
|
|
|
14812
15217
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
14813
15218
|
initLogger5();
|
|
14814
15219
|
const configPath = resolveConfigPath();
|
|
14815
|
-
const raw =
|
|
14816
|
-
const remnicCfg =
|
|
14817
|
-
const config =
|
|
15220
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
15221
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15222
|
+
const config = parseConfig17(remnicCfg);
|
|
14818
15223
|
const orchestrator = new Orchestrator10(config);
|
|
14819
15224
|
const service = new EngramAccessService2(orchestrator);
|
|
14820
15225
|
const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
|
|
@@ -15217,7 +15622,7 @@ function readPid() {
|
|
|
15217
15622
|
function inferPort() {
|
|
15218
15623
|
try {
|
|
15219
15624
|
const configPath = resolveConfigPath();
|
|
15220
|
-
const raw = JSON.parse(
|
|
15625
|
+
const raw = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
15221
15626
|
return raw.server?.port ?? 4318;
|
|
15222
15627
|
} catch {
|
|
15223
15628
|
return 4318;
|
|
@@ -15312,13 +15717,13 @@ function daemonInstall() {
|
|
|
15312
15717
|
process.exit(1);
|
|
15313
15718
|
}
|
|
15314
15719
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
15315
|
-
|
|
15720
|
+
fs28.mkdirSync(LOGS_DIR, { recursive: true });
|
|
15316
15721
|
if (isMacOS()) {
|
|
15317
15722
|
const templatePath = path19.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
15318
|
-
const template =
|
|
15723
|
+
const template = fs28.readFileSync(templatePath, "utf8");
|
|
15319
15724
|
const plist = renderTemplate(template, vars);
|
|
15320
|
-
|
|
15321
|
-
|
|
15725
|
+
fs28.mkdirSync(path19.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
15726
|
+
fs28.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
15322
15727
|
try {
|
|
15323
15728
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
15324
15729
|
} catch (err) {
|
|
@@ -15335,10 +15740,10 @@ function daemonInstall() {
|
|
|
15335
15740
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
15336
15741
|
} else if (isLinux()) {
|
|
15337
15742
|
const templatePath = path19.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
15338
|
-
const template =
|
|
15743
|
+
const template = fs28.readFileSync(templatePath, "utf8");
|
|
15339
15744
|
const unit = renderTemplate(template, vars);
|
|
15340
|
-
|
|
15341
|
-
|
|
15745
|
+
fs28.mkdirSync(path19.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
15746
|
+
fs28.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
15342
15747
|
try {
|
|
15343
15748
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
15344
15749
|
} catch (err) {
|
|
@@ -15374,7 +15779,7 @@ function daemonUninstall() {
|
|
|
15374
15779
|
} catch {
|
|
15375
15780
|
}
|
|
15376
15781
|
try {
|
|
15377
|
-
|
|
15782
|
+
fs28.unlinkSync(plistPath);
|
|
15378
15783
|
removed = true;
|
|
15379
15784
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
15380
15785
|
} catch {
|
|
@@ -15394,7 +15799,7 @@ function daemonUninstall() {
|
|
|
15394
15799
|
let removed = false;
|
|
15395
15800
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
15396
15801
|
try {
|
|
15397
|
-
|
|
15802
|
+
fs28.unlinkSync(unitPath);
|
|
15398
15803
|
removed = true;
|
|
15399
15804
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
15400
15805
|
} catch {
|
|
@@ -15461,13 +15866,13 @@ async function daemonStatus() {
|
|
|
15461
15866
|
console.log(` Port: ${port}`);
|
|
15462
15867
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
15463
15868
|
console.log(` Platform: ${process.platform}`);
|
|
15464
|
-
console.log(` PID file: ${
|
|
15465
|
-
console.log(` Log file: ${
|
|
15869
|
+
console.log(` PID file: ${fs28.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
15870
|
+
console.log(` Log file: ${fs28.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
15466
15871
|
try {
|
|
15467
15872
|
const configPath = resolveConfigPath();
|
|
15468
|
-
const raw =
|
|
15469
|
-
const remnicCfg =
|
|
15470
|
-
const config =
|
|
15873
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
15874
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15875
|
+
const config = parseConfig17(remnicCfg);
|
|
15471
15876
|
const extRoot = resolveExtensionsRoot(config);
|
|
15472
15877
|
const noopLog = { warn: () => {
|
|
15473
15878
|
}, debug: () => {
|
|
@@ -15506,9 +15911,9 @@ function daemonStart() {
|
|
|
15506
15911
|
return;
|
|
15507
15912
|
}
|
|
15508
15913
|
}
|
|
15509
|
-
|
|
15510
|
-
|
|
15511
|
-
const logStream =
|
|
15914
|
+
fs28.mkdirSync(PID_DIR, { recursive: true });
|
|
15915
|
+
fs28.mkdirSync(LOGS_DIR, { recursive: true });
|
|
15916
|
+
const logStream = fs28.openSync(LOG_FILE, "a");
|
|
15512
15917
|
const serverBin = resolveServerBin();
|
|
15513
15918
|
const isSource = serverBin.endsWith(".ts");
|
|
15514
15919
|
let cmd;
|
|
@@ -15530,7 +15935,7 @@ function daemonStart() {
|
|
|
15530
15935
|
}
|
|
15531
15936
|
});
|
|
15532
15937
|
child.unref();
|
|
15533
|
-
|
|
15938
|
+
fs28.writeFileSync(PID_FILE, String(child.pid));
|
|
15534
15939
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
15535
15940
|
console.log(` Log: ${LOG_FILE}`);
|
|
15536
15941
|
}
|
|
@@ -15564,11 +15969,11 @@ function daemonStop() {
|
|
|
15564
15969
|
console.log("Process not found (cleaning up PID file)");
|
|
15565
15970
|
}
|
|
15566
15971
|
try {
|
|
15567
|
-
|
|
15972
|
+
fs28.unlinkSync(PID_FILE);
|
|
15568
15973
|
} catch {
|
|
15569
15974
|
}
|
|
15570
15975
|
try {
|
|
15571
|
-
|
|
15976
|
+
fs28.unlinkSync(LEGACY_PID_FILE);
|
|
15572
15977
|
} catch {
|
|
15573
15978
|
}
|
|
15574
15979
|
}
|
|
@@ -15696,9 +16101,9 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
15696
16101
|
async function cmdBinary(rest) {
|
|
15697
16102
|
initLogger5();
|
|
15698
16103
|
const configPath = resolveConfigPath();
|
|
15699
|
-
const raw =
|
|
15700
|
-
const remnicCfg =
|
|
15701
|
-
const config =
|
|
16104
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
16105
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16106
|
+
const config = parseConfig17(remnicCfg);
|
|
15702
16107
|
const memoryDir = resolveMemoryDir();
|
|
15703
16108
|
const blConfig = {
|
|
15704
16109
|
enabled: config.binaryLifecycleEnabled,
|
|
@@ -15887,7 +16292,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
15887
16292
|
} else if (slotIsActiveLegacy) {
|
|
15888
16293
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
15889
16294
|
}
|
|
15890
|
-
if (!
|
|
16295
|
+
if (!fs28.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
15891
16296
|
if (hasLegacy && migrateLegacy) {
|
|
15892
16297
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
15893
16298
|
}
|
|
@@ -15907,8 +16312,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
15907
16312
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
15908
16313
|
return;
|
|
15909
16314
|
}
|
|
15910
|
-
if (
|
|
15911
|
-
const st =
|
|
16315
|
+
if (fs28.existsSync(memoryDir)) {
|
|
16316
|
+
const st = fs28.statSync(memoryDir);
|
|
15912
16317
|
if (!st.isDirectory()) {
|
|
15913
16318
|
throw new Error(
|
|
15914
16319
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -15916,12 +16321,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
15916
16321
|
);
|
|
15917
16322
|
}
|
|
15918
16323
|
} else {
|
|
15919
|
-
|
|
16324
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
15920
16325
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
15921
16326
|
}
|
|
15922
16327
|
const configDir = path19.dirname(configPath);
|
|
15923
|
-
if (!
|
|
15924
|
-
|
|
16328
|
+
if (!fs28.existsSync(configDir)) {
|
|
16329
|
+
fs28.mkdirSync(configDir, { recursive: true });
|
|
15925
16330
|
}
|
|
15926
16331
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
15927
16332
|
console.log("\nDone! Summary of changes:");
|
|
@@ -15950,7 +16355,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15950
16355
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
15951
16356
|
const fallbackMemoryDir = path19.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
15952
16357
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
15953
|
-
const configExistedBefore =
|
|
16358
|
+
const configExistedBefore = fs28.existsSync(configPath);
|
|
15954
16359
|
const existingConfig = readOpenclawConfig(configPath);
|
|
15955
16360
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
15956
16361
|
const preservedMemoryDir = opts.memoryDir ? path19.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
@@ -16175,15 +16580,15 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
16175
16580
|
}
|
|
16176
16581
|
function createOpenclawUpgradeBackupDir() {
|
|
16177
16582
|
const backupsRoot = path19.join(resolveOpenclawStateDir(), "backups");
|
|
16178
|
-
|
|
16179
|
-
return
|
|
16583
|
+
fs28.mkdirSync(backupsRoot, { recursive: true });
|
|
16584
|
+
return fs28.mkdtempSync(path19.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
16180
16585
|
}
|
|
16181
16586
|
async function cmdTaxonomy(rest) {
|
|
16182
16587
|
initLogger5();
|
|
16183
16588
|
const configPath = resolveConfigPath();
|
|
16184
|
-
const raw =
|
|
16185
|
-
const remnicCfg =
|
|
16186
|
-
const config =
|
|
16589
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
16590
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16591
|
+
const config = parseConfig17(remnicCfg);
|
|
16187
16592
|
if (!config.taxonomyEnabled) {
|
|
16188
16593
|
console.error(
|
|
16189
16594
|
"Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
|
|
@@ -16219,8 +16624,8 @@ async function cmdTaxonomy(rest) {
|
|
|
16219
16624
|
console.log(doc);
|
|
16220
16625
|
if (config.taxonomyAutoGenResolver) {
|
|
16221
16626
|
const resolverPath = path19.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16222
|
-
|
|
16223
|
-
|
|
16627
|
+
fs28.mkdirSync(path19.dirname(resolverPath), { recursive: true });
|
|
16628
|
+
fs28.writeFileSync(resolverPath, doc);
|
|
16224
16629
|
console.error(`Written: ${resolverPath}`);
|
|
16225
16630
|
}
|
|
16226
16631
|
break;
|
|
@@ -16266,7 +16671,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16266
16671
|
if (config.taxonomyAutoGenResolver) {
|
|
16267
16672
|
const doc = generateResolverDocument(taxonomy);
|
|
16268
16673
|
const resolverPath = path19.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16269
|
-
|
|
16674
|
+
fs28.writeFileSync(resolverPath, doc);
|
|
16270
16675
|
console.error(`Regenerated: ${resolverPath}`);
|
|
16271
16676
|
}
|
|
16272
16677
|
break;
|
|
@@ -16297,7 +16702,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16297
16702
|
if (config.taxonomyAutoGenResolver) {
|
|
16298
16703
|
const doc = generateResolverDocument(taxonomy);
|
|
16299
16704
|
const resolverPath = path19.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16300
|
-
|
|
16705
|
+
fs28.writeFileSync(resolverPath, doc);
|
|
16301
16706
|
console.error(`Regenerated: ${resolverPath}`);
|
|
16302
16707
|
}
|
|
16303
16708
|
break;
|
|
@@ -16488,12 +16893,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
16488
16893
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
16489
16894
|
);
|
|
16490
16895
|
}
|
|
16491
|
-
if (!
|
|
16896
|
+
if (!fs28.existsSync(args.memoryDir)) {
|
|
16492
16897
|
throw new Error(
|
|
16493
16898
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
16494
16899
|
);
|
|
16495
16900
|
}
|
|
16496
|
-
if (!
|
|
16901
|
+
if (!fs28.statSync(args.memoryDir).isDirectory()) {
|
|
16497
16902
|
throw new Error(
|
|
16498
16903
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
16499
16904
|
);
|
|
@@ -16579,10 +16984,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
16579
16984
|
}
|
|
16580
16985
|
const formatted = adapter.formatRecords(records);
|
|
16581
16986
|
const outDir = path19.dirname(args.output);
|
|
16582
|
-
|
|
16987
|
+
fs28.mkdirSync(outDir, { recursive: true });
|
|
16583
16988
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
16584
|
-
|
|
16585
|
-
|
|
16989
|
+
fs28.writeFileSync(tmpPath, formatted, "utf-8");
|
|
16990
|
+
fs28.renameSync(tmpPath, args.output);
|
|
16586
16991
|
stdout.write(
|
|
16587
16992
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
16588
16993
|
`
|
|
@@ -16625,6 +17030,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16625
17030
|
await cmdQuery(queryText, json, explain);
|
|
16626
17031
|
break;
|
|
16627
17032
|
}
|
|
17033
|
+
case "recall":
|
|
17034
|
+
await runRecallNavigateCommand(rest);
|
|
17035
|
+
break;
|
|
16628
17036
|
case "action-confidence":
|
|
16629
17037
|
await cmdActionConfidence(rest);
|
|
16630
17038
|
break;
|
|
@@ -16760,7 +17168,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16760
17168
|
}
|
|
16761
17169
|
}, 500);
|
|
16762
17170
|
};
|
|
16763
|
-
|
|
17171
|
+
fs28.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
16764
17172
|
if (filename && filename.startsWith(".")) return;
|
|
16765
17173
|
rebuild();
|
|
16766
17174
|
});
|
|
@@ -16768,12 +17176,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16768
17176
|
});
|
|
16769
17177
|
} else if (subAction === "validate") {
|
|
16770
17178
|
const treeDir = outputDir;
|
|
16771
|
-
if (!
|
|
17179
|
+
if (!fs28.existsSync(treeDir)) {
|
|
16772
17180
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
16773
17181
|
process.exit(1);
|
|
16774
17182
|
}
|
|
16775
17183
|
const indexPath = path19.join(treeDir, "INDEX.md");
|
|
16776
|
-
if (!
|
|
17184
|
+
if (!fs28.existsSync(indexPath)) {
|
|
16777
17185
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
16778
17186
|
process.exit(1);
|
|
16779
17187
|
}
|
|
@@ -16960,6 +17368,10 @@ Other:
|
|
|
16960
17368
|
await runMeetingsBinaryCommand(rest);
|
|
16961
17369
|
break;
|
|
16962
17370
|
}
|
|
17371
|
+
case "timeline": {
|
|
17372
|
+
await runTimelineBinaryCommand(rest);
|
|
17373
|
+
break;
|
|
17374
|
+
}
|
|
16963
17375
|
case "location":
|
|
16964
17376
|
await runLocationBinaryCommand(rest);
|
|
16965
17377
|
break;
|
|
@@ -16972,6 +17384,18 @@ Other:
|
|
|
16972
17384
|
case "standup":
|
|
16973
17385
|
await runStandupBinaryCommand(rest);
|
|
16974
17386
|
break;
|
|
17387
|
+
case "journal":
|
|
17388
|
+
await runJournalBinaryCommand(rest);
|
|
17389
|
+
break;
|
|
17390
|
+
case "journal-vault":
|
|
17391
|
+
await runJournalVaultBinaryCommand(rest);
|
|
17392
|
+
break;
|
|
17393
|
+
case "activity-privacy":
|
|
17394
|
+
await runActivityPrivacyBinaryCommand(rest);
|
|
17395
|
+
break;
|
|
17396
|
+
case "vault-publish":
|
|
17397
|
+
await runVaultPublishBinaryCommand(rest);
|
|
17398
|
+
break;
|
|
16975
17399
|
case "codegraph":
|
|
16976
17400
|
await runCodegraphBinaryCommand(rest);
|
|
16977
17401
|
break;
|
|
@@ -16988,9 +17412,9 @@ Other:
|
|
|
16988
17412
|
const targetFactory = async () => {
|
|
16989
17413
|
if (!orchestratorSingleton) {
|
|
16990
17414
|
const configPath = resolveConfigPath();
|
|
16991
|
-
const raw =
|
|
16992
|
-
const remnicCfg =
|
|
16993
|
-
const config =
|
|
17415
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
17416
|
+
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
17417
|
+
const config = parseConfig17(remnicCfg);
|
|
16994
17418
|
orchestratorSingleton = new Orchestrator10(config);
|
|
16995
17419
|
await orchestratorSingleton.initialize();
|
|
16996
17420
|
await orchestratorSingleton.deferredReady;
|