@remnic/cli 9.69.30 → 9.69.32
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 +300 -235
- 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;
|
|
@@ -2612,6 +2646,10 @@ async function computeConvergePlan(options = {}) {
|
|
|
2612
2646
|
return collapseActiveFactDuplicates(plan, localManifests, peerManifests, semanticAgreementMap);
|
|
2613
2647
|
}
|
|
2614
2648
|
async function executeConvergeApply(options = {}) {
|
|
2649
|
+
const rawConcurrency = Number(process.env.REMNIC_CONVERGE_TRANSFER_CONCURRENCY ?? 8);
|
|
2650
|
+
if (!Number.isInteger(rawConcurrency) || rawConcurrency < 1) {
|
|
2651
|
+
throw new Error("converge: REMNIC_CONVERGE_TRANSFER_CONCURRENCY must be a positive integer");
|
|
2652
|
+
}
|
|
2615
2653
|
const conflictPolicy = options.conflictPolicy ?? options.config?.converge.conflictPolicy ?? DEFAULT_CONVERGE_CONFLICT_POLICY;
|
|
2616
2654
|
const plan = await computeConvergePlan({ ...options, conflictPolicy });
|
|
2617
2655
|
if (plan.converged && !options.dryRun) {
|
|
@@ -2693,8 +2731,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2693
2731
|
} catch {
|
|
2694
2732
|
}
|
|
2695
2733
|
}
|
|
2696
|
-
|
|
2697
|
-
if (entry.action === "identical") continue;
|
|
2734
|
+
const executeTransferEntry = async (entry) => {
|
|
2698
2735
|
let transferType = "none";
|
|
2699
2736
|
if (entry.action === "pull") {
|
|
2700
2737
|
transferType = "pull";
|
|
@@ -2735,7 +2772,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2735
2772
|
}
|
|
2736
2773
|
if (!remoteFile || entry.peerSha256 && remoteFile.sha256 !== entry.peerSha256) {
|
|
2737
2774
|
actualTransfers.failed += 1;
|
|
2738
|
-
|
|
2775
|
+
return;
|
|
2739
2776
|
}
|
|
2740
2777
|
let namespaceFiles = options.localFileBuffers.get(entry.namespace);
|
|
2741
2778
|
if (!namespaceFiles) {
|
|
@@ -2745,12 +2782,12 @@ async function executeConvergeApply(options = {}) {
|
|
|
2745
2782
|
namespaceFiles.set(localPath, remoteFile.content);
|
|
2746
2783
|
if (entry.action === "conflict") actualTransfers.conflictsResolved += 1;
|
|
2747
2784
|
else actualTransfers.pulled += 1;
|
|
2748
|
-
|
|
2785
|
+
return;
|
|
2749
2786
|
}
|
|
2750
2787
|
const rootDir = rootMap.get(entry.namespace);
|
|
2751
2788
|
if (!rootDir) {
|
|
2752
2789
|
actualTransfers.failed += 1;
|
|
2753
|
-
|
|
2790
|
+
return;
|
|
2754
2791
|
}
|
|
2755
2792
|
const io = await createOfflineStorageIo(rootDir);
|
|
2756
2793
|
const expectedLocalSha256 = entry.action === "conflict" ? entry.localSha256 : entry.baseSha256;
|
|
@@ -2842,7 +2879,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2842
2879
|
if (current.sha256 !== entry.localSha256) {
|
|
2843
2880
|
throw new Error(`local file changed during push: ${localPath}`);
|
|
2844
2881
|
}
|
|
2845
|
-
const stat2 = await
|
|
2882
|
+
const stat2 = await fs17.promises.stat(filePath);
|
|
2846
2883
|
let chunks;
|
|
2847
2884
|
let chunkOffset = 0;
|
|
2848
2885
|
const resetChunks = async () => {
|
|
@@ -2868,7 +2905,7 @@ async function executeConvergeApply(options = {}) {
|
|
|
2868
2905
|
while (chunkOffset < offset) {
|
|
2869
2906
|
const skipped = await chunks.next();
|
|
2870
2907
|
if (skipped.done || chunkOffset + skipped.value.length > offset) {
|
|
2871
|
-
throw new Error(`
|
|
2908
|
+
throw new Error(`upload resume failed at ${offset}: ${localPath}`);
|
|
2872
2909
|
}
|
|
2873
2910
|
chunkOffset += skipped.value.length;
|
|
2874
2911
|
}
|
|
@@ -3026,6 +3063,12 @@ async function executeConvergeApply(options = {}) {
|
|
|
3026
3063
|
if (suppressed) actualTransfers.suppressed += 1;
|
|
3027
3064
|
else actualTransfers.failed += 1;
|
|
3028
3065
|
}
|
|
3066
|
+
};
|
|
3067
|
+
const TRANSFER_BATCH_SIZE = rawConcurrency;
|
|
3068
|
+
const actionable = plan.entries.filter((entry) => entry.action !== "identical");
|
|
3069
|
+
for (let i = 0; i < actionable.length; i += TRANSFER_BATCH_SIZE) {
|
|
3070
|
+
const batch = actionable.slice(i, i + TRANSFER_BATCH_SIZE);
|
|
3071
|
+
await Promise.all(batch.map((entry) => executeTransferEntry(entry)));
|
|
3029
3072
|
}
|
|
3030
3073
|
if (options.peerUrl && peerMutatedNamespaces.size > 0) {
|
|
3031
3074
|
const namespaces = [...peerMutatedNamespaces].sort();
|
|
@@ -3115,48 +3158,54 @@ function convergeTimeoutFlagToMs(seconds) {
|
|
|
3115
3158
|
async function cmdConverge(action, rest, json, config = parseConfig13({})) {
|
|
3116
3159
|
if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
3117
3160
|
console.log(`Usage: remnic converge <plan|apply|watch> [options]
|
|
3118
|
-
|
|
3119
3161
|
Subcommands:
|
|
3120
3162
|
plan Compute and display reconciliation plan
|
|
3121
|
-
apply
|
|
3122
|
-
watch Run apply on a cadence until stopped (scheduled replication)
|
|
3163
|
+
apply/watch Transport (aliases: transport, sync) / scheduled watch
|
|
3123
3164
|
|
|
3124
|
-
Options:
|
|
3125
3165
|
--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)
|
|
3166
|
+
--token <t> / --token-file <p> / REMNIC_CONVERGE_PEER_TOKEN Credential
|
|
3167
|
+
channels (--token is argv-visible; prefer the other two)
|
|
3168
|
+
--conflict-policy <policy> Override (newest-wins|manual; default newest-wins)
|
|
3169
|
+
--interval <seconds> Watch cadence seconds (watch only; default 300)
|
|
3170
|
+
--timeout <seconds> Peer HTTP timeout seconds (default 30; boot-scale 300+)
|
|
3135
3171
|
--dry-run Simulate transfers without mutating disk or remote peer
|
|
3136
3172
|
--json Output detailed JSON plan report
|
|
3137
3173
|
`);
|
|
3138
3174
|
return;
|
|
3139
3175
|
}
|
|
3140
3176
|
if (action !== "plan" && action !== "apply" && action !== "transport" && action !== "sync" && action !== "watch") {
|
|
3141
|
-
process.stderr.write(`converge: unknown action "${action}". Use
|
|
3177
|
+
process.stderr.write(`converge: unknown action "${action}". Use plan, apply, or watch.
|
|
3142
3178
|
`);
|
|
3143
3179
|
process.exitCode = 2;
|
|
3144
3180
|
return;
|
|
3145
3181
|
}
|
|
3146
3182
|
let peerUrl;
|
|
3147
3183
|
let peerToken;
|
|
3184
|
+
let tokenFile;
|
|
3148
3185
|
let dryRun = false;
|
|
3149
3186
|
let conflictPolicy;
|
|
3150
3187
|
let intervalSeconds;
|
|
3151
3188
|
let timeoutMsFlag;
|
|
3152
3189
|
for (let i = 0; i < rest.length; i += 1) {
|
|
3153
3190
|
const arg = rest[i];
|
|
3154
|
-
if (
|
|
3155
|
-
|
|
3191
|
+
if (arg === "--token-file") {
|
|
3192
|
+
tokenFile = parseConvergeTokenFileFlag(rest[i + 1]);
|
|
3193
|
+
if (tokenFile === null) {
|
|
3194
|
+
process.stderr.write("converge: --token-file requires a path.\n");
|
|
3195
|
+
process.exitCode = 2;
|
|
3196
|
+
return;
|
|
3197
|
+
}
|
|
3156
3198
|
i += 1;
|
|
3157
3199
|
} else if (arg === "--token" && rest[i + 1]) {
|
|
3158
3200
|
peerToken = rest[i + 1];
|
|
3159
3201
|
i += 1;
|
|
3202
|
+
} else if (arg === "--token") {
|
|
3203
|
+
process.stderr.write("converge: --token requires a value.\n");
|
|
3204
|
+
process.exitCode = 2;
|
|
3205
|
+
return;
|
|
3206
|
+
} else if ((arg === "--peer" || arg === "--remote-url" || arg === "--remote") && rest[i + 1]) {
|
|
3207
|
+
peerUrl = rest[i + 1];
|
|
3208
|
+
i += 1;
|
|
3160
3209
|
} else if (arg === "--dry-run") {
|
|
3161
3210
|
dryRun = true;
|
|
3162
3211
|
} else if (arg === "--interval") {
|
|
@@ -3188,6 +3237,22 @@ Options:
|
|
|
3188
3237
|
i += 1;
|
|
3189
3238
|
}
|
|
3190
3239
|
}
|
|
3240
|
+
const tokenChannel = resolveConvergeTokenChannel(
|
|
3241
|
+
{ argvToken: peerToken, tokenFile: tokenFile ?? void 0 },
|
|
3242
|
+
process.env
|
|
3243
|
+
);
|
|
3244
|
+
if (!tokenChannel.ok) {
|
|
3245
|
+
process.stderr.write(`converge: ${tokenChannel.error}
|
|
3246
|
+
`);
|
|
3247
|
+
process.exitCode = 2;
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
3250
|
+
peerToken = tokenChannel.token;
|
|
3251
|
+
if (tokenChannel.tokenFromArgv) {
|
|
3252
|
+
process.stderr.write(
|
|
3253
|
+
"converge: note: --token is argv-visible; prefer --token-file or REMNIC_CONVERGE_PEER_TOKEN\n"
|
|
3254
|
+
);
|
|
3255
|
+
}
|
|
3191
3256
|
if (action === "watch") {
|
|
3192
3257
|
const controller = new AbortController();
|
|
3193
3258
|
const onSignal = () => controller.abort();
|
|
@@ -3397,7 +3462,7 @@ function renderReplayResult(result, targetNamespace, format) {
|
|
|
3397
3462
|
}
|
|
3398
3463
|
|
|
3399
3464
|
// src/quarantine-replay.ts
|
|
3400
|
-
import * as
|
|
3465
|
+
import * as fs18 from "fs";
|
|
3401
3466
|
import { EngramAccessService, Orchestrator as Orchestrator8, initLogger as initLogger3, parseConfig as parseConfig14, resolveRemnicConfigRecord as resolveRemnicConfigRecord13 } from "@remnic/core";
|
|
3402
3467
|
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
3403
3468
|
function valueFlag(args, flag) {
|
|
@@ -3446,7 +3511,7 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
3446
3511
|
let orchestrator;
|
|
3447
3512
|
try {
|
|
3448
3513
|
const configPath = resolveConfigPath2();
|
|
3449
|
-
const raw =
|
|
3514
|
+
const raw = fs18.existsSync(configPath) ? JSON.parse(fs18.readFileSync(configPath, "utf8")) : {};
|
|
3450
3515
|
const config = parseConfig14(resolveRemnicConfigRecord13(raw));
|
|
3451
3516
|
orchestrator = new Orchestrator8(config);
|
|
3452
3517
|
await orchestrator.initialize();
|
|
@@ -3478,7 +3543,7 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
3478
3543
|
}
|
|
3479
3544
|
|
|
3480
3545
|
// src/offline-impression-rotation.ts
|
|
3481
|
-
import
|
|
3546
|
+
import fs19 from "fs";
|
|
3482
3547
|
import { parseConfig as parseConfig15, resolveRemnicConfigRecord as resolveRemnicConfigRecord14, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
3483
3548
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
3484
3549
|
function parseConfigQuietly(raw) {
|
|
@@ -3513,7 +3578,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
3513
3578
|
function resolveOfflineImpressionRotation(configPath) {
|
|
3514
3579
|
let raw;
|
|
3515
3580
|
try {
|
|
3516
|
-
raw =
|
|
3581
|
+
raw = fs19.existsSync(configPath) ? JSON.parse(fs19.readFileSync(configPath, "utf8")) : {};
|
|
3517
3582
|
} catch {
|
|
3518
3583
|
throw new Error(
|
|
3519
3584
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -3546,8 +3611,8 @@ import {
|
|
|
3546
3611
|
existsSync as existsSync2,
|
|
3547
3612
|
lstatSync,
|
|
3548
3613
|
readdirSync,
|
|
3549
|
-
readFileSync as
|
|
3550
|
-
statSync
|
|
3614
|
+
readFileSync as readFileSync3,
|
|
3615
|
+
statSync as statSync2
|
|
3551
3616
|
} from "fs";
|
|
3552
3617
|
import path3 from "path";
|
|
3553
3618
|
import { fileURLToPath } from "url";
|
|
@@ -3580,7 +3645,7 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
3580
3645
|
}
|
|
3581
3646
|
let packageName;
|
|
3582
3647
|
try {
|
|
3583
|
-
packageName = JSON.parse(
|
|
3648
|
+
packageName = JSON.parse(readFileSync3(packageJsonPath, "utf8")).name;
|
|
3584
3649
|
} catch {
|
|
3585
3650
|
return { stale: false };
|
|
3586
3651
|
}
|
|
@@ -3609,7 +3674,7 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
3609
3674
|
if (!newestSource) {
|
|
3610
3675
|
return { stale: false };
|
|
3611
3676
|
}
|
|
3612
|
-
const distMtimeMs =
|
|
3677
|
+
const distMtimeMs = statSync2(distPath).mtimeMs;
|
|
3613
3678
|
if (newestSource.mtimeMs > distMtimeMs + STALE_BUILD_TOLERANCE_MS) {
|
|
3614
3679
|
return {
|
|
3615
3680
|
stale: true,
|
|
@@ -3658,7 +3723,7 @@ function newestMtime(roots) {
|
|
|
3658
3723
|
}
|
|
3659
3724
|
function isDirectory(entryPath) {
|
|
3660
3725
|
try {
|
|
3661
|
-
return
|
|
3726
|
+
return statSync2(entryPath).isDirectory();
|
|
3662
3727
|
} catch {
|
|
3663
3728
|
return false;
|
|
3664
3729
|
}
|
|
@@ -3771,7 +3836,7 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
3771
3836
|
}
|
|
3772
3837
|
|
|
3773
3838
|
// src/cmd-security.ts
|
|
3774
|
-
import
|
|
3839
|
+
import fs20 from "fs";
|
|
3775
3840
|
import {
|
|
3776
3841
|
Orchestrator as Orchestrator9,
|
|
3777
3842
|
parseConfig as parseConfig16,
|
|
@@ -3791,7 +3856,7 @@ async function cmdSecurity(rest) {
|
|
|
3791
3856
|
}
|
|
3792
3857
|
initLogger4();
|
|
3793
3858
|
const configPath = resolveConfigPath();
|
|
3794
|
-
const raw =
|
|
3859
|
+
const raw = fs20.existsSync(configPath) ? JSON.parse(fs20.readFileSync(configPath, "utf8")) : {};
|
|
3795
3860
|
const config = parseConfig16(resolveRemnicConfigRecord15(raw));
|
|
3796
3861
|
const orchestrator = new Orchestrator9(config);
|
|
3797
3862
|
await orchestrator.initialize();
|
|
@@ -3816,7 +3881,7 @@ async function cmdSecurity(rest) {
|
|
|
3816
3881
|
}
|
|
3817
3882
|
|
|
3818
3883
|
// src/daemon-service-candidates.ts
|
|
3819
|
-
import
|
|
3884
|
+
import fs21 from "fs";
|
|
3820
3885
|
import path5 from "path";
|
|
3821
3886
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
3822
3887
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -3838,7 +3903,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
3838
3903
|
function anyFileExists(paths) {
|
|
3839
3904
|
return paths.some((candidate) => {
|
|
3840
3905
|
try {
|
|
3841
|
-
return
|
|
3906
|
+
return fs21.statSync(candidate).isFile();
|
|
3842
3907
|
} catch {
|
|
3843
3908
|
return false;
|
|
3844
3909
|
}
|
|
@@ -3850,7 +3915,7 @@ function commandNames(command) {
|
|
|
3850
3915
|
}
|
|
3851
3916
|
function isRunnableNodeScript(filePath) {
|
|
3852
3917
|
try {
|
|
3853
|
-
const text =
|
|
3918
|
+
const text = fs21.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
3854
3919
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
3855
3920
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
3856
3921
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -3863,7 +3928,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
3863
3928
|
function resolveShimNodeScript(filePath) {
|
|
3864
3929
|
let text;
|
|
3865
3930
|
try {
|
|
3866
|
-
text =
|
|
3931
|
+
text = fs21.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
3867
3932
|
} catch {
|
|
3868
3933
|
return void 0;
|
|
3869
3934
|
}
|
|
@@ -3875,8 +3940,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
3875
3940
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
3876
3941
|
const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
|
|
3877
3942
|
try {
|
|
3878
|
-
if (
|
|
3879
|
-
return
|
|
3943
|
+
if (fs21.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
3944
|
+
return fs21.realpathSync(resolved);
|
|
3880
3945
|
}
|
|
3881
3946
|
} catch {
|
|
3882
3947
|
}
|
|
@@ -3884,7 +3949,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
3884
3949
|
return void 0;
|
|
3885
3950
|
}
|
|
3886
3951
|
function resolveRunnableNodeScript(filePath) {
|
|
3887
|
-
const realPath =
|
|
3952
|
+
const realPath = fs21.realpathSync(filePath);
|
|
3888
3953
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
3889
3954
|
return resolveShimNodeScript(realPath);
|
|
3890
3955
|
}
|
|
@@ -3894,9 +3959,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
3894
3959
|
for (const name of commandNames(command)) {
|
|
3895
3960
|
const candidate = path5.join(dir, name);
|
|
3896
3961
|
try {
|
|
3897
|
-
const stat2 =
|
|
3962
|
+
const stat2 = fs21.statSync(candidate);
|
|
3898
3963
|
if (!stat2.isFile()) continue;
|
|
3899
|
-
if (process.platform !== "win32")
|
|
3964
|
+
if (process.platform !== "win32") fs21.accessSync(candidate, fs21.constants.X_OK);
|
|
3900
3965
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
3901
3966
|
if (runnable) return runnable;
|
|
3902
3967
|
} catch {
|
|
@@ -5369,7 +5434,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
5369
5434
|
}
|
|
5370
5435
|
|
|
5371
5436
|
// src/bench-fallback.ts
|
|
5372
|
-
import
|
|
5437
|
+
import fs22 from "fs";
|
|
5373
5438
|
import path9 from "path";
|
|
5374
5439
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
5375
5440
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -5441,7 +5506,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
5441
5506
|
);
|
|
5442
5507
|
}
|
|
5443
5508
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
5444
|
-
const entries =
|
|
5509
|
+
const entries = fs22.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
5445
5510
|
if (entries.length === 0) {
|
|
5446
5511
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
5447
5512
|
}
|
|
@@ -5449,7 +5514,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
5449
5514
|
}
|
|
5450
5515
|
|
|
5451
5516
|
// src/openclaw-upgrade-swap.ts
|
|
5452
|
-
import
|
|
5517
|
+
import fs23 from "fs";
|
|
5453
5518
|
import path10 from "path";
|
|
5454
5519
|
function describeError(error) {
|
|
5455
5520
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -5461,7 +5526,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
5461
5526
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
5462
5527
|
if (explicitMode !== void 0) return explicitMode;
|
|
5463
5528
|
try {
|
|
5464
|
-
return
|
|
5529
|
+
return fs23.statSync(targetPath).mode & 4095;
|
|
5465
5530
|
} catch (error) {
|
|
5466
5531
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
5467
5532
|
return 384;
|
|
@@ -5471,8 +5536,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
5471
5536
|
}
|
|
5472
5537
|
function resolveAtomicReplacementPath(targetPath) {
|
|
5473
5538
|
try {
|
|
5474
|
-
if (
|
|
5475
|
-
return
|
|
5539
|
+
if (fs23.lstatSync(targetPath).isSymbolicLink()) {
|
|
5540
|
+
return fs23.realpathSync(targetPath);
|
|
5476
5541
|
}
|
|
5477
5542
|
} catch (error) {
|
|
5478
5543
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -5489,7 +5554,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
5489
5554
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
5490
5555
|
if (!displacedDir) return void 0;
|
|
5491
5556
|
try {
|
|
5492
|
-
|
|
5557
|
+
fs23.rmSync(displacedDir, { recursive: true, force: true });
|
|
5493
5558
|
return void 0;
|
|
5494
5559
|
} catch (error) {
|
|
5495
5560
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -5497,43 +5562,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
5497
5562
|
}
|
|
5498
5563
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
5499
5564
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
5500
|
-
|
|
5565
|
+
fs23.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
5501
5566
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
5502
5567
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
5503
5568
|
try {
|
|
5504
5569
|
if (options.hooks?.writeTempFileSync) {
|
|
5505
5570
|
options.hooks.writeTempFileSync(tempPath);
|
|
5506
5571
|
} else {
|
|
5507
|
-
|
|
5572
|
+
fs23.writeFileSync(tempPath, data, { mode });
|
|
5508
5573
|
}
|
|
5509
|
-
|
|
5510
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5574
|
+
fs23.chmodSync(tempPath, mode);
|
|
5575
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs23.renameSync;
|
|
5511
5576
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
5512
5577
|
} catch (error) {
|
|
5513
|
-
|
|
5578
|
+
fs23.rmSync(tempPath, { force: true });
|
|
5514
5579
|
throw error;
|
|
5515
5580
|
}
|
|
5516
5581
|
}
|
|
5517
5582
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
5518
|
-
if (!
|
|
5583
|
+
if (!fs23.existsSync(sourcePath)) return;
|
|
5519
5584
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
5520
|
-
|
|
5585
|
+
fs23.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
5521
5586
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
5522
|
-
const mode =
|
|
5587
|
+
const mode = fs23.statSync(sourcePath).mode & 4095;
|
|
5523
5588
|
try {
|
|
5524
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
5589
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs23.copyFileSync;
|
|
5525
5590
|
copyTempFileSync(sourcePath, tempPath);
|
|
5526
|
-
|
|
5527
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
5591
|
+
fs23.chmodSync(tempPath, mode);
|
|
5592
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs23.renameSync;
|
|
5528
5593
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
5529
5594
|
} catch (error) {
|
|
5530
|
-
|
|
5595
|
+
fs23.rmSync(tempPath, { force: true });
|
|
5531
5596
|
throw error;
|
|
5532
5597
|
}
|
|
5533
5598
|
}
|
|
5534
5599
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
5535
5600
|
if (!rollbackDir) return;
|
|
5536
|
-
|
|
5601
|
+
fs23.rmSync(rollbackDir, { recursive: true, force: true });
|
|
5537
5602
|
}
|
|
5538
5603
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
5539
5604
|
if (!rollbackDir) return void 0;
|
|
@@ -5545,20 +5610,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
5545
5610
|
}
|
|
5546
5611
|
}
|
|
5547
5612
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
5548
|
-
if (!
|
|
5613
|
+
if (!fs23.existsSync(rollbackDir)) {
|
|
5549
5614
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
5550
5615
|
}
|
|
5551
|
-
|
|
5552
|
-
const displacedDir =
|
|
5616
|
+
fs23.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
5617
|
+
const displacedDir = fs23.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
5553
5618
|
if (displacedDir) {
|
|
5554
|
-
|
|
5619
|
+
fs23.renameSync(targetDir, displacedDir);
|
|
5555
5620
|
}
|
|
5556
5621
|
try {
|
|
5557
|
-
|
|
5622
|
+
fs23.renameSync(rollbackDir, targetDir);
|
|
5558
5623
|
} catch (restoreError) {
|
|
5559
|
-
if (displacedDir &&
|
|
5624
|
+
if (displacedDir && fs23.existsSync(displacedDir)) {
|
|
5560
5625
|
try {
|
|
5561
|
-
|
|
5626
|
+
fs23.renameSync(displacedDir, targetDir);
|
|
5562
5627
|
} catch (revertError) {
|
|
5563
5628
|
throw new AggregateError(
|
|
5564
5629
|
[restoreError, revertError],
|
|
@@ -5574,23 +5639,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
5574
5639
|
return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
|
|
5575
5640
|
}
|
|
5576
5641
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
5577
|
-
if (!
|
|
5642
|
+
if (!fs23.existsSync(backupDir)) {
|
|
5578
5643
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
5579
5644
|
}
|
|
5580
|
-
|
|
5645
|
+
fs23.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
5581
5646
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
5582
|
-
const displacedDir =
|
|
5583
|
-
|
|
5647
|
+
const displacedDir = fs23.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
5648
|
+
fs23.cpSync(backupDir, stagedDir, { recursive: true });
|
|
5584
5649
|
if (displacedDir) {
|
|
5585
|
-
|
|
5650
|
+
fs23.renameSync(targetDir, displacedDir);
|
|
5586
5651
|
}
|
|
5587
5652
|
try {
|
|
5588
|
-
|
|
5653
|
+
fs23.renameSync(stagedDir, targetDir);
|
|
5589
5654
|
} catch (restoreError) {
|
|
5590
|
-
|
|
5591
|
-
if (displacedDir &&
|
|
5655
|
+
fs23.rmSync(targetDir, { recursive: true, force: true });
|
|
5656
|
+
if (displacedDir && fs23.existsSync(displacedDir)) {
|
|
5592
5657
|
try {
|
|
5593
|
-
|
|
5658
|
+
fs23.renameSync(displacedDir, targetDir);
|
|
5594
5659
|
} catch (revertError) {
|
|
5595
5660
|
throw new AggregateError(
|
|
5596
5661
|
[restoreError, revertError],
|
|
@@ -5598,7 +5663,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
5598
5663
|
);
|
|
5599
5664
|
}
|
|
5600
5665
|
}
|
|
5601
|
-
|
|
5666
|
+
fs23.rmSync(stagedDir, { recursive: true, force: true });
|
|
5602
5667
|
throw new Error(
|
|
5603
5668
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
5604
5669
|
{ cause: restoreError }
|
|
@@ -5623,7 +5688,7 @@ function rollbackOpenclawUpgrade({
|
|
|
5623
5688
|
let configRemovalAttempted = false;
|
|
5624
5689
|
let pluginRestored = false;
|
|
5625
5690
|
try {
|
|
5626
|
-
if (rollbackDir &&
|
|
5691
|
+
if (rollbackDir && fs23.existsSync(rollbackDir)) {
|
|
5627
5692
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
5628
5693
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
5629
5694
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -5633,7 +5698,7 @@ function rollbackOpenclawUpgrade({
|
|
|
5633
5698
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
5634
5699
|
}
|
|
5635
5700
|
try {
|
|
5636
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
5701
|
+
if (!pluginRestored && pluginBackupDir && fs23.existsSync(pluginBackupDir)) {
|
|
5637
5702
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
5638
5703
|
if (rollbackRestoreError) {
|
|
5639
5704
|
notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
|
|
@@ -5658,12 +5723,12 @@ function rollbackOpenclawUpgrade({
|
|
|
5658
5723
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
5659
5724
|
}
|
|
5660
5725
|
try {
|
|
5661
|
-
if (configBackupPath &&
|
|
5726
|
+
if (configBackupPath && fs23.existsSync(configBackupPath)) {
|
|
5662
5727
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
5663
5728
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
5664
|
-
} else if (removeConfigIfUnbacked &&
|
|
5729
|
+
} else if (removeConfigIfUnbacked && fs23.existsSync(configPath)) {
|
|
5665
5730
|
configRemovalAttempted = true;
|
|
5666
|
-
|
|
5731
|
+
fs23.rmSync(configPath, { force: true });
|
|
5667
5732
|
notes.push("Removed OpenClaw config created during the failed upgrade");
|
|
5668
5733
|
}
|
|
5669
5734
|
} catch (error) {
|
|
@@ -5716,7 +5781,7 @@ Run this manually when you're ready:
|
|
|
5716
5781
|
|
|
5717
5782
|
// src/openclaw-managed-upgrade-loader.ts
|
|
5718
5783
|
import { execFileSync } from "child_process";
|
|
5719
|
-
import
|
|
5784
|
+
import fs24 from "fs";
|
|
5720
5785
|
import os from "os";
|
|
5721
5786
|
import path11 from "path";
|
|
5722
5787
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -5792,7 +5857,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
|
|
|
5792
5857
|
function readCliAdapterRange() {
|
|
5793
5858
|
const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
|
|
5794
5859
|
const manifestPath = path11.resolve(moduleDir, "../package.json");
|
|
5795
|
-
const manifest = JSON.parse(
|
|
5860
|
+
const manifest = JSON.parse(fs24.readFileSync(manifestPath, "utf8"));
|
|
5796
5861
|
if (manifest.name !== "@remnic/cli") {
|
|
5797
5862
|
throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
|
|
5798
5863
|
}
|
|
@@ -5836,7 +5901,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5836
5901
|
const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
|
|
5837
5902
|
if (!adapterMissing) throw error;
|
|
5838
5903
|
}
|
|
5839
|
-
const temporaryRoot =
|
|
5904
|
+
const temporaryRoot = fs24.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
5840
5905
|
try {
|
|
5841
5906
|
const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
|
|
5842
5907
|
const installArgs = [
|
|
@@ -5851,12 +5916,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5851
5916
|
];
|
|
5852
5917
|
(hooks.runNpmInstall ?? runNpmInstall)(installArgs);
|
|
5853
5918
|
const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
|
|
5854
|
-
|
|
5919
|
+
fs24.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
|
|
5855
5920
|
`, "utf8");
|
|
5856
5921
|
return await importModule(pathToFileURL2(resolverPath).href);
|
|
5857
5922
|
} finally {
|
|
5858
5923
|
try {
|
|
5859
|
-
|
|
5924
|
+
fs24.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
5860
5925
|
} catch (error) {
|
|
5861
5926
|
const detail = error instanceof Error ? error.message : String(error);
|
|
5862
5927
|
console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
|
|
@@ -5865,12 +5930,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
5865
5930
|
}
|
|
5866
5931
|
|
|
5867
5932
|
// src/remote-daemon.ts
|
|
5868
|
-
import
|
|
5933
|
+
import fs25 from "fs";
|
|
5869
5934
|
import { readCompatEnv } from "@remnic/core";
|
|
5870
5935
|
import { isLoopbackHost } from "@remnic/core/runtime/http-transport.js";
|
|
5871
5936
|
function readRemnicConfigRecord(configPath) {
|
|
5872
5937
|
try {
|
|
5873
|
-
const parsed = JSON.parse(
|
|
5938
|
+
const parsed = JSON.parse(fs25.readFileSync(configPath, "utf8"));
|
|
5874
5939
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
5875
5940
|
return parsed;
|
|
5876
5941
|
}
|
|
@@ -6118,7 +6183,7 @@ async function remoteRecallXray(daemon, request) {
|
|
|
6118
6183
|
}
|
|
6119
6184
|
|
|
6120
6185
|
// src/daemon-service.ts
|
|
6121
|
-
import
|
|
6186
|
+
import fs26 from "fs";
|
|
6122
6187
|
import path12 from "path";
|
|
6123
6188
|
import * as childProcess from "child_process";
|
|
6124
6189
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -6130,7 +6195,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
6130
6195
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
6131
6196
|
}
|
|
6132
6197
|
function resolveServerBinDetails(options = {}) {
|
|
6133
|
-
const existsSync4 = options.existsSync ??
|
|
6198
|
+
const existsSync4 = options.existsSync ?? fs26.existsSync;
|
|
6134
6199
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
6135
6200
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
6136
6201
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -6189,15 +6254,15 @@ function resolveServerBin(options = {}) {
|
|
|
6189
6254
|
return resolveServerBinDetails(options).path;
|
|
6190
6255
|
}
|
|
6191
6256
|
function readVerifiedDaemonPid(options) {
|
|
6192
|
-
const
|
|
6193
|
-
const unlinkSync = options.unlinkSync ??
|
|
6257
|
+
const readFileSync5 = options.readFileSync ?? fs26.readFileSync;
|
|
6258
|
+
const unlinkSync = options.unlinkSync ?? fs26.unlinkSync;
|
|
6194
6259
|
const processKill = options.processKill ?? process.kill;
|
|
6195
6260
|
const platform = options.platform ?? process.platform;
|
|
6196
6261
|
const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
6197
6262
|
for (const file of options.pidFiles) {
|
|
6198
6263
|
let pid;
|
|
6199
6264
|
try {
|
|
6200
|
-
pid = parseDaemonPid(
|
|
6265
|
+
pid = parseDaemonPid(readFileSync5(file, "utf8"));
|
|
6201
6266
|
} catch {
|
|
6202
6267
|
continue;
|
|
6203
6268
|
}
|
|
@@ -6290,8 +6355,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
6290
6355
|
}
|
|
6291
6356
|
}
|
|
6292
6357
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
6293
|
-
const existsSync4 = options.existsSync ??
|
|
6294
|
-
const
|
|
6358
|
+
const existsSync4 = options.existsSync ?? fs26.existsSync;
|
|
6359
|
+
const readFileSync5 = options.readFileSync ?? fs26.readFileSync;
|
|
6295
6360
|
if (!existsSync4(plistPath)) {
|
|
6296
6361
|
return {
|
|
6297
6362
|
installed: false,
|
|
@@ -6302,7 +6367,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
6302
6367
|
}
|
|
6303
6368
|
let content;
|
|
6304
6369
|
try {
|
|
6305
|
-
content =
|
|
6370
|
+
content = readFileSync5(plistPath, "utf8");
|
|
6306
6371
|
} catch {
|
|
6307
6372
|
return {
|
|
6308
6373
|
installed: true,
|
|
@@ -6469,7 +6534,7 @@ function stripConfigArgv(args) {
|
|
|
6469
6534
|
}
|
|
6470
6535
|
|
|
6471
6536
|
// src/import-dispatch.ts
|
|
6472
|
-
import
|
|
6537
|
+
import fs27 from "fs";
|
|
6473
6538
|
import {
|
|
6474
6539
|
runImporter,
|
|
6475
6540
|
validateImportBatchSize,
|
|
@@ -6477,7 +6542,7 @@ import {
|
|
|
6477
6542
|
} from "@remnic/core";
|
|
6478
6543
|
|
|
6479
6544
|
// src/import-bundle-detect.ts
|
|
6480
|
-
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as
|
|
6545
|
+
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
6481
6546
|
import path13 from "path";
|
|
6482
6547
|
function detectBundleEntries(bundleDir, options = {}) {
|
|
6483
6548
|
const readdir3 = options.readdirImpl ?? defaultReaddir;
|
|
@@ -6599,7 +6664,7 @@ function defaultReaddir(dir) {
|
|
|
6599
6664
|
return readdirSync2(dir);
|
|
6600
6665
|
}
|
|
6601
6666
|
function defaultReadFile(p) {
|
|
6602
|
-
return
|
|
6667
|
+
return readFileSync4(p, "utf-8");
|
|
6603
6668
|
}
|
|
6604
6669
|
function defaultIsDirectory(p) {
|
|
6605
6670
|
try {
|
|
@@ -6989,7 +7054,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
6989
7054
|
let materializedTarget;
|
|
6990
7055
|
let materializePromise;
|
|
6991
7056
|
const io = {
|
|
6992
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
7057
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs27.promises.readFile(p, "utf-8")),
|
|
6993
7058
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
6994
7059
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
6995
7060
|
getWriteTarget: async () => {
|
|
@@ -7102,7 +7167,7 @@ async function cmdCapture(rest, io) {
|
|
|
7102
7167
|
}
|
|
7103
7168
|
|
|
7104
7169
|
// src/import-lossless-claw-cmd.ts
|
|
7105
|
-
import
|
|
7170
|
+
import fs28 from "fs";
|
|
7106
7171
|
import path14 from "path";
|
|
7107
7172
|
import {
|
|
7108
7173
|
applyLcmSchema,
|
|
@@ -7214,15 +7279,15 @@ async function loadImportLosslessClawModule() {
|
|
|
7214
7279
|
|
|
7215
7280
|
// src/import-lossless-claw-cmd.ts
|
|
7216
7281
|
function assertDirectoryOrAbsent(p, label) {
|
|
7217
|
-
if (
|
|
7282
|
+
if (fs28.existsSync(p) && !fs28.statSync(p).isDirectory()) {
|
|
7218
7283
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
7219
7284
|
}
|
|
7220
7285
|
}
|
|
7221
7286
|
function assertFile(p, label) {
|
|
7222
|
-
if (!
|
|
7287
|
+
if (!fs28.existsSync(p)) {
|
|
7223
7288
|
throw new Error(`${label} does not exist: ${p}`);
|
|
7224
7289
|
}
|
|
7225
|
-
if (!
|
|
7290
|
+
if (!fs28.statSync(p).isFile()) {
|
|
7226
7291
|
throw new Error(`${label} is not a file: ${p}`);
|
|
7227
7292
|
}
|
|
7228
7293
|
}
|
|
@@ -7254,7 +7319,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
7254
7319
|
try {
|
|
7255
7320
|
if (parsed.dryRun) {
|
|
7256
7321
|
const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
|
|
7257
|
-
if (
|
|
7322
|
+
if (fs28.existsSync(lcmPath)) {
|
|
7258
7323
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
7259
7324
|
} else {
|
|
7260
7325
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -8606,7 +8671,7 @@ async function resolveAllBenchmarks() {
|
|
|
8606
8671
|
if (packageBenchmarks) {
|
|
8607
8672
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
8608
8673
|
}
|
|
8609
|
-
if (!
|
|
8674
|
+
if (!fs29.existsSync(EVAL_RUNNER_PATH)) {
|
|
8610
8675
|
return [];
|
|
8611
8676
|
}
|
|
8612
8677
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -8654,7 +8719,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
8654
8719
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
8655
8720
|
);
|
|
8656
8721
|
}
|
|
8657
|
-
if (!
|
|
8722
|
+
if (!fs29.existsSync(EVAL_RUNNER_PATH)) {
|
|
8658
8723
|
console.error(
|
|
8659
8724
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
8660
8725
|
);
|
|
@@ -8664,7 +8729,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
8664
8729
|
path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
8665
8730
|
path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
8666
8731
|
];
|
|
8667
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
8732
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs29.existsSync(candidate)) ?? "tsx";
|
|
8668
8733
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
8669
8734
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
8670
8735
|
benchmarkId,
|
|
@@ -8809,9 +8874,9 @@ var PERSONAMEM_COMPLETION_MARKER = path18.join(
|
|
|
8809
8874
|
);
|
|
8810
8875
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
8811
8876
|
try {
|
|
8812
|
-
const datasetRoot =
|
|
8877
|
+
const datasetRoot = fs29.realpathSync(datasetPath);
|
|
8813
8878
|
const candidatePath = path18.resolve(datasetRoot, relativePath);
|
|
8814
|
-
const candidateRealPath =
|
|
8879
|
+
const candidateRealPath = fs29.realpathSync(candidatePath);
|
|
8815
8880
|
const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
|
|
8816
8881
|
if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
|
|
8817
8882
|
return null;
|
|
@@ -8870,14 +8935,14 @@ function parseCsvRows(raw) {
|
|
|
8870
8935
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
8871
8936
|
try {
|
|
8872
8937
|
const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
8873
|
-
if (
|
|
8938
|
+
if (fs29.statSync(completionMarkerPath).isFile()) {
|
|
8874
8939
|
return true;
|
|
8875
8940
|
}
|
|
8876
8941
|
} catch {
|
|
8877
8942
|
}
|
|
8878
8943
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
8879
8944
|
try {
|
|
8880
|
-
return
|
|
8945
|
+
return fs29.statSync(path18.join(datasetPath, candidate)).isFile();
|
|
8881
8946
|
} catch {
|
|
8882
8947
|
return false;
|
|
8883
8948
|
}
|
|
@@ -8886,7 +8951,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8886
8951
|
return false;
|
|
8887
8952
|
}
|
|
8888
8953
|
try {
|
|
8889
|
-
const rows = parseCsvRows(
|
|
8954
|
+
const rows = parseCsvRows(fs29.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
|
|
8890
8955
|
if (rows.length < 2) {
|
|
8891
8956
|
return false;
|
|
8892
8957
|
}
|
|
@@ -8901,7 +8966,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8901
8966
|
}
|
|
8902
8967
|
return historyPaths.every((relativePath) => {
|
|
8903
8968
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
8904
|
-
return resolvedPath !== null &&
|
|
8969
|
+
return resolvedPath !== null && fs29.statSync(resolvedPath).isFile();
|
|
8905
8970
|
});
|
|
8906
8971
|
} catch {
|
|
8907
8972
|
return false;
|
|
@@ -8909,7 +8974,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
8909
8974
|
}
|
|
8910
8975
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
8911
8976
|
try {
|
|
8912
|
-
return
|
|
8977
|
+
return fs29.statSync(path18.join(datasetPath, relativePath)).isFile();
|
|
8913
8978
|
} catch {
|
|
8914
8979
|
return false;
|
|
8915
8980
|
}
|
|
@@ -8929,10 +8994,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
8929
8994
|
return candidateFilenames.some((filename) => {
|
|
8930
8995
|
const filePath = path18.join(datasetPath, filename);
|
|
8931
8996
|
try {
|
|
8932
|
-
if (!
|
|
8997
|
+
if (!fs29.statSync(filePath).isFile()) {
|
|
8933
8998
|
return false;
|
|
8934
8999
|
}
|
|
8935
|
-
const raw =
|
|
9000
|
+
const raw = fs29.readFileSync(filePath, "utf8");
|
|
8936
9001
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
8937
9002
|
} catch {
|
|
8938
9003
|
return false;
|
|
@@ -8948,7 +9013,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
8948
9013
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
8949
9014
|
let stats;
|
|
8950
9015
|
try {
|
|
8951
|
-
stats =
|
|
9016
|
+
stats = fs29.statSync(datasetPath);
|
|
8952
9017
|
} catch {
|
|
8953
9018
|
return false;
|
|
8954
9019
|
}
|
|
@@ -8958,7 +9023,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8958
9023
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
8959
9024
|
if (!marker) {
|
|
8960
9025
|
try {
|
|
8961
|
-
return
|
|
9026
|
+
return fs29.readdirSync(datasetPath).length > 0;
|
|
8962
9027
|
} catch {
|
|
8963
9028
|
return false;
|
|
8964
9029
|
}
|
|
@@ -8966,7 +9031,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8966
9031
|
if (marker.allOf) {
|
|
8967
9032
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
8968
9033
|
try {
|
|
8969
|
-
return
|
|
9034
|
+
return fs29.statSync(path18.join(datasetPath, name)).isFile();
|
|
8970
9035
|
} catch {
|
|
8971
9036
|
return false;
|
|
8972
9037
|
}
|
|
@@ -8978,7 +9043,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8978
9043
|
if (marker.anyOf) {
|
|
8979
9044
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
8980
9045
|
try {
|
|
8981
|
-
return
|
|
9046
|
+
return fs29.statSync(path18.join(datasetPath, name)).isFile();
|
|
8982
9047
|
} catch {
|
|
8983
9048
|
return false;
|
|
8984
9049
|
}
|
|
@@ -8996,7 +9061,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
8996
9061
|
}
|
|
8997
9062
|
if (marker.ext) {
|
|
8998
9063
|
try {
|
|
8999
|
-
return
|
|
9064
|
+
return fs29.readdirSync(datasetPath).some(
|
|
9000
9065
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
9001
9066
|
);
|
|
9002
9067
|
} catch {
|
|
@@ -9008,7 +9073,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
9008
9073
|
async function launchBenchUi(resultsDir) {
|
|
9009
9074
|
const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
9010
9075
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
9011
|
-
if (!
|
|
9076
|
+
if (!fs29.existsSync(path18.join(benchUiDir, "package.json"))) {
|
|
9012
9077
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
9013
9078
|
process.exit(1);
|
|
9014
9079
|
}
|
|
@@ -9046,13 +9111,13 @@ function listDownloadableBenchmarks() {
|
|
|
9046
9111
|
}
|
|
9047
9112
|
function resolveDatasetDownloadScriptPath() {
|
|
9048
9113
|
const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
9049
|
-
if (
|
|
9114
|
+
if (fs29.existsSync(bundled)) {
|
|
9050
9115
|
return bundled;
|
|
9051
9116
|
}
|
|
9052
9117
|
return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
9053
9118
|
}
|
|
9054
9119
|
function isRepoCheckout() {
|
|
9055
|
-
return
|
|
9120
|
+
return fs29.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs29.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
9056
9121
|
}
|
|
9057
9122
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
9058
9123
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -9365,8 +9430,8 @@ async function exportBenchPackageResult(parsed) {
|
|
|
9365
9430
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
9366
9431
|
});
|
|
9367
9432
|
if (parsed.output) {
|
|
9368
|
-
|
|
9369
|
-
|
|
9433
|
+
fs29.mkdirSync(path18.dirname(parsed.output), { recursive: true });
|
|
9434
|
+
fs29.writeFileSync(parsed.output, rendered);
|
|
9370
9435
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
9371
9436
|
return;
|
|
9372
9437
|
}
|
|
@@ -9411,7 +9476,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
9411
9476
|
process.exit(1);
|
|
9412
9477
|
}
|
|
9413
9478
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
9414
|
-
if (!
|
|
9479
|
+
if (!fs29.existsSync(scriptPath)) {
|
|
9415
9480
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
9416
9481
|
process.exit(1);
|
|
9417
9482
|
}
|
|
@@ -9611,7 +9676,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
9611
9676
|
);
|
|
9612
9677
|
process.exit(1);
|
|
9613
9678
|
}
|
|
9614
|
-
const sourceResultSha256 = createHash4("sha256").update(
|
|
9679
|
+
const sourceResultSha256 = createHash4("sha256").update(fs29.readFileSync(latest.path)).digest("hex");
|
|
9615
9680
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
9616
9681
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
9617
9682
|
console.error(
|
|
@@ -10026,7 +10091,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
10026
10091
|
}
|
|
10027
10092
|
let decoded;
|
|
10028
10093
|
try {
|
|
10029
|
-
decoded = JSON.parse(
|
|
10094
|
+
decoded = JSON.parse(fs29.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
10030
10095
|
} catch (error) {
|
|
10031
10096
|
throw new Error(
|
|
10032
10097
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -10122,7 +10187,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
10122
10187
|
const benchModule = await loadBenchModule();
|
|
10123
10188
|
return {
|
|
10124
10189
|
async promoteArtifactsToPublished(args) {
|
|
10125
|
-
const { mkdirSync, readFileSync:
|
|
10190
|
+
const { mkdirSync, readFileSync: readFileSync5, writeFileSync } = await import("fs");
|
|
10126
10191
|
const path19 = await import("path");
|
|
10127
10192
|
mkdirSync(args.publishedOutDir, { recursive: true });
|
|
10128
10193
|
if (args.artifactPaths.length === 0) {
|
|
@@ -10132,7 +10197,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
10132
10197
|
return;
|
|
10133
10198
|
}
|
|
10134
10199
|
for (const artifactPath of args.artifactPaths) {
|
|
10135
|
-
const raw =
|
|
10200
|
+
const raw = readFileSync5(artifactPath, "utf8");
|
|
10136
10201
|
const parsedUnknown = JSON.parse(raw);
|
|
10137
10202
|
const parsedObj = parsedUnknown !== null && typeof parsedUnknown === "object" && !Array.isArray(parsedUnknown) ? parsedUnknown : {};
|
|
10138
10203
|
const gitShaShort = (parsedObj.meta?.gitSha ?? "unknown").slice(0, 7);
|
|
@@ -10701,7 +10766,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
10701
10766
|
return void 0;
|
|
10702
10767
|
}
|
|
10703
10768
|
try {
|
|
10704
|
-
return
|
|
10769
|
+
return fs29.realpathSync(datasetDir);
|
|
10705
10770
|
} catch {
|
|
10706
10771
|
return datasetDir;
|
|
10707
10772
|
}
|
|
@@ -10755,7 +10820,7 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
10755
10820
|
}
|
|
10756
10821
|
function loadStandaloneConvergeCommandConfig() {
|
|
10757
10822
|
const configPath = resolveConfigPath();
|
|
10758
|
-
const raw =
|
|
10823
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
10759
10824
|
return parseConfig17(resolveRemnicConfigRecord16(raw));
|
|
10760
10825
|
}
|
|
10761
10826
|
function parseConvergePluginConfig(value) {
|
|
@@ -10775,7 +10840,7 @@ function loadConvergeCommandConfig() {
|
|
|
10775
10840
|
}
|
|
10776
10841
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
10777
10842
|
const configPath = resolveConfigPath(cliPath);
|
|
10778
|
-
if (
|
|
10843
|
+
if (fs29.existsSync(configPath)) {
|
|
10779
10844
|
return configPath;
|
|
10780
10845
|
}
|
|
10781
10846
|
if (cliPath) {
|
|
@@ -10785,7 +10850,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
10785
10850
|
}
|
|
10786
10851
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
10787
10852
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
10788
|
-
if (
|
|
10853
|
+
if (fs29.existsSync(configPath)) {
|
|
10789
10854
|
return configPath;
|
|
10790
10855
|
}
|
|
10791
10856
|
if (cliPath) {
|
|
@@ -10892,7 +10957,7 @@ function resolveMemoryDir() {
|
|
|
10892
10957
|
const envMemoryDir = readCompatEnv2("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
10893
10958
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
10894
10959
|
const configPath = resolveConfigPath();
|
|
10895
|
-
const raw =
|
|
10960
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
10896
10961
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
10897
10962
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
10898
10963
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
@@ -10901,18 +10966,18 @@ function resolveMemoryDir() {
|
|
|
10901
10966
|
const standalonePath = path18.join(home, ".remnic", "memory");
|
|
10902
10967
|
const legacyStandalonePath = path18.join(home, ".engram", "memory");
|
|
10903
10968
|
const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
10904
|
-
if (
|
|
10905
|
-
if (
|
|
10969
|
+
if (fs29.existsSync(standalonePath)) return standalonePath;
|
|
10970
|
+
if (fs29.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
10906
10971
|
return openclawPath;
|
|
10907
10972
|
})();
|
|
10908
10973
|
const manifestPath = getManifestPath();
|
|
10909
|
-
if (
|
|
10974
|
+
if (fs29.existsSync(manifestPath)) {
|
|
10910
10975
|
try {
|
|
10911
10976
|
const active = getActiveSpace();
|
|
10912
10977
|
if (active?.memoryDir) {
|
|
10913
10978
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
10914
|
-
if (!
|
|
10915
|
-
|
|
10979
|
+
if (!fs29.existsSync(activeMemoryDir)) {
|
|
10980
|
+
fs29.mkdirSync(activeMemoryDir, { recursive: true });
|
|
10916
10981
|
}
|
|
10917
10982
|
return activeMemoryDir;
|
|
10918
10983
|
}
|
|
@@ -10961,13 +11026,13 @@ function resolveOpenclawConfigPath(cliPath) {
|
|
|
10961
11026
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
10962
11027
|
if (envPath) return path18.resolve(expandTilde(envPath));
|
|
10963
11028
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
10964
|
-
if (
|
|
11029
|
+
if (fs29.existsSync(candidate)) return candidate;
|
|
10965
11030
|
}
|
|
10966
11031
|
return path18.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
10967
11032
|
}
|
|
10968
11033
|
function readOpenclawConfig(configPath) {
|
|
10969
|
-
if (!
|
|
10970
|
-
const raw =
|
|
11034
|
+
if (!fs29.existsSync(configPath)) return {};
|
|
11035
|
+
const raw = fs29.readFileSync(configPath, "utf-8");
|
|
10971
11036
|
let parsed;
|
|
10972
11037
|
try {
|
|
10973
11038
|
parsed = JSON.parse(raw);
|
|
@@ -11069,9 +11134,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
11069
11134
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
11070
11135
|
}
|
|
11071
11136
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
11072
|
-
if (!
|
|
11073
|
-
|
|
11074
|
-
|
|
11137
|
+
if (!fs29.existsSync(sourcePath)) return false;
|
|
11138
|
+
fs29.mkdirSync(path18.dirname(backupPath), { recursive: true });
|
|
11139
|
+
fs29.cpSync(sourcePath, backupPath, { recursive: true });
|
|
11075
11140
|
return true;
|
|
11076
11141
|
}
|
|
11077
11142
|
function restartOpenclawGateway() {
|
|
@@ -11090,7 +11155,7 @@ function restartOpenclawGateway() {
|
|
|
11090
11155
|
}
|
|
11091
11156
|
function cmdInit() {
|
|
11092
11157
|
const configPath = path18.join(process.cwd(), "remnic.config.json");
|
|
11093
|
-
if (
|
|
11158
|
+
if (fs29.existsSync(configPath)) {
|
|
11094
11159
|
console.log(`Config already exists: ${configPath}`);
|
|
11095
11160
|
return;
|
|
11096
11161
|
}
|
|
@@ -11106,7 +11171,7 @@ function cmdInit() {
|
|
|
11106
11171
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
11107
11172
|
}
|
|
11108
11173
|
};
|
|
11109
|
-
|
|
11174
|
+
fs29.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
11110
11175
|
console.log(`Created ${configPath}`);
|
|
11111
11176
|
console.log("\nSet these environment variables:");
|
|
11112
11177
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -11528,7 +11593,7 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
11528
11593
|
}
|
|
11529
11594
|
initLogger5();
|
|
11530
11595
|
const configPath = resolveConfigPath();
|
|
11531
|
-
const raw =
|
|
11596
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11532
11597
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11533
11598
|
const config = parseConfig17(remnicCfg);
|
|
11534
11599
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -11708,7 +11773,7 @@ async function cmdXray(rest) {
|
|
|
11708
11773
|
}
|
|
11709
11774
|
initLogger5();
|
|
11710
11775
|
const configPath = resolveConfigPath();
|
|
11711
|
-
const raw =
|
|
11776
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11712
11777
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11713
11778
|
const config = parseConfig17(remnicCfg);
|
|
11714
11779
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -11741,7 +11806,7 @@ async function runWhoKnowsCommand(rest, io) {
|
|
|
11741
11806
|
async function withLocalService(fn) {
|
|
11742
11807
|
initLogger5();
|
|
11743
11808
|
const configPath = resolveConfigPath();
|
|
11744
|
-
const raw =
|
|
11809
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11745
11810
|
const orchestrator = new Orchestrator10(parseConfig17(resolveRemnicConfigRecord16(raw)));
|
|
11746
11811
|
await orchestrator.initialize();
|
|
11747
11812
|
await orchestrator.deferredReady;
|
|
@@ -11774,7 +11839,7 @@ async function cmdPromotionCandidates(rest) {
|
|
|
11774
11839
|
async function cmdVersions(rest) {
|
|
11775
11840
|
initLogger5();
|
|
11776
11841
|
const configPath = resolveConfigPath();
|
|
11777
|
-
const raw =
|
|
11842
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11778
11843
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11779
11844
|
const config = parseConfig17(remnicCfg);
|
|
11780
11845
|
if (!config.versioningEnabled) {
|
|
@@ -11890,7 +11955,7 @@ Options:
|
|
|
11890
11955
|
async function cmdEnrich(rest) {
|
|
11891
11956
|
initLogger5();
|
|
11892
11957
|
const configPath = resolveConfigPath();
|
|
11893
|
-
const raw =
|
|
11958
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
11894
11959
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
11895
11960
|
const config = parseConfig17(remnicCfg);
|
|
11896
11961
|
const subcommand = rest[0];
|
|
@@ -12084,7 +12149,7 @@ Registered providers:`);
|
|
|
12084
12149
|
async function cmdExtensions(action, rest) {
|
|
12085
12150
|
initLogger5();
|
|
12086
12151
|
const configPath = resolveConfigPath();
|
|
12087
|
-
const raw =
|
|
12152
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
12088
12153
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
12089
12154
|
const config = parseConfig17(remnicCfg);
|
|
12090
12155
|
const root = resolveExtensionsRoot(config);
|
|
@@ -12135,7 +12200,7 @@ Root: ${root}`);
|
|
|
12135
12200
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
12136
12201
|
let entries = [];
|
|
12137
12202
|
try {
|
|
12138
|
-
entries =
|
|
12203
|
+
entries = fs29.readdirSync(root);
|
|
12139
12204
|
} catch {
|
|
12140
12205
|
console.log(`Extensions root does not exist: ${root}`);
|
|
12141
12206
|
process.exitCode = 0;
|
|
@@ -12146,7 +12211,7 @@ Root: ${root}`);
|
|
|
12146
12211
|
for (const entry of entries) {
|
|
12147
12212
|
const entryPath = path18.join(root, entry);
|
|
12148
12213
|
try {
|
|
12149
|
-
if (!
|
|
12214
|
+
if (!fs29.statSync(entryPath).isDirectory()) continue;
|
|
12150
12215
|
} catch {
|
|
12151
12216
|
continue;
|
|
12152
12217
|
}
|
|
@@ -12178,7 +12243,7 @@ Root: ${root}`);
|
|
|
12178
12243
|
async function cmdBriefing(rest) {
|
|
12179
12244
|
initLogger5();
|
|
12180
12245
|
const configPath = resolveConfigPath();
|
|
12181
|
-
const raw =
|
|
12246
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
12182
12247
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
12183
12248
|
const config = parseConfig17(remnicCfg);
|
|
12184
12249
|
if (!config.briefing.enabled) {
|
|
@@ -12258,10 +12323,10 @@ async function cmdBriefing(rest) {
|
|
|
12258
12323
|
if (save) {
|
|
12259
12324
|
try {
|
|
12260
12325
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
12261
|
-
|
|
12326
|
+
fs29.mkdirSync(saveDir, { recursive: true });
|
|
12262
12327
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
12263
12328
|
const filePath = path18.join(saveDir, filename);
|
|
12264
|
-
|
|
12329
|
+
fs29.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
12265
12330
|
console.error(`Saved briefing: ${filePath}`);
|
|
12266
12331
|
} catch (err) {
|
|
12267
12332
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -12279,7 +12344,7 @@ async function cmdDoctor() {
|
|
|
12279
12344
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
12280
12345
|
});
|
|
12281
12346
|
const configPath = resolveConfigPath();
|
|
12282
|
-
const configExists =
|
|
12347
|
+
const configExists = fs29.existsSync(configPath);
|
|
12283
12348
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
12284
12349
|
let standaloneConfig;
|
|
12285
12350
|
let standaloneConfigError;
|
|
@@ -12287,7 +12352,7 @@ async function cmdDoctor() {
|
|
|
12287
12352
|
let configuredNs = { invalid: false };
|
|
12288
12353
|
if (configExists) {
|
|
12289
12354
|
try {
|
|
12290
|
-
const raw = JSON.parse(
|
|
12355
|
+
const raw = JSON.parse(fs29.readFileSync(configPath, "utf8"));
|
|
12291
12356
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
12292
12357
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
12293
12358
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
@@ -12303,7 +12368,7 @@ async function cmdDoctor() {
|
|
|
12303
12368
|
memoryDir = parseConfig17({}).memoryDir;
|
|
12304
12369
|
}
|
|
12305
12370
|
try {
|
|
12306
|
-
|
|
12371
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
12307
12372
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
12308
12373
|
} catch {
|
|
12309
12374
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -12332,7 +12397,7 @@ async function cmdDoctor() {
|
|
|
12332
12397
|
});
|
|
12333
12398
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
12334
12399
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
12335
|
-
const openclawConfigExists =
|
|
12400
|
+
const openclawConfigExists = fs29.existsSync(openclawConfigPath);
|
|
12336
12401
|
let openclawConfig = {};
|
|
12337
12402
|
let openclawConfigValid = false;
|
|
12338
12403
|
let openclawPluginModeConfigured = false;
|
|
@@ -12340,7 +12405,7 @@ async function cmdDoctor() {
|
|
|
12340
12405
|
let activeOpenclawEntryConfig = null;
|
|
12341
12406
|
if (openclawConfigExists) {
|
|
12342
12407
|
try {
|
|
12343
|
-
const parsed = JSON.parse(
|
|
12408
|
+
const parsed = JSON.parse(fs29.readFileSync(openclawConfigPath, "utf-8"));
|
|
12344
12409
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
12345
12410
|
openclawConfig = parsed;
|
|
12346
12411
|
openclawConfigValid = true;
|
|
@@ -12420,9 +12485,9 @@ async function cmdDoctor() {
|
|
|
12420
12485
|
let memDirOk = false;
|
|
12421
12486
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
12422
12487
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
12423
|
-
if (
|
|
12488
|
+
if (fs29.existsSync(resolvedMemDir)) {
|
|
12424
12489
|
try {
|
|
12425
|
-
const stat2 =
|
|
12490
|
+
const stat2 = fs29.statSync(resolvedMemDir);
|
|
12426
12491
|
if (stat2.isDirectory()) {
|
|
12427
12492
|
memDirOk = true;
|
|
12428
12493
|
memDirDetail = resolvedMemDir;
|
|
@@ -12577,12 +12642,12 @@ async function cmdDoctor() {
|
|
|
12577
12642
|
}
|
|
12578
12643
|
function cmdConfig() {
|
|
12579
12644
|
const configPath = resolveConfigPath();
|
|
12580
|
-
if (!
|
|
12645
|
+
if (!fs29.existsSync(configPath)) {
|
|
12581
12646
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
12582
12647
|
return;
|
|
12583
12648
|
}
|
|
12584
12649
|
console.log(`Config: ${configPath}`);
|
|
12585
|
-
const rawConfig =
|
|
12650
|
+
const rawConfig = fs29.readFileSync(configPath, "utf8");
|
|
12586
12651
|
const redacted = rawConfig.replace(
|
|
12587
12652
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
12588
12653
|
"$1[REDACTED]$3"
|
|
@@ -12690,7 +12755,7 @@ async function cmdReview(action, rest) {
|
|
|
12690
12755
|
const configPath = resolveConfigPath();
|
|
12691
12756
|
let tombstonesConfig = null;
|
|
12692
12757
|
try {
|
|
12693
|
-
const rawCfg =
|
|
12758
|
+
const rawCfg = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
12694
12759
|
const remnicCfg = resolveRemnicConfigRecord16(rawCfg);
|
|
12695
12760
|
const config = parseConfig17(remnicCfg);
|
|
12696
12761
|
tombstonesConfig = {
|
|
@@ -13434,7 +13499,7 @@ async function pushOfflineFileContent(args) {
|
|
|
13434
13499
|
}
|
|
13435
13500
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
13436
13501
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
13437
|
-
const stat2 =
|
|
13502
|
+
const stat2 = fs29.statSync(filePath);
|
|
13438
13503
|
if (stat2.mtimeMs !== args.file.mtimeMs) {
|
|
13439
13504
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
13440
13505
|
}
|
|
@@ -13925,7 +13990,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
13925
13990
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
13926
13991
|
}
|
|
13927
13992
|
async function runOfflineSyncOnce(options) {
|
|
13928
|
-
|
|
13993
|
+
fs29.mkdirSync(options.memoryDir, { recursive: true });
|
|
13929
13994
|
let activeStatePath = options.statePath;
|
|
13930
13995
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
13931
13996
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -14558,7 +14623,7 @@ Environment fallbacks:
|
|
|
14558
14623
|
const configPath = resolveConfigPath();
|
|
14559
14624
|
let config;
|
|
14560
14625
|
try {
|
|
14561
|
-
const rawConfig =
|
|
14626
|
+
const rawConfig = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
14562
14627
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
14563
14628
|
} catch {
|
|
14564
14629
|
throw new Error(
|
|
@@ -14573,7 +14638,7 @@ Environment fallbacks:
|
|
|
14573
14638
|
const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
14574
14639
|
if (action === "prepare") {
|
|
14575
14640
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
14576
|
-
|
|
14641
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
14577
14642
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
14578
14643
|
remoteUrl,
|
|
14579
14644
|
token,
|
|
@@ -14672,7 +14737,7 @@ Environment fallbacks:
|
|
|
14672
14737
|
return;
|
|
14673
14738
|
}
|
|
14674
14739
|
if (action === "status") {
|
|
14675
|
-
|
|
14740
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
14676
14741
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
14677
14742
|
if (state && remoteUrl && statePath) {
|
|
14678
14743
|
assertOfflineStateMatches({
|
|
@@ -14810,7 +14875,7 @@ function cmdDedup(json) {
|
|
|
14810
14875
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
14811
14876
|
if (!configPath) return fallback;
|
|
14812
14877
|
try {
|
|
14813
|
-
const parsed = JSON.parse(
|
|
14878
|
+
const parsed = JSON.parse(fs29.readFileSync(configPath, "utf8"));
|
|
14814
14879
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
14815
14880
|
const { token: _token, ...config } = parsed;
|
|
14816
14881
|
return config;
|
|
@@ -14988,7 +15053,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
14988
15053
|
const pub = factory();
|
|
14989
15054
|
const available = await pub.isHostAvailable();
|
|
14990
15055
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
14991
|
-
const extensionExists = available && extRoot ?
|
|
15056
|
+
const extensionExists = available && extRoot ? fs29.existsSync(extRoot) : false;
|
|
14992
15057
|
publisherChecks.push({
|
|
14993
15058
|
name: `Publisher: ${targetHostId}`,
|
|
14994
15059
|
ok: !available || extensionExists,
|
|
@@ -15062,7 +15127,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
15062
15127
|
let connectorsCfg;
|
|
15063
15128
|
const configPath = resolveConfigPath();
|
|
15064
15129
|
try {
|
|
15065
|
-
const raw =
|
|
15130
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15066
15131
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
15067
15132
|
} catch {
|
|
15068
15133
|
process.stderr.write(
|
|
@@ -15138,7 +15203,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
15138
15203
|
}
|
|
15139
15204
|
initLogger5();
|
|
15140
15205
|
const configPath = resolveConfigPath();
|
|
15141
|
-
const raw =
|
|
15206
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15142
15207
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15143
15208
|
const config = parseConfig17(remnicCfg);
|
|
15144
15209
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -15263,7 +15328,7 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
15263
15328
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
15264
15329
|
process.exit(1);
|
|
15265
15330
|
}
|
|
15266
|
-
const rawConfig =
|
|
15331
|
+
const rawConfig = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15267
15332
|
const pluginConfig = resolveRemnicConfigRecord16(rawConfig);
|
|
15268
15333
|
const config = parseConfig17(pluginConfig);
|
|
15269
15334
|
if (subAction === "generate") {
|
|
@@ -15285,13 +15350,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
15285
15350
|
} else if (subAction === "validate") {
|
|
15286
15351
|
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
|
|
15287
15352
|
const resolved = path18.resolve(targetPath);
|
|
15288
|
-
if (!
|
|
15353
|
+
if (!fs29.existsSync(resolved)) {
|
|
15289
15354
|
console.error(`File not found: ${resolved}`);
|
|
15290
15355
|
process.exit(1);
|
|
15291
15356
|
}
|
|
15292
15357
|
let parsed;
|
|
15293
15358
|
try {
|
|
15294
|
-
parsed = JSON.parse(
|
|
15359
|
+
parsed = JSON.parse(fs29.readFileSync(resolved, "utf8"));
|
|
15295
15360
|
} catch {
|
|
15296
15361
|
console.error(`Invalid JSON in ${resolved}`);
|
|
15297
15362
|
process.exit(1);
|
|
@@ -15494,7 +15559,7 @@ async function cmdSpace(action, rest, json) {
|
|
|
15494
15559
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
15495
15560
|
initLogger5();
|
|
15496
15561
|
const configPath = resolveConfigPath();
|
|
15497
|
-
const raw =
|
|
15562
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
15498
15563
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
15499
15564
|
const config = parseConfig17(remnicCfg);
|
|
15500
15565
|
const orchestrator = new Orchestrator10(config);
|
|
@@ -15899,7 +15964,7 @@ function readPid() {
|
|
|
15899
15964
|
function inferPort() {
|
|
15900
15965
|
try {
|
|
15901
15966
|
const configPath = resolveConfigPath();
|
|
15902
|
-
const raw = JSON.parse(
|
|
15967
|
+
const raw = JSON.parse(fs29.readFileSync(configPath, "utf8"));
|
|
15903
15968
|
return raw.server?.port ?? 4318;
|
|
15904
15969
|
} catch {
|
|
15905
15970
|
return 4318;
|
|
@@ -15994,13 +16059,13 @@ function daemonInstall() {
|
|
|
15994
16059
|
process.exit(1);
|
|
15995
16060
|
}
|
|
15996
16061
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
15997
|
-
|
|
16062
|
+
fs29.mkdirSync(LOGS_DIR, { recursive: true });
|
|
15998
16063
|
if (isMacOS()) {
|
|
15999
16064
|
const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
16000
|
-
const template =
|
|
16065
|
+
const template = fs29.readFileSync(templatePath, "utf8");
|
|
16001
16066
|
const plist = renderTemplate(template, vars);
|
|
16002
|
-
|
|
16003
|
-
|
|
16067
|
+
fs29.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
16068
|
+
fs29.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
16004
16069
|
try {
|
|
16005
16070
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
16006
16071
|
} catch (err) {
|
|
@@ -16017,10 +16082,10 @@ function daemonInstall() {
|
|
|
16017
16082
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
16018
16083
|
} else if (isLinux()) {
|
|
16019
16084
|
const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
16020
|
-
const template =
|
|
16085
|
+
const template = fs29.readFileSync(templatePath, "utf8");
|
|
16021
16086
|
const unit = renderTemplate(template, vars);
|
|
16022
|
-
|
|
16023
|
-
|
|
16087
|
+
fs29.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
16088
|
+
fs29.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
16024
16089
|
try {
|
|
16025
16090
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
16026
16091
|
} catch (err) {
|
|
@@ -16056,7 +16121,7 @@ function daemonUninstall() {
|
|
|
16056
16121
|
} catch {
|
|
16057
16122
|
}
|
|
16058
16123
|
try {
|
|
16059
|
-
|
|
16124
|
+
fs29.unlinkSync(plistPath);
|
|
16060
16125
|
removed = true;
|
|
16061
16126
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
16062
16127
|
} catch {
|
|
@@ -16076,7 +16141,7 @@ function daemonUninstall() {
|
|
|
16076
16141
|
let removed = false;
|
|
16077
16142
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
16078
16143
|
try {
|
|
16079
|
-
|
|
16144
|
+
fs29.unlinkSync(unitPath);
|
|
16080
16145
|
removed = true;
|
|
16081
16146
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
16082
16147
|
} catch {
|
|
@@ -16156,11 +16221,11 @@ async function daemonStatus() {
|
|
|
16156
16221
|
console.log(` Port: ${port}`);
|
|
16157
16222
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
16158
16223
|
console.log(` Platform: ${process.platform}`);
|
|
16159
|
-
console.log(` PID file: ${
|
|
16160
|
-
console.log(` Log file: ${
|
|
16224
|
+
console.log(` PID file: ${fs29.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
16225
|
+
console.log(` Log file: ${fs29.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
16161
16226
|
try {
|
|
16162
16227
|
const configPath = resolveConfigPath();
|
|
16163
|
-
const raw =
|
|
16228
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
16164
16229
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16165
16230
|
const config = parseConfig17(remnicCfg);
|
|
16166
16231
|
const extRoot = resolveExtensionsRoot(config);
|
|
@@ -16208,9 +16273,9 @@ function daemonStart() {
|
|
|
16208
16273
|
return;
|
|
16209
16274
|
}
|
|
16210
16275
|
}
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
const logStream =
|
|
16276
|
+
fs29.mkdirSync(PID_DIR, { recursive: true });
|
|
16277
|
+
fs29.mkdirSync(LOGS_DIR, { recursive: true });
|
|
16278
|
+
const logStream = fs29.openSync(LOG_FILE, "a");
|
|
16214
16279
|
const serverBin = resolveServerBin();
|
|
16215
16280
|
const isSource = serverBin.endsWith(".ts");
|
|
16216
16281
|
let cmd;
|
|
@@ -16232,7 +16297,7 @@ function daemonStart() {
|
|
|
16232
16297
|
}
|
|
16233
16298
|
});
|
|
16234
16299
|
child.unref();
|
|
16235
|
-
|
|
16300
|
+
fs29.writeFileSync(PID_FILE, String(child.pid));
|
|
16236
16301
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
16237
16302
|
console.log(` Log: ${LOG_FILE}`);
|
|
16238
16303
|
}
|
|
@@ -16266,11 +16331,11 @@ function daemonStop() {
|
|
|
16266
16331
|
console.log("Process not found (cleaning up PID file)");
|
|
16267
16332
|
}
|
|
16268
16333
|
try {
|
|
16269
|
-
|
|
16334
|
+
fs29.unlinkSync(PID_FILE);
|
|
16270
16335
|
} catch {
|
|
16271
16336
|
}
|
|
16272
16337
|
try {
|
|
16273
|
-
|
|
16338
|
+
fs29.unlinkSync(LEGACY_PID_FILE);
|
|
16274
16339
|
} catch {
|
|
16275
16340
|
}
|
|
16276
16341
|
}
|
|
@@ -16398,7 +16463,7 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
16398
16463
|
async function cmdBinary(rest) {
|
|
16399
16464
|
initLogger5();
|
|
16400
16465
|
const configPath = resolveConfigPath();
|
|
16401
|
-
const raw =
|
|
16466
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
16402
16467
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16403
16468
|
const config = parseConfig17(remnicCfg);
|
|
16404
16469
|
const memoryDir = resolveMemoryDir();
|
|
@@ -16589,7 +16654,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
16589
16654
|
} else if (slotIsActiveLegacy) {
|
|
16590
16655
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
16591
16656
|
}
|
|
16592
|
-
if (!
|
|
16657
|
+
if (!fs29.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
16593
16658
|
if (hasLegacy && migrateLegacy) {
|
|
16594
16659
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
16595
16660
|
}
|
|
@@ -16609,8 +16674,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
16609
16674
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
16610
16675
|
return;
|
|
16611
16676
|
}
|
|
16612
|
-
if (
|
|
16613
|
-
const st =
|
|
16677
|
+
if (fs29.existsSync(memoryDir)) {
|
|
16678
|
+
const st = fs29.statSync(memoryDir);
|
|
16614
16679
|
if (!st.isDirectory()) {
|
|
16615
16680
|
throw new Error(
|
|
16616
16681
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -16618,12 +16683,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
16618
16683
|
);
|
|
16619
16684
|
}
|
|
16620
16685
|
} else {
|
|
16621
|
-
|
|
16686
|
+
fs29.mkdirSync(memoryDir, { recursive: true });
|
|
16622
16687
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
16623
16688
|
}
|
|
16624
16689
|
const configDir = path18.dirname(configPath);
|
|
16625
|
-
if (!
|
|
16626
|
-
|
|
16690
|
+
if (!fs29.existsSync(configDir)) {
|
|
16691
|
+
fs29.mkdirSync(configDir, { recursive: true });
|
|
16627
16692
|
}
|
|
16628
16693
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
16629
16694
|
console.log("\nDone! Summary of changes:");
|
|
@@ -16652,7 +16717,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
16652
16717
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
16653
16718
|
const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
16654
16719
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
16655
|
-
const configExistedBefore =
|
|
16720
|
+
const configExistedBefore = fs29.existsSync(configPath);
|
|
16656
16721
|
const existingConfig = readOpenclawConfig(configPath);
|
|
16657
16722
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
16658
16723
|
const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
@@ -16877,13 +16942,13 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
16877
16942
|
}
|
|
16878
16943
|
function createOpenclawUpgradeBackupDir() {
|
|
16879
16944
|
const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
|
|
16880
|
-
|
|
16881
|
-
return
|
|
16945
|
+
fs29.mkdirSync(backupsRoot, { recursive: true });
|
|
16946
|
+
return fs29.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
16882
16947
|
}
|
|
16883
16948
|
async function cmdTaxonomy(rest) {
|
|
16884
16949
|
initLogger5();
|
|
16885
16950
|
const configPath = resolveConfigPath();
|
|
16886
|
-
const raw =
|
|
16951
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
16887
16952
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
16888
16953
|
const config = parseConfig17(remnicCfg);
|
|
16889
16954
|
if (!config.taxonomyEnabled) {
|
|
@@ -16921,8 +16986,8 @@ async function cmdTaxonomy(rest) {
|
|
|
16921
16986
|
console.log(doc);
|
|
16922
16987
|
if (config.taxonomyAutoGenResolver) {
|
|
16923
16988
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16924
|
-
|
|
16925
|
-
|
|
16989
|
+
fs29.mkdirSync(path18.dirname(resolverPath), { recursive: true });
|
|
16990
|
+
fs29.writeFileSync(resolverPath, doc);
|
|
16926
16991
|
console.error(`Written: ${resolverPath}`);
|
|
16927
16992
|
}
|
|
16928
16993
|
break;
|
|
@@ -16968,7 +17033,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16968
17033
|
if (config.taxonomyAutoGenResolver) {
|
|
16969
17034
|
const doc = generateResolverDocument(taxonomy);
|
|
16970
17035
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
16971
|
-
|
|
17036
|
+
fs29.writeFileSync(resolverPath, doc);
|
|
16972
17037
|
console.error(`Regenerated: ${resolverPath}`);
|
|
16973
17038
|
}
|
|
16974
17039
|
break;
|
|
@@ -16999,7 +17064,7 @@ async function cmdTaxonomy(rest) {
|
|
|
16999
17064
|
if (config.taxonomyAutoGenResolver) {
|
|
17000
17065
|
const doc = generateResolverDocument(taxonomy);
|
|
17001
17066
|
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
17002
|
-
|
|
17067
|
+
fs29.writeFileSync(resolverPath, doc);
|
|
17003
17068
|
console.error(`Regenerated: ${resolverPath}`);
|
|
17004
17069
|
}
|
|
17005
17070
|
break;
|
|
@@ -17190,12 +17255,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
17190
17255
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
17191
17256
|
);
|
|
17192
17257
|
}
|
|
17193
|
-
if (!
|
|
17258
|
+
if (!fs29.existsSync(args.memoryDir)) {
|
|
17194
17259
|
throw new Error(
|
|
17195
17260
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
17196
17261
|
);
|
|
17197
17262
|
}
|
|
17198
|
-
if (!
|
|
17263
|
+
if (!fs29.statSync(args.memoryDir).isDirectory()) {
|
|
17199
17264
|
throw new Error(
|
|
17200
17265
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
17201
17266
|
);
|
|
@@ -17281,10 +17346,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
17281
17346
|
}
|
|
17282
17347
|
const formatted = adapter.formatRecords(records);
|
|
17283
17348
|
const outDir = path18.dirname(args.output);
|
|
17284
|
-
|
|
17349
|
+
fs29.mkdirSync(outDir, { recursive: true });
|
|
17285
17350
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
17286
|
-
|
|
17287
|
-
|
|
17351
|
+
fs29.writeFileSync(tmpPath, formatted, "utf-8");
|
|
17352
|
+
fs29.renameSync(tmpPath, args.output);
|
|
17288
17353
|
stdout.write(
|
|
17289
17354
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
17290
17355
|
`
|
|
@@ -17468,7 +17533,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
17468
17533
|
}
|
|
17469
17534
|
}, 500);
|
|
17470
17535
|
};
|
|
17471
|
-
|
|
17536
|
+
fs29.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
17472
17537
|
if (filename && filename.startsWith(".")) return;
|
|
17473
17538
|
rebuild();
|
|
17474
17539
|
});
|
|
@@ -17476,12 +17541,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
17476
17541
|
});
|
|
17477
17542
|
} else if (subAction === "validate") {
|
|
17478
17543
|
const treeDir = outputDir;
|
|
17479
|
-
if (!
|
|
17544
|
+
if (!fs29.existsSync(treeDir)) {
|
|
17480
17545
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
17481
17546
|
process.exit(1);
|
|
17482
17547
|
}
|
|
17483
17548
|
const indexPath = path18.join(treeDir, "INDEX.md");
|
|
17484
|
-
if (!
|
|
17549
|
+
if (!fs29.existsSync(indexPath)) {
|
|
17485
17550
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
17486
17551
|
process.exit(1);
|
|
17487
17552
|
}
|
|
@@ -17715,7 +17780,7 @@ Other:
|
|
|
17715
17780
|
const targetFactory = async () => {
|
|
17716
17781
|
if (!orchestratorSingleton) {
|
|
17717
17782
|
const configPath = resolveConfigPath();
|
|
17718
|
-
const raw =
|
|
17783
|
+
const raw = fs29.existsSync(configPath) ? JSON.parse(fs29.readFileSync(configPath, "utf8")) : {};
|
|
17719
17784
|
const remnicCfg = resolveRemnicConfigRecord16(raw);
|
|
17720
17785
|
const config = parseConfig17(remnicCfg);
|
|
17721
17786
|
orchestratorSingleton = new Orchestrator10(config);
|