@remnic/cli 9.69.30 → 9.69.31
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 +285 -229
- 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 fs29 from "fs";
|
|
22
22
|
import os3 from "os";
|
|
23
23
|
import path18 from "path";
|
|
24
24
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -1403,7 +1403,7 @@ async function loadWecloneExportModule() {
|
|
|
1403
1403
|
}
|
|
1404
1404
|
|
|
1405
1405
|
// src/converge.ts
|
|
1406
|
-
import * as
|
|
1406
|
+
import * as fs17 from "fs";
|
|
1407
1407
|
import { createHash as createHash3 } from "crypto";
|
|
1408
1408
|
import * as path2 from "path";
|
|
1409
1409
|
import {
|
|
@@ -1771,6 +1771,40 @@ async function convergeWatch(options) {
|
|
|
1771
1771
|
return outcome;
|
|
1772
1772
|
}
|
|
1773
1773
|
|
|
1774
|
+
// src/converge-token-channel.ts
|
|
1775
|
+
import * as fs16 from "fs";
|
|
1776
|
+
function parseConvergeTokenFileFlag(raw) {
|
|
1777
|
+
return raw !== void 0 && raw.length > 0 ? raw : null;
|
|
1778
|
+
}
|
|
1779
|
+
function resolveConvergeTokenChannel(input, env) {
|
|
1780
|
+
if (input.argvToken !== void 0 && input.argvToken.length === 0) {
|
|
1781
|
+
return { ok: false, error: "--token requires a non-empty value" };
|
|
1782
|
+
}
|
|
1783
|
+
const tokenFromArgv = input.argvToken !== void 0;
|
|
1784
|
+
if (!tokenFromArgv && input.tokenFile !== void 0) {
|
|
1785
|
+
try {
|
|
1786
|
+
const stat2 = fs16.statSync(input.tokenFile);
|
|
1787
|
+
if (process.platform !== "win32" && stat2.mode & 63) {
|
|
1788
|
+
return { ok: false, error: `--token-file ${input.tokenFile} must not be group- or world-readable (chmod 600)` };
|
|
1789
|
+
}
|
|
1790
|
+
const token = fs16.readFileSync(input.tokenFile, "utf8").trim();
|
|
1791
|
+
if (token.length === 0) {
|
|
1792
|
+
return { ok: false, error: `--token-file ${input.tokenFile} is empty` };
|
|
1793
|
+
}
|
|
1794
|
+
return { ok: true, token, tokenFromArgv };
|
|
1795
|
+
} catch (err) {
|
|
1796
|
+
return { ok: false, error: `--token-file ${input.tokenFile} could not be read: ${err}` };
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
if (!tokenFromArgv && input.tokenFile === void 0 && env.REMNIC_CONVERGE_PEER_TOKEN !== void 0) {
|
|
1800
|
+
if (env.REMNIC_CONVERGE_PEER_TOKEN.length === 0) {
|
|
1801
|
+
return { ok: false, error: "REMNIC_CONVERGE_PEER_TOKEN is set but empty" };
|
|
1802
|
+
}
|
|
1803
|
+
return { ok: true, token: env.REMNIC_CONVERGE_PEER_TOKEN, tokenFromArgv: false };
|
|
1804
|
+
}
|
|
1805
|
+
return { ok: true, token: input.argvToken, tokenFromArgv };
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1774
1808
|
// src/converge.ts
|
|
1775
1809
|
import { resolveAgentAccessAuthToken } from "@remnic/core/resolve-auth-token.js";
|
|
1776
1810
|
|
|
@@ -2331,7 +2365,7 @@ async function readLocalTombstoneEvidence(rootDir) {
|
|
|
2331
2365
|
for (const relativePath of TOMBSTONE_PATHS) {
|
|
2332
2366
|
let content;
|
|
2333
2367
|
try {
|
|
2334
|
-
content = await
|
|
2368
|
+
content = await fs17.promises.readFile(path2.join(rootDir, relativePath), "utf-8");
|
|
2335
2369
|
} catch (error) {
|
|
2336
2370
|
if (error.code === "ENOENT") continue;
|
|
2337
2371
|
throw error;
|
|
@@ -2346,7 +2380,7 @@ async function discoverCursorNamespaces(memoryDir, peerUrl) {
|
|
|
2346
2380
|
const cursorDir = path2.join(path2.resolve(memoryDir), ".remnic", "state", "converge-cursors");
|
|
2347
2381
|
let entries;
|
|
2348
2382
|
try {
|
|
2349
|
-
entries = await
|
|
2383
|
+
entries = await fs17.promises.readdir(cursorDir, { withFileTypes: true });
|
|
2350
2384
|
} catch (error) {
|
|
2351
2385
|
if (error.code === "ENOENT") return [];
|
|
2352
2386
|
throw error;
|
|
@@ -2842,7 +2876,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2842
2876
|
if (current.sha256 !== entry.localSha256) {
|
|
2843
2877
|
throw new Error(`local file changed during push: ${localPath}`);
|
|
2844
2878
|
}
|
|
2845
|
-
const stat2 = await
|
|
2879
|
+
const stat2 = await fs17.promises.stat(filePath);
|
|
2846
2880
|
let chunks;
|
|
2847
2881
|
let chunkOffset = 0;
|
|
2848
2882
|
const resetChunks = async () => {
|
|
@@ -3115,48 +3149,54 @@ function convergeTimeoutFlagToMs(seconds) {
|
|
|
3115
3149
|
async function cmdConverge(action, rest, json, config = parseConfig13({})) {
|
|
3116
3150
|
if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
3117
3151
|
console.log(`Usage: remnic converge <plan|apply|watch> [options]
|
|
3118
|
-
|
|
3119
3152
|
Subcommands:
|
|
3120
3153
|
plan Compute and display reconciliation plan
|
|
3121
|
-
apply
|
|
3122
|
-
watch Run apply on a cadence until stopped (scheduled replication)
|
|
3154
|
+
apply/watch Transport (aliases: transport, sync) / scheduled watch
|
|
3123
3155
|
|
|
3124
|
-
Options:
|
|
3125
3156
|
--peer <url> Peer server URL (or --remote-url / --remote)
|
|
3126
|
-
--token <
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
--
|
|
3131
|
-
Watch cadence in seconds (watch only; default 300, min 1)
|
|
3132
|
-
--timeout <seconds>
|
|
3133
|
-
Per-request peer HTTP timeout (default 30; use 300+ for
|
|
3134
|
-
boot-scale namespaces of ~100k files)
|
|
3157
|
+
--token <t> / --token-file <p> / REMNIC_CONVERGE_PEER_TOKEN Credential
|
|
3158
|
+
channels (--token is argv-visible; prefer the other two)
|
|
3159
|
+
--conflict-policy <policy> Override (newest-wins|manual; default newest-wins)
|
|
3160
|
+
--interval <seconds> Watch cadence seconds (watch only; default 300)
|
|
3161
|
+
--timeout <seconds> Peer HTTP timeout seconds (default 30; boot-scale 300+)
|
|
3135
3162
|
--dry-run Simulate transfers without mutating disk or remote peer
|
|
3136
3163
|
--json Output detailed JSON plan report
|
|
3137
3164
|
`);
|
|
3138
3165
|
return;
|
|
3139
3166
|
}
|
|
3140
3167
|
if (action !== "plan" && action !== "apply" && action !== "transport" && action !== "sync" && action !== "watch") {
|
|
3141
|
-
process.stderr.write(`converge: unknown action "${action}". Use
|
|
3168
|
+
process.stderr.write(`converge: unknown action "${action}". Use plan, apply, or watch.
|
|
3142
3169
|
`);
|
|
3143
3170
|
process.exitCode = 2;
|
|
3144
3171
|
return;
|
|
3145
3172
|
}
|
|
3146
3173
|
let peerUrl;
|
|
3147
3174
|
let peerToken;
|
|
3175
|
+
let tokenFile;
|
|
3148
3176
|
let dryRun = false;
|
|
3149
3177
|
let conflictPolicy;
|
|
3150
3178
|
let intervalSeconds;
|
|
3151
3179
|
let timeoutMsFlag;
|
|
3152
3180
|
for (let i = 0; i < rest.length; i += 1) {
|
|
3153
3181
|
const arg = rest[i];
|
|
3154
|
-
if (
|
|
3155
|
-
|
|
3182
|
+
if (arg === "--token-file") {
|
|
3183
|
+
tokenFile = parseConvergeTokenFileFlag(rest[i + 1]);
|
|
3184
|
+
if (tokenFile === null) {
|
|
3185
|
+
process.stderr.write("converge: --token-file requires a path.\n");
|
|
3186
|
+
process.exitCode = 2;
|
|
3187
|
+
return;
|
|
3188
|
+
}
|
|
3156
3189
|
i += 1;
|
|
3157
3190
|
} else if (arg === "--token" && rest[i + 1]) {
|
|
3158
3191
|
peerToken = rest[i + 1];
|
|
3159
3192
|
i += 1;
|
|
3193
|
+
} else if (arg === "--token") {
|
|
3194
|
+
process.stderr.write("converge: --token requires a value.\n");
|
|
3195
|
+
process.exitCode = 2;
|
|
3196
|
+
return;
|
|
3197
|
+
} else if ((arg === "--peer" || arg === "--remote-url" || arg === "--remote") && rest[i + 1]) {
|
|
3198
|
+
peerUrl = rest[i + 1];
|
|
3199
|
+
i += 1;
|
|
3160
3200
|
} else if (arg === "--dry-run") {
|
|
3161
3201
|
dryRun = true;
|
|
3162
3202
|
} else if (arg === "--interval") {
|
|
@@ -3188,6 +3228,22 @@ Options:
|
|
|
3188
3228
|
i += 1;
|
|
3189
3229
|
}
|
|
3190
3230
|
}
|
|
3231
|
+
const tokenChannel = resolveConvergeTokenChannel(
|
|
3232
|
+
{ argvToken: peerToken, tokenFile: tokenFile ?? void 0 },
|
|
3233
|
+
process.env
|
|
3234
|
+
);
|
|
3235
|
+
if (!tokenChannel.ok) {
|
|
3236
|
+
process.stderr.write(`converge: ${tokenChannel.error}
|
|
3237
|
+
`);
|
|
3238
|
+
process.exitCode = 2;
|
|
3239
|
+
return;
|
|
3240
|
+
}
|
|
3241
|
+
peerToken = tokenChannel.token;
|
|
3242
|
+
if (tokenChannel.tokenFromArgv) {
|
|
3243
|
+
process.stderr.write(
|
|
3244
|
+
"converge: note: --token is argv-visible; prefer --token-file or REMNIC_CONVERGE_PEER_TOKEN\n"
|
|
3245
|
+
);
|
|
3246
|
+
}
|
|
3191
3247
|
if (action === "watch") {
|
|
3192
3248
|
const controller = new AbortController();
|
|
3193
3249
|
const onSignal = () => controller.abort();
|
|
@@ -3397,7 +3453,7 @@ function renderReplayResult(result, targetNamespace, format) {
|
|
|
3397
3453
|
}
|
|
3398
3454
|
|
|
3399
3455
|
// src/quarantine-replay.ts
|
|
3400
|
-
import * as
|
|
3456
|
+
import * as fs18 from "fs";
|
|
3401
3457
|
import { EngramAccessService, Orchestrator as Orchestrator8, initLogger as initLogger3, parseConfig as parseConfig14, resolveRemnicConfigRecord as resolveRemnicConfigRecord13 } from "@remnic/core";
|
|
3402
3458
|
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
3403
3459
|
function valueFlag(args, flag) {
|
|
@@ -3446,7 +3502,7 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
3446
3502
|
let orchestrator;
|
|
3447
3503
|
try {
|
|
3448
3504
|
const configPath = resolveConfigPath2();
|
|
3449
|
-
const raw =
|
|
3505
|
+
const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
|
|
3450
3506
|
const config = parseConfig14(resolveRemnicConfigRecord13(raw));
|
|
3451
3507
|
orchestrator = new Orchestrator8(config);
|
|
3452
3508
|
await orchestrator.initialize();
|
|
@@ -3478,7 +3534,7 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
3478
3534
|
}
|
|
3479
3535
|
|
|
3480
3536
|
// src/offline-impression-rotation.ts
|
|
3481
|
-
import
|
|
3537
|
+
import fs19 from "fs";
|
|
3482
3538
|
import { parseConfig as parseConfig15, resolveRemnicConfigRecord as resolveRemnicConfigRecord14, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
3483
3539
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
3484
3540
|
function parseConfigQuietly(raw) {
|
|
@@ -3513,7 +3569,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
3513
3569
|
function resolveOfflineImpressionRotation(configPath) {
|
|
3514
3570
|
let raw;
|
|
3515
3571
|
try {
|
|
3516
|
-
raw =
|
|
3572
|
+
raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
3517
3573
|
} catch {
|
|
3518
3574
|
throw new Error(
|
|
3519
3575
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -3546,8 +3602,8 @@ import {
|
|
|
3546
3602
|
existsSync as existsSync2,
|
|
3547
3603
|
lstatSync,
|
|
3548
3604
|
readdirSync,
|
|
3549
|
-
readFileSync as
|
|
3550
|
-
statSync
|
|
3605
|
+
readFileSync as readFileSync3,
|
|
3606
|
+
statSync as statSync2
|
|
3551
3607
|
} from "fs";
|
|
3552
3608
|
import path3 from "path";
|
|
3553
3609
|
import { fileURLToPath } from "url";
|
|
@@ -3580,7 +3636,7 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
3580
3636
|
}
|
|
3581
3637
|
let packageName;
|
|
3582
3638
|
try {
|
|
3583
|
-
packageName = JSON.parse(
|
|
3639
|
+
packageName = JSON.parse(readFileSync3(packageJsonPath, "utf8")).name;
|
|
3584
3640
|
} catch {
|
|
3585
3641
|
return { stale: false };
|
|
3586
3642
|
}
|
|
@@ -3609,7 +3665,7 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
3609
3665
|
if (!newestSource) {
|
|
3610
3666
|
return { stale: false };
|
|
3611
3667
|
}
|
|
3612
|
-
const distMtimeMs =
|
|
3668
|
+
const distMtimeMs = statSync2(distPath).mtimeMs;
|
|
3613
3669
|
if (newestSource.mtimeMs > distMtimeMs + STALE_BUILD_TOLERANCE_MS) {
|
|
3614
3670
|
return {
|
|
3615
3671
|
stale: true,
|
|
@@ -3658,7 +3714,7 @@ function newestMtime(roots) {
|
|
|
3658
3714
|
}
|
|
3659
3715
|
function isDirectory(entryPath) {
|
|
3660
3716
|
try {
|
|
3661
|
-
return
|
|
3717
|
+
return statSync2(entryPath).isDirectory();
|
|
3662
3718
|
} catch {
|
|
3663
3719
|
return false;
|
|
3664
3720
|
}
|
|
@@ -3771,7 +3827,7 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
3771
3827
|
}
|
|
3772
3828
|
|
|
3773
3829
|
// src/cmd-security.ts
|
|
3774
|
-
import
|
|
3830
|
+
import fs20 from "fs";
|
|
3775
3831
|
import {
|
|
3776
3832
|
Orchestrator as Orchestrator9,
|
|
3777
3833
|
parseConfig as parseConfig16,
|
|
@@ -3791,7 +3847,7 @@ async function cmdSecurity(rest) {
|
|
|
3791
3847
|
}
|
|
3792
3848
|
initLogger4();
|
|
3793
3849
|
const configPath = resolveConfigPath();
|
|
3794
|
-
const raw =
|
|
3850
|
+
const raw = fs20.existsSync(configPath) ? JSON.parse(fs20.readFileSync(configPath, "utf8")) : {};
|
|
3795
3851
|
const config = parseConfig16(resolveRemnicConfigRecord15(raw));
|
|
3796
3852
|
const orchestrator = new Orchestrator9(config);
|
|
3797
3853
|
await orchestrator.initialize();
|
|
@@ -3816,7 +3872,7 @@ async function cmdSecurity(rest) {
|
|
|
3816
3872
|
}
|
|
3817
3873
|
|
|
3818
3874
|
// src/daemon-service-candidates.ts
|
|
3819
|
-
import
|
|
3875
|
+
import fs21 from "fs";
|
|
3820
3876
|
import path5 from "path";
|
|
3821
3877
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
3822
3878
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -3838,7 +3894,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
3838
3894
|
function anyFileExists(paths) {
|
|
3839
3895
|
return paths.some((candidate) => {
|
|
3840
3896
|
try {
|
|
3841
|
-
return
|
|
3897
|
+
return fs21.statSync(candidate).isFile();
|
|
3842
3898
|
} catch {
|
|
3843
3899
|
return false;
|
|
3844
3900
|
}
|
|
@@ -3850,7 +3906,7 @@ function commandNames(command) {
|
|
|
3850
3906
|
}
|
|
3851
3907
|
function isRunnableNodeScript(filePath) {
|
|
3852
3908
|
try {
|
|
3853
|
-
const text =
|
|
3909
|
+
const text = fs21.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
3854
3910
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
3855
3911
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
3856
3912
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -3863,7 +3919,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
3863
3919
|
function resolveShimNodeScript(filePath) {
|
|
3864
3920
|
let text;
|
|
3865
3921
|
try {
|
|
3866
|
-
text =
|
|
3922
|
+
text = fs21.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
3867
3923
|
} catch {
|
|
3868
3924
|
return void 0;
|
|
3869
3925
|
}
|
|
@@ -3875,8 +3931,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
3875
3931
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
3876
3932
|
const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
|
|
3877
3933
|
try {
|
|
3878
|
-
if (
|
|
3879
|
-
return
|
|
3934
|
+
if (fs21.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
3935
|
+
return fs21.realpathSync(resolved);
|
|
3880
3936
|
}
|
|
3881
3937
|
} catch {
|
|
3882
3938
|
}
|
|
@@ -3884,7 +3940,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
3884
3940
|
return void 0;
|
|
3885
3941
|
}
|
|
3886
3942
|
function resolveRunnableNodeScript(filePath) {
|
|
3887
|
-
const realPath =
|
|
3943
|
+
const realPath = fs21.realpathSync(filePath);
|
|
3888
3944
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
3889
3945
|
return resolveShimNodeScript(realPath);
|
|
3890
3946
|
}
|
|
@@ -3894,9 +3950,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
3894
3950
|
for (const name of commandNames(command)) {
|
|
3895
3951
|
const candidate = path5.join(dir, name);
|
|
3896
3952
|
try {
|
|
3897
|
-
const stat2 =
|
|
3953
|
+
const stat2 = fs21.statSync(candidate);
|
|
3898
3954
|
if (!stat2.isFile()) continue;
|
|
3899
|
-
if (process.platform !== "win32")
|
|
3955
|
+
if (process.platform !== "win32") fs21.accessSync(candidate, fs21.constants.X_OK);
|
|
3900
3956
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
3901
3957
|
if (runnable) return runnable;
|
|
3902
3958
|
} catch {
|
|
@@ -5369,7 +5425,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
5369
5425
|
}
|
|
5370
5426
|
|
|
5371
5427
|
// src/bench-fallback.ts
|
|
5372
|
-
import
|
|
5428
|
+
import fs22 from "fs";
|
|
5373
5429
|
import path9 from "path";
|
|
5374
5430
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
5375
5431
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -5441,7 +5497,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
5441
5497
|
);
|
|
5442
5498
|
}
|
|
5443
5499
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
5444
|
-
const entries =
|
|
5500
|
+
const entries = fs22.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
5445
5501
|
if (entries.length === 0) {
|
|
5446
5502
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
5447
5503
|
}
|
|
@@ -5449,7 +5505,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
5449
5505
|
}
|
|
5450
5506
|
|
|
5451
5507
|
// src/openclaw-upgrade-swap.ts
|
|
5452
|
-
import
|
|
5508
|
+
import fs23 from "fs";
|
|
5453
5509
|
import path10 from "path";
|
|
5454
5510
|
function describeError(error) {
|
|
5455
5511
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -5461,7 +5517,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
5461
5517
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
5462
5518
|
if (explicitMode !== void 0) return explicitMode;
|
|
5463
5519
|
try {
|
|
5464
|
-
return
|
|
5520
|
+
return fs23.statSync(targetPath).mode & 4095;
|
|
5465
5521
|
} catch (error) {
|
|
5466
5522
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
5467
5523
|
return 384;
|
|
@@ -5471,8 +5527,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
5471
5527
|
}
|
|
5472
5528
|
function resolveAtomicReplacementPath(targetPath) {
|
|
5473
5529
|
try {
|
|
5474
|
-
if (
|
|
5475
|
-
return
|
|
5530
|
+
if (fs23.lstatSync(targetPath).isSymbolicLink()) {
|
|
5531
|
+
return fs23.realpathSync(targetPath);
|
|
5476
5532
|
}
|
|
5477
5533
|
} catch (error) {
|
|
5478
5534
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -5489,7 +5545,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
5489
5545
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
5490
5546
|
if (!displacedDir) return void 0;
|
|
5491
5547
|
try {
|
|
5492
|
-
|
|
5548
|
+
fs23.rmSync(displacedDir, { recursive: true, force: true });
|
|
5493
5549
|
return void 0;
|
|
5494
5550
|
} catch (error) {
|
|
5495
5551
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -5497,43 +5553,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
5497
5553
|
}
|
|
5498
5554
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
5499
5555
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
5500
|
-
|
|
5556
|
+
fs23.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
5501
5557
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
5502
5558
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
5503
5559
|
try {
|
|
5504
5560
|
if (options.hooks?.writeTempFileSync) {
|
|
5505
5561
|
options.hooks.writeTempFileSync(tempPath);
|
|
5506
5562
|
} else {
|
|
5507
|
-
|
|
5563
|
+
fs23.writeFileSync(tempPath, data, { mode });
|
|
5508
5564
|
}
|
|
5509
|
-
|
|
5510
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5565
|
+
fs23.chmodSync(tempPath, mode);
|
|
5566
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs23.renameSync;
|
|
5511
5567
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
5512
5568
|
} catch (error) {
|
|
5513
|
-
|
|
5569
|
+
fs23.rmSync(tempPath, { force: true });
|
|
5514
5570
|
throw error;
|
|
5515
5571
|
}
|
|
5516
5572
|
}
|
|
5517
5573
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
5518
|
-
if (!
|
|
5574
|
+
if (!fs23.existsSync(sourcePath)) return;
|
|
5519
5575
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
5520
|
-
|
|
5576
|
+
fs23.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
5521
5577
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
5522
|
-
const mode =
|
|
5578
|
+
const mode = fs23.statSync(sourcePath).mode & 4095;
|
|
5523
5579
|
try {
|
|
5524
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
5580
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs23.copyFileSync;
|
|
5525
5581
|
copyTempFileSync(sourcePath, tempPath);
|
|
5526
|
-
|
|
5527
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5582
|
+
fs23.chmodSync(tempPath, mode);
|
|
5583
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs23.renameSync;
|
|
5528
5584
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
5529
5585
|
} catch (error) {
|
|
5530
|
-
|
|
5586
|
+
fs23.rmSync(tempPath, { force: true });
|
|
5531
5587
|
throw error;
|
|
5532
5588
|
}
|
|
5533
5589
|
}
|
|
5534
5590
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
5535
5591
|
if (!rollbackDir) return;
|
|
5536
|
-
|
|
5592
|
+
fs23.rmSync(rollbackDir, { recursive: true, force: true });
|
|
5537
5593
|
}
|
|
5538
5594
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
5539
5595
|
if (!rollbackDir) return void 0;
|
|
@@ -5545,20 +5601,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
5545
5601
|
}
|
|
5546
5602
|
}
|
|
5547
5603
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
5548
|
-
if (!
|
|
5604
|
+
if (!fs23.existsSync(rollbackDir)) {
|
|
5549
5605
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
5550
5606
|
}
|
|
5551
|
-
|
|
5552
|
-
const displacedDir =
|
|
5607
|
+
fs23.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
5608
|
+
const displacedDir = fs23.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
5553
5609
|
if (displacedDir) {
|
|
5554
|
-
|
|
5610
|
+
fs23.renameSync(targetDir, displacedDir);
|
|
5555
5611
|
}
|
|
5556
5612
|
try {
|
|
5557
|
-
|
|
5613
|
+
fs23.renameSync(rollbackDir, targetDir);
|
|
5558
5614
|
} catch (restoreError) {
|
|
5559
|
-
if (displacedDir &&
|
|
5615
|
+
if (displacedDir && fs23.existsSync(displacedDir)) {
|
|
5560
5616
|
try {
|
|
5561
|
-
|
|
5617
|
+
fs23.renameSync(displacedDir, targetDir);
|
|
5562
5618
|
} catch (revertError) {
|
|
5563
5619
|
throw new AggregateError(
|
|
5564
5620
|
[restoreError, revertError],
|
|
@@ -5574,23 +5630,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
5574
5630
|
return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
|
|
5575
5631
|
}
|
|
5576
5632
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
5577
|
-
if (!
|
|
5633
|
+
if (!fs23.existsSync(backupDir)) {
|
|
5578
5634
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
5579
5635
|
}
|
|
5580
|
-
|
|
5636
|
+
fs23.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
5581
5637
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
5582
|
-
const displacedDir =
|
|
5583
|
-
|
|
5638
|
+
const displacedDir = fs23.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
5639
|
+
fs23.cpSync(backupDir, stagedDir, { recursive: true });
|
|
5584
5640
|
if (displacedDir) {
|
|
5585
|
-
|
|
5641
|
+
fs23.renameSync(targetDir, displacedDir);
|
|
5586
5642
|
}
|
|
5587
5643
|
try {
|
|
5588
|
-
|
|
5644
|
+
fs23.renameSync(stagedDir, targetDir);
|
|
5589
5645
|
} catch (restoreError) {
|
|
5590
|
-
|
|
5591
|
-
if (displacedDir &&
|
|
5646
|
+
fs23.rmSync(targetDir, { recursive: true, force: true });
|
|
5647
|
+
if (displacedDir && fs23.existsSync(displacedDir)) {
|
|
5592
5648
|
try {
|
|
5593
|
-
|
|
5649
|
+
fs23.renameSync(displacedDir, targetDir);
|
|
5594
5650
|
} catch (revertError) {
|
|
5595
5651
|
throw new AggregateError(
|
|
5596
5652
|
[restoreError, revertError],
|
|
@@ -5598,7 +5654,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
5598
5654
|
);
|
|
5599
5655
|
}
|
|
5600
5656
|
}
|
|
5601
|
-
|
|
5657
|
+
fs23.rmSync(stagedDir, { recursive: true, force: true });
|
|
5602
5658
|
throw new Error(
|
|
5603
5659
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
5604
5660
|
{ cause: restoreError }
|
|
@@ -5623,7 +5679,7 @@ function rollbackOpenclawUpgrade({
|
|
|
5623
5679
|
let configRemovalAttempted = false;
|
|
5624
5680
|
let pluginRestored = false;
|
|
5625
5681
|
try {
|
|
5626
|
-
if (rollbackDir &&
|
|
5682
|
+
if (rollbackDir && fs23.existsSync(rollbackDir)) {
|
|
5627
5683
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
5628
5684
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
5629
5685
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -5633,7 +5689,7 @@ function rollbackOpenclawUpgrade({
|
|
|
5633
5689
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
5634
5690
|
}
|
|
5635
5691
|
try {
|
|
5636
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
5692
|
+
if (!pluginRestored && pluginBackupDir && fs23.existsSync(pluginBackupDir)) {
|
|
5637
5693
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
5638
5694
|
if (rollbackRestoreError) {
|
|
5639
5695
|
notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
|
|
@@ -5658,12 +5714,12 @@ function rollbackOpenclawUpgrade({
|
|
|
5658
5714
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
5659
5715
|
}
|
|
5660
5716
|
try {
|
|
5661
|
-
if (configBackupPath &&
|
|
5717
|
+
if (configBackupPath && fs23.existsSync(configBackupPath)) {
|
|
5662
5718
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
5663
5719
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
5664
|
-
} else if (removeConfigIfUnbacked &&
|
|
5720
|
+
} else if (removeConfigIfUnbacked && fs23.existsSync(configPath)) {
|
|
5665
5721
|
configRemovalAttempted = true;
|
|
5666
|
-
|
|
5722
|
+
fs23.rmSync(configPath, { force: true });
|
|
5667
5723
|
notes.push("Removed OpenClaw config created during the failed upgrade");
|
|
5668
5724
|
}
|
|
5669
5725
|
} catch (error) {
|
|
@@ -5716,7 +5772,7 @@ Run this manually when you're ready:
|
|
|
5716
5772
|
|
|
5717
5773
|
// src/openclaw-managed-upgrade-loader.ts
|
|
5718
5774
|
import { execFileSync } from "child_process";
|
|
5719
|
-
import
|
|
5775
|
+
import fs24 from "fs";
|
|
5720
5776
|
import os from "os";
|
|
5721
5777
|
import path11 from "path";
|
|
5722
5778
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -5792,7 +5848,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
|
|
|
5792
5848
|
function readCliAdapterRange() {
|
|
5793
5849
|
const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
|
|
5794
5850
|
const manifestPath = path11.resolve(moduleDir, "../package.json");
|
|
5795
|
-
const manifest = JSON.parse(
|
|
5851
|
+
const manifest = JSON.parse(fs24.readFileSync(manifestPath, "utf8"));
|
|
5796
5852
|
if (manifest.name !== "@remnic/cli") {
|
|
5797
5853
|
throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
|
|
5798
5854
|
}
|
|
@@ -5836,7 +5892,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5836
5892
|
const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
|
|
5837
5893
|
if (!adapterMissing) throw error;
|
|
5838
5894
|
}
|
|
5839
|
-
const temporaryRoot =
|
|
5895
|
+
const temporaryRoot = fs24.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
5840
5896
|
try {
|
|
5841
5897
|
const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
|
|
5842
5898
|
const installArgs = [
|
|
@@ -5851,12 +5907,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5851
5907
|
];
|
|
5852
5908
|
(hooks.runNpmInstall ?? runNpmInstall)(installArgs);
|
|
5853
5909
|
const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
|
|
5854
|
-
|
|
5910
|
+
fs24.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
|
|
5855
5911
|
`, "utf8");
|
|
5856
5912
|
return await importModule(pathToFileURL2(resolverPath).href);
|
|
5857
5913
|
} finally {
|
|
5858
5914
|
try {
|
|
5859
|
-
|
|
5915
|
+
fs24.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
5860
5916
|
} catch (error) {
|
|
5861
5917
|
const detail = error instanceof Error ? error.message : String(error);
|
|
5862
5918
|
console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
|
|
@@ -5865,12 +5921,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5865
5921
|
}
|
|
5866
5922
|
|
|
5867
5923
|
// src/remote-daemon.ts
|
|
5868
|
-
import
|
|
5924
|
+
import fs25 from "fs";
|
|
5869
5925
|
import { readCompatEnv } from "@remnic/core";
|
|
5870
5926
|
import { isLoopbackHost } from "@remnic/core/runtime/http-transport.js";
|
|
5871
5927
|
function readRemnicConfigRecord(configPath) {
|
|
5872
5928
|
try {
|
|
5873
|
-
const parsed = JSON.parse(
|
|
5929
|
+
const parsed = JSON.parse(fs25.readFileSync(configPath, "utf8"));
|
|
5874
5930
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5875
5931
|
return parsed;
|
|
5876
5932
|
}
|
|
@@ -6118,7 +6174,7 @@ async function remoteRecallXray(daemon, request) {
|
|
|
6118
6174
|
}
|
|
6119
6175
|
|
|
6120
6176
|
// src/daemon-service.ts
|
|
6121
|
-
import
|
|
6177
|
+
import fs26 from "fs";
|
|
6122
6178
|
import path12 from "path";
|
|
6123
6179
|
import * as childProcess from "child_process";
|
|
6124
6180
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -6130,7 +6186,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
6130
6186
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
6131
6187
|
}
|
|
6132
6188
|
function resolveServerBinDetails(options = {}) {
|
|
6133
|
-
const existsSync4 = options.existsSync ??
|
|
6189
|
+
const existsSync4 = options.existsSync ?? fs26.existsSync;
|
|
6134
6190
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
6135
6191
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
6136
6192
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -6189,15 +6245,15 @@ function resolveServerBin(options = {}) {
|
|
|
6189
6245
|
return resolveServerBinDetails(options).path;
|
|
6190
6246
|
}
|
|
6191
6247
|
function readVerifiedDaemonPid(options) {
|
|
6192
|
-
const
|
|
6193
|
-
const unlinkSync = options.unlinkSync ??
|
|
6248
|
+
const readFileSync5 = options.readFileSync ?? fs26.readFileSync;
|
|
6249
|
+
const unlinkSync = options.unlinkSync ?? fs26.unlinkSync;
|
|
6194
6250
|
const processKill = options.processKill ?? process.kill;
|
|
6195
6251
|
const platform = options.platform ?? process.platform;
|
|
6196
6252
|
const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
6197
6253
|
for (const file of options.pidFiles) {
|
|
6198
6254
|
let pid;
|
|
6199
6255
|
try {
|
|
6200
|
-
pid = parseDaemonPid(
|
|
6256
|
+
pid = parseDaemonPid(readFileSync5(file, "utf8"));
|
|
6201
6257
|
} catch {
|
|
6202
6258
|
continue;
|
|
6203
6259
|
}
|
|
@@ -6290,8 +6346,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
6290
6346
|
}
|
|
6291
6347
|
}
|
|
6292
6348
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
6293
|
-
const existsSync4 = options.existsSync ??
|
|
6294
|
-
const
|
|
6349
|
+
const existsSync4 = options.existsSync ?? fs26.existsSync;
|
|
6350
|
+
const readFileSync5 = options.readFileSync ?? fs26.readFileSync;
|
|
6295
6351
|
if (!existsSync4(plistPath)) {
|
|
6296
6352
|
return {
|
|
6297
6353
|
installed: false,
|
|
@@ -6302,7 +6358,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
6302
6358
|
}
|
|
6303
6359
|
let content;
|
|
6304
6360
|
try {
|
|
6305
|
-
content =
|
|
6361
|
+
content = readFileSync5(plistPath, "utf8");
|
|
6306
6362
|
} catch {
|
|
6307
6363
|
return {
|
|
6308
6364
|
installed: true,
|
|
@@ -6469,7 +6525,7 @@ function stripConfigArgv(args) {
|
|
|
6469
6525
|
}
|
|
6470
6526
|
|
|
6471
6527
|
// src/import-dispatch.ts
|
|
6472
|
-
import
|
|
6528
|
+
import fs27 from "fs";
|
|
6473
6529
|
import {
|
|
6474
6530
|
runImporter,
|
|
6475
6531
|
validateImportBatchSize,
|
|
@@ -6477,7 +6533,7 @@ import {
|
|
|
6477
6533
|
} from "@remnic/core";
|
|
6478
6534
|
|
|
6479
6535
|
// src/import-bundle-detect.ts
|
|
6480
|
-
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as
|
|
6536
|
+
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
6481
6537
|
import path13 from "path";
|
|
6482
6538
|
function detectBundleEntries(bundleDir, options = {}) {
|
|
6483
6539
|
const readdir3 = options.readdirImpl ?? defaultReaddir;
|
|
@@ -6599,7 +6655,7 @@ function defaultReaddir(dir) {
|
|
|
6599
6655
|
return readdirSync2(dir);
|
|
6600
6656
|
}
|
|
6601
6657
|
function defaultReadFile(p) {
|
|
6602
|
-
return
|
|
6658
|
+
return readFileSync4(p, "utf-8");
|
|
6603
6659
|
}
|
|
6604
6660
|
function defaultIsDirectory(p) {
|
|
6605
6661
|
try {
|
|
@@ -6989,7 +7045,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
6989
7045
|
let materializedTarget;
|
|
6990
7046
|
let materializePromise;
|
|
6991
7047
|
const io = {
|
|
6992
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
7048
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs27.promises.readFile(p, "utf-8")),
|
|
6993
7049
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
6994
7050
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
6995
7051
|
getWriteTarget: async () => {
|
|
@@ -7102,7 +7158,7 @@ async function cmdCapture(rest, io) {
|
|
|
7102
7158
|
}
|
|
7103
7159
|
|
|
7104
7160
|
// src/import-lossless-claw-cmd.ts
|
|
7105
|
-
import
|
|
7161
|
+
import fs28 from "fs";
|
|
7106
7162
|
import path14 from "path";
|
|
7107
7163
|
import {
|
|
7108
7164
|
applyLcmSchema,
|
|
@@ -7214,15 +7270,15 @@ async function loadImportLosslessClawModule() {
|
|
|
7214
7270
|
|
|
7215
7271
|
// src/import-lossless-claw-cmd.ts
|
|
7216
7272
|
function assertDirectoryOrAbsent(p, label) {
|
|
7217
|
-
if (
|
|
7273
|
+
if (fs28.existsSync(p) && !fs28.statSync(p).isDirectory()) {
|
|
7218
7274
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
7219
7275
|
}
|
|
7220
7276
|
}
|
|
7221
7277
|
function assertFile(p, label) {
|
|
7222
|
-
if (!
|
|
7278
|
+
if (!fs28.existsSync(p)) {
|
|
7223
7279
|
throw new Error(`${label} does not exist: ${p}`);
|
|
7224
7280
|
}
|
|
7225
|
-
if (!
|
|
7281
|
+
if (!fs28.statSync(p).isFile()) {
|
|
7226
7282
|
throw new Error(`${label} is not a file: ${p}`);
|
|
7227
7283
|
}
|
|
7228
7284
|
}
|
|
@@ -7254,7 +7310,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
7254
7310
|
try {
|
|
7255
7311
|
if (parsed.dryRun) {
|
|
7256
7312
|
const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
|
|
7257
|
-
if (
|
|
7313
|
+
if (fs28.existsSync(lcmPath)) {
|
|
7258
7314
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
7259
7315
|
} else {
|
|
7260
7316
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -8606,7 +8662,7 @@ async function resolveAllBenchmarks() {
|
|
|
8606
8662
|
if (packageBenchmarks) {
|
|
8607
8663
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
8608
8664
|
}
|
|
8609
|
-
if (!
|
|
8665
|
+
if (!fs29.existsSync(EVAL_RUNNER_PATH)) {
|
|
8610
8666
|
return [];
|
|
8611
8667
|
}
|
|
8612
8668
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -8654,7 +8710,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
8654
8710
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
8655
8711
|
);
|
|
8656
8712
|
}
|
|
8657
|
-
if (!
|
|
8713
|
+
if (!fs29.existsSync(EVAL_RUNNER_PATH)) {
|
|
8658
8714
|
console.error(
|
|
8659
8715
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
8660
8716
|
);
|
|
@@ -8664,7 +8720,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
8664
8720
|
path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
8665
8721
|
path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
8666
8722
|
];
|
|
8667
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
8723
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs29.existsSync(candidate)) ?? "tsx";
|
|
8668
8724
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
8669
8725
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
8670
8726
|
benchmarkId,
|
|
@@ -8809,9 +8865,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
|
|
|
8809
8865
|
);
|
|
8810
8866
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
8811
8867
|
try {
|
|
8812
|
-
const datasetRoot =
|
|
8868
|
+
const datasetRoot = fs29.realpathSync(datasetPath);
|
|
8813
8869
|
const candidatePath = path18.resolve(datasetRoot, relativePath);
|
|
8814
|
-
const candidateRealPath =
|
|
8870
|
+
const candidateRealPath = fs29.realpathSync(candidatePath);
|
|
8815
8871
|
const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
|
|
8816
8872
|
if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
|
|
8817
8873
|
return null;
|
|
@@ -8870,14 +8926,14 @@ function parseCsvRows(raw) {
|
|
|
8870
8926
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
8871
8927
|
try {
|
|
8872
8928
|
const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
8873
|
-
if (
|
|
8929
|
+
if (fs29.statSync(completionMarkerPath).isFile()) {
|
|
8874
8930
|
return true;
|
|
8875
8931
|
}
|
|
8876
8932
|
} catch {
|
|
8877
8933
|
}
|
|
8878
8934
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
8879
8935
|
try {
|
|
8880
|
-
return
|
|
8936
|
+
return fs29.statSync(path18.join(datasetPath, candidate)).isFile();
|
|
8881
8937
|
} catch {
|
|
8882
8938
|
return false;
|
|
8883
8939
|
}
|
|
@@ -8886,7 +8942,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8886
8942
|
return false;
|
|
8887
8943
|
}
|
|
8888
8944
|
try {
|
|
8889
|
-
const rows = parseCsvRows(
|
|
8945
|
+
const rows = parseCsvRows(fs29.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
|
|
8890
8946
|
if (rows.length < 2) {
|
|
8891
8947
|
return false;
|
|
8892
8948
|
}
|
|
@@ -8901,7 +8957,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8901
8957
|
}
|
|
8902
8958
|
return historyPaths.every((relativePath) => {
|
|
8903
8959
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
8904
|
-
return resolvedPath !== null &&
|
|
8960
|
+
return resolvedPath !== null && fs29.statSync(resolvedPath).isFile();
|
|
8905
8961
|
});
|
|
8906
8962
|
} catch {
|
|
8907
8963
|
return false;
|
|
@@ -8909,7 +8965,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8909
8965
|
}
|
|
8910
8966
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
8911
8967
|
try {
|
|
8912
|
-
return
|
|
8968
|
+
return fs29.statSync(path18.join(datasetPath, relativePath)).isFile();
|
|
8913
8969
|
} catch {
|
|
8914
8970
|
return false;
|
|
8915
8971
|
}
|
|
@@ -8929,10 +8985,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
8929
8985
|
return candidateFilenames.some((filename) => {
|
|
8930
8986
|
const filePath = path18.join(datasetPath, filename);
|
|
8931
8987
|
try {
|
|
8932
|
-
if (!
|
|
8988
|
+
if (!fs29.statSync(filePath).isFile()) {
|
|
8933
8989
|
return false;
|
|
8934
8990
|
}
|
|
8935
|
-
const raw =
|
|
8991
|
+
const raw = fs29.readFileSync(filePath, "utf8");
|
|
8936
8992
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
8937
8993
|
} catch {
|
|
8938
8994
|
return false;
|
|
@@ -8948,7 +9004,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
8948
9004
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
8949
9005
|
let stats;
|
|
8950
9006
|
try {
|
|
8951
|
-
stats =
|
|
9007
|
+
stats = fs29.statSync(datasetPath);
|
|
8952
9008
|
} catch {
|
|
8953
9009
|
return false;
|
|
8954
9010
|
}
|
|
@@ -8958,7 +9014,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8958
9014
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
8959
9015
|
if (!marker) {
|
|
8960
9016
|
try {
|
|
8961
|
-
return
|
|
9017
|
+
return fs29.readdirSync(datasetPath).length > 0;
|
|
8962
9018
|
} catch {
|
|
8963
9019
|
return false;
|
|
8964
9020
|
}
|
|
@@ -8966,7 +9022,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8966
9022
|
if (marker.allOf) {
|
|
8967
9023
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
8968
9024
|
try {
|
|
8969
|
-
return
|
|
9025
|
+
return fs29.statSync(path18.join(datasetPath, name)).isFile();
|
|
8970
9026
|
} catch {
|
|
8971
9027
|
return false;
|
|
8972
9028
|
}
|
|
@@ -8978,7 +9034,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8978
9034
|
if (marker.anyOf) {
|
|
8979
9035
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
8980
9036
|
try {
|
|
8981
|
-
return
|
|
9037
|
+
return fs29.statSync(path18.join(datasetPath, name)).isFile();
|
|
8982
9038
|
} catch {
|
|
8983
9039
|
return false;
|
|
8984
9040
|
}
|
|
@@ -8996,7 +9052,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8996
9052
|
}
|
|
8997
9053
|
if (marker.ext) {
|
|
8998
9054
|
try {
|
|
8999
|
-
return
|
|
9055
|
+
return fs29.readdirSync(datasetPath).some(
|
|
9000
9056
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
9001
9057
|
);
|
|
9002
9058
|
} catch {
|
|
@@ -9008,7 +9064,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
9008
9064
|
async function launchBenchUi(resultsDir) {
|
|
9009
9065
|
const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
9010
9066
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
9011
|
-
if (!
|
|
9067
|
+
if (!fs29.existsSync(path18.join(benchUiDir, "package.json"))) {
|
|
9012
9068
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
9013
9069
|
process.exit(1);
|
|
9014
9070
|
}
|
|
@@ -9046,13 +9102,13 @@ function listDownloadableBenchmarks() {
|
|
|
9046
9102
|
}
|
|
9047
9103
|
function resolveDatasetDownloadScriptPath() {
|
|
9048
9104
|
const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
9049
|
-
if (
|
|
9105
|
+
if (fs29.existsSync(bundled)) {
|
|
9050
9106
|
return bundled;
|
|
9051
9107
|
}
|
|
9052
9108
|
return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
9053
9109
|
}
|
|
9054
9110
|
function isRepoCheckout() {
|
|
9055
|
-
return
|
|
9111
|
+
return fs29.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs29.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
9056
9112
|
}
|
|
9057
9113
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
9058
9114
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -9365,8 +9421,8 @@ async function exportBenchPackageResult(parsed) {
|
|
|
9365
9421
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
9366
9422
|
});
|
|
9367
9423
|
if (parsed.output) {
|
|
9368
|
-
|
|
9369
|
-
|
|
9424
|
+
fs29.mkdirSync(path18.dirname(parsed.output), { recursive: true });
|
|
9425
|
+
fs29.writeFileSync(parsed.output, rendered);
|
|
9370
9426
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
9371
9427
|
return;
|
|
9372
9428
|
}
|
|
@@ -9411,7 +9467,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
9411
9467
|
process.exit(1);
|
|
9412
9468
|
}
|
|
9413
9469
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
9414
|
-
if (!
|
|
9470
|
+
if (!fs29.existsSync(scriptPath)) {
|
|
9415
9471
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
9416
9472
|
process.exit(1);
|
|
9417
9473
|
}
|
|
@@ -9611,7 +9667,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
9611
9667
|
);
|
|
9612
9668
|
process.exit(1);
|
|
9613
9669
|
}
|
|
9614
|
-
const sourceResultSha256 = createHash4("sha256").update(
|
|
9670
|
+
const sourceResultSha256 = createHash4("sha256").update(fs29.readFileSync(latest.path)).digest("hex");
|
|
9615
9671
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
9616
9672
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
9617
9673
|
console.error(
|
|
@@ -10026,7 +10082,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
10026
10082
|
}
|
|
10027
10083
|
let decoded;
|
|
10028
10084
|
try {
|
|
10029
|
-
decoded = JSON.parse(
|
|
10085
|
+
decoded = JSON.parse(fs29.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
10030
10086
|
} catch (error) {
|
|
10031
10087
|
throw new Error(
|
|
10032
10088
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -10122,7 +10178,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
10122
10178
|
const benchModule = await loadBenchModule();
|
|
10123
10179
|
return {
|
|
10124
10180
|
async promoteArtifactsToPublished(args) {
|
|
10125
|
-
const { mkdirSync, readFileSync:
|
|
10181
|
+
const { mkdirSync, readFileSync: readFileSync5, writeFileSync } = await import("fs");
|
|
10126
10182
|
const path19 = await import("path");
|
|
10127
10183
|
mkdirSync(args.publishedOutDir, { recursive: true });
|
|
10128
10184
|
if (args.artifactPaths.length === 0) {
|
|
@@ -10132,7 +10188,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
10132
10188
|
return;
|
|
10133
10189
|
}
|
|
10134
10190
|
for (const artifactPath of args.artifactPaths) {
|
|
10135
|
-
const raw =
|
|
10191
|
+
const raw = readFileSync5(artifactPath, "utf8");
|
|
10136
10192
|
const parsedUnknown = JSON.parse(raw);
|
|
10137
10193
|
const parsedObj = parsedUnknown !== null && typeof parsedUnknown === "object" && !Array.isArray(parsedUnknown) ? parsedUnknown : {};
|
|
10138
10194
|
const gitShaShort = (parsedObj.meta?.gitSha ?? "unknown").slice(0, 7);
|
|
@@ -10701,7 +10757,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
10701
10757
|
return void 0;
|
|
10702
10758
|
}
|
|
10703
10759
|
try {
|
|
10704
|
-
return
|
|
10760
|
+
return fs29.realpathSync(datasetDir);
|
|
10705
10761
|
} catch {
|
|
10706
10762
|
return datasetDir;
|
|
10707
10763
|
}
|
|
@@ -10755,7 +10811,7 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
10755
10811
|
}
|
|
10756
10812
|
function loadStandaloneConvergeCommandConfig() {
|
|
10757
10813
|
const configPath = resolveConfigPath();
|
|
10758
|
-
const raw =
|
|
10814
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
10759
10815
|
return parseConfig17(resolveRemnicConfigRecord16(raw));
|
|
10760
10816
|
}
|
|
10761
10817
|
function parseConvergePluginConfig(value) {
|
|
@@ -10775,7 +10831,7 @@ function loadConvergeCommandConfig() {
|
|
|
10775
10831
|
}
|
|
10776
10832
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
10777
10833
|
const configPath = resolveConfigPath(cliPath);
|
|
10778
|
-
if (
|
|
10834
|
+
if (fs29.existsSync(configPath)) {
|
|
10779
10835
|
return configPath;
|
|
10780
10836
|
}
|
|
10781
10837
|
if (cliPath) {
|
|
@@ -10785,7 +10841,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
10785
10841
|
}
|
|
10786
10842
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
10787
10843
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
10788
|
-
if (
|
|
10844
|
+
if (fs29.existsSync(configPath)) {
|
|
10789
10845
|
return configPath;
|
|
10790
10846
|
}
|
|
10791
10847
|
if (cliPath) {
|
|
@@ -10892,7 +10948,7 @@ function resolveMemoryDir() {
|
|
|
10892
10948
|
const envMemoryDir = readCompatEnv2("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
10893
10949
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
10894
10950
|
const configPath = resolveConfigPath();
|
|
10895
|
-
const raw =
|
|
10951
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
10896
10952
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
10897
10953
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
10898
10954
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
@@ -10901,18 +10957,18 @@ function resolveMemoryDir() {
|
|
|
10901
10957
|
const standalonePath = path18.join(home, ".remnic", "memory");
|
|
10902
10958
|
const legacyStandalonePath = path18.join(home, ".engram", "memory");
|
|
10903
10959
|
const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
10904
|
-
if (
|
|
10905
|
-
if (
|
|
10960
|
+
if (fs29.existsSync(standalonePath)) return standalonePath;
|
|
10961
|
+
if (fs29.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
10906
10962
|
return openclawPath;
|
|
10907
10963
|
})();
|
|
10908
10964
|
const manifestPath = getManifestPath();
|
|
10909
|
-
if (
|
|
10965
|
+
if (fs29.existsSync(manifestPath)) {
|
|
10910
10966
|
try {
|
|
10911
10967
|
const active = getActiveSpace();
|
|
10912
10968
|
if (active?.memoryDir) {
|
|
10913
10969
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
10914
|
-
if (!
|
|
10915
|
-
|
|
10970
|
+
if (!fs29.existsSync(activeMemoryDir)) {
|
|
10971
|
+
fs29.mkdirSync(activeMemoryDir, { recursive: true });
|
|
10916
10972
|
}
|
|
10917
10973
|
return activeMemoryDir;
|
|
10918
10974
|
}
|
|
@@ -10961,13 +11017,13 @@ function resolveOpenclawConfigPath(cliPath) {
|
|
|
10961
11017
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
10962
11018
|
if (envPath) return path18.resolve(expandTilde(envPath));
|
|
10963
11019
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
10964
|
-
if (
|
|
11020
|
+
if (fs29.existsSync(candidate)) return candidate;
|
|
10965
11021
|
}
|
|
10966
11022
|
return path18.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
10967
11023
|
}
|
|
10968
11024
|
function readOpenclawConfig(configPath) {
|
|
10969
|
-
if (!
|
|
10970
|
-
const raw =
|
|
11025
|
+
if (!fs29.existsSync(configPath)) return {};
|
|
11026
|
+
const raw = fs29.readFileSync(configPath, "utf-8");
|
|
10971
11027
|
let parsed;
|
|
10972
11028
|
try {
|
|
10973
11029
|
parsed = JSON.parse(raw);
|
|
@@ -11069,9 +11125,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
11069
11125
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
11070
11126
|
}
|
|
11071
11127
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
11072
|
-
if (!
|
|
11073
|
-
|
|
11074
|
-
|
|
11128
|
+
if (!fs29.existsSync(sourcePath)) return false;
|
|
11129
|
+
fs29.mkdirSync(path18.dirname(backupPath), { recursive: true });
|
|
11130
|
+
fs29.cpSync(sourcePath, backupPath, { recursive: true });
|
|
11075
11131
|
return true;
|
|
11076
11132
|
}
|
|
11077
11133
|
function restartOpenclawGateway() {
|
|
@@ -11090,7 +11146,7 @@ function restartOpenclawGateway() {
|
|
|
11090
11146
|
}
|
|
11091
11147
|
function cmdInit() {
|
|
11092
11148
|
const configPath = path18.join(process.cwd(), "remnic.config.json");
|
|
11093
|
-
if (
|
|
11149
|
+
if (fs29.existsSync(configPath)) {
|
|
11094
11150
|
console.log(`Config already exists: ${configPath}`);
|
|
11095
11151
|
return;
|
|
11096
11152
|
}
|
|
@@ -11106,7 +11162,7 @@ function cmdInit() {
|
|
|
11106
11162
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
11107
11163
|
}
|
|
11108
11164
|
};
|
|
11109
|
-
|
|
11165
|
+
fs29.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
11110
11166
|
console.log(`Created ${configPath}`);
|
|
11111
11167
|
console.log("\nSet these environment variables:");
|
|
11112
11168
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -11528,7 +11584,7 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
11528
11584
|
}
|
|
11529
11585
|
initLogger5();
|
|
11530
11586
|
const configPath = resolveConfigPath();
|
|
11531
|
-
const raw =
|
|
11587
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11532
11588
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11533
11589
|
const config = parseConfig17(remnicCfg);
|
|
11534
11590
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -11708,7 +11764,7 @@ async function cmdXray(rest) {
|
|
|
11708
11764
|
}
|
|
11709
11765
|
initLogger5();
|
|
11710
11766
|
const configPath = resolveConfigPath();
|
|
11711
|
-
const raw =
|
|
11767
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11712
11768
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11713
11769
|
const config = parseConfig17(remnicCfg);
|
|
11714
11770
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -11741,7 +11797,7 @@ async function runWhoKnowsCommand(rest, io) {
|
|
|
11741
11797
|
async function withLocalService(fn) {
|
|
11742
11798
|
initLogger5();
|
|
11743
11799
|
const configPath = resolveConfigPath();
|
|
11744
|
-
const raw =
|
|
11800
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11745
11801
|
const orchestrator = new Orchestrator10(parseConfig17(resolveRemnicConfigRecord16(raw)));
|
|
11746
11802
|
await orchestrator.initialize();
|
|
11747
11803
|
await orchestrator.deferredReady;
|
|
@@ -11774,7 +11830,7 @@ async function cmdPromotionCandidates(rest) {
|
|
|
11774
11830
|
async function cmdVersions(rest) {
|
|
11775
11831
|
initLogger5();
|
|
11776
11832
|
const configPath = resolveConfigPath();
|
|
11777
|
-
const raw =
|
|
11833
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11778
11834
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11779
11835
|
const config = parseConfig17(remnicCfg);
|
|
11780
11836
|
if (!config.versioningEnabled) {
|
|
@@ -11890,7 +11946,7 @@ Options:
|
|
|
11890
11946
|
async function cmdEnrich(rest) {
|
|
11891
11947
|
initLogger5();
|
|
11892
11948
|
const configPath = resolveConfigPath();
|
|
11893
|
-
const raw =
|
|
11949
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11894
11950
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11895
11951
|
const config = parseConfig17(remnicCfg);
|
|
11896
11952
|
const subcommand = rest[0];
|
|
@@ -12084,7 +12140,7 @@ Registered providers:`);
|
|
|
12084
12140
|
async function cmdExtensions(action, rest) {
|
|
12085
12141
|
initLogger5();
|
|
12086
12142
|
const configPath = resolveConfigPath();
|
|
12087
|
-
const raw =
|
|
12143
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
12088
12144
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
12089
12145
|
const config = parseConfig17(remnicCfg);
|
|
12090
12146
|
const root = resolveExtensionsRoot(config);
|
|
@@ -12135,7 +12191,7 @@ Root: ${root}`);
|
|
|
12135
12191
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
12136
12192
|
let entries = [];
|
|
12137
12193
|
try {
|
|
12138
|
-
entries =
|
|
12194
|
+
entries = fs29.readdirSync(root);
|
|
12139
12195
|
} catch {
|
|
12140
12196
|
console.log(`Extensions root does not exist: ${root}`);
|
|
12141
12197
|
process.exitCode = 0;
|
|
@@ -12146,7 +12202,7 @@ Root: ${root}`);
|
|
|
12146
12202
|
for (const entry of entries) {
|
|
12147
12203
|
const entryPath = path18.join(root, entry);
|
|
12148
12204
|
try {
|
|
12149
|
-
if (!
|
|
12205
|
+
if (!fs29.statSync(entryPath).isDirectory()) continue;
|
|
12150
12206
|
} catch {
|
|
12151
12207
|
continue;
|
|
12152
12208
|
}
|
|
@@ -12178,7 +12234,7 @@ Root: ${root}`);
|
|
|
12178
12234
|
async function cmdBriefing(rest) {
|
|
12179
12235
|
initLogger5();
|
|
12180
12236
|
const configPath = resolveConfigPath();
|
|
12181
|
-
const raw =
|
|
12237
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
12182
12238
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
12183
12239
|
const config = parseConfig17(remnicCfg);
|
|
12184
12240
|
if (!config.briefing.enabled) {
|
|
@@ -12258,10 +12314,10 @@ async function cmdBriefing(rest) {
|
|
|
12258
12314
|
if (save) {
|
|
12259
12315
|
try {
|
|
12260
12316
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
12261
|
-
|
|
12317
|
+
fs29.mkdirSync(saveDir, { recursive: true });
|
|
12262
12318
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
12263
12319
|
const filePath = path18.join(saveDir, filename);
|
|
12264
|
-
|
|
12320
|
+
fs29.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
12265
12321
|
console.error(`Saved briefing: ${filePath}`);
|
|
12266
12322
|
} catch (err) {
|
|
12267
12323
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -12279,7 +12335,7 @@ async function cmdDoctor() {
|
|
|
12279
12335
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
12280
12336
|
});
|
|
12281
12337
|
const configPath = resolveConfigPath();
|
|
12282
|
-
const configExists =
|
|
12338
|
+
const configExists = fs29.existsSync(configPath);
|
|
12283
12339
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
12284
12340
|
let standaloneConfig;
|
|
12285
12341
|
let standaloneConfigError;
|
|
@@ -12287,7 +12343,7 @@ async function cmdDoctor() {
|
|
|
12287
12343
|
let configuredNs = { invalid: false };
|
|
12288
12344
|
if (configExists) {
|
|
12289
12345
|
try {
|
|
12290
|
-
const raw = JSON.parse(
|
|
12346
|
+
const raw = JSON.parse(fs29.readFileSync(configPath, "utf8"));
|
|
12291
12347
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
12292
12348
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
12293
12349
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
@@ -12303,7 +12359,7 @@ async function cmdDoctor() {
|
|
|
12303
12359
|
memoryDir = parseConfig17({}).memoryDir;
|
|
12304
12360
|
}
|
|
12305
12361
|
try {
|
|
12306
|
-
|
|
12362
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
12307
12363
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
12308
12364
|
} catch {
|
|
12309
12365
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -12332,7 +12388,7 @@ async function cmdDoctor() {
|
|
|
12332
12388
|
});
|
|
12333
12389
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
12334
12390
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
12335
|
-
const openclawConfigExists =
|
|
12391
|
+
const openclawConfigExists = fs29.existsSync(openclawConfigPath);
|
|
12336
12392
|
let openclawConfig = {};
|
|
12337
12393
|
let openclawConfigValid = false;
|
|
12338
12394
|
let openclawPluginModeConfigured = false;
|
|
@@ -12340,7 +12396,7 @@ async function cmdDoctor() {
|
|
|
12340
12396
|
let activeOpenclawEntryConfig = null;
|
|
12341
12397
|
if (openclawConfigExists) {
|
|
12342
12398
|
try {
|
|
12343
|
-
const parsed = JSON.parse(
|
|
12399
|
+
const parsed = JSON.parse(fs29.readFileSync(openclawConfigPath, "utf-8"));
|
|
12344
12400
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
12345
12401
|
openclawConfig = parsed;
|
|
12346
12402
|
openclawConfigValid = true;
|
|
@@ -12420,9 +12476,9 @@ async function cmdDoctor() {
|
|
|
12420
12476
|
let memDirOk = false;
|
|
12421
12477
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
12422
12478
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
12423
|
-
if (
|
|
12479
|
+
if (fs29.existsSync(resolvedMemDir)) {
|
|
12424
12480
|
try {
|
|
12425
|
-
const stat2 =
|
|
12481
|
+
const stat2 = fs29.statSync(resolvedMemDir);
|
|
12426
12482
|
if (stat2.isDirectory()) {
|
|
12427
12483
|
memDirOk = true;
|
|
12428
12484
|
memDirDetail = resolvedMemDir;
|
|
@@ -12577,12 +12633,12 @@ async function cmdDoctor() {
|
|
|
12577
12633
|
}
|
|
12578
12634
|
function cmdConfig() {
|
|
12579
12635
|
const configPath = resolveConfigPath();
|
|
12580
|
-
if (!
|
|
12636
|
+
if (!fs29.existsSync(configPath)) {
|
|
12581
12637
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
12582
12638
|
return;
|
|
12583
12639
|
}
|
|
12584
12640
|
console.log(`Config: ${configPath}`);
|
|
12585
|
-
const rawConfig =
|
|
12641
|
+
const rawConfig = fs29.readFileSync(configPath, "utf8");
|
|
12586
12642
|
const redacted = rawConfig.replace(
|
|
12587
12643
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
12588
12644
|
"$1[REDACTED]$3"
|
|
@@ -12690,7 +12746,7 @@ async function cmdReview(action, rest) {
|
|
|
12690
12746
|
const configPath = resolveConfigPath();
|
|
12691
12747
|
let tombstonesConfig = null;
|
|
12692
12748
|
try {
|
|
12693
|
-
const rawCfg =
|
|
12749
|
+
const rawCfg = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
12694
12750
|
const remnicCfg = resolveRemnicConfigRecord16(rawCfg);
|
|
12695
12751
|
const config = parseConfig17(remnicCfg);
|
|
12696
12752
|
tombstonesConfig = {
|
|
@@ -13434,7 +13490,7 @@ async function pushOfflineFileContent(args) {
|
|
|
13434
13490
|
}
|
|
13435
13491
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
13436
13492
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
13437
|
-
const stat2 =
|
|
13493
|
+
const stat2 = fs29.statSync(filePath);
|
|
13438
13494
|
if (stat2.mtimeMs !== args.file.mtimeMs) {
|
|
13439
13495
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
13440
13496
|
}
|
|
@@ -13925,7 +13981,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
13925
13981
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
13926
13982
|
}
|
|
13927
13983
|
async function runOfflineSyncOnce(options) {
|
|
13928
|
-
|
|
13984
|
+
fs29.mkdirSync(options.memoryDir, { recursive: true });
|
|
13929
13985
|
let activeStatePath = options.statePath;
|
|
13930
13986
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
13931
13987
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -14558,7 +14614,7 @@ Environment fallbacks:
|
|
|
14558
14614
|
const configPath = resolveConfigPath();
|
|
14559
14615
|
let config;
|
|
14560
14616
|
try {
|
|
14561
|
-
const rawConfig =
|
|
14617
|
+
const rawConfig = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
14562
14618
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
14563
14619
|
} catch {
|
|
14564
14620
|
throw new Error(
|
|
@@ -14573,7 +14629,7 @@ Environment fallbacks:
|
|
|
14573
14629
|
const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
14574
14630
|
if (action === "prepare") {
|
|
14575
14631
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
14576
|
-
|
|
14632
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
14577
14633
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
14578
14634
|
remoteUrl,
|
|
14579
14635
|
token,
|
|
@@ -14672,7 +14728,7 @@ Environment fallbacks:
|
|
|
14672
14728
|
return;
|
|
14673
14729
|
}
|
|
14674
14730
|
if (action === "status") {
|
|
14675
|
-
|
|
14731
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
14676
14732
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
14677
14733
|
if (state && remoteUrl && statePath) {
|
|
14678
14734
|
assertOfflineStateMatches({
|
|
@@ -14810,7 +14866,7 @@ function cmdDedup(json) {
|
|
|
14810
14866
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
14811
14867
|
if (!configPath) return fallback;
|
|
14812
14868
|
try {
|
|
14813
|
-
const parsed = JSON.parse(
|
|
14869
|
+
const parsed = JSON.parse(fs29.readFileSync(configPath, "utf8"));
|
|
14814
14870
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
14815
14871
|
const { token: _token, ...config } = parsed;
|
|
14816
14872
|
return config;
|
|
@@ -14988,7 +15044,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14988
15044
|
const pub = factory();
|
|
14989
15045
|
const available = await pub.isHostAvailable();
|
|
14990
15046
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
14991
|
-
const extensionExists = available && extRoot ?
|
|
15047
|
+
const extensionExists = available && extRoot ? fs29.existsSync(extRoot) : false;
|
|
14992
15048
|
publisherChecks.push({
|
|
14993
15049
|
name: `Publisher: ${targetHostId}`,
|
|
14994
15050
|
ok: !available || extensionExists,
|
|
@@ -15062,7 +15118,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
15062
15118
|
let connectorsCfg;
|
|
15063
15119
|
const configPath = resolveConfigPath();
|
|
15064
15120
|
try {
|
|
15065
|
-
const raw =
|
|
15121
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15066
15122
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
15067
15123
|
} catch {
|
|
15068
15124
|
process.stderr.write(
|
|
@@ -15138,7 +15194,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
15138
15194
|
}
|
|
15139
15195
|
initLogger5();
|
|
15140
15196
|
const configPath = resolveConfigPath();
|
|
15141
|
-
const raw =
|
|
15197
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15142
15198
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15143
15199
|
const config = parseConfig17(remnicCfg);
|
|
15144
15200
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -15263,7 +15319,7 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
15263
15319
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
15264
15320
|
process.exit(1);
|
|
15265
15321
|
}
|
|
15266
|
-
const rawConfig =
|
|
15322
|
+
const rawConfig = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15267
15323
|
const pluginConfig = resolveRemnicConfigRecord16(rawConfig);
|
|
15268
15324
|
const config = parseConfig17(pluginConfig);
|
|
15269
15325
|
if (subAction === "generate") {
|
|
@@ -15285,13 +15341,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
15285
15341
|
} else if (subAction === "validate") {
|
|
15286
15342
|
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
|
|
15287
15343
|
const resolved = path18.resolve(targetPath);
|
|
15288
|
-
if (!
|
|
15344
|
+
if (!fs29.existsSync(resolved)) {
|
|
15289
15345
|
console.error(`File not found: ${resolved}`);
|
|
15290
15346
|
process.exit(1);
|
|
15291
15347
|
}
|
|
15292
15348
|
let parsed;
|
|
15293
15349
|
try {
|
|
15294
|
-
parsed = JSON.parse(
|
|
15350
|
+
parsed = JSON.parse(fs29.readFileSync(resolved, "utf8"));
|
|
15295
15351
|
} catch {
|
|
15296
15352
|
console.error(`Invalid JSON in ${resolved}`);
|
|
15297
15353
|
process.exit(1);
|
|
@@ -15494,7 +15550,7 @@ async function cmdSpace(action, rest, json) {
|
|
|
15494
15550
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
15495
15551
|
initLogger5();
|
|
15496
15552
|
const configPath = resolveConfigPath();
|
|
15497
|
-
const raw =
|
|
15553
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15498
15554
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15499
15555
|
const config = parseConfig17(remnicCfg);
|
|
15500
15556
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -15899,7 +15955,7 @@ function readPid() {
|
|
|
15899
15955
|
function inferPort() {
|
|
15900
15956
|
try {
|
|
15901
15957
|
const configPath = resolveConfigPath();
|
|
15902
|
-
const raw = JSON.parse(
|
|
15958
|
+
const raw = JSON.parse(fs29.readFileSync(configPath, "utf8"));
|
|
15903
15959
|
return raw.server?.port ?? 4318;
|
|
15904
15960
|
} catch {
|
|
15905
15961
|
return 4318;
|
|
@@ -15994,13 +16050,13 @@ function daemonInstall() {
|
|
|
15994
16050
|
process.exit(1);
|
|
15995
16051
|
}
|
|
15996
16052
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
15997
|
-
|
|
16053
|
+
fs29.mkdirSync(LOGS_DIR, { recursive: true });
|
|
15998
16054
|
if (isMacOS()) {
|
|
15999
16055
|
const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
16000
|
-
const template =
|
|
16056
|
+
const template = fs29.readFileSync(templatePath, "utf8");
|
|
16001
16057
|
const plist = renderTemplate(template, vars);
|
|
16002
|
-
|
|
16003
|
-
|
|
16058
|
+
fs29.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
16059
|
+
fs29.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
16004
16060
|
try {
|
|
16005
16061
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
16006
16062
|
} catch (err) {
|
|
@@ -16017,10 +16073,10 @@ function daemonInstall() {
|
|
|
16017
16073
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
16018
16074
|
} else if (isLinux()) {
|
|
16019
16075
|
const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
16020
|
-
const template =
|
|
16076
|
+
const template = fs29.readFileSync(templatePath, "utf8");
|
|
16021
16077
|
const unit = renderTemplate(template, vars);
|
|
16022
|
-
|
|
16023
|
-
|
|
16078
|
+
fs29.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
16079
|
+
fs29.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
16024
16080
|
try {
|
|
16025
16081
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
16026
16082
|
} catch (err) {
|
|
@@ -16056,7 +16112,7 @@ function daemonUninstall() {
|
|
|
16056
16112
|
} catch {
|
|
16057
16113
|
}
|
|
16058
16114
|
try {
|
|
16059
|
-
|
|
16115
|
+
fs29.unlinkSync(plistPath);
|
|
16060
16116
|
removed = true;
|
|
16061
16117
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
16062
16118
|
} catch {
|
|
@@ -16076,7 +16132,7 @@ function daemonUninstall() {
|
|
|
16076
16132
|
let removed = false;
|
|
16077
16133
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
16078
16134
|
try {
|
|
16079
|
-
|
|
16135
|
+
fs29.unlinkSync(unitPath);
|
|
16080
16136
|
removed = true;
|
|
16081
16137
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
16082
16138
|
} catch {
|
|
@@ -16156,11 +16212,11 @@ async function daemonStatus() {
|
|
|
16156
16212
|
console.log(` Port: ${port}`);
|
|
16157
16213
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
16158
16214
|
console.log(` Platform: ${process.platform}`);
|
|
16159
|
-
console.log(` PID file: ${
|
|
16160
|
-
console.log(` Log file: ${
|
|
16215
|
+
console.log(` PID file: ${fs29.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
16216
|
+
console.log(` Log file: ${fs29.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
16161
16217
|
try {
|
|
16162
16218
|
const configPath = resolveConfigPath();
|
|
16163
|
-
const raw =
|
|
16219
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
16164
16220
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16165
16221
|
const config = parseConfig17(remnicCfg);
|
|
16166
16222
|
const extRoot = resolveExtensionsRoot(config);
|
|
@@ -16208,9 +16264,9 @@ function daemonStart() {
|
|
|
16208
16264
|
return;
|
|
16209
16265
|
}
|
|
16210
16266
|
}
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
const logStream =
|
|
16267
|
+
fs29.mkdirSync(PID_DIR, { recursive: true });
|
|
16268
|
+
fs29.mkdirSync(LOGS_DIR, { recursive: true });
|
|
16269
|
+
const logStream = fs29.openSync(LOG_FILE, "a");
|
|
16214
16270
|
const serverBin = resolveServerBin();
|
|
16215
16271
|
const isSource = serverBin.endsWith(".ts");
|
|
16216
16272
|
let cmd;
|
|
@@ -16232,7 +16288,7 @@ function daemonStart() {
|
|
|
16232
16288
|
}
|
|
16233
16289
|
});
|
|
16234
16290
|
child.unref();
|
|
16235
|
-
|
|
16291
|
+
fs29.writeFileSync(PID_FILE, String(child.pid));
|
|
16236
16292
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
16237
16293
|
console.log(` Log: ${LOG_FILE}`);
|
|
16238
16294
|
}
|
|
@@ -16266,11 +16322,11 @@ function daemonStop() {
|
|
|
16266
16322
|
console.log("Process not found (cleaning up PID file)");
|
|
16267
16323
|
}
|
|
16268
16324
|
try {
|
|
16269
|
-
|
|
16325
|
+
fs29.unlinkSync(PID_FILE);
|
|
16270
16326
|
} catch {
|
|
16271
16327
|
}
|
|
16272
16328
|
try {
|
|
16273
|
-
|
|
16329
|
+
fs29.unlinkSync(LEGACY_PID_FILE);
|
|
16274
16330
|
} catch {
|
|
16275
16331
|
}
|
|
16276
16332
|
}
|
|
@@ -16398,7 +16454,7 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
16398
16454
|
async function cmdBinary(rest) {
|
|
16399
16455
|
initLogger5();
|
|
16400
16456
|
const configPath = resolveConfigPath();
|
|
16401
|
-
const raw =
|
|
16457
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
16402
16458
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16403
16459
|
const config = parseConfig17(remnicCfg);
|
|
16404
16460
|
const memoryDir = resolveMemoryDir();
|
|
@@ -16589,7 +16645,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
16589
16645
|
} else if (slotIsActiveLegacy) {
|
|
16590
16646
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
16591
16647
|
}
|
|
16592
|
-
if (!
|
|
16648
|
+
if (!fs29.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
16593
16649
|
if (hasLegacy && migrateLegacy) {
|
|
16594
16650
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
16595
16651
|
}
|
|
@@ -16609,8 +16665,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
16609
16665
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
16610
16666
|
return;
|
|
16611
16667
|
}
|
|
16612
|
-
if (
|
|
16613
|
-
const st =
|
|
16668
|
+
if (fs29.existsSync(memoryDir)) {
|
|
16669
|
+
const st = fs29.statSync(memoryDir);
|
|
16614
16670
|
if (!st.isDirectory()) {
|
|
16615
16671
|
throw new Error(
|
|
16616
16672
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -16618,12 +16674,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
16618
16674
|
);
|
|
16619
16675
|
}
|
|
16620
16676
|
} else {
|
|
16621
|
-
|
|
16677
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
16622
16678
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
16623
16679
|
}
|
|
16624
16680
|
const configDir = path18.dirname(configPath);
|
|
16625
|
-
if (!
|
|
16626
|
-
|
|
16681
|
+
if (!fs29.existsSync(configDir)) {
|
|
16682
|
+
fs29.mkdirSync(configDir, { recursive: true });
|
|
16627
16683
|
}
|
|
16628
16684
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
16629
16685
|
console.log("\nDone! Summary of changes:");
|
|
@@ -16652,7 +16708,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
16652
16708
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
16653
16709
|
const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
16654
16710
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
16655
|
-
const configExistedBefore =
|
|
16711
|
+
const configExistedBefore = fs29.existsSync(configPath);
|
|
16656
16712
|
const existingConfig = readOpenclawConfig(configPath);
|
|
16657
16713
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
16658
16714
|
const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
@@ -16877,13 +16933,13 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
16877
16933
|
}
|
|
16878
16934
|
function createOpenclawUpgradeBackupDir() {
|
|
16879
16935
|
const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
|
|
16880
|
-
|
|
16881
|
-
return
|
|
16936
|
+
fs29.mkdirSync(backupsRoot, { recursive: true });
|
|
16937
|
+
return fs29.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
16882
16938
|
}
|
|
16883
16939
|
async function cmdTaxonomy(rest) {
|
|
16884
16940
|
initLogger5();
|
|
16885
16941
|
const configPath = resolveConfigPath();
|
|
16886
|
-
const raw =
|
|
16942
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
16887
16943
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16888
16944
|
const config = parseConfig17(remnicCfg);
|
|
16889
16945
|
if (!config.taxonomyEnabled) {
|
|
@@ -16921,8 +16977,8 @@ async function cmdTaxonomy(rest) {
|
|
|
16921
16977
|
console.log(doc);
|
|
16922
16978
|
if (config.taxonomyAutoGenResolver) {
|
|
16923
16979
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16924
|
-
|
|
16925
|
-
|
|
16980
|
+
fs29.mkdirSync(path18.dirname(resolverPath), { recursive: true });
|
|
16981
|
+
fs29.writeFileSync(resolverPath, doc);
|
|
16926
16982
|
console.error(`Written: ${resolverPath}`);
|
|
16927
16983
|
}
|
|
16928
16984
|
break;
|
|
@@ -16968,7 +17024,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16968
17024
|
if (config.taxonomyAutoGenResolver) {
|
|
16969
17025
|
const doc = generateResolverDocument(taxonomy);
|
|
16970
17026
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16971
|
-
|
|
17027
|
+
fs29.writeFileSync(resolverPath, doc);
|
|
16972
17028
|
console.error(`Regenerated: ${resolverPath}`);
|
|
16973
17029
|
}
|
|
16974
17030
|
break;
|
|
@@ -16999,7 +17055,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16999
17055
|
if (config.taxonomyAutoGenResolver) {
|
|
17000
17056
|
const doc = generateResolverDocument(taxonomy);
|
|
17001
17057
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
17002
|
-
|
|
17058
|
+
fs29.writeFileSync(resolverPath, doc);
|
|
17003
17059
|
console.error(`Regenerated: ${resolverPath}`);
|
|
17004
17060
|
}
|
|
17005
17061
|
break;
|
|
@@ -17190,12 +17246,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
17190
17246
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
17191
17247
|
);
|
|
17192
17248
|
}
|
|
17193
|
-
if (!
|
|
17249
|
+
if (!fs29.existsSync(args.memoryDir)) {
|
|
17194
17250
|
throw new Error(
|
|
17195
17251
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
17196
17252
|
);
|
|
17197
17253
|
}
|
|
17198
|
-
if (!
|
|
17254
|
+
if (!fs29.statSync(args.memoryDir).isDirectory()) {
|
|
17199
17255
|
throw new Error(
|
|
17200
17256
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
17201
17257
|
);
|
|
@@ -17281,10 +17337,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
17281
17337
|
}
|
|
17282
17338
|
const formatted = adapter.formatRecords(records);
|
|
17283
17339
|
const outDir = path18.dirname(args.output);
|
|
17284
|
-
|
|
17340
|
+
fs29.mkdirSync(outDir, { recursive: true });
|
|
17285
17341
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
17286
|
-
|
|
17287
|
-
|
|
17342
|
+
fs29.writeFileSync(tmpPath, formatted, "utf-8");
|
|
17343
|
+
fs29.renameSync(tmpPath, args.output);
|
|
17288
17344
|
stdout.write(
|
|
17289
17345
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
17290
17346
|
`
|
|
@@ -17468,7 +17524,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
17468
17524
|
}
|
|
17469
17525
|
}, 500);
|
|
17470
17526
|
};
|
|
17471
|
-
|
|
17527
|
+
fs29.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
17472
17528
|
if (filename && filename.startsWith(".")) return;
|
|
17473
17529
|
rebuild();
|
|
17474
17530
|
});
|
|
@@ -17476,12 +17532,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
17476
17532
|
});
|
|
17477
17533
|
} else if (subAction === "validate") {
|
|
17478
17534
|
const treeDir = outputDir;
|
|
17479
|
-
if (!
|
|
17535
|
+
if (!fs29.existsSync(treeDir)) {
|
|
17480
17536
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
17481
17537
|
process.exit(1);
|
|
17482
17538
|
}
|
|
17483
17539
|
const indexPath = path18.join(treeDir, "INDEX.md");
|
|
17484
|
-
if (!
|
|
17540
|
+
if (!fs29.existsSync(indexPath)) {
|
|
17485
17541
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
17486
17542
|
process.exit(1);
|
|
17487
17543
|
}
|
|
@@ -17715,7 +17771,7 @@ Other:
|
|
|
17715
17771
|
const targetFactory = async () => {
|
|
17716
17772
|
if (!orchestratorSingleton) {
|
|
17717
17773
|
const configPath = resolveConfigPath();
|
|
17718
|
-
const raw =
|
|
17774
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
17719
17775
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
17720
17776
|
const config = parseConfig17(remnicCfg);
|
|
17721
17777
|
orchestratorSingleton = new Orchestrator10(config);
|