@remnic/cli 9.66.1 → 9.66.3
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 +644 -249
- 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";
|
|
@@ -588,45 +588,9 @@ async function runJournalBinaryCommand(rest) {
|
|
|
588
588
|
}
|
|
589
589
|
}
|
|
590
590
|
|
|
591
|
-
// src/commands/
|
|
591
|
+
// src/commands/journal-vault.ts
|
|
592
592
|
import fs10 from "fs";
|
|
593
|
-
import {
|
|
594
|
-
async function runExternalWikiBinaryCommand(rest) {
|
|
595
|
-
let roots;
|
|
596
|
-
try {
|
|
597
|
-
const configPath = resolveConfigPath();
|
|
598
|
-
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
599
|
-
roots = parseConfig10(resolveRemnicConfigRecord10(raw)).externalWikis;
|
|
600
|
-
} catch {
|
|
601
|
-
console.error(
|
|
602
|
-
"external-wiki: failed to load the Remnic config - run `remnic doctor` and check the config file for errors"
|
|
603
|
-
);
|
|
604
|
-
process.exitCode = 1;
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
try {
|
|
608
|
-
const code = await runExternalWikiCliCommand(roots, rest, {
|
|
609
|
-
stdout: process.stdout,
|
|
610
|
-
stderr: process.stderr
|
|
611
|
-
});
|
|
612
|
-
if (code !== 0) process.exitCode = code;
|
|
613
|
-
} catch {
|
|
614
|
-
console.error("external-wiki: search failed");
|
|
615
|
-
process.exitCode = 1;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// src/commands/procedural.ts
|
|
620
|
-
import fs11 from "fs";
|
|
621
|
-
import {
|
|
622
|
-
StorageManager,
|
|
623
|
-
computeProcedureStats,
|
|
624
|
-
formatProcedureStatsText,
|
|
625
|
-
initLogger,
|
|
626
|
-
parseConfig as parseConfig11,
|
|
627
|
-
resolveRemnicConfigRecord as resolveRemnicConfigRecord11,
|
|
628
|
-
runProcedureLibraryMaintenance
|
|
629
|
-
} from "@remnic/core";
|
|
593
|
+
import { readVaultJournal } from "@remnic/core";
|
|
630
594
|
|
|
631
595
|
// src/cli-args.ts
|
|
632
596
|
function resolveFlag(args, flag) {
|
|
@@ -684,6 +648,324 @@ function parseTaxonomyResolveArgs(args, booleanFlags = TAXONOMY_RESOLVE_BOOLEAN_
|
|
|
684
648
|
return { textParts, values, booleans };
|
|
685
649
|
}
|
|
686
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/activity-export.ts
|
|
781
|
+
import { observationsForExport, parseActivityPrivacy, parseFlexibleIsoTimestamp as parseFlexibleIsoTimestamp2 } from "@remnic/core";
|
|
782
|
+
var defaultIo3 = {
|
|
783
|
+
stdout: (line) => {
|
|
784
|
+
process.stdout.write(`${line}
|
|
785
|
+
`);
|
|
786
|
+
},
|
|
787
|
+
stderr: (line) => {
|
|
788
|
+
process.stderr.write(`${line}
|
|
789
|
+
`);
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
function activityExportHelp() {
|
|
793
|
+
return `Usage: remnic activity-export --from <iso> [--to <iso>] [--format json] [--enabled <true|false>]
|
|
794
|
+
|
|
795
|
+
Print a JSON array of {id, capturedAt} in the half-open [from, to) window.
|
|
796
|
+
`;
|
|
797
|
+
}
|
|
798
|
+
function parseEnabled2(rest, io) {
|
|
799
|
+
const raw = resolveFlag(rest, "--enabled");
|
|
800
|
+
if (raw === void 0) {
|
|
801
|
+
if (hasFlag(rest, "--enabled")) {
|
|
802
|
+
io.stderr("activity-export: --enabled requires true or false");
|
|
803
|
+
return void 0;
|
|
804
|
+
}
|
|
805
|
+
return true;
|
|
806
|
+
}
|
|
807
|
+
if (raw === "true") return true;
|
|
808
|
+
if (raw === "false") return false;
|
|
809
|
+
io.stderr("activity-export: --enabled must be true or false");
|
|
810
|
+
return void 0;
|
|
811
|
+
}
|
|
812
|
+
function runActivityExportCommand(rest, io = defaultIo3, items = [], nowMs = Date.now()) {
|
|
813
|
+
if (rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" || rest[0] === "help") {
|
|
814
|
+
io.stdout(activityExportHelp().trimEnd());
|
|
815
|
+
return 0;
|
|
816
|
+
}
|
|
817
|
+
const fromRaw = resolveFlag(rest, "--from");
|
|
818
|
+
if (fromRaw === void 0) {
|
|
819
|
+
io.stderr("activity-export: --from <iso> is required");
|
|
820
|
+
return 1;
|
|
821
|
+
}
|
|
822
|
+
const fromMs = parseFlexibleIsoTimestamp2(fromRaw);
|
|
823
|
+
if (fromMs === null) {
|
|
824
|
+
io.stderr("activity-export: --from must be an ISO timestamp");
|
|
825
|
+
return 1;
|
|
826
|
+
}
|
|
827
|
+
const toRaw = resolveFlag(rest, "--to");
|
|
828
|
+
let toMs;
|
|
829
|
+
if (toRaw === void 0) {
|
|
830
|
+
if (hasFlag(rest, "--to")) {
|
|
831
|
+
io.stderr("activity-export: --to requires an ISO timestamp");
|
|
832
|
+
return 1;
|
|
833
|
+
}
|
|
834
|
+
toMs = nowMs;
|
|
835
|
+
} else {
|
|
836
|
+
const parsed = parseFlexibleIsoTimestamp2(toRaw);
|
|
837
|
+
if (parsed === null) {
|
|
838
|
+
io.stderr("activity-export: --to must be an ISO timestamp");
|
|
839
|
+
return 1;
|
|
840
|
+
}
|
|
841
|
+
toMs = parsed;
|
|
842
|
+
}
|
|
843
|
+
const format = resolveFlag(rest, "--format");
|
|
844
|
+
if (format === void 0) {
|
|
845
|
+
if (hasFlag(rest, "--format")) {
|
|
846
|
+
io.stderr("activity-export: --format requires json");
|
|
847
|
+
return 1;
|
|
848
|
+
}
|
|
849
|
+
} else if (format !== "json") {
|
|
850
|
+
io.stderr("activity-export: --format must be json");
|
|
851
|
+
return 1;
|
|
852
|
+
}
|
|
853
|
+
const enabled = parseEnabled2(rest, io);
|
|
854
|
+
if (enabled === void 0) return 1;
|
|
855
|
+
const policy = parseActivityPrivacy({ enabled, exportIncludeObservations: true });
|
|
856
|
+
const exported = observationsForExport(items, policy).filter((item) => {
|
|
857
|
+
const at = parseFlexibleIsoTimestamp2(item.capturedAt);
|
|
858
|
+
return at !== null && at >= fromMs && at < toMs;
|
|
859
|
+
}).map((item) => ({ id: item.id, capturedAt: item.capturedAt }));
|
|
860
|
+
io.stdout(JSON.stringify(exported));
|
|
861
|
+
return 0;
|
|
862
|
+
}
|
|
863
|
+
async function runActivityExportBinaryCommand(rest) {
|
|
864
|
+
const code = runActivityExportCommand(rest);
|
|
865
|
+
if (code !== 0) process.exitCode = code;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// src/commands/vault-publish.ts
|
|
869
|
+
import fs11 from "fs";
|
|
870
|
+
import { applyManagedRegion } from "@remnic/core";
|
|
871
|
+
var defaultIo4 = {
|
|
872
|
+
stdout: (line) => {
|
|
873
|
+
process.stdout.write(`${line}
|
|
874
|
+
`);
|
|
875
|
+
},
|
|
876
|
+
stderr: (line) => {
|
|
877
|
+
process.stderr.write(`${line}
|
|
878
|
+
`);
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
function vaultPublishHelp() {
|
|
882
|
+
return `Usage: remnic vault-publish apply --file <path> --name <region> --content <text>
|
|
883
|
+
|
|
884
|
+
apply Replace the marked region. Missing markers print no_marker.
|
|
885
|
+
`;
|
|
886
|
+
}
|
|
887
|
+
function runVaultPublishCommand(rest, io = defaultIo4) {
|
|
888
|
+
if (rest.length === 0 || rest[0] === "--help" || rest[0] === "-h" || rest[0] === "help") {
|
|
889
|
+
io.stdout(vaultPublishHelp().trimEnd());
|
|
890
|
+
return 0;
|
|
891
|
+
}
|
|
892
|
+
if (rest[0] !== "apply") {
|
|
893
|
+
io.stderr(`vault-publish: unknown action "${rest[0]}".`);
|
|
894
|
+
io.stderr(vaultPublishHelp().trimEnd());
|
|
895
|
+
return 1;
|
|
896
|
+
}
|
|
897
|
+
const filePath = resolveFlag(rest, "--file");
|
|
898
|
+
const name = resolveFlag(rest, "--name");
|
|
899
|
+
const content = resolveFlag(rest, "--content");
|
|
900
|
+
if (filePath === void 0 || name === void 0 || content === void 0) {
|
|
901
|
+
io.stderr("vault-publish: apply requires --file <path>, --name <region>, and --content <text>");
|
|
902
|
+
return 1;
|
|
903
|
+
}
|
|
904
|
+
let fileText;
|
|
905
|
+
try {
|
|
906
|
+
fileText = fs11.readFileSync(filePath, "utf8");
|
|
907
|
+
} catch (err) {
|
|
908
|
+
if (err.code === "ENOENT") {
|
|
909
|
+
io.stderr("missing_file");
|
|
910
|
+
return 1;
|
|
911
|
+
}
|
|
912
|
+
io.stderr(err instanceof Error ? err.message : String(err));
|
|
913
|
+
return 1;
|
|
914
|
+
}
|
|
915
|
+
const applied = applyManagedRegion(fileText, { strategy: "markers", name, content });
|
|
916
|
+
if (!applied.ok) {
|
|
917
|
+
io.stderr(applied.reason);
|
|
918
|
+
return 1;
|
|
919
|
+
}
|
|
920
|
+
if (applied.text !== fileText) fs11.writeFileSync(filePath, applied.text);
|
|
921
|
+
io.stdout("ok");
|
|
922
|
+
return 0;
|
|
923
|
+
}
|
|
924
|
+
async function runVaultPublishBinaryCommand(rest) {
|
|
925
|
+
const code = runVaultPublishCommand(rest);
|
|
926
|
+
if (code !== 0) process.exitCode = code;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// src/commands/external-wiki.ts
|
|
930
|
+
import fs12 from "fs";
|
|
931
|
+
import { parseConfig as parseConfig10, resolveRemnicConfigRecord as resolveRemnicConfigRecord10, runExternalWikiCliCommand } from "@remnic/core";
|
|
932
|
+
async function runExternalWikiBinaryCommand(rest) {
|
|
933
|
+
let roots;
|
|
934
|
+
try {
|
|
935
|
+
const configPath = resolveConfigPath();
|
|
936
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
937
|
+
roots = parseConfig10(resolveRemnicConfigRecord10(raw)).externalWikis;
|
|
938
|
+
} catch {
|
|
939
|
+
console.error(
|
|
940
|
+
"external-wiki: failed to load the Remnic config - run `remnic doctor` and check the config file for errors"
|
|
941
|
+
);
|
|
942
|
+
process.exitCode = 1;
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
try {
|
|
946
|
+
const code = await runExternalWikiCliCommand(roots, rest, {
|
|
947
|
+
stdout: process.stdout,
|
|
948
|
+
stderr: process.stderr
|
|
949
|
+
});
|
|
950
|
+
if (code !== 0) process.exitCode = code;
|
|
951
|
+
} catch {
|
|
952
|
+
console.error("external-wiki: search failed");
|
|
953
|
+
process.exitCode = 1;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// src/commands/procedural.ts
|
|
958
|
+
import fs13 from "fs";
|
|
959
|
+
import {
|
|
960
|
+
StorageManager,
|
|
961
|
+
computeProcedureStats,
|
|
962
|
+
formatProcedureStatsText,
|
|
963
|
+
initLogger,
|
|
964
|
+
parseConfig as parseConfig11,
|
|
965
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord11,
|
|
966
|
+
runProcedureLibraryMaintenance
|
|
967
|
+
} from "@remnic/core";
|
|
968
|
+
|
|
687
969
|
// src/path-utils.ts
|
|
688
970
|
function resolveHomeDir() {
|
|
689
971
|
return process.env.HOME ?? process.env.USERPROFILE ?? "~";
|
|
@@ -755,7 +1037,7 @@ Shared with:
|
|
|
755
1037
|
process.exit(1);
|
|
756
1038
|
}
|
|
757
1039
|
const configPath = resolveConfigPath();
|
|
758
|
-
const raw =
|
|
1040
|
+
const raw = fs13.existsSync(configPath) ? JSON.parse(fs13.readFileSync(configPath, "utf8")) : {};
|
|
759
1041
|
const config = parseConfig11(resolveRemnicConfigRecord11(raw));
|
|
760
1042
|
const memoryDir = expandTilde(
|
|
761
1043
|
typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
@@ -811,7 +1093,7 @@ function formatProcedureMaintenanceText(report) {
|
|
|
811
1093
|
}
|
|
812
1094
|
|
|
813
1095
|
// src/commands/drift.ts
|
|
814
|
-
import
|
|
1096
|
+
import fs14 from "fs";
|
|
815
1097
|
import {
|
|
816
1098
|
Orchestrator as Orchestrator7,
|
|
817
1099
|
initLogger as initLogger2,
|
|
@@ -876,7 +1158,7 @@ Resolve a drifted item with the existing review surface:
|
|
|
876
1158
|
process.exit(1);
|
|
877
1159
|
}
|
|
878
1160
|
const configPath = resolveConfigPath();
|
|
879
|
-
const raw =
|
|
1161
|
+
const raw = fs14.existsSync(configPath) ? JSON.parse(fs14.readFileSync(configPath, "utf8")) : {};
|
|
880
1162
|
const config = parseConfig12(resolveRemnicConfigRecord12(raw));
|
|
881
1163
|
const memoryDirOverridden = typeof memoryDirOverride === "string" && memoryDirOverride.length > 0;
|
|
882
1164
|
const memoryDir = expandTilde(
|
|
@@ -940,6 +1222,104 @@ function formatPreferenceDriftText(report) {
|
|
|
940
1222
|
return lines.join("\n") + "\n";
|
|
941
1223
|
}
|
|
942
1224
|
|
|
1225
|
+
// src/commands/recall-navigate.ts
|
|
1226
|
+
import {
|
|
1227
|
+
expandRecallNode,
|
|
1228
|
+
traverseRecallLink
|
|
1229
|
+
} from "@remnic/core";
|
|
1230
|
+
var RECALL_NAV_UNAVAILABLE_TAG = "[unavailable] budget_off";
|
|
1231
|
+
function recallNavigateHelp() {
|
|
1232
|
+
return `Usage: remnic recall <expand|traverse> --node <json> [--budget <n>] [--type <linkType>]
|
|
1233
|
+
|
|
1234
|
+
expand Re-render one node at the next disclosure level
|
|
1235
|
+
traverse Follow typed links from a node
|
|
1236
|
+
|
|
1237
|
+
--budget 0 turns navigation off and prints ${RECALL_NAV_UNAVAILABLE_TAG}
|
|
1238
|
+
--type required for traverse: supports, contradicts, elaborates, supersedes, causes
|
|
1239
|
+
`;
|
|
1240
|
+
}
|
|
1241
|
+
function takeFlag5(rest, name) {
|
|
1242
|
+
const index = rest.indexOf(name);
|
|
1243
|
+
if (index < 0) return void 0;
|
|
1244
|
+
const value = rest[index + 1];
|
|
1245
|
+
if (value === void 0 || value.startsWith("-")) {
|
|
1246
|
+
throw new Error(`${name} requires a value`);
|
|
1247
|
+
}
|
|
1248
|
+
return value;
|
|
1249
|
+
}
|
|
1250
|
+
function parseBudget(rest) {
|
|
1251
|
+
if (!rest.includes("--budget")) return 1;
|
|
1252
|
+
const raw = takeFlag5(rest, "--budget");
|
|
1253
|
+
const budget = Number(raw);
|
|
1254
|
+
if (!Number.isFinite(budget)) {
|
|
1255
|
+
throw new Error(`--budget must be a number (got ${JSON.stringify(raw)})`);
|
|
1256
|
+
}
|
|
1257
|
+
return budget;
|
|
1258
|
+
}
|
|
1259
|
+
function parseNode(raw) {
|
|
1260
|
+
let value;
|
|
1261
|
+
try {
|
|
1262
|
+
value = JSON.parse(raw);
|
|
1263
|
+
} catch {
|
|
1264
|
+
throw new Error("--node must be JSON");
|
|
1265
|
+
}
|
|
1266
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1267
|
+
throw new Error("--node must be a JSON object");
|
|
1268
|
+
}
|
|
1269
|
+
const node = value;
|
|
1270
|
+
if (typeof node.id !== "string" || node.id.length === 0) {
|
|
1271
|
+
throw new Error("--node.id must be a non-empty string");
|
|
1272
|
+
}
|
|
1273
|
+
if (typeof node.disclosure !== "string") {
|
|
1274
|
+
throw new Error("--node.disclosure is required");
|
|
1275
|
+
}
|
|
1276
|
+
return node;
|
|
1277
|
+
}
|
|
1278
|
+
function emitUnavailable(io) {
|
|
1279
|
+
io.stdout(RECALL_NAV_UNAVAILABLE_TAG);
|
|
1280
|
+
return 0;
|
|
1281
|
+
}
|
|
1282
|
+
function runRecallNavigate(rest, io) {
|
|
1283
|
+
const action = rest[0];
|
|
1284
|
+
if (rest.length === 0 || action === "--help" || action === "-h" || action === "help") {
|
|
1285
|
+
io.stdout(recallNavigateHelp());
|
|
1286
|
+
return 0;
|
|
1287
|
+
}
|
|
1288
|
+
try {
|
|
1289
|
+
const budget = parseBudget(rest);
|
|
1290
|
+
const nodeRaw = takeFlag5(rest, "--node");
|
|
1291
|
+
if (nodeRaw === void 0) throw new Error("--node is required");
|
|
1292
|
+
const node = parseNode(nodeRaw);
|
|
1293
|
+
if (action === "expand") {
|
|
1294
|
+
const result = expandRecallNode(node, { budget });
|
|
1295
|
+
if (result.status === "unavailable") return emitUnavailable(io);
|
|
1296
|
+
io.stdout(JSON.stringify(result));
|
|
1297
|
+
return 0;
|
|
1298
|
+
}
|
|
1299
|
+
if (action === "traverse") {
|
|
1300
|
+
const linkType = takeFlag5(rest, "--type");
|
|
1301
|
+
if (linkType === void 0) throw new Error("traverse requires --type");
|
|
1302
|
+
const result = traverseRecallLink(node, linkType, { budget });
|
|
1303
|
+
if (result.status === "unavailable") return emitUnavailable(io);
|
|
1304
|
+
io.stdout(JSON.stringify(result));
|
|
1305
|
+
return 0;
|
|
1306
|
+
}
|
|
1307
|
+
io.stderr(`recall: unknown action "${action}".`);
|
|
1308
|
+
io.stderr(recallNavigateHelp());
|
|
1309
|
+
return 1;
|
|
1310
|
+
} catch (err) {
|
|
1311
|
+
io.stderr(err instanceof Error ? err.message : String(err));
|
|
1312
|
+
return 1;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
async function runRecallNavigateCommand(rest) {
|
|
1316
|
+
const code = runRecallNavigate(rest, {
|
|
1317
|
+
stdout: (line) => console.log(line),
|
|
1318
|
+
stderr: (line) => console.error(line)
|
|
1319
|
+
});
|
|
1320
|
+
if (code !== 0) process.exitCode = code;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
943
1323
|
// src/optional-module-loader.ts
|
|
944
1324
|
function isSpecifierNotFoundError(err, specifier) {
|
|
945
1325
|
if (!err || typeof err !== "object") {
|
|
@@ -990,7 +1370,7 @@ async function loadWecloneExportModule() {
|
|
|
990
1370
|
}
|
|
991
1371
|
|
|
992
1372
|
// src/converge.ts
|
|
993
|
-
import * as
|
|
1373
|
+
import * as fs16 from "fs";
|
|
994
1374
|
import { createHash as createHash3 } from "crypto";
|
|
995
1375
|
import * as path3 from "path";
|
|
996
1376
|
import {
|
|
@@ -1022,7 +1402,7 @@ import {
|
|
|
1022
1402
|
|
|
1023
1403
|
// src/offline-storage-io.ts
|
|
1024
1404
|
import { createDecipheriv, createHash } from "crypto";
|
|
1025
|
-
import
|
|
1405
|
+
import fs15 from "fs";
|
|
1026
1406
|
import { lstat, mkdtemp, readdir, rm } from "fs/promises";
|
|
1027
1407
|
import path2 from "path";
|
|
1028
1408
|
import {
|
|
@@ -1184,7 +1564,7 @@ async function* readOfflineSyncFileChunks(options) {
|
|
|
1184
1564
|
});
|
|
1185
1565
|
}
|
|
1186
1566
|
async function readFilePrefix(filePath, length) {
|
|
1187
|
-
const handle = await
|
|
1567
|
+
const handle = await fs15.promises.open(filePath, "r");
|
|
1188
1568
|
try {
|
|
1189
1569
|
const out = Buffer.alloc(length);
|
|
1190
1570
|
const { bytesRead } = await handle.read(out, 0, length, 0);
|
|
@@ -1194,7 +1574,7 @@ async function readFilePrefix(filePath, length) {
|
|
|
1194
1574
|
}
|
|
1195
1575
|
}
|
|
1196
1576
|
async function* readPlainOfflineFileChunks(filePath, chunkSize) {
|
|
1197
|
-
const stream =
|
|
1577
|
+
const stream = fs15.createReadStream(filePath, { highWaterMark: chunkSize });
|
|
1198
1578
|
for await (const chunk of stream) {
|
|
1199
1579
|
yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
1200
1580
|
}
|
|
@@ -1231,9 +1611,9 @@ async function* readEncryptedOfflineFileChunks(options) {
|
|
|
1231
1611
|
});
|
|
1232
1612
|
decipher.setAuthTag(authTag);
|
|
1233
1613
|
decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
|
|
1234
|
-
const output =
|
|
1614
|
+
const output = fs15.createWriteStream(tempPath, { mode: 384 });
|
|
1235
1615
|
try {
|
|
1236
|
-
const stream =
|
|
1616
|
+
const stream = fs15.createReadStream(options.filePath, {
|
|
1237
1617
|
start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
|
|
1238
1618
|
highWaterMark: options.chunkSize
|
|
1239
1619
|
});
|
|
@@ -1843,7 +2223,7 @@ async function readLocalTombstoneEvidence(rootDir) {
|
|
|
1843
2223
|
for (const relativePath of TOMBSTONE_PATHS) {
|
|
1844
2224
|
let content;
|
|
1845
2225
|
try {
|
|
1846
|
-
content = await
|
|
2226
|
+
content = await fs16.promises.readFile(path3.join(rootDir, relativePath), "utf-8");
|
|
1847
2227
|
} catch (error) {
|
|
1848
2228
|
if (error.code === "ENOENT") continue;
|
|
1849
2229
|
throw error;
|
|
@@ -1858,7 +2238,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
|
|
|
1858
2238
|
const cursorDir = path3.join(path3.resolve(memoryDir), ".remnic", "state", "converge-cursors");
|
|
1859
2239
|
let entries;
|
|
1860
2240
|
try {
|
|
1861
|
-
entries = await
|
|
2241
|
+
entries = await fs16.promises.readdir(cursorDir, { withFileTypes: true });
|
|
1862
2242
|
} catch (error) {
|
|
1863
2243
|
if (error.code === "ENOENT") return [];
|
|
1864
2244
|
throw error;
|
|
@@ -2348,7 +2728,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2348
2728
|
if (current.sha256 !== entry.localSha256) {
|
|
2349
2729
|
throw new Error(`local file changed during push: ${localPath}`);
|
|
2350
2730
|
}
|
|
2351
|
-
const stat2 = await
|
|
2731
|
+
const stat2 = await fs16.promises.stat(filePath);
|
|
2352
2732
|
let chunks;
|
|
2353
2733
|
let chunkOffset = 0;
|
|
2354
2734
|
const resetChunks = async () => {
|
|
@@ -2831,7 +3211,7 @@ function renderReplayResult(result, targetNamespace, format) {
|
|
|
2831
3211
|
}
|
|
2832
3212
|
|
|
2833
3213
|
// src/quarantine-replay.ts
|
|
2834
|
-
import * as
|
|
3214
|
+
import * as fs17 from "fs";
|
|
2835
3215
|
import { EngramAccessService, Orchestrator as Orchestrator8, initLogger as initLogger3, parseConfig as parseConfig14, resolveRemnicConfigRecord as resolveRemnicConfigRecord13 } from "@remnic/core";
|
|
2836
3216
|
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
2837
3217
|
function valueFlag(args, flag) {
|
|
@@ -2880,7 +3260,7 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
2880
3260
|
let orchestrator;
|
|
2881
3261
|
try {
|
|
2882
3262
|
const configPath = resolveConfigPath2();
|
|
2883
|
-
const raw =
|
|
3263
|
+
const raw = fs17.existsSync(configPath) ? JSON.parse(fs17.readFileSync(configPath, "utf8")) : {};
|
|
2884
3264
|
const config = parseConfig14(resolveRemnicConfigRecord13(raw));
|
|
2885
3265
|
orchestrator = new Orchestrator8(config);
|
|
2886
3266
|
await orchestrator.initialize();
|
|
@@ -2912,7 +3292,7 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
2912
3292
|
}
|
|
2913
3293
|
|
|
2914
3294
|
// src/offline-impression-rotation.ts
|
|
2915
|
-
import
|
|
3295
|
+
import fs18 from "fs";
|
|
2916
3296
|
import { parseConfig as parseConfig15, resolveRemnicConfigRecord as resolveRemnicConfigRecord14, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
2917
3297
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
2918
3298
|
function parseConfigQuietly(raw) {
|
|
@@ -2947,7 +3327,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
2947
3327
|
function resolveOfflineImpressionRotation(configPath) {
|
|
2948
3328
|
let raw;
|
|
2949
3329
|
try {
|
|
2950
|
-
raw =
|
|
3330
|
+
raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
|
|
2951
3331
|
} catch {
|
|
2952
3332
|
throw new Error(
|
|
2953
3333
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -3205,7 +3585,7 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
3205
3585
|
}
|
|
3206
3586
|
|
|
3207
3587
|
// src/cmd-security.ts
|
|
3208
|
-
import
|
|
3588
|
+
import fs19 from "fs";
|
|
3209
3589
|
import {
|
|
3210
3590
|
Orchestrator as Orchestrator9,
|
|
3211
3591
|
parseConfig as parseConfig16,
|
|
@@ -3225,7 +3605,7 @@ async function cmdSecurity(rest) {
|
|
|
3225
3605
|
}
|
|
3226
3606
|
initLogger4();
|
|
3227
3607
|
const configPath = resolveConfigPath();
|
|
3228
|
-
const raw =
|
|
3608
|
+
const raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
3229
3609
|
const config = parseConfig16(resolveRemnicConfigRecord15(raw));
|
|
3230
3610
|
const orchestrator = new Orchestrator9(config);
|
|
3231
3611
|
await orchestrator.initialize();
|
|
@@ -3250,7 +3630,7 @@ async function cmdSecurity(rest) {
|
|
|
3250
3630
|
}
|
|
3251
3631
|
|
|
3252
3632
|
// src/daemon-service-candidates.ts
|
|
3253
|
-
import
|
|
3633
|
+
import fs20 from "fs";
|
|
3254
3634
|
import path6 from "path";
|
|
3255
3635
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
3256
3636
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -3272,7 +3652,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
3272
3652
|
function anyFileExists(paths) {
|
|
3273
3653
|
return paths.some((candidate) => {
|
|
3274
3654
|
try {
|
|
3275
|
-
return
|
|
3655
|
+
return fs20.statSync(candidate).isFile();
|
|
3276
3656
|
} catch {
|
|
3277
3657
|
return false;
|
|
3278
3658
|
}
|
|
@@ -3284,7 +3664,7 @@ function commandNames(command) {
|
|
|
3284
3664
|
}
|
|
3285
3665
|
function isRunnableNodeScript(filePath) {
|
|
3286
3666
|
try {
|
|
3287
|
-
const text =
|
|
3667
|
+
const text = fs20.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
3288
3668
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
3289
3669
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
3290
3670
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -3297,7 +3677,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
3297
3677
|
function resolveShimNodeScript(filePath) {
|
|
3298
3678
|
let text;
|
|
3299
3679
|
try {
|
|
3300
|
-
text =
|
|
3680
|
+
text = fs20.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
3301
3681
|
} catch {
|
|
3302
3682
|
return void 0;
|
|
3303
3683
|
}
|
|
@@ -3309,8 +3689,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
3309
3689
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
3310
3690
|
const resolved = path6.isAbsolute(candidate) ? candidate : path6.resolve(basedir, candidate);
|
|
3311
3691
|
try {
|
|
3312
|
-
if (
|
|
3313
|
-
return
|
|
3692
|
+
if (fs20.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
3693
|
+
return fs20.realpathSync(resolved);
|
|
3314
3694
|
}
|
|
3315
3695
|
} catch {
|
|
3316
3696
|
}
|
|
@@ -3318,7 +3698,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
3318
3698
|
return void 0;
|
|
3319
3699
|
}
|
|
3320
3700
|
function resolveRunnableNodeScript(filePath) {
|
|
3321
|
-
const realPath =
|
|
3701
|
+
const realPath = fs20.realpathSync(filePath);
|
|
3322
3702
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
3323
3703
|
return resolveShimNodeScript(realPath);
|
|
3324
3704
|
}
|
|
@@ -3328,9 +3708,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
3328
3708
|
for (const name of commandNames(command)) {
|
|
3329
3709
|
const candidate = path6.join(dir, name);
|
|
3330
3710
|
try {
|
|
3331
|
-
const stat2 =
|
|
3711
|
+
const stat2 = fs20.statSync(candidate);
|
|
3332
3712
|
if (!stat2.isFile()) continue;
|
|
3333
|
-
if (process.platform !== "win32")
|
|
3713
|
+
if (process.platform !== "win32") fs20.accessSync(candidate, fs20.constants.X_OK);
|
|
3334
3714
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
3335
3715
|
if (runnable) return runnable;
|
|
3336
3716
|
} catch {
|
|
@@ -4803,7 +5183,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
4803
5183
|
}
|
|
4804
5184
|
|
|
4805
5185
|
// src/bench-fallback.ts
|
|
4806
|
-
import
|
|
5186
|
+
import fs21 from "fs";
|
|
4807
5187
|
import path10 from "path";
|
|
4808
5188
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
4809
5189
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -4875,7 +5255,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
4875
5255
|
);
|
|
4876
5256
|
}
|
|
4877
5257
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
4878
|
-
const entries =
|
|
5258
|
+
const entries = fs21.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
4879
5259
|
if (entries.length === 0) {
|
|
4880
5260
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
4881
5261
|
}
|
|
@@ -4883,7 +5263,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
4883
5263
|
}
|
|
4884
5264
|
|
|
4885
5265
|
// src/openclaw-upgrade-swap.ts
|
|
4886
|
-
import
|
|
5266
|
+
import fs22 from "fs";
|
|
4887
5267
|
import path11 from "path";
|
|
4888
5268
|
function describeError(error) {
|
|
4889
5269
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4895,7 +5275,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
4895
5275
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
4896
5276
|
if (explicitMode !== void 0) return explicitMode;
|
|
4897
5277
|
try {
|
|
4898
|
-
return
|
|
5278
|
+
return fs22.statSync(targetPath).mode & 4095;
|
|
4899
5279
|
} catch (error) {
|
|
4900
5280
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
4901
5281
|
return 384;
|
|
@@ -4905,8 +5285,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
4905
5285
|
}
|
|
4906
5286
|
function resolveAtomicReplacementPath(targetPath) {
|
|
4907
5287
|
try {
|
|
4908
|
-
if (
|
|
4909
|
-
return
|
|
5288
|
+
if (fs22.lstatSync(targetPath).isSymbolicLink()) {
|
|
5289
|
+
return fs22.realpathSync(targetPath);
|
|
4910
5290
|
}
|
|
4911
5291
|
} catch (error) {
|
|
4912
5292
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -4923,7 +5303,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
4923
5303
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
4924
5304
|
if (!displacedDir) return void 0;
|
|
4925
5305
|
try {
|
|
4926
|
-
|
|
5306
|
+
fs22.rmSync(displacedDir, { recursive: true, force: true });
|
|
4927
5307
|
return void 0;
|
|
4928
5308
|
} catch (error) {
|
|
4929
5309
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -4931,43 +5311,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
4931
5311
|
}
|
|
4932
5312
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
4933
5313
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4934
|
-
|
|
5314
|
+
fs22.mkdirSync(path11.dirname(resolvedTargetPath), { recursive: true });
|
|
4935
5315
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
4936
5316
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
4937
5317
|
try {
|
|
4938
5318
|
if (options.hooks?.writeTempFileSync) {
|
|
4939
5319
|
options.hooks.writeTempFileSync(tempPath);
|
|
4940
5320
|
} else {
|
|
4941
|
-
|
|
5321
|
+
fs22.writeFileSync(tempPath, data, { mode });
|
|
4942
5322
|
}
|
|
4943
|
-
|
|
4944
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5323
|
+
fs22.chmodSync(tempPath, mode);
|
|
5324
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs22.renameSync;
|
|
4945
5325
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4946
5326
|
} catch (error) {
|
|
4947
|
-
|
|
5327
|
+
fs22.rmSync(tempPath, { force: true });
|
|
4948
5328
|
throw error;
|
|
4949
5329
|
}
|
|
4950
5330
|
}
|
|
4951
5331
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
4952
|
-
if (!
|
|
5332
|
+
if (!fs22.existsSync(sourcePath)) return;
|
|
4953
5333
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4954
|
-
|
|
5334
|
+
fs22.mkdirSync(path11.dirname(resolvedTargetPath), { recursive: true });
|
|
4955
5335
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
4956
|
-
const mode =
|
|
5336
|
+
const mode = fs22.statSync(sourcePath).mode & 4095;
|
|
4957
5337
|
try {
|
|
4958
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
5338
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs22.copyFileSync;
|
|
4959
5339
|
copyTempFileSync(sourcePath, tempPath);
|
|
4960
|
-
|
|
4961
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5340
|
+
fs22.chmodSync(tempPath, mode);
|
|
5341
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs22.renameSync;
|
|
4962
5342
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4963
5343
|
} catch (error) {
|
|
4964
|
-
|
|
5344
|
+
fs22.rmSync(tempPath, { force: true });
|
|
4965
5345
|
throw error;
|
|
4966
5346
|
}
|
|
4967
5347
|
}
|
|
4968
5348
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
4969
5349
|
if (!rollbackDir) return;
|
|
4970
|
-
|
|
5350
|
+
fs22.rmSync(rollbackDir, { recursive: true, force: true });
|
|
4971
5351
|
}
|
|
4972
5352
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
4973
5353
|
if (!rollbackDir) return void 0;
|
|
@@ -4979,20 +5359,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
4979
5359
|
}
|
|
4980
5360
|
}
|
|
4981
5361
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
4982
|
-
if (!
|
|
5362
|
+
if (!fs22.existsSync(rollbackDir)) {
|
|
4983
5363
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
4984
5364
|
}
|
|
4985
|
-
|
|
4986
|
-
const displacedDir =
|
|
5365
|
+
fs22.mkdirSync(path11.dirname(targetDir), { recursive: true });
|
|
5366
|
+
const displacedDir = fs22.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
4987
5367
|
if (displacedDir) {
|
|
4988
|
-
|
|
5368
|
+
fs22.renameSync(targetDir, displacedDir);
|
|
4989
5369
|
}
|
|
4990
5370
|
try {
|
|
4991
|
-
|
|
5371
|
+
fs22.renameSync(rollbackDir, targetDir);
|
|
4992
5372
|
} catch (restoreError) {
|
|
4993
|
-
if (displacedDir &&
|
|
5373
|
+
if (displacedDir && fs22.existsSync(displacedDir)) {
|
|
4994
5374
|
try {
|
|
4995
|
-
|
|
5375
|
+
fs22.renameSync(displacedDir, targetDir);
|
|
4996
5376
|
} catch (revertError) {
|
|
4997
5377
|
throw new AggregateError(
|
|
4998
5378
|
[restoreError, revertError],
|
|
@@ -5008,23 +5388,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
5008
5388
|
return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
|
|
5009
5389
|
}
|
|
5010
5390
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
5011
|
-
if (!
|
|
5391
|
+
if (!fs22.existsSync(backupDir)) {
|
|
5012
5392
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
5013
5393
|
}
|
|
5014
|
-
|
|
5394
|
+
fs22.mkdirSync(path11.dirname(targetDir), { recursive: true });
|
|
5015
5395
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
5016
|
-
const displacedDir =
|
|
5017
|
-
|
|
5396
|
+
const displacedDir = fs22.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
5397
|
+
fs22.cpSync(backupDir, stagedDir, { recursive: true });
|
|
5018
5398
|
if (displacedDir) {
|
|
5019
|
-
|
|
5399
|
+
fs22.renameSync(targetDir, displacedDir);
|
|
5020
5400
|
}
|
|
5021
5401
|
try {
|
|
5022
|
-
|
|
5402
|
+
fs22.renameSync(stagedDir, targetDir);
|
|
5023
5403
|
} catch (restoreError) {
|
|
5024
|
-
|
|
5025
|
-
if (displacedDir &&
|
|
5404
|
+
fs22.rmSync(targetDir, { recursive: true, force: true });
|
|
5405
|
+
if (displacedDir && fs22.existsSync(displacedDir)) {
|
|
5026
5406
|
try {
|
|
5027
|
-
|
|
5407
|
+
fs22.renameSync(displacedDir, targetDir);
|
|
5028
5408
|
} catch (revertError) {
|
|
5029
5409
|
throw new AggregateError(
|
|
5030
5410
|
[restoreError, revertError],
|
|
@@ -5032,7 +5412,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
5032
5412
|
);
|
|
5033
5413
|
}
|
|
5034
5414
|
}
|
|
5035
|
-
|
|
5415
|
+
fs22.rmSync(stagedDir, { recursive: true, force: true });
|
|
5036
5416
|
throw new Error(
|
|
5037
5417
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
5038
5418
|
{ cause: restoreError }
|
|
@@ -5057,7 +5437,7 @@ function rollbackOpenclawUpgrade({
|
|
|
5057
5437
|
let configRemovalAttempted = false;
|
|
5058
5438
|
let pluginRestored = false;
|
|
5059
5439
|
try {
|
|
5060
|
-
if (rollbackDir &&
|
|
5440
|
+
if (rollbackDir && fs22.existsSync(rollbackDir)) {
|
|
5061
5441
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
5062
5442
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
5063
5443
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -5067,7 +5447,7 @@ function rollbackOpenclawUpgrade({
|
|
|
5067
5447
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
5068
5448
|
}
|
|
5069
5449
|
try {
|
|
5070
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
5450
|
+
if (!pluginRestored && pluginBackupDir && fs22.existsSync(pluginBackupDir)) {
|
|
5071
5451
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
5072
5452
|
if (rollbackRestoreError) {
|
|
5073
5453
|
notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
|
|
@@ -5092,12 +5472,12 @@ function rollbackOpenclawUpgrade({
|
|
|
5092
5472
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
5093
5473
|
}
|
|
5094
5474
|
try {
|
|
5095
|
-
if (configBackupPath &&
|
|
5475
|
+
if (configBackupPath && fs22.existsSync(configBackupPath)) {
|
|
5096
5476
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
5097
5477
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
5098
|
-
} else if (removeConfigIfUnbacked &&
|
|
5478
|
+
} else if (removeConfigIfUnbacked && fs22.existsSync(configPath)) {
|
|
5099
5479
|
configRemovalAttempted = true;
|
|
5100
|
-
|
|
5480
|
+
fs22.rmSync(configPath, { force: true });
|
|
5101
5481
|
notes.push("Removed OpenClaw config created during the failed upgrade");
|
|
5102
5482
|
}
|
|
5103
5483
|
} catch (error) {
|
|
@@ -5150,7 +5530,7 @@ Run this manually when you're ready:
|
|
|
5150
5530
|
|
|
5151
5531
|
// src/openclaw-managed-upgrade-loader.ts
|
|
5152
5532
|
import { execFileSync } from "child_process";
|
|
5153
|
-
import
|
|
5533
|
+
import fs23 from "fs";
|
|
5154
5534
|
import os from "os";
|
|
5155
5535
|
import path12 from "path";
|
|
5156
5536
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -5226,7 +5606,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
|
|
|
5226
5606
|
function readCliAdapterRange() {
|
|
5227
5607
|
const moduleDir = path12.dirname(fileURLToPath3(import.meta.url));
|
|
5228
5608
|
const manifestPath = path12.resolve(moduleDir, "../package.json");
|
|
5229
|
-
const manifest = JSON.parse(
|
|
5609
|
+
const manifest = JSON.parse(fs23.readFileSync(manifestPath, "utf8"));
|
|
5230
5610
|
if (manifest.name !== "@remnic/cli") {
|
|
5231
5611
|
throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
|
|
5232
5612
|
}
|
|
@@ -5270,7 +5650,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5270
5650
|
const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
|
|
5271
5651
|
if (!adapterMissing) throw error;
|
|
5272
5652
|
}
|
|
5273
|
-
const temporaryRoot =
|
|
5653
|
+
const temporaryRoot = fs23.mkdtempSync(path12.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
5274
5654
|
try {
|
|
5275
5655
|
const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
|
|
5276
5656
|
const installArgs = [
|
|
@@ -5285,12 +5665,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5285
5665
|
];
|
|
5286
5666
|
(hooks.runNpmInstall ?? runNpmInstall)(installArgs);
|
|
5287
5667
|
const resolverPath = path12.join(temporaryRoot, "load-managed-upgrade.mjs");
|
|
5288
|
-
|
|
5668
|
+
fs23.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
|
|
5289
5669
|
`, "utf8");
|
|
5290
5670
|
return await importModule(pathToFileURL2(resolverPath).href);
|
|
5291
5671
|
} finally {
|
|
5292
5672
|
try {
|
|
5293
|
-
|
|
5673
|
+
fs23.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
5294
5674
|
} catch (error) {
|
|
5295
5675
|
const detail = error instanceof Error ? error.message : String(error);
|
|
5296
5676
|
console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
|
|
@@ -5299,13 +5679,13 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5299
5679
|
}
|
|
5300
5680
|
|
|
5301
5681
|
// src/remote-daemon.ts
|
|
5302
|
-
import
|
|
5682
|
+
import fs24 from "fs";
|
|
5303
5683
|
function readCompatEnv(primary, legacy) {
|
|
5304
5684
|
return process.env[primary] ?? process.env[legacy];
|
|
5305
5685
|
}
|
|
5306
5686
|
function readRemnicConfigRecord(configPath) {
|
|
5307
5687
|
try {
|
|
5308
|
-
const parsed = JSON.parse(
|
|
5688
|
+
const parsed = JSON.parse(fs24.readFileSync(configPath, "utf8"));
|
|
5309
5689
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5310
5690
|
return parsed;
|
|
5311
5691
|
}
|
|
@@ -5534,7 +5914,7 @@ async function remoteRecallXray(daemon, request) {
|
|
|
5534
5914
|
}
|
|
5535
5915
|
|
|
5536
5916
|
// src/daemon-service.ts
|
|
5537
|
-
import
|
|
5917
|
+
import fs25 from "fs";
|
|
5538
5918
|
import path13 from "path";
|
|
5539
5919
|
import * as childProcess from "child_process";
|
|
5540
5920
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -5546,7 +5926,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
5546
5926
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
5547
5927
|
}
|
|
5548
5928
|
function resolveServerBinDetails(options = {}) {
|
|
5549
|
-
const existsSync4 = options.existsSync ??
|
|
5929
|
+
const existsSync4 = options.existsSync ?? fs25.existsSync;
|
|
5550
5930
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
5551
5931
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
5552
5932
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -5605,8 +5985,8 @@ function resolveServerBin(options = {}) {
|
|
|
5605
5985
|
return resolveServerBinDetails(options).path;
|
|
5606
5986
|
}
|
|
5607
5987
|
function readVerifiedDaemonPid(options) {
|
|
5608
|
-
const readFileSync4 = options.readFileSync ??
|
|
5609
|
-
const unlinkSync = options.unlinkSync ??
|
|
5988
|
+
const readFileSync4 = options.readFileSync ?? fs25.readFileSync;
|
|
5989
|
+
const unlinkSync = options.unlinkSync ?? fs25.unlinkSync;
|
|
5610
5990
|
const processKill = options.processKill ?? process.kill;
|
|
5611
5991
|
const platform = options.platform ?? process.platform;
|
|
5612
5992
|
const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
@@ -5706,8 +6086,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
5706
6086
|
}
|
|
5707
6087
|
}
|
|
5708
6088
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
5709
|
-
const existsSync4 = options.existsSync ??
|
|
5710
|
-
const readFileSync4 = options.readFileSync ??
|
|
6089
|
+
const existsSync4 = options.existsSync ?? fs25.existsSync;
|
|
6090
|
+
const readFileSync4 = options.readFileSync ?? fs25.readFileSync;
|
|
5711
6091
|
if (!existsSync4(plistPath)) {
|
|
5712
6092
|
return {
|
|
5713
6093
|
installed: false,
|
|
@@ -5885,7 +6265,7 @@ function stripConfigArgv(args) {
|
|
|
5885
6265
|
}
|
|
5886
6266
|
|
|
5887
6267
|
// src/import-dispatch.ts
|
|
5888
|
-
import
|
|
6268
|
+
import fs26 from "fs";
|
|
5889
6269
|
import {
|
|
5890
6270
|
runImporter,
|
|
5891
6271
|
validateImportBatchSize,
|
|
@@ -6405,7 +6785,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
6405
6785
|
let materializedTarget;
|
|
6406
6786
|
let materializePromise;
|
|
6407
6787
|
const io = {
|
|
6408
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
6788
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs26.promises.readFile(p, "utf-8")),
|
|
6409
6789
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
6410
6790
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
6411
6791
|
getWriteTarget: async () => {
|
|
@@ -6518,7 +6898,7 @@ async function cmdCapture(rest, io) {
|
|
|
6518
6898
|
}
|
|
6519
6899
|
|
|
6520
6900
|
// src/import-lossless-claw-cmd.ts
|
|
6521
|
-
import
|
|
6901
|
+
import fs27 from "fs";
|
|
6522
6902
|
import path15 from "path";
|
|
6523
6903
|
import {
|
|
6524
6904
|
applyLcmSchema,
|
|
@@ -6630,15 +7010,15 @@ async function loadImportLosslessClawModule() {
|
|
|
6630
7010
|
|
|
6631
7011
|
// src/import-lossless-claw-cmd.ts
|
|
6632
7012
|
function assertDirectoryOrAbsent(p, label) {
|
|
6633
|
-
if (
|
|
7013
|
+
if (fs27.existsSync(p) && !fs27.statSync(p).isDirectory()) {
|
|
6634
7014
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
6635
7015
|
}
|
|
6636
7016
|
}
|
|
6637
7017
|
function assertFile(p, label) {
|
|
6638
|
-
if (!
|
|
7018
|
+
if (!fs27.existsSync(p)) {
|
|
6639
7019
|
throw new Error(`${label} does not exist: ${p}`);
|
|
6640
7020
|
}
|
|
6641
|
-
if (!
|
|
7021
|
+
if (!fs27.statSync(p).isFile()) {
|
|
6642
7022
|
throw new Error(`${label} is not a file: ${p}`);
|
|
6643
7023
|
}
|
|
6644
7024
|
}
|
|
@@ -6670,7 +7050,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
6670
7050
|
try {
|
|
6671
7051
|
if (parsed.dryRun) {
|
|
6672
7052
|
const lcmPath = path15.join(memoryDir, "state", "lcm.sqlite");
|
|
6673
|
-
if (
|
|
7053
|
+
if (fs27.existsSync(lcmPath)) {
|
|
6674
7054
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
6675
7055
|
} else {
|
|
6676
7056
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -8022,7 +8402,7 @@ async function resolveAllBenchmarks() {
|
|
|
8022
8402
|
if (packageBenchmarks) {
|
|
8023
8403
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
8024
8404
|
}
|
|
8025
|
-
if (!
|
|
8405
|
+
if (!fs28.existsSync(EVAL_RUNNER_PATH)) {
|
|
8026
8406
|
return [];
|
|
8027
8407
|
}
|
|
8028
8408
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -8070,7 +8450,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
8070
8450
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
8071
8451
|
);
|
|
8072
8452
|
}
|
|
8073
|
-
if (!
|
|
8453
|
+
if (!fs28.existsSync(EVAL_RUNNER_PATH)) {
|
|
8074
8454
|
console.error(
|
|
8075
8455
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
8076
8456
|
);
|
|
@@ -8080,7 +8460,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
8080
8460
|
path19.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
8081
8461
|
path19.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
8082
8462
|
];
|
|
8083
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
8463
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs28.existsSync(candidate)) ?? "tsx";
|
|
8084
8464
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
8085
8465
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
8086
8466
|
benchmarkId,
|
|
@@ -8225,9 +8605,9 @@ var PERSONAMEM_COMPLETION_MARKER = path19.join(
|
|
|
8225
8605
|
);
|
|
8226
8606
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
8227
8607
|
try {
|
|
8228
|
-
const datasetRoot =
|
|
8608
|
+
const datasetRoot = fs28.realpathSync(datasetPath);
|
|
8229
8609
|
const candidatePath = path19.resolve(datasetRoot, relativePath);
|
|
8230
|
-
const candidateRealPath =
|
|
8610
|
+
const candidateRealPath = fs28.realpathSync(candidatePath);
|
|
8231
8611
|
const relativeToRoot = path19.relative(datasetRoot, candidateRealPath);
|
|
8232
8612
|
if (relativeToRoot.startsWith("..") || path19.isAbsolute(relativeToRoot)) {
|
|
8233
8613
|
return null;
|
|
@@ -8286,14 +8666,14 @@ function parseCsvRows(raw) {
|
|
|
8286
8666
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
8287
8667
|
try {
|
|
8288
8668
|
const completionMarkerPath = path19.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
8289
|
-
if (
|
|
8669
|
+
if (fs28.statSync(completionMarkerPath).isFile()) {
|
|
8290
8670
|
return true;
|
|
8291
8671
|
}
|
|
8292
8672
|
} catch {
|
|
8293
8673
|
}
|
|
8294
8674
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
8295
8675
|
try {
|
|
8296
|
-
return
|
|
8676
|
+
return fs28.statSync(path19.join(datasetPath, candidate)).isFile();
|
|
8297
8677
|
} catch {
|
|
8298
8678
|
return false;
|
|
8299
8679
|
}
|
|
@@ -8302,7 +8682,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8302
8682
|
return false;
|
|
8303
8683
|
}
|
|
8304
8684
|
try {
|
|
8305
|
-
const rows = parseCsvRows(
|
|
8685
|
+
const rows = parseCsvRows(fs28.readFileSync(path19.join(datasetPath, datasetFile), "utf8"));
|
|
8306
8686
|
if (rows.length < 2) {
|
|
8307
8687
|
return false;
|
|
8308
8688
|
}
|
|
@@ -8317,7 +8697,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8317
8697
|
}
|
|
8318
8698
|
return historyPaths.every((relativePath) => {
|
|
8319
8699
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
8320
|
-
return resolvedPath !== null &&
|
|
8700
|
+
return resolvedPath !== null && fs28.statSync(resolvedPath).isFile();
|
|
8321
8701
|
});
|
|
8322
8702
|
} catch {
|
|
8323
8703
|
return false;
|
|
@@ -8325,7 +8705,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8325
8705
|
}
|
|
8326
8706
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
8327
8707
|
try {
|
|
8328
|
-
return
|
|
8708
|
+
return fs28.statSync(path19.join(datasetPath, relativePath)).isFile();
|
|
8329
8709
|
} catch {
|
|
8330
8710
|
return false;
|
|
8331
8711
|
}
|
|
@@ -8345,10 +8725,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
8345
8725
|
return candidateFilenames.some((filename) => {
|
|
8346
8726
|
const filePath = path19.join(datasetPath, filename);
|
|
8347
8727
|
try {
|
|
8348
|
-
if (!
|
|
8728
|
+
if (!fs28.statSync(filePath).isFile()) {
|
|
8349
8729
|
return false;
|
|
8350
8730
|
}
|
|
8351
|
-
const raw =
|
|
8731
|
+
const raw = fs28.readFileSync(filePath, "utf8");
|
|
8352
8732
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
8353
8733
|
} catch {
|
|
8354
8734
|
return false;
|
|
@@ -8364,7 +8744,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
8364
8744
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
8365
8745
|
let stats;
|
|
8366
8746
|
try {
|
|
8367
|
-
stats =
|
|
8747
|
+
stats = fs28.statSync(datasetPath);
|
|
8368
8748
|
} catch {
|
|
8369
8749
|
return false;
|
|
8370
8750
|
}
|
|
@@ -8374,7 +8754,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8374
8754
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
8375
8755
|
if (!marker) {
|
|
8376
8756
|
try {
|
|
8377
|
-
return
|
|
8757
|
+
return fs28.readdirSync(datasetPath).length > 0;
|
|
8378
8758
|
} catch {
|
|
8379
8759
|
return false;
|
|
8380
8760
|
}
|
|
@@ -8382,7 +8762,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8382
8762
|
if (marker.allOf) {
|
|
8383
8763
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
8384
8764
|
try {
|
|
8385
|
-
return
|
|
8765
|
+
return fs28.statSync(path19.join(datasetPath, name)).isFile();
|
|
8386
8766
|
} catch {
|
|
8387
8767
|
return false;
|
|
8388
8768
|
}
|
|
@@ -8394,7 +8774,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8394
8774
|
if (marker.anyOf) {
|
|
8395
8775
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
8396
8776
|
try {
|
|
8397
|
-
return
|
|
8777
|
+
return fs28.statSync(path19.join(datasetPath, name)).isFile();
|
|
8398
8778
|
} catch {
|
|
8399
8779
|
return false;
|
|
8400
8780
|
}
|
|
@@ -8412,7 +8792,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8412
8792
|
}
|
|
8413
8793
|
if (marker.ext) {
|
|
8414
8794
|
try {
|
|
8415
|
-
return
|
|
8795
|
+
return fs28.readdirSync(datasetPath).some(
|
|
8416
8796
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
8417
8797
|
);
|
|
8418
8798
|
} catch {
|
|
@@ -8424,7 +8804,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8424
8804
|
async function launchBenchUi(resultsDir) {
|
|
8425
8805
|
const benchUiDir = path19.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
8426
8806
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
8427
|
-
if (!
|
|
8807
|
+
if (!fs28.existsSync(path19.join(benchUiDir, "package.json"))) {
|
|
8428
8808
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
8429
8809
|
process.exit(1);
|
|
8430
8810
|
}
|
|
@@ -8462,13 +8842,13 @@ function listDownloadableBenchmarks() {
|
|
|
8462
8842
|
}
|
|
8463
8843
|
function resolveDatasetDownloadScriptPath() {
|
|
8464
8844
|
const bundled = path19.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
8465
|
-
if (
|
|
8845
|
+
if (fs28.existsSync(bundled)) {
|
|
8466
8846
|
return bundled;
|
|
8467
8847
|
}
|
|
8468
8848
|
return path19.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
8469
8849
|
}
|
|
8470
8850
|
function isRepoCheckout() {
|
|
8471
|
-
return
|
|
8851
|
+
return fs28.existsSync(path19.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs28.existsSync(path19.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
8472
8852
|
}
|
|
8473
8853
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
8474
8854
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -8781,8 +9161,8 @@ async function exportBenchPackageResult(parsed) {
|
|
|
8781
9161
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
8782
9162
|
});
|
|
8783
9163
|
if (parsed.output) {
|
|
8784
|
-
|
|
8785
|
-
|
|
9164
|
+
fs28.mkdirSync(path19.dirname(parsed.output), { recursive: true });
|
|
9165
|
+
fs28.writeFileSync(parsed.output, rendered);
|
|
8786
9166
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
8787
9167
|
return;
|
|
8788
9168
|
}
|
|
@@ -8827,7 +9207,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
8827
9207
|
process.exit(1);
|
|
8828
9208
|
}
|
|
8829
9209
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
8830
|
-
if (!
|
|
9210
|
+
if (!fs28.existsSync(scriptPath)) {
|
|
8831
9211
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
8832
9212
|
process.exit(1);
|
|
8833
9213
|
}
|
|
@@ -9027,7 +9407,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
9027
9407
|
);
|
|
9028
9408
|
process.exit(1);
|
|
9029
9409
|
}
|
|
9030
|
-
const sourceResultSha256 = createHash4("sha256").update(
|
|
9410
|
+
const sourceResultSha256 = createHash4("sha256").update(fs28.readFileSync(latest.path)).digest("hex");
|
|
9031
9411
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
9032
9412
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
9033
9413
|
console.error(
|
|
@@ -9442,7 +9822,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
9442
9822
|
}
|
|
9443
9823
|
let decoded;
|
|
9444
9824
|
try {
|
|
9445
|
-
decoded = JSON.parse(
|
|
9825
|
+
decoded = JSON.parse(fs28.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
9446
9826
|
} catch (error) {
|
|
9447
9827
|
throw new Error(
|
|
9448
9828
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -10117,7 +10497,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
10117
10497
|
return void 0;
|
|
10118
10498
|
}
|
|
10119
10499
|
try {
|
|
10120
|
-
return
|
|
10500
|
+
return fs28.realpathSync(datasetDir);
|
|
10121
10501
|
} catch {
|
|
10122
10502
|
return datasetDir;
|
|
10123
10503
|
}
|
|
@@ -10171,7 +10551,7 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
10171
10551
|
}
|
|
10172
10552
|
function loadStandaloneConvergeCommandConfig() {
|
|
10173
10553
|
const configPath = resolveConfigPath();
|
|
10174
|
-
const raw =
|
|
10554
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
10175
10555
|
return parseConfig17(resolveRemnicConfigRecord16(raw));
|
|
10176
10556
|
}
|
|
10177
10557
|
function parseConvergePluginConfig(value) {
|
|
@@ -10200,13 +10580,13 @@ function resolveConfigPath(cliPath) {
|
|
|
10200
10580
|
path19.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
10201
10581
|
];
|
|
10202
10582
|
for (const candidate of candidates) {
|
|
10203
|
-
if (
|
|
10583
|
+
if (fs28.existsSync(candidate)) return candidate;
|
|
10204
10584
|
}
|
|
10205
10585
|
return path19.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
10206
10586
|
}
|
|
10207
10587
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
10208
10588
|
const configPath = resolveConfigPath(cliPath);
|
|
10209
|
-
if (
|
|
10589
|
+
if (fs28.existsSync(configPath)) {
|
|
10210
10590
|
return configPath;
|
|
10211
10591
|
}
|
|
10212
10592
|
if (cliPath) {
|
|
@@ -10216,7 +10596,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
10216
10596
|
}
|
|
10217
10597
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
10218
10598
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
10219
|
-
if (
|
|
10599
|
+
if (fs28.existsSync(configPath)) {
|
|
10220
10600
|
return configPath;
|
|
10221
10601
|
}
|
|
10222
10602
|
if (cliPath) {
|
|
@@ -10323,7 +10703,7 @@ function resolveMemoryDir() {
|
|
|
10323
10703
|
const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
10324
10704
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
10325
10705
|
const configPath = resolveConfigPath();
|
|
10326
|
-
const raw =
|
|
10706
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
10327
10707
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
10328
10708
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
10329
10709
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
@@ -10332,18 +10712,18 @@ function resolveMemoryDir() {
|
|
|
10332
10712
|
const standalonePath = path19.join(home, ".remnic", "memory");
|
|
10333
10713
|
const legacyStandalonePath = path19.join(home, ".engram", "memory");
|
|
10334
10714
|
const openclawPath = path19.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
10335
|
-
if (
|
|
10336
|
-
if (
|
|
10715
|
+
if (fs28.existsSync(standalonePath)) return standalonePath;
|
|
10716
|
+
if (fs28.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
10337
10717
|
return openclawPath;
|
|
10338
10718
|
})();
|
|
10339
10719
|
const manifestPath = getManifestPath();
|
|
10340
|
-
if (
|
|
10720
|
+
if (fs28.existsSync(manifestPath)) {
|
|
10341
10721
|
try {
|
|
10342
10722
|
const active = getActiveSpace();
|
|
10343
10723
|
if (active?.memoryDir) {
|
|
10344
10724
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
10345
|
-
if (!
|
|
10346
|
-
|
|
10725
|
+
if (!fs28.existsSync(activeMemoryDir)) {
|
|
10726
|
+
fs28.mkdirSync(activeMemoryDir, { recursive: true });
|
|
10347
10727
|
}
|
|
10348
10728
|
return activeMemoryDir;
|
|
10349
10729
|
}
|
|
@@ -10392,13 +10772,13 @@ function resolveOpenclawConfigPath(cliPath) {
|
|
|
10392
10772
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
10393
10773
|
if (envPath) return path19.resolve(expandTilde(envPath));
|
|
10394
10774
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
10395
|
-
if (
|
|
10775
|
+
if (fs28.existsSync(candidate)) return candidate;
|
|
10396
10776
|
}
|
|
10397
10777
|
return path19.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
10398
10778
|
}
|
|
10399
10779
|
function readOpenclawConfig(configPath) {
|
|
10400
|
-
if (!
|
|
10401
|
-
const raw =
|
|
10780
|
+
if (!fs28.existsSync(configPath)) return {};
|
|
10781
|
+
const raw = fs28.readFileSync(configPath, "utf-8");
|
|
10402
10782
|
let parsed;
|
|
10403
10783
|
try {
|
|
10404
10784
|
parsed = JSON.parse(raw);
|
|
@@ -10500,9 +10880,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
10500
10880
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
10501
10881
|
}
|
|
10502
10882
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
10503
|
-
if (!
|
|
10504
|
-
|
|
10505
|
-
|
|
10883
|
+
if (!fs28.existsSync(sourcePath)) return false;
|
|
10884
|
+
fs28.mkdirSync(path19.dirname(backupPath), { recursive: true });
|
|
10885
|
+
fs28.cpSync(sourcePath, backupPath, { recursive: true });
|
|
10506
10886
|
return true;
|
|
10507
10887
|
}
|
|
10508
10888
|
function restartOpenclawGateway() {
|
|
@@ -10521,7 +10901,7 @@ function restartOpenclawGateway() {
|
|
|
10521
10901
|
}
|
|
10522
10902
|
function cmdInit() {
|
|
10523
10903
|
const configPath = path19.join(process.cwd(), "remnic.config.json");
|
|
10524
|
-
if (
|
|
10904
|
+
if (fs28.existsSync(configPath)) {
|
|
10525
10905
|
console.log(`Config already exists: ${configPath}`);
|
|
10526
10906
|
return;
|
|
10527
10907
|
}
|
|
@@ -10537,7 +10917,7 @@ function cmdInit() {
|
|
|
10537
10917
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
10538
10918
|
}
|
|
10539
10919
|
};
|
|
10540
|
-
|
|
10920
|
+
fs28.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
10541
10921
|
console.log(`Created ${configPath}`);
|
|
10542
10922
|
console.log("\nSet these environment variables:");
|
|
10543
10923
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -10959,7 +11339,7 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
10959
11339
|
}
|
|
10960
11340
|
initLogger5();
|
|
10961
11341
|
const configPath = resolveConfigPath();
|
|
10962
|
-
const raw =
|
|
11342
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
10963
11343
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
10964
11344
|
const config = parseConfig17(remnicCfg);
|
|
10965
11345
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -11139,7 +11519,7 @@ async function cmdXray(rest) {
|
|
|
11139
11519
|
}
|
|
11140
11520
|
initLogger5();
|
|
11141
11521
|
const configPath = resolveConfigPath();
|
|
11142
|
-
const raw =
|
|
11522
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11143
11523
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11144
11524
|
const config = parseConfig17(remnicCfg);
|
|
11145
11525
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -11172,7 +11552,7 @@ async function runWhoKnowsCommand(rest, io) {
|
|
|
11172
11552
|
async function withLocalService(fn) {
|
|
11173
11553
|
initLogger5();
|
|
11174
11554
|
const configPath = resolveConfigPath();
|
|
11175
|
-
const raw =
|
|
11555
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11176
11556
|
const orchestrator = new Orchestrator10(parseConfig17(resolveRemnicConfigRecord16(raw)));
|
|
11177
11557
|
await orchestrator.initialize();
|
|
11178
11558
|
await orchestrator.deferredReady;
|
|
@@ -11205,7 +11585,7 @@ async function cmdPromotionCandidates(rest) {
|
|
|
11205
11585
|
async function cmdVersions(rest) {
|
|
11206
11586
|
initLogger5();
|
|
11207
11587
|
const configPath = resolveConfigPath();
|
|
11208
|
-
const raw =
|
|
11588
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11209
11589
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11210
11590
|
const config = parseConfig17(remnicCfg);
|
|
11211
11591
|
if (!config.versioningEnabled) {
|
|
@@ -11321,7 +11701,7 @@ Options:
|
|
|
11321
11701
|
async function cmdEnrich(rest) {
|
|
11322
11702
|
initLogger5();
|
|
11323
11703
|
const configPath = resolveConfigPath();
|
|
11324
|
-
const raw =
|
|
11704
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11325
11705
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11326
11706
|
const config = parseConfig17(remnicCfg);
|
|
11327
11707
|
const subcommand = rest[0];
|
|
@@ -11515,7 +11895,7 @@ Registered providers:`);
|
|
|
11515
11895
|
async function cmdExtensions(action, rest) {
|
|
11516
11896
|
initLogger5();
|
|
11517
11897
|
const configPath = resolveConfigPath();
|
|
11518
|
-
const raw =
|
|
11898
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11519
11899
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11520
11900
|
const config = parseConfig17(remnicCfg);
|
|
11521
11901
|
const root = resolveExtensionsRoot(config);
|
|
@@ -11566,7 +11946,7 @@ Root: ${root}`);
|
|
|
11566
11946
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
11567
11947
|
let entries = [];
|
|
11568
11948
|
try {
|
|
11569
|
-
entries =
|
|
11949
|
+
entries = fs28.readdirSync(root);
|
|
11570
11950
|
} catch {
|
|
11571
11951
|
console.log(`Extensions root does not exist: ${root}`);
|
|
11572
11952
|
process.exitCode = 0;
|
|
@@ -11577,7 +11957,7 @@ Root: ${root}`);
|
|
|
11577
11957
|
for (const entry of entries) {
|
|
11578
11958
|
const entryPath = path19.join(root, entry);
|
|
11579
11959
|
try {
|
|
11580
|
-
if (!
|
|
11960
|
+
if (!fs28.statSync(entryPath).isDirectory()) continue;
|
|
11581
11961
|
} catch {
|
|
11582
11962
|
continue;
|
|
11583
11963
|
}
|
|
@@ -11609,7 +11989,7 @@ Root: ${root}`);
|
|
|
11609
11989
|
async function cmdBriefing(rest) {
|
|
11610
11990
|
initLogger5();
|
|
11611
11991
|
const configPath = resolveConfigPath();
|
|
11612
|
-
const raw =
|
|
11992
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
11613
11993
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11614
11994
|
const config = parseConfig17(remnicCfg);
|
|
11615
11995
|
if (!config.briefing.enabled) {
|
|
@@ -11689,10 +12069,10 @@ async function cmdBriefing(rest) {
|
|
|
11689
12069
|
if (save) {
|
|
11690
12070
|
try {
|
|
11691
12071
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
11692
|
-
|
|
12072
|
+
fs28.mkdirSync(saveDir, { recursive: true });
|
|
11693
12073
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
11694
12074
|
const filePath = path19.join(saveDir, filename);
|
|
11695
|
-
|
|
12075
|
+
fs28.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
11696
12076
|
console.error(`Saved briefing: ${filePath}`);
|
|
11697
12077
|
} catch (err) {
|
|
11698
12078
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -11710,7 +12090,7 @@ async function cmdDoctor() {
|
|
|
11710
12090
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
11711
12091
|
});
|
|
11712
12092
|
const configPath = resolveConfigPath();
|
|
11713
|
-
const configExists =
|
|
12093
|
+
const configExists = fs28.existsSync(configPath);
|
|
11714
12094
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
11715
12095
|
let standaloneConfig;
|
|
11716
12096
|
let standaloneConfigError;
|
|
@@ -11718,7 +12098,7 @@ async function cmdDoctor() {
|
|
|
11718
12098
|
let configuredNs = { invalid: false };
|
|
11719
12099
|
if (configExists) {
|
|
11720
12100
|
try {
|
|
11721
|
-
const raw = JSON.parse(
|
|
12101
|
+
const raw = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
11722
12102
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11723
12103
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
11724
12104
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
@@ -11734,7 +12114,7 @@ async function cmdDoctor() {
|
|
|
11734
12114
|
memoryDir = parseConfig17({}).memoryDir;
|
|
11735
12115
|
}
|
|
11736
12116
|
try {
|
|
11737
|
-
|
|
12117
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
11738
12118
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
11739
12119
|
} catch {
|
|
11740
12120
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -11763,7 +12143,7 @@ async function cmdDoctor() {
|
|
|
11763
12143
|
});
|
|
11764
12144
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
11765
12145
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
11766
|
-
const openclawConfigExists =
|
|
12146
|
+
const openclawConfigExists = fs28.existsSync(openclawConfigPath);
|
|
11767
12147
|
let openclawConfig = {};
|
|
11768
12148
|
let openclawConfigValid = false;
|
|
11769
12149
|
let openclawPluginModeConfigured = false;
|
|
@@ -11771,7 +12151,7 @@ async function cmdDoctor() {
|
|
|
11771
12151
|
let activeOpenclawEntryConfig = null;
|
|
11772
12152
|
if (openclawConfigExists) {
|
|
11773
12153
|
try {
|
|
11774
|
-
const parsed = JSON.parse(
|
|
12154
|
+
const parsed = JSON.parse(fs28.readFileSync(openclawConfigPath, "utf-8"));
|
|
11775
12155
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
11776
12156
|
openclawConfig = parsed;
|
|
11777
12157
|
openclawConfigValid = true;
|
|
@@ -11851,9 +12231,9 @@ async function cmdDoctor() {
|
|
|
11851
12231
|
let memDirOk = false;
|
|
11852
12232
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
11853
12233
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
11854
|
-
if (
|
|
12234
|
+
if (fs28.existsSync(resolvedMemDir)) {
|
|
11855
12235
|
try {
|
|
11856
|
-
const stat2 =
|
|
12236
|
+
const stat2 = fs28.statSync(resolvedMemDir);
|
|
11857
12237
|
if (stat2.isDirectory()) {
|
|
11858
12238
|
memDirOk = true;
|
|
11859
12239
|
memDirDetail = resolvedMemDir;
|
|
@@ -12008,12 +12388,12 @@ async function cmdDoctor() {
|
|
|
12008
12388
|
}
|
|
12009
12389
|
function cmdConfig() {
|
|
12010
12390
|
const configPath = resolveConfigPath();
|
|
12011
|
-
if (!
|
|
12391
|
+
if (!fs28.existsSync(configPath)) {
|
|
12012
12392
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
12013
12393
|
return;
|
|
12014
12394
|
}
|
|
12015
12395
|
console.log(`Config: ${configPath}`);
|
|
12016
|
-
const rawConfig =
|
|
12396
|
+
const rawConfig = fs28.readFileSync(configPath, "utf8");
|
|
12017
12397
|
const redacted = rawConfig.replace(
|
|
12018
12398
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
12019
12399
|
"$1[REDACTED]$3"
|
|
@@ -12121,7 +12501,7 @@ async function cmdReview(action, rest) {
|
|
|
12121
12501
|
const configPath = resolveConfigPath();
|
|
12122
12502
|
let tombstonesConfig = null;
|
|
12123
12503
|
try {
|
|
12124
|
-
const rawCfg =
|
|
12504
|
+
const rawCfg = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
12125
12505
|
const remnicCfg = resolveRemnicConfigRecord16(rawCfg);
|
|
12126
12506
|
const config = parseConfig17(remnicCfg);
|
|
12127
12507
|
tombstonesConfig = {
|
|
@@ -12865,7 +13245,7 @@ async function pushOfflineFileContent(args) {
|
|
|
12865
13245
|
}
|
|
12866
13246
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
12867
13247
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
12868
|
-
const stat2 =
|
|
13248
|
+
const stat2 = fs28.statSync(filePath);
|
|
12869
13249
|
if (stat2.mtimeMs !== args.file.mtimeMs) {
|
|
12870
13250
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
12871
13251
|
}
|
|
@@ -13356,7 +13736,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
13356
13736
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
13357
13737
|
}
|
|
13358
13738
|
async function runOfflineSyncOnce(options) {
|
|
13359
|
-
|
|
13739
|
+
fs28.mkdirSync(options.memoryDir, { recursive: true });
|
|
13360
13740
|
let activeStatePath = options.statePath;
|
|
13361
13741
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
13362
13742
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -13989,7 +14369,7 @@ Environment fallbacks:
|
|
|
13989
14369
|
const configPath = resolveConfigPath();
|
|
13990
14370
|
let config;
|
|
13991
14371
|
try {
|
|
13992
|
-
const rawConfig =
|
|
14372
|
+
const rawConfig = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
13993
14373
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
13994
14374
|
} catch {
|
|
13995
14375
|
throw new Error(
|
|
@@ -14004,7 +14384,7 @@ Environment fallbacks:
|
|
|
14004
14384
|
const statePath = statePathExplicit ? path19.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
14005
14385
|
if (action === "prepare") {
|
|
14006
14386
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
14007
|
-
|
|
14387
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
14008
14388
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
14009
14389
|
remoteUrl,
|
|
14010
14390
|
token,
|
|
@@ -14103,7 +14483,7 @@ Environment fallbacks:
|
|
|
14103
14483
|
return;
|
|
14104
14484
|
}
|
|
14105
14485
|
if (action === "status") {
|
|
14106
|
-
|
|
14486
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
14107
14487
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
14108
14488
|
if (state && remoteUrl && statePath) {
|
|
14109
14489
|
assertOfflineStateMatches({
|
|
@@ -14241,7 +14621,7 @@ function cmdDedup(json) {
|
|
|
14241
14621
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
14242
14622
|
if (!configPath) return fallback;
|
|
14243
14623
|
try {
|
|
14244
|
-
const parsed = JSON.parse(
|
|
14624
|
+
const parsed = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
14245
14625
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
14246
14626
|
const { token: _token, ...config } = parsed;
|
|
14247
14627
|
return config;
|
|
@@ -14419,7 +14799,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14419
14799
|
const pub = factory();
|
|
14420
14800
|
const available = await pub.isHostAvailable();
|
|
14421
14801
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
14422
|
-
const extensionExists = available && extRoot ?
|
|
14802
|
+
const extensionExists = available && extRoot ? fs28.existsSync(extRoot) : false;
|
|
14423
14803
|
publisherChecks.push({
|
|
14424
14804
|
name: `Publisher: ${targetHostId}`,
|
|
14425
14805
|
ok: !available || extensionExists,
|
|
@@ -14493,7 +14873,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14493
14873
|
let connectorsCfg;
|
|
14494
14874
|
const configPath = resolveConfigPath();
|
|
14495
14875
|
try {
|
|
14496
|
-
const raw =
|
|
14876
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14497
14877
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
14498
14878
|
} catch {
|
|
14499
14879
|
process.stderr.write(
|
|
@@ -14569,7 +14949,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14569
14949
|
}
|
|
14570
14950
|
initLogger5();
|
|
14571
14951
|
const configPath = resolveConfigPath();
|
|
14572
|
-
const raw =
|
|
14952
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14573
14953
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
14574
14954
|
const config = parseConfig17(remnicCfg);
|
|
14575
14955
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -14694,7 +15074,7 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
14694
15074
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
14695
15075
|
process.exit(1);
|
|
14696
15076
|
}
|
|
14697
|
-
const rawConfig =
|
|
15077
|
+
const rawConfig = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14698
15078
|
const pluginConfig = resolveRemnicConfigRecord16(rawConfig);
|
|
14699
15079
|
const config = parseConfig17(pluginConfig);
|
|
14700
15080
|
if (subAction === "generate") {
|
|
@@ -14716,13 +15096,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
14716
15096
|
} else if (subAction === "validate") {
|
|
14717
15097
|
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path19.join(process.cwd(), "marketplace.json");
|
|
14718
15098
|
const resolved = path19.resolve(targetPath);
|
|
14719
|
-
if (!
|
|
15099
|
+
if (!fs28.existsSync(resolved)) {
|
|
14720
15100
|
console.error(`File not found: ${resolved}`);
|
|
14721
15101
|
process.exit(1);
|
|
14722
15102
|
}
|
|
14723
15103
|
let parsed;
|
|
14724
15104
|
try {
|
|
14725
|
-
parsed = JSON.parse(
|
|
15105
|
+
parsed = JSON.parse(fs28.readFileSync(resolved, "utf8"));
|
|
14726
15106
|
} catch {
|
|
14727
15107
|
console.error(`Invalid JSON in ${resolved}`);
|
|
14728
15108
|
process.exit(1);
|
|
@@ -14925,7 +15305,7 @@ async function cmdSpace(action, rest, json) {
|
|
|
14925
15305
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
14926
15306
|
initLogger5();
|
|
14927
15307
|
const configPath = resolveConfigPath();
|
|
14928
|
-
const raw =
|
|
15308
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
14929
15309
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
14930
15310
|
const config = parseConfig17(remnicCfg);
|
|
14931
15311
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -15330,7 +15710,7 @@ function readPid() {
|
|
|
15330
15710
|
function inferPort() {
|
|
15331
15711
|
try {
|
|
15332
15712
|
const configPath = resolveConfigPath();
|
|
15333
|
-
const raw = JSON.parse(
|
|
15713
|
+
const raw = JSON.parse(fs28.readFileSync(configPath, "utf8"));
|
|
15334
15714
|
return raw.server?.port ?? 4318;
|
|
15335
15715
|
} catch {
|
|
15336
15716
|
return 4318;
|
|
@@ -15425,13 +15805,13 @@ function daemonInstall() {
|
|
|
15425
15805
|
process.exit(1);
|
|
15426
15806
|
}
|
|
15427
15807
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
15428
|
-
|
|
15808
|
+
fs28.mkdirSync(LOGS_DIR, { recursive: true });
|
|
15429
15809
|
if (isMacOS()) {
|
|
15430
15810
|
const templatePath = path19.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
15431
|
-
const template =
|
|
15811
|
+
const template = fs28.readFileSync(templatePath, "utf8");
|
|
15432
15812
|
const plist = renderTemplate(template, vars);
|
|
15433
|
-
|
|
15434
|
-
|
|
15813
|
+
fs28.mkdirSync(path19.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
15814
|
+
fs28.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
15435
15815
|
try {
|
|
15436
15816
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
15437
15817
|
} catch (err) {
|
|
@@ -15448,10 +15828,10 @@ function daemonInstall() {
|
|
|
15448
15828
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
15449
15829
|
} else if (isLinux()) {
|
|
15450
15830
|
const templatePath = path19.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
15451
|
-
const template =
|
|
15831
|
+
const template = fs28.readFileSync(templatePath, "utf8");
|
|
15452
15832
|
const unit = renderTemplate(template, vars);
|
|
15453
|
-
|
|
15454
|
-
|
|
15833
|
+
fs28.mkdirSync(path19.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
15834
|
+
fs28.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
15455
15835
|
try {
|
|
15456
15836
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
15457
15837
|
} catch (err) {
|
|
@@ -15487,7 +15867,7 @@ function daemonUninstall() {
|
|
|
15487
15867
|
} catch {
|
|
15488
15868
|
}
|
|
15489
15869
|
try {
|
|
15490
|
-
|
|
15870
|
+
fs28.unlinkSync(plistPath);
|
|
15491
15871
|
removed = true;
|
|
15492
15872
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
15493
15873
|
} catch {
|
|
@@ -15507,7 +15887,7 @@ function daemonUninstall() {
|
|
|
15507
15887
|
let removed = false;
|
|
15508
15888
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
15509
15889
|
try {
|
|
15510
|
-
|
|
15890
|
+
fs28.unlinkSync(unitPath);
|
|
15511
15891
|
removed = true;
|
|
15512
15892
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
15513
15893
|
} catch {
|
|
@@ -15574,11 +15954,11 @@ async function daemonStatus() {
|
|
|
15574
15954
|
console.log(` Port: ${port}`);
|
|
15575
15955
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
15576
15956
|
console.log(` Platform: ${process.platform}`);
|
|
15577
|
-
console.log(` PID file: ${
|
|
15578
|
-
console.log(` Log file: ${
|
|
15957
|
+
console.log(` PID file: ${fs28.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
15958
|
+
console.log(` Log file: ${fs28.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
15579
15959
|
try {
|
|
15580
15960
|
const configPath = resolveConfigPath();
|
|
15581
|
-
const raw =
|
|
15961
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
15582
15962
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15583
15963
|
const config = parseConfig17(remnicCfg);
|
|
15584
15964
|
const extRoot = resolveExtensionsRoot(config);
|
|
@@ -15619,9 +15999,9 @@ function daemonStart() {
|
|
|
15619
15999
|
return;
|
|
15620
16000
|
}
|
|
15621
16001
|
}
|
|
15622
|
-
|
|
15623
|
-
|
|
15624
|
-
const logStream =
|
|
16002
|
+
fs28.mkdirSync(PID_DIR, { recursive: true });
|
|
16003
|
+
fs28.mkdirSync(LOGS_DIR, { recursive: true });
|
|
16004
|
+
const logStream = fs28.openSync(LOG_FILE, "a");
|
|
15625
16005
|
const serverBin = resolveServerBin();
|
|
15626
16006
|
const isSource = serverBin.endsWith(".ts");
|
|
15627
16007
|
let cmd;
|
|
@@ -15643,7 +16023,7 @@ function daemonStart() {
|
|
|
15643
16023
|
}
|
|
15644
16024
|
});
|
|
15645
16025
|
child.unref();
|
|
15646
|
-
|
|
16026
|
+
fs28.writeFileSync(PID_FILE, String(child.pid));
|
|
15647
16027
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
15648
16028
|
console.log(` Log: ${LOG_FILE}`);
|
|
15649
16029
|
}
|
|
@@ -15677,11 +16057,11 @@ function daemonStop() {
|
|
|
15677
16057
|
console.log("Process not found (cleaning up PID file)");
|
|
15678
16058
|
}
|
|
15679
16059
|
try {
|
|
15680
|
-
|
|
16060
|
+
fs28.unlinkSync(PID_FILE);
|
|
15681
16061
|
} catch {
|
|
15682
16062
|
}
|
|
15683
16063
|
try {
|
|
15684
|
-
|
|
16064
|
+
fs28.unlinkSync(LEGACY_PID_FILE);
|
|
15685
16065
|
} catch {
|
|
15686
16066
|
}
|
|
15687
16067
|
}
|
|
@@ -15809,7 +16189,7 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
15809
16189
|
async function cmdBinary(rest) {
|
|
15810
16190
|
initLogger5();
|
|
15811
16191
|
const configPath = resolveConfigPath();
|
|
15812
|
-
const raw =
|
|
16192
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
15813
16193
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15814
16194
|
const config = parseConfig17(remnicCfg);
|
|
15815
16195
|
const memoryDir = resolveMemoryDir();
|
|
@@ -16000,7 +16380,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
16000
16380
|
} else if (slotIsActiveLegacy) {
|
|
16001
16381
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
16002
16382
|
}
|
|
16003
|
-
if (!
|
|
16383
|
+
if (!fs28.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
16004
16384
|
if (hasLegacy && migrateLegacy) {
|
|
16005
16385
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
16006
16386
|
}
|
|
@@ -16020,8 +16400,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
16020
16400
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
16021
16401
|
return;
|
|
16022
16402
|
}
|
|
16023
|
-
if (
|
|
16024
|
-
const st =
|
|
16403
|
+
if (fs28.existsSync(memoryDir)) {
|
|
16404
|
+
const st = fs28.statSync(memoryDir);
|
|
16025
16405
|
if (!st.isDirectory()) {
|
|
16026
16406
|
throw new Error(
|
|
16027
16407
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -16029,12 +16409,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
16029
16409
|
);
|
|
16030
16410
|
}
|
|
16031
16411
|
} else {
|
|
16032
|
-
|
|
16412
|
+
fs28.mkdirSync(memoryDir, { recursive: true });
|
|
16033
16413
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
16034
16414
|
}
|
|
16035
16415
|
const configDir = path19.dirname(configPath);
|
|
16036
|
-
if (!
|
|
16037
|
-
|
|
16416
|
+
if (!fs28.existsSync(configDir)) {
|
|
16417
|
+
fs28.mkdirSync(configDir, { recursive: true });
|
|
16038
16418
|
}
|
|
16039
16419
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
16040
16420
|
console.log("\nDone! Summary of changes:");
|
|
@@ -16063,7 +16443,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
16063
16443
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
16064
16444
|
const fallbackMemoryDir = path19.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
16065
16445
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
16066
|
-
const configExistedBefore =
|
|
16446
|
+
const configExistedBefore = fs28.existsSync(configPath);
|
|
16067
16447
|
const existingConfig = readOpenclawConfig(configPath);
|
|
16068
16448
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
16069
16449
|
const preservedMemoryDir = opts.memoryDir ? path19.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
@@ -16288,13 +16668,13 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
16288
16668
|
}
|
|
16289
16669
|
function createOpenclawUpgradeBackupDir() {
|
|
16290
16670
|
const backupsRoot = path19.join(resolveOpenclawStateDir(), "backups");
|
|
16291
|
-
|
|
16292
|
-
return
|
|
16671
|
+
fs28.mkdirSync(backupsRoot, { recursive: true });
|
|
16672
|
+
return fs28.mkdtempSync(path19.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
16293
16673
|
}
|
|
16294
16674
|
async function cmdTaxonomy(rest) {
|
|
16295
16675
|
initLogger5();
|
|
16296
16676
|
const configPath = resolveConfigPath();
|
|
16297
|
-
const raw =
|
|
16677
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
16298
16678
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16299
16679
|
const config = parseConfig17(remnicCfg);
|
|
16300
16680
|
if (!config.taxonomyEnabled) {
|
|
@@ -16332,8 +16712,8 @@ async function cmdTaxonomy(rest) {
|
|
|
16332
16712
|
console.log(doc);
|
|
16333
16713
|
if (config.taxonomyAutoGenResolver) {
|
|
16334
16714
|
const resolverPath = path19.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16335
|
-
|
|
16336
|
-
|
|
16715
|
+
fs28.mkdirSync(path19.dirname(resolverPath), { recursive: true });
|
|
16716
|
+
fs28.writeFileSync(resolverPath, doc);
|
|
16337
16717
|
console.error(`Written: ${resolverPath}`);
|
|
16338
16718
|
}
|
|
16339
16719
|
break;
|
|
@@ -16379,7 +16759,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16379
16759
|
if (config.taxonomyAutoGenResolver) {
|
|
16380
16760
|
const doc = generateResolverDocument(taxonomy);
|
|
16381
16761
|
const resolverPath = path19.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16382
|
-
|
|
16762
|
+
fs28.writeFileSync(resolverPath, doc);
|
|
16383
16763
|
console.error(`Regenerated: ${resolverPath}`);
|
|
16384
16764
|
}
|
|
16385
16765
|
break;
|
|
@@ -16410,7 +16790,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16410
16790
|
if (config.taxonomyAutoGenResolver) {
|
|
16411
16791
|
const doc = generateResolverDocument(taxonomy);
|
|
16412
16792
|
const resolverPath = path19.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16413
|
-
|
|
16793
|
+
fs28.writeFileSync(resolverPath, doc);
|
|
16414
16794
|
console.error(`Regenerated: ${resolverPath}`);
|
|
16415
16795
|
}
|
|
16416
16796
|
break;
|
|
@@ -16601,12 +16981,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
16601
16981
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
16602
16982
|
);
|
|
16603
16983
|
}
|
|
16604
|
-
if (!
|
|
16984
|
+
if (!fs28.existsSync(args.memoryDir)) {
|
|
16605
16985
|
throw new Error(
|
|
16606
16986
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
16607
16987
|
);
|
|
16608
16988
|
}
|
|
16609
|
-
if (!
|
|
16989
|
+
if (!fs28.statSync(args.memoryDir).isDirectory()) {
|
|
16610
16990
|
throw new Error(
|
|
16611
16991
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
16612
16992
|
);
|
|
@@ -16692,10 +17072,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
16692
17072
|
}
|
|
16693
17073
|
const formatted = adapter.formatRecords(records);
|
|
16694
17074
|
const outDir = path19.dirname(args.output);
|
|
16695
|
-
|
|
17075
|
+
fs28.mkdirSync(outDir, { recursive: true });
|
|
16696
17076
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
16697
|
-
|
|
16698
|
-
|
|
17077
|
+
fs28.writeFileSync(tmpPath, formatted, "utf-8");
|
|
17078
|
+
fs28.renameSync(tmpPath, args.output);
|
|
16699
17079
|
stdout.write(
|
|
16700
17080
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
16701
17081
|
`
|
|
@@ -16738,6 +17118,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16738
17118
|
await cmdQuery(queryText, json, explain);
|
|
16739
17119
|
break;
|
|
16740
17120
|
}
|
|
17121
|
+
case "recall":
|
|
17122
|
+
await runRecallNavigateCommand(rest);
|
|
17123
|
+
break;
|
|
16741
17124
|
case "action-confidence":
|
|
16742
17125
|
await cmdActionConfidence(rest);
|
|
16743
17126
|
break;
|
|
@@ -16873,7 +17256,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16873
17256
|
}
|
|
16874
17257
|
}, 500);
|
|
16875
17258
|
};
|
|
16876
|
-
|
|
17259
|
+
fs28.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
16877
17260
|
if (filename && filename.startsWith(".")) return;
|
|
16878
17261
|
rebuild();
|
|
16879
17262
|
});
|
|
@@ -16881,12 +17264,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
16881
17264
|
});
|
|
16882
17265
|
} else if (subAction === "validate") {
|
|
16883
17266
|
const treeDir = outputDir;
|
|
16884
|
-
if (!
|
|
17267
|
+
if (!fs28.existsSync(treeDir)) {
|
|
16885
17268
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
16886
17269
|
process.exit(1);
|
|
16887
17270
|
}
|
|
16888
17271
|
const indexPath = path19.join(treeDir, "INDEX.md");
|
|
16889
|
-
if (!
|
|
17272
|
+
if (!fs28.existsSync(indexPath)) {
|
|
16890
17273
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
16891
17274
|
process.exit(1);
|
|
16892
17275
|
}
|
|
@@ -17092,6 +17475,18 @@ Other:
|
|
|
17092
17475
|
case "journal":
|
|
17093
17476
|
await runJournalBinaryCommand(rest);
|
|
17094
17477
|
break;
|
|
17478
|
+
case "journal-vault":
|
|
17479
|
+
await runJournalVaultBinaryCommand(rest);
|
|
17480
|
+
break;
|
|
17481
|
+
case "activity-privacy":
|
|
17482
|
+
await runActivityPrivacyBinaryCommand(rest);
|
|
17483
|
+
break;
|
|
17484
|
+
case "activity-export":
|
|
17485
|
+
await runActivityExportBinaryCommand(rest);
|
|
17486
|
+
break;
|
|
17487
|
+
case "vault-publish":
|
|
17488
|
+
await runVaultPublishBinaryCommand(rest);
|
|
17489
|
+
break;
|
|
17095
17490
|
case "codegraph":
|
|
17096
17491
|
await runCodegraphBinaryCommand(rest);
|
|
17097
17492
|
break;
|
|
@@ -17108,7 +17503,7 @@ Other:
|
|
|
17108
17503
|
const targetFactory = async () => {
|
|
17109
17504
|
if (!orchestratorSingleton) {
|
|
17110
17505
|
const configPath = resolveConfigPath();
|
|
17111
|
-
const raw =
|
|
17506
|
+
const raw = fs28.existsSync(configPath) ? JSON.parse(fs28.readFileSync(configPath, "utf8")) : {};
|
|
17112
17507
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
17113
17508
|
const config = parseConfig17(remnicCfg);
|
|
17114
17509
|
orchestratorSingleton = new Orchestrator10(config);
|