agent-remnote 1.4.0 → 1.5.0
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/CHANGELOG.md +15 -0
- package/dist/main.js +1818 -984
- package/package.json +1 -1
- package/plugin-artifacts/PluginZip.zip +0 -0
- package/plugin-artifacts/dist/build-info.json +3 -3
- package/plugin-artifacts/dist/index-sandbox.js +1 -1
- package/plugin-artifacts/dist/index.js +1 -1
- package/plugin-artifacts/dist/{indexPlugin-BOnVUzfc.js → indexPlugin-B6yR4-RE.js} +1 -1
package/dist/main.js
CHANGED
|
@@ -43214,6 +43214,7 @@ var option = (self) => matchEffect(self, {
|
|
|
43214
43214
|
onSuccess: (a) => succeed(some2(a))
|
|
43215
43215
|
});
|
|
43216
43216
|
var orElseFail = /* @__PURE__ */ dual(2, (self, evaluate2) => orElse2(self, () => failSync(evaluate2)));
|
|
43217
|
+
var orElseSucceed = /* @__PURE__ */ dual(2, (self, evaluate2) => orElse2(self, () => sync(evaluate2)));
|
|
43217
43218
|
var patchFiberRefs = (patch11) => updateFiberRefs((fiberId2, fiberRefs3) => pipe(patch11, patch9(fiberId2, fiberRefs3)));
|
|
43218
43219
|
var promise = (evaluate2) => evaluate2.length >= 1 ? async_((resolve, signal) => {
|
|
43219
43220
|
try {
|
|
@@ -48400,6 +48401,7 @@ var withUnhandledErrorLogLevel2 = withUnhandledErrorLogLevel;
|
|
|
48400
48401
|
var orDie2 = orDie;
|
|
48401
48402
|
var orElse4 = orElse2;
|
|
48402
48403
|
var orElseFail2 = orElseFail;
|
|
48404
|
+
var orElseSucceed2 = orElseSucceed;
|
|
48403
48405
|
var runtime4 = runtime3;
|
|
48404
48406
|
var unsafeMakeSemaphore2 = unsafeMakeSemaphore;
|
|
48405
48407
|
var makeSemaphore2 = makeSemaphore;
|
|
@@ -73990,6 +73992,7 @@ var platformRunnerImpl = /* @__PURE__ */ PlatformRunner2.of({
|
|
|
73990
73992
|
// src/main.ts
|
|
73991
73993
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
73992
73994
|
import { format as format10 } from "node:util";
|
|
73995
|
+
import { isMainThread as isMainThread2, parentPort as parentPort3, workerData as workerData2 } from "node:worker_threads";
|
|
73993
73996
|
|
|
73994
73997
|
// src/services/UserConfigFile.ts
|
|
73995
73998
|
import { promises as fs4 } from "node:fs";
|
|
@@ -74323,6 +74326,41 @@ function isConfigCommandInvocation(argv) {
|
|
|
74323
74326
|
}
|
|
74324
74327
|
return tokens[i] === "config";
|
|
74325
74328
|
}
|
|
74329
|
+
function isDoctorCommandInvocation(argv) {
|
|
74330
|
+
const tokens = argv.slice(2);
|
|
74331
|
+
let i = 0;
|
|
74332
|
+
while (i < tokens.length) {
|
|
74333
|
+
const raw4 = String(tokens[i] ?? "");
|
|
74334
|
+
if (!raw4)
|
|
74335
|
+
break;
|
|
74336
|
+
if (raw4 === "--") {
|
|
74337
|
+
i += 1;
|
|
74338
|
+
break;
|
|
74339
|
+
}
|
|
74340
|
+
if (!raw4.startsWith("-"))
|
|
74341
|
+
break;
|
|
74342
|
+
const { flag, inlineValue } = splitFlagInlineValue(raw4);
|
|
74343
|
+
if (ROOT_VALUE_FLAGS.has(flag)) {
|
|
74344
|
+
i += inlineValue !== null ? 1 : 2;
|
|
74345
|
+
continue;
|
|
74346
|
+
}
|
|
74347
|
+
if (ROOT_BOOL_FLAGS.has(flag) || BUILTIN_BOOL_FLAGS.has(flag)) {
|
|
74348
|
+
if (inlineValue !== null) {
|
|
74349
|
+
i += 1;
|
|
74350
|
+
continue;
|
|
74351
|
+
}
|
|
74352
|
+
const next4 = tokens[i + 1];
|
|
74353
|
+
if (typeof next4 === "string" && isBooleanLiteralToken(next4)) {
|
|
74354
|
+
i += 2;
|
|
74355
|
+
continue;
|
|
74356
|
+
}
|
|
74357
|
+
i += 1;
|
|
74358
|
+
continue;
|
|
74359
|
+
}
|
|
74360
|
+
break;
|
|
74361
|
+
}
|
|
74362
|
+
return tokens[i] === "doctor";
|
|
74363
|
+
}
|
|
74326
74364
|
function normalizeApiBasePath(raw4) {
|
|
74327
74365
|
const trimmed2 = raw4.trim();
|
|
74328
74366
|
if (!trimmed2)
|
|
@@ -74534,7 +74572,9 @@ function readUserConfigFile(configFile) {
|
|
|
74534
74572
|
const nestedHost = apiObject?.host;
|
|
74535
74573
|
const nestedPort = apiObject?.port;
|
|
74536
74574
|
const nestedBasePath = apiObject?.basePath;
|
|
74537
|
-
const
|
|
74575
|
+
const hasRootApiBaseUrl = Object.prototype.hasOwnProperty.call(config3, "apiBaseUrl");
|
|
74576
|
+
const hasNestedBaseUrl = apiObject ? Object.prototype.hasOwnProperty.call(apiObject, "baseUrl") : false;
|
|
74577
|
+
const apiBaseUrl = hasRootApiBaseUrl ? config3.apiBaseUrl : nestedBaseUrl;
|
|
74538
74578
|
const apiHostRaw = config3.apiHost ?? nestedHost;
|
|
74539
74579
|
const apiPortRaw = config3.apiPort ?? nestedPort;
|
|
74540
74580
|
const apiBasePathRaw = config3.apiBasePath ?? nestedBasePath;
|
|
@@ -74546,6 +74586,20 @@ function readUserConfigFile(configFile) {
|
|
|
74546
74586
|
details: { config_file: file6 }
|
|
74547
74587
|
});
|
|
74548
74588
|
}
|
|
74589
|
+
const normalizedApiBaseUrl = apiBaseUrl === undefined ? undefined : (() => {
|
|
74590
|
+
const normalized = normalizeApiBaseUrl(apiBaseUrl);
|
|
74591
|
+
const rootNormalized = typeof config3.apiBaseUrl === "string" ? normalizeApiBaseUrl(config3.apiBaseUrl) : undefined;
|
|
74592
|
+
const nestedNormalized = typeof nestedBaseUrl === "string" ? normalizeApiBaseUrl(nestedBaseUrl) : undefined;
|
|
74593
|
+
if (hasRootApiBaseUrl && hasNestedBaseUrl && rootNormalized !== nestedNormalized) {
|
|
74594
|
+
throw new CliError({
|
|
74595
|
+
code: "INVALID_ARGS",
|
|
74596
|
+
message: `Config keys apiBaseUrl and api.baseUrl conflict: ${file6}`,
|
|
74597
|
+
exitCode: 2,
|
|
74598
|
+
details: { config_file: file6 }
|
|
74599
|
+
});
|
|
74600
|
+
}
|
|
74601
|
+
return normalized;
|
|
74602
|
+
})();
|
|
74549
74603
|
const apiHost = apiHostRaw === undefined ? undefined : (() => {
|
|
74550
74604
|
if (typeof apiHostRaw !== "string") {
|
|
74551
74605
|
throw new CliError({
|
|
@@ -74555,7 +74609,18 @@ function readUserConfigFile(configFile) {
|
|
|
74555
74609
|
details: { config_file: file6 }
|
|
74556
74610
|
});
|
|
74557
74611
|
}
|
|
74558
|
-
|
|
74612
|
+
const normalized = normalizeApiHost(apiHostRaw);
|
|
74613
|
+
const rootNormalized = typeof config3.apiHost === "string" ? normalizeApiHost(config3.apiHost) : undefined;
|
|
74614
|
+
const nestedNormalized = typeof nestedHost === "string" ? normalizeApiHost(nestedHost) : undefined;
|
|
74615
|
+
if (rootNormalized !== undefined && nestedNormalized !== undefined && rootNormalized !== nestedNormalized) {
|
|
74616
|
+
throw new CliError({
|
|
74617
|
+
code: "INVALID_ARGS",
|
|
74618
|
+
message: `Config keys apiHost and api.host conflict: ${file6}`,
|
|
74619
|
+
exitCode: 2,
|
|
74620
|
+
details: { config_file: file6 }
|
|
74621
|
+
});
|
|
74622
|
+
}
|
|
74623
|
+
return normalized;
|
|
74559
74624
|
})();
|
|
74560
74625
|
const apiPort = apiPortRaw === undefined ? undefined : (() => {
|
|
74561
74626
|
if (typeof apiPortRaw !== "number" && typeof apiPortRaw !== "string") {
|
|
@@ -74566,7 +74631,18 @@ function readUserConfigFile(configFile) {
|
|
|
74566
74631
|
details: { config_file: file6 }
|
|
74567
74632
|
});
|
|
74568
74633
|
}
|
|
74569
|
-
|
|
74634
|
+
const normalized = normalizeApiPort(apiPortRaw);
|
|
74635
|
+
const rootNormalized = typeof config3.apiPort === "number" || typeof config3.apiPort === "string" ? normalizeApiPort(config3.apiPort) : undefined;
|
|
74636
|
+
const nestedNormalized = typeof nestedPort === "number" || typeof nestedPort === "string" ? normalizeApiPort(nestedPort) : undefined;
|
|
74637
|
+
if (rootNormalized !== undefined && nestedNormalized !== undefined && rootNormalized !== nestedNormalized) {
|
|
74638
|
+
throw new CliError({
|
|
74639
|
+
code: "INVALID_ARGS",
|
|
74640
|
+
message: `Config keys apiPort and api.port conflict: ${file6}`,
|
|
74641
|
+
exitCode: 2,
|
|
74642
|
+
details: { config_file: file6 }
|
|
74643
|
+
});
|
|
74644
|
+
}
|
|
74645
|
+
return normalized;
|
|
74570
74646
|
})();
|
|
74571
74647
|
const apiBasePath = apiBasePathRaw === undefined ? undefined : (() => {
|
|
74572
74648
|
if (typeof apiBasePathRaw !== "string") {
|
|
@@ -74577,12 +74653,23 @@ function readUserConfigFile(configFile) {
|
|
|
74577
74653
|
details: { config_file: file6 }
|
|
74578
74654
|
});
|
|
74579
74655
|
}
|
|
74580
|
-
|
|
74656
|
+
const normalized = normalizeApiBasePath(apiBasePathRaw);
|
|
74657
|
+
const rootNormalized = typeof config3.apiBasePath === "string" ? normalizeApiBasePath(config3.apiBasePath) : undefined;
|
|
74658
|
+
const nestedNormalized = typeof nestedBasePath === "string" ? normalizeApiBasePath(nestedBasePath) : undefined;
|
|
74659
|
+
if (rootNormalized !== undefined && nestedNormalized !== undefined && rootNormalized !== nestedNormalized) {
|
|
74660
|
+
throw new CliError({
|
|
74661
|
+
code: "INVALID_ARGS",
|
|
74662
|
+
message: `Config keys apiBasePath and api.basePath conflict: ${file6}`,
|
|
74663
|
+
exitCode: 2,
|
|
74664
|
+
details: { config_file: file6 }
|
|
74665
|
+
});
|
|
74666
|
+
}
|
|
74667
|
+
return normalized;
|
|
74581
74668
|
})();
|
|
74582
74669
|
if (apiBaseUrl === undefined && apiHost === undefined && apiPort === undefined && apiBasePath === undefined) {
|
|
74583
74670
|
return {};
|
|
74584
74671
|
}
|
|
74585
|
-
return { apiBaseUrl, apiHost, apiPort, apiBasePath };
|
|
74672
|
+
return { apiBaseUrl: normalizedApiBaseUrl, apiHost, apiPort, apiBasePath };
|
|
74586
74673
|
}
|
|
74587
74674
|
function resolveConfig() {
|
|
74588
74675
|
return gen2(function* () {
|
|
@@ -74597,7 +74684,7 @@ function resolveConfig() {
|
|
|
74597
74684
|
details: { config_file: configFile, error: String(error4?.message || error4) }
|
|
74598
74685
|
})
|
|
74599
74686
|
}));
|
|
74600
|
-
const userConfig = userConfigResult._tag === "Right" ? userConfigResult.right : isConfigCommandInvocation(process.argv) ? {} : yield* fail8(userConfigResult.left);
|
|
74687
|
+
const userConfig = userConfigResult._tag === "Right" ? userConfigResult.right : isConfigCommandInvocation(process.argv) || isDoctorCommandInvocation(process.argv) ? {} : yield* fail8(userConfigResult.left);
|
|
74601
74688
|
const wsStateFile = resolveWsStateFile(raw4.wsStateFile);
|
|
74602
74689
|
const remnoteDb = optionalTrimmed(raw4.remnoteDb) ? resolveUserFilePath(raw4.remnoteDb) : inferRemnoteDbFromWsState({ wsStateFile, wsStateStaleMs: raw4.wsStateStaleMs }) || undefined;
|
|
74603
74690
|
const storeDb = resolveUserFilePath(raw4.storeDb);
|
|
@@ -74697,8 +74784,22 @@ function readApiBaseUrl(doc) {
|
|
|
74697
74784
|
const root = doc.apiBaseUrl;
|
|
74698
74785
|
const api = doc.api;
|
|
74699
74786
|
const nested4 = isPlainObject(api) ? api.baseUrl : undefined;
|
|
74700
|
-
const rootValue = root === undefined ? undefined : typeof root === "string" ?
|
|
74701
|
-
|
|
74787
|
+
const rootValue = root === undefined ? undefined : typeof root === "string" ? (() => {
|
|
74788
|
+
try {
|
|
74789
|
+
return normalizeApiBaseUrl(root);
|
|
74790
|
+
} catch (error4) {
|
|
74791
|
+
errors3.push(isCliError(error4) ? error4.message : "Config key apiBaseUrl must be a valid URL");
|
|
74792
|
+
return;
|
|
74793
|
+
}
|
|
74794
|
+
})() : (errors3.push("Config key apiBaseUrl must be a string"), undefined);
|
|
74795
|
+
const nestedValue = nested4 === undefined ? undefined : typeof nested4 === "string" ? (() => {
|
|
74796
|
+
try {
|
|
74797
|
+
return normalizeApiBaseUrl(nested4);
|
|
74798
|
+
} catch (error4) {
|
|
74799
|
+
errors3.push(isCliError(error4) ? error4.message : "Config key api.baseUrl must be a valid URL");
|
|
74800
|
+
return;
|
|
74801
|
+
}
|
|
74802
|
+
})() : (errors3.push("Config key api.baseUrl must be a string"), undefined);
|
|
74702
74803
|
if (rootValue && nestedValue && rootValue !== nestedValue) {
|
|
74703
74804
|
errors3.push("Config keys apiBaseUrl and api.baseUrl conflict");
|
|
74704
74805
|
}
|
|
@@ -74811,6 +74912,34 @@ function inspectDoc(configFile, exists3, doc) {
|
|
|
74811
74912
|
valid: errors3.length === 0
|
|
74812
74913
|
};
|
|
74813
74914
|
}
|
|
74915
|
+
function canonicalizeDoc(doc) {
|
|
74916
|
+
const next4 = cloneDoc(doc);
|
|
74917
|
+
const inspection = inspectDoc("", true, next4);
|
|
74918
|
+
if (!inspection.valid) {
|
|
74919
|
+
return next4;
|
|
74920
|
+
}
|
|
74921
|
+
if (inspection.values.apiBaseUrl !== undefined) {
|
|
74922
|
+
next4.apiBaseUrl = inspection.values.apiBaseUrl;
|
|
74923
|
+
}
|
|
74924
|
+
if (inspection.values.apiHost !== undefined) {
|
|
74925
|
+
next4.apiHost = inspection.values.apiHost;
|
|
74926
|
+
}
|
|
74927
|
+
if (inspection.values.apiPort !== undefined) {
|
|
74928
|
+
next4.apiPort = inspection.values.apiPort;
|
|
74929
|
+
}
|
|
74930
|
+
if (inspection.values.apiBasePath !== undefined) {
|
|
74931
|
+
next4.apiBasePath = inspection.values.apiBasePath;
|
|
74932
|
+
}
|
|
74933
|
+
const api = next4.api;
|
|
74934
|
+
if (isPlainObject(api)) {
|
|
74935
|
+
delete api.baseUrl;
|
|
74936
|
+
delete api.host;
|
|
74937
|
+
delete api.port;
|
|
74938
|
+
delete api.basePath;
|
|
74939
|
+
removeEmptyApiObject(next4);
|
|
74940
|
+
}
|
|
74941
|
+
return next4;
|
|
74942
|
+
}
|
|
74814
74943
|
async function ensureDir(filePath) {
|
|
74815
74944
|
await fs4.mkdir(path7.dirname(filePath), { recursive: true });
|
|
74816
74945
|
}
|
|
@@ -75002,6 +75131,69 @@ var UserConfigFileLive = succeed10(UserConfigFile, {
|
|
|
75002
75131
|
}
|
|
75003
75132
|
return inspectDoc(parsed.configFile, parsed.exists, parsed.doc);
|
|
75004
75133
|
}),
|
|
75134
|
+
previewRepair: () => gen2(function* () {
|
|
75135
|
+
const cfg = yield* AppConfig;
|
|
75136
|
+
const parsed = yield* promise2(() => readDocDetailed(cfg.configFile));
|
|
75137
|
+
const { configFile, doc, exists: exists3 } = yield* try_3({
|
|
75138
|
+
try: () => requireParsedDoc(parsed),
|
|
75139
|
+
catch: (error4) => toCliFailure(error4, "Invalid config file")
|
|
75140
|
+
});
|
|
75141
|
+
const before2 = inspectDoc(configFile, exists3, doc);
|
|
75142
|
+
const nextDoc = canonicalizeDoc(doc);
|
|
75143
|
+
const after3 = inspectDoc(configFile, exists3, nextDoc);
|
|
75144
|
+
return {
|
|
75145
|
+
configFile,
|
|
75146
|
+
exists: exists3,
|
|
75147
|
+
changed: JSON.stringify(doc) !== JSON.stringify(nextDoc),
|
|
75148
|
+
before: before2,
|
|
75149
|
+
after: after3,
|
|
75150
|
+
nextDoc
|
|
75151
|
+
};
|
|
75152
|
+
}),
|
|
75153
|
+
repair: () => gen2(function* () {
|
|
75154
|
+
const cfg = yield* AppConfig;
|
|
75155
|
+
const parsed = yield* promise2(() => readDocDetailed(cfg.configFile));
|
|
75156
|
+
const { configFile, doc, exists: exists3 } = yield* try_3({
|
|
75157
|
+
try: () => requireParsedDoc(parsed),
|
|
75158
|
+
catch: (error4) => toCliFailure(error4, "Invalid config file")
|
|
75159
|
+
});
|
|
75160
|
+
const before2 = inspectDoc(configFile, exists3, doc);
|
|
75161
|
+
const nextDoc = canonicalizeDoc(doc);
|
|
75162
|
+
const after3 = inspectDoc(configFile, exists3, nextDoc);
|
|
75163
|
+
const preview = {
|
|
75164
|
+
configFile,
|
|
75165
|
+
exists: exists3,
|
|
75166
|
+
changed: JSON.stringify(doc) !== JSON.stringify(nextDoc),
|
|
75167
|
+
before: before2,
|
|
75168
|
+
after: after3,
|
|
75169
|
+
nextDoc
|
|
75170
|
+
};
|
|
75171
|
+
if (!preview.changed) {
|
|
75172
|
+
return {
|
|
75173
|
+
...preview,
|
|
75174
|
+
written: false
|
|
75175
|
+
};
|
|
75176
|
+
}
|
|
75177
|
+
if (!preview.before.valid) {
|
|
75178
|
+
return {
|
|
75179
|
+
...preview,
|
|
75180
|
+
written: false
|
|
75181
|
+
};
|
|
75182
|
+
}
|
|
75183
|
+
yield* tryPromise2({
|
|
75184
|
+
try: async () => await writeDoc(preview.configFile, preview.nextDoc),
|
|
75185
|
+
catch: (error4) => new CliError({
|
|
75186
|
+
code: "INTERNAL",
|
|
75187
|
+
message: "Failed to write config file",
|
|
75188
|
+
exitCode: 1,
|
|
75189
|
+
details: { config_file: preview.configFile, error: String(error4?.message || error4) }
|
|
75190
|
+
})
|
|
75191
|
+
});
|
|
75192
|
+
return {
|
|
75193
|
+
...preview,
|
|
75194
|
+
written: true
|
|
75195
|
+
};
|
|
75196
|
+
}),
|
|
75005
75197
|
get: (key) => gen2(function* () {
|
|
75006
75198
|
const targetKey = yield* try_3({
|
|
75007
75199
|
try: () => canonicalKey(key),
|
|
@@ -75715,35 +75907,181 @@ var configCommand = exports_Command.make("config", {}).pipe(exports_Command.with
|
|
|
75715
75907
|
configValidateCommand
|
|
75716
75908
|
]));
|
|
75717
75909
|
|
|
75718
|
-
// src/services/
|
|
75719
|
-
import {
|
|
75910
|
+
// src/services/ApiDaemonFiles.ts
|
|
75911
|
+
import { promises as fs8 } from "node:fs";
|
|
75720
75912
|
import path10 from "node:path";
|
|
75913
|
+
class ApiDaemonFiles extends Tag2("ApiDaemonFiles")() {
|
|
75914
|
+
}
|
|
75915
|
+
function ensureDir4(p3) {
|
|
75916
|
+
return fs8.mkdir(path10.dirname(p3), { recursive: true }).then(() => {
|
|
75917
|
+
return;
|
|
75918
|
+
});
|
|
75919
|
+
}
|
|
75920
|
+
function defaultPidFile2() {
|
|
75921
|
+
const envPidFile = process.env.REMNOTE_API_PID_FILE;
|
|
75922
|
+
if (typeof envPidFile === "string" && envPidFile.trim())
|
|
75923
|
+
return resolveUserFilePath(envPidFile);
|
|
75924
|
+
return path10.join(homeDir(), ".agent-remnote", "api.pid");
|
|
75925
|
+
}
|
|
75926
|
+
function defaultLogFile2() {
|
|
75927
|
+
const envLogFile = process.env.REMNOTE_API_LOG_FILE;
|
|
75928
|
+
if (typeof envLogFile === "string" && envLogFile.trim())
|
|
75929
|
+
return resolveUserFilePath(envLogFile);
|
|
75930
|
+
return path10.join(homeDir(), ".agent-remnote", "api.log");
|
|
75931
|
+
}
|
|
75932
|
+
function defaultStateFile2() {
|
|
75933
|
+
const envStateFile = process.env.REMNOTE_API_STATE_FILE;
|
|
75934
|
+
if (typeof envStateFile === "string" && envStateFile.trim())
|
|
75935
|
+
return resolveUserFilePath(envStateFile);
|
|
75936
|
+
return path10.join(homeDir(), ".agent-remnote", "api.state.json");
|
|
75937
|
+
}
|
|
75938
|
+
function parseJson2(raw4, filePath) {
|
|
75939
|
+
try {
|
|
75940
|
+
return JSON.parse(raw4);
|
|
75941
|
+
} catch (error4) {
|
|
75942
|
+
throw new CliError({
|
|
75943
|
+
code: "INTERNAL",
|
|
75944
|
+
message: `Failed to parse JSON file: ${filePath}`,
|
|
75945
|
+
exitCode: 1,
|
|
75946
|
+
details: { file_path: filePath, error: String(error4?.message || error4) }
|
|
75947
|
+
});
|
|
75948
|
+
}
|
|
75949
|
+
}
|
|
75950
|
+
var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
75951
|
+
defaultPidFile: defaultPidFile2,
|
|
75952
|
+
defaultLogFile: defaultLogFile2,
|
|
75953
|
+
defaultStateFile: defaultStateFile2,
|
|
75954
|
+
readPidFile: (pidFilePath) => tryPromise2({
|
|
75955
|
+
try: async () => {
|
|
75956
|
+
const resolved = resolveUserFilePath(pidFilePath);
|
|
75957
|
+
const raw4 = await fs8.readFile(resolved, "utf8");
|
|
75958
|
+
return parseJson2(raw4, resolved);
|
|
75959
|
+
},
|
|
75960
|
+
catch: (error4) => {
|
|
75961
|
+
const code2 = error4?.code;
|
|
75962
|
+
if (code2 === "ENOENT")
|
|
75963
|
+
return;
|
|
75964
|
+
if (isCliError(error4))
|
|
75965
|
+
return error4;
|
|
75966
|
+
return new CliError({
|
|
75967
|
+
code: "INTERNAL",
|
|
75968
|
+
message: "Failed to read api pid file",
|
|
75969
|
+
exitCode: 1,
|
|
75970
|
+
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
75971
|
+
});
|
|
75972
|
+
}
|
|
75973
|
+
}).pipe(catchAll2((error4) => {
|
|
75974
|
+
if (error4 === undefined)
|
|
75975
|
+
return succeed8(undefined);
|
|
75976
|
+
return fail8(error4);
|
|
75977
|
+
})),
|
|
75978
|
+
writePidFile: (pidFilePath, value8) => tryPromise2({
|
|
75979
|
+
try: async () => {
|
|
75980
|
+
const resolved = resolveUserFilePath(pidFilePath);
|
|
75981
|
+
await ensureDir4(resolved);
|
|
75982
|
+
await fs8.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
75983
|
+
`, "utf8");
|
|
75984
|
+
},
|
|
75985
|
+
catch: (error4) => new CliError({
|
|
75986
|
+
code: "INTERNAL",
|
|
75987
|
+
message: "Failed to write api pid file",
|
|
75988
|
+
exitCode: 1,
|
|
75989
|
+
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
75990
|
+
})
|
|
75991
|
+
}),
|
|
75992
|
+
deletePidFile: (pidFilePath) => tryPromise2({
|
|
75993
|
+
try: async () => {
|
|
75994
|
+
const resolved = resolveUserFilePath(pidFilePath);
|
|
75995
|
+
await fs8.rm(resolved, { force: true });
|
|
75996
|
+
},
|
|
75997
|
+
catch: (error4) => new CliError({
|
|
75998
|
+
code: "INTERNAL",
|
|
75999
|
+
message: "Failed to delete api pid file",
|
|
76000
|
+
exitCode: 1,
|
|
76001
|
+
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
76002
|
+
})
|
|
76003
|
+
}),
|
|
76004
|
+
readStateFile: (stateFilePath) => tryPromise2({
|
|
76005
|
+
try: async () => {
|
|
76006
|
+
const resolved = resolveUserFilePath(stateFilePath);
|
|
76007
|
+
const raw4 = await fs8.readFile(resolved, "utf8");
|
|
76008
|
+
return parseJson2(raw4, resolved);
|
|
76009
|
+
},
|
|
76010
|
+
catch: (error4) => {
|
|
76011
|
+
const code2 = error4?.code;
|
|
76012
|
+
if (code2 === "ENOENT")
|
|
76013
|
+
return;
|
|
76014
|
+
if (isCliError(error4))
|
|
76015
|
+
return error4;
|
|
76016
|
+
return new CliError({
|
|
76017
|
+
code: "INTERNAL",
|
|
76018
|
+
message: "Failed to read api state file",
|
|
76019
|
+
exitCode: 1,
|
|
76020
|
+
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
76021
|
+
});
|
|
76022
|
+
}
|
|
76023
|
+
}).pipe(catchAll2((error4) => {
|
|
76024
|
+
if (error4 === undefined)
|
|
76025
|
+
return succeed8(undefined);
|
|
76026
|
+
return fail8(error4);
|
|
76027
|
+
})),
|
|
76028
|
+
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
76029
|
+
try: async () => {
|
|
76030
|
+
const resolved = resolveUserFilePath(stateFilePath);
|
|
76031
|
+
await ensureDir4(resolved);
|
|
76032
|
+
await fs8.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
76033
|
+
`, "utf8");
|
|
76034
|
+
},
|
|
76035
|
+
catch: (error4) => new CliError({
|
|
76036
|
+
code: "INTERNAL",
|
|
76037
|
+
message: "Failed to write api state file",
|
|
76038
|
+
exitCode: 1,
|
|
76039
|
+
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
76040
|
+
})
|
|
76041
|
+
}),
|
|
76042
|
+
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
76043
|
+
try: async () => {
|
|
76044
|
+
const resolved = resolveUserFilePath(stateFilePath);
|
|
76045
|
+
await fs8.rm(resolved, { force: true });
|
|
76046
|
+
},
|
|
76047
|
+
catch: (error4) => new CliError({
|
|
76048
|
+
code: "INTERNAL",
|
|
76049
|
+
message: "Failed to delete api state file",
|
|
76050
|
+
exitCode: 1,
|
|
76051
|
+
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
76052
|
+
})
|
|
76053
|
+
})
|
|
76054
|
+
});
|
|
76055
|
+
|
|
76056
|
+
// src/services/FsAccess.ts
|
|
76057
|
+
import { constants as FS_CONSTANTS, promises as fs9 } from "node:fs";
|
|
76058
|
+
import path11 from "node:path";
|
|
75721
76059
|
|
|
75722
76060
|
class FsAccess extends Tag2("FsAccess")() {
|
|
75723
76061
|
}
|
|
75724
76062
|
async function canWritePath(filePath) {
|
|
75725
76063
|
try {
|
|
75726
|
-
await
|
|
75727
|
-
await
|
|
76064
|
+
await fs9.mkdir(path11.dirname(filePath), { recursive: true });
|
|
76065
|
+
await fs9.access(path11.dirname(filePath), FS_CONSTANTS.W_OK);
|
|
75728
76066
|
return true;
|
|
75729
76067
|
} catch {
|
|
75730
76068
|
return false;
|
|
75731
76069
|
}
|
|
75732
76070
|
}
|
|
75733
76071
|
async function checkWritableFile(filePath) {
|
|
75734
|
-
const dir2 =
|
|
76072
|
+
const dir2 = path11.dirname(filePath);
|
|
75735
76073
|
try {
|
|
75736
|
-
await
|
|
76074
|
+
await fs9.mkdir(dir2, { recursive: true });
|
|
75737
76075
|
} catch (e) {
|
|
75738
76076
|
return { ok: false, reason: `failed_to_create_dir: ${String(e?.message || e)}` };
|
|
75739
76077
|
}
|
|
75740
76078
|
try {
|
|
75741
|
-
await
|
|
76079
|
+
await fs9.access(dir2, FS_CONSTANTS.W_OK);
|
|
75742
76080
|
} catch (e) {
|
|
75743
76081
|
return { ok: false, reason: `dir_not_writable: ${String(e?.message || e)}` };
|
|
75744
76082
|
}
|
|
75745
76083
|
try {
|
|
75746
|
-
await
|
|
76084
|
+
await fs9.access(filePath, FS_CONSTANTS.W_OK);
|
|
75747
76085
|
return { ok: true };
|
|
75748
76086
|
} catch {
|
|
75749
76087
|
return { ok: true };
|
|
@@ -75752,7 +76090,7 @@ async function checkWritableFile(filePath) {
|
|
|
75752
76090
|
var FsAccessLive = succeed10(FsAccess, {
|
|
75753
76091
|
isFile: (filePath) => tryPromise2({
|
|
75754
76092
|
try: async () => {
|
|
75755
|
-
const st = await
|
|
76093
|
+
const st = await fs9.stat(filePath);
|
|
75756
76094
|
return st.isFile();
|
|
75757
76095
|
},
|
|
75758
76096
|
catch: (e) => e
|
|
@@ -75767,8 +76105,270 @@ var FsAccessLive = succeed10(FsAccess, {
|
|
|
75767
76105
|
}).pipe(catchAll2(() => succeed8({ ok: false, reason: "unknown_error" })))
|
|
75768
76106
|
});
|
|
75769
76107
|
|
|
76108
|
+
// src/services/PluginServerFiles.ts
|
|
76109
|
+
import { promises as fs10 } from "node:fs";
|
|
76110
|
+
import path12 from "node:path";
|
|
76111
|
+
class PluginServerFiles extends Tag2("PluginServerFiles")() {
|
|
76112
|
+
}
|
|
76113
|
+
function ensureDir5(p3) {
|
|
76114
|
+
return fs10.mkdir(path12.dirname(p3), { recursive: true }).then(() => {
|
|
76115
|
+
return;
|
|
76116
|
+
});
|
|
76117
|
+
}
|
|
76118
|
+
function defaultPidFile3() {
|
|
76119
|
+
const envPidFile = process.env.REMNOTE_PLUGIN_SERVER_PID_FILE;
|
|
76120
|
+
if (typeof envPidFile === "string" && envPidFile.trim())
|
|
76121
|
+
return resolveUserFilePath(envPidFile);
|
|
76122
|
+
return path12.join(homeDir(), ".agent-remnote", "plugin-server.pid");
|
|
76123
|
+
}
|
|
76124
|
+
function defaultLogFile3() {
|
|
76125
|
+
const envLogFile = process.env.REMNOTE_PLUGIN_SERVER_LOG_FILE;
|
|
76126
|
+
if (typeof envLogFile === "string" && envLogFile.trim())
|
|
76127
|
+
return resolveUserFilePath(envLogFile);
|
|
76128
|
+
return path12.join(homeDir(), ".agent-remnote", "plugin-server.log");
|
|
76129
|
+
}
|
|
76130
|
+
function defaultStateFile3() {
|
|
76131
|
+
const envStateFile = process.env.REMNOTE_PLUGIN_SERVER_STATE_FILE;
|
|
76132
|
+
if (typeof envStateFile === "string" && envStateFile.trim())
|
|
76133
|
+
return resolveUserFilePath(envStateFile);
|
|
76134
|
+
return path12.join(homeDir(), ".agent-remnote", "plugin-server.state.json");
|
|
76135
|
+
}
|
|
76136
|
+
function parseJson3(raw4, filePath) {
|
|
76137
|
+
try {
|
|
76138
|
+
return JSON.parse(raw4);
|
|
76139
|
+
} catch (error4) {
|
|
76140
|
+
throw new CliError({
|
|
76141
|
+
code: "INTERNAL",
|
|
76142
|
+
message: `Failed to parse JSON file: ${filePath}`,
|
|
76143
|
+
exitCode: 1,
|
|
76144
|
+
details: { file_path: filePath, error: String(error4?.message || error4) }
|
|
76145
|
+
});
|
|
76146
|
+
}
|
|
76147
|
+
}
|
|
76148
|
+
var PluginServerFilesLive = succeed10(PluginServerFiles, {
|
|
76149
|
+
defaultPidFile: defaultPidFile3,
|
|
76150
|
+
defaultLogFile: defaultLogFile3,
|
|
76151
|
+
defaultStateFile: defaultStateFile3,
|
|
76152
|
+
readPidFile: (pidFilePath) => tryPromise2({
|
|
76153
|
+
try: async () => {
|
|
76154
|
+
const resolved = resolveUserFilePath(pidFilePath);
|
|
76155
|
+
const raw4 = await fs10.readFile(resolved, "utf8");
|
|
76156
|
+
return parseJson3(raw4, resolved);
|
|
76157
|
+
},
|
|
76158
|
+
catch: (error4) => {
|
|
76159
|
+
const code2 = error4?.code;
|
|
76160
|
+
if (code2 === "ENOENT")
|
|
76161
|
+
return;
|
|
76162
|
+
if (isCliError(error4))
|
|
76163
|
+
return error4;
|
|
76164
|
+
return new CliError({
|
|
76165
|
+
code: "INTERNAL",
|
|
76166
|
+
message: "Failed to read plugin server pid file",
|
|
76167
|
+
exitCode: 1,
|
|
76168
|
+
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
76169
|
+
});
|
|
76170
|
+
}
|
|
76171
|
+
}).pipe(catchAll2((error4) => {
|
|
76172
|
+
if (error4 === undefined)
|
|
76173
|
+
return succeed8(undefined);
|
|
76174
|
+
return fail8(error4);
|
|
76175
|
+
})),
|
|
76176
|
+
writePidFile: (pidFilePath, value8) => tryPromise2({
|
|
76177
|
+
try: async () => {
|
|
76178
|
+
const resolved = resolveUserFilePath(pidFilePath);
|
|
76179
|
+
await ensureDir5(resolved);
|
|
76180
|
+
await fs10.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
76181
|
+
`, "utf8");
|
|
76182
|
+
},
|
|
76183
|
+
catch: (error4) => new CliError({
|
|
76184
|
+
code: "INTERNAL",
|
|
76185
|
+
message: "Failed to write plugin server pid file",
|
|
76186
|
+
exitCode: 1,
|
|
76187
|
+
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
76188
|
+
})
|
|
76189
|
+
}),
|
|
76190
|
+
deletePidFile: (pidFilePath) => tryPromise2({
|
|
76191
|
+
try: async () => {
|
|
76192
|
+
const resolved = resolveUserFilePath(pidFilePath);
|
|
76193
|
+
await fs10.rm(resolved, { force: true });
|
|
76194
|
+
},
|
|
76195
|
+
catch: (error4) => new CliError({
|
|
76196
|
+
code: "INTERNAL",
|
|
76197
|
+
message: "Failed to delete plugin server pid file",
|
|
76198
|
+
exitCode: 1,
|
|
76199
|
+
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
76200
|
+
})
|
|
76201
|
+
}),
|
|
76202
|
+
readStateFile: (stateFilePath) => tryPromise2({
|
|
76203
|
+
try: async () => {
|
|
76204
|
+
const resolved = resolveUserFilePath(stateFilePath);
|
|
76205
|
+
const raw4 = await fs10.readFile(resolved, "utf8");
|
|
76206
|
+
return parseJson3(raw4, resolved);
|
|
76207
|
+
},
|
|
76208
|
+
catch: (error4) => {
|
|
76209
|
+
const code2 = error4?.code;
|
|
76210
|
+
if (code2 === "ENOENT")
|
|
76211
|
+
return;
|
|
76212
|
+
if (isCliError(error4))
|
|
76213
|
+
return error4;
|
|
76214
|
+
return new CliError({
|
|
76215
|
+
code: "INTERNAL",
|
|
76216
|
+
message: "Failed to read plugin server state file",
|
|
76217
|
+
exitCode: 1,
|
|
76218
|
+
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
76219
|
+
});
|
|
76220
|
+
}
|
|
76221
|
+
}).pipe(catchAll2((error4) => {
|
|
76222
|
+
if (error4 === undefined)
|
|
76223
|
+
return succeed8(undefined);
|
|
76224
|
+
return fail8(error4);
|
|
76225
|
+
})),
|
|
76226
|
+
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
76227
|
+
try: async () => {
|
|
76228
|
+
const resolved = resolveUserFilePath(stateFilePath);
|
|
76229
|
+
await ensureDir5(resolved);
|
|
76230
|
+
await fs10.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
76231
|
+
`, "utf8");
|
|
76232
|
+
},
|
|
76233
|
+
catch: (error4) => new CliError({
|
|
76234
|
+
code: "INTERNAL",
|
|
76235
|
+
message: "Failed to write plugin server state file",
|
|
76236
|
+
exitCode: 1,
|
|
76237
|
+
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
76238
|
+
})
|
|
76239
|
+
}),
|
|
76240
|
+
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
76241
|
+
try: async () => {
|
|
76242
|
+
const resolved = resolveUserFilePath(stateFilePath);
|
|
76243
|
+
await fs10.rm(resolved, { force: true });
|
|
76244
|
+
},
|
|
76245
|
+
catch: (error4) => new CliError({
|
|
76246
|
+
code: "INTERNAL",
|
|
76247
|
+
message: "Failed to delete plugin server state file",
|
|
76248
|
+
exitCode: 1,
|
|
76249
|
+
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
76250
|
+
})
|
|
76251
|
+
})
|
|
76252
|
+
});
|
|
76253
|
+
|
|
76254
|
+
// src/services/Process.ts
|
|
76255
|
+
import { execFile, spawn as spawn2 } from "node:child_process";
|
|
76256
|
+
import fs11 from "node:fs";
|
|
76257
|
+
import path13 from "node:path";
|
|
76258
|
+
class Process extends Tag2("Process")() {
|
|
76259
|
+
}
|
|
76260
|
+
function ensureDirSync(filePath) {
|
|
76261
|
+
fs11.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
76262
|
+
}
|
|
76263
|
+
var ProcessLive = succeed10(Process, {
|
|
76264
|
+
isPidRunning: (pid) => sync3(() => {
|
|
76265
|
+
if (!Number.isFinite(pid) || pid <= 0)
|
|
76266
|
+
return false;
|
|
76267
|
+
try {
|
|
76268
|
+
process.kill(pid, 0);
|
|
76269
|
+
return true;
|
|
76270
|
+
} catch (error4) {
|
|
76271
|
+
if (error4?.code === "EPERM")
|
|
76272
|
+
return true;
|
|
76273
|
+
return false;
|
|
76274
|
+
}
|
|
76275
|
+
}),
|
|
76276
|
+
getCommandLine: (pid) => async((resume2) => {
|
|
76277
|
+
if (!Number.isFinite(pid) || pid <= 0) {
|
|
76278
|
+
resume2(succeed8(undefined));
|
|
76279
|
+
return;
|
|
76280
|
+
}
|
|
76281
|
+
const finish = (value8) => resume2(succeed8(value8));
|
|
76282
|
+
if (process.platform === "win32") {
|
|
76283
|
+
execFile("powershell.exe", ["-NoProfile", "-Command", `(Get-CimInstance Win32_Process -Filter "ProcessId=${pid}").CommandLine`], { windowsHide: true }, (error4, stdout2) => {
|
|
76284
|
+
if (error4) {
|
|
76285
|
+
finish(undefined);
|
|
76286
|
+
return;
|
|
76287
|
+
}
|
|
76288
|
+
const text15 = String(stdout2 ?? "").trim();
|
|
76289
|
+
finish(text15 || undefined);
|
|
76290
|
+
});
|
|
76291
|
+
return;
|
|
76292
|
+
}
|
|
76293
|
+
execFile("ps", ["-p", String(pid), "-o", "command="], (error4, stdout2) => {
|
|
76294
|
+
if (error4) {
|
|
76295
|
+
finish(undefined);
|
|
76296
|
+
return;
|
|
76297
|
+
}
|
|
76298
|
+
const text15 = String(stdout2 ?? "").trim();
|
|
76299
|
+
finish(text15 || undefined);
|
|
76300
|
+
});
|
|
76301
|
+
}),
|
|
76302
|
+
spawnDetached: (params3) => try_3({
|
|
76303
|
+
try: () => {
|
|
76304
|
+
ensureDirSync(params3.logFile);
|
|
76305
|
+
const fd = fs11.openSync(params3.logFile, "a");
|
|
76306
|
+
const child = spawn2(params3.command, [...params3.args], {
|
|
76307
|
+
cwd: params3.cwd,
|
|
76308
|
+
env: params3.env,
|
|
76309
|
+
detached: true,
|
|
76310
|
+
stdio: ["ignore", fd, fd]
|
|
76311
|
+
});
|
|
76312
|
+
child.unref();
|
|
76313
|
+
return child.pid;
|
|
76314
|
+
},
|
|
76315
|
+
catch: (error4) => {
|
|
76316
|
+
if (isCliError(error4))
|
|
76317
|
+
return error4;
|
|
76318
|
+
return new CliError({
|
|
76319
|
+
code: "INTERNAL",
|
|
76320
|
+
message: "Failed to start background process",
|
|
76321
|
+
exitCode: 1,
|
|
76322
|
+
details: { error: String(error4?.message || error4) }
|
|
76323
|
+
});
|
|
76324
|
+
}
|
|
76325
|
+
}).pipe(flatMap9((pid) => {
|
|
76326
|
+
if (typeof pid !== "number" || !Number.isFinite(pid)) {
|
|
76327
|
+
return fail8(new CliError({
|
|
76328
|
+
code: "INTERNAL",
|
|
76329
|
+
message: "Failed to start background process (pid is unavailable)",
|
|
76330
|
+
exitCode: 1
|
|
76331
|
+
}));
|
|
76332
|
+
}
|
|
76333
|
+
return succeed8(pid);
|
|
76334
|
+
})),
|
|
76335
|
+
kill: (pid, signal) => try_3({
|
|
76336
|
+
try: () => {
|
|
76337
|
+
process.kill(pid, signal);
|
|
76338
|
+
},
|
|
76339
|
+
catch: (error4) => new CliError({
|
|
76340
|
+
code: "INTERNAL",
|
|
76341
|
+
message: `Failed to send signal (${signal})`,
|
|
76342
|
+
exitCode: 1,
|
|
76343
|
+
details: { pid, signal, error: String(error4?.message || error4) }
|
|
76344
|
+
})
|
|
76345
|
+
}),
|
|
76346
|
+
waitForExit: ({ pid, timeoutMs }) => async((resume2) => {
|
|
76347
|
+
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
76348
|
+
const tick2 = () => {
|
|
76349
|
+
let alive = false;
|
|
76350
|
+
try {
|
|
76351
|
+
process.kill(pid, 0);
|
|
76352
|
+
alive = true;
|
|
76353
|
+
} catch (error4) {
|
|
76354
|
+
alive = error4?.code === "EPERM";
|
|
76355
|
+
}
|
|
76356
|
+
if (!alive) {
|
|
76357
|
+
resume2(succeed8(true));
|
|
76358
|
+
return;
|
|
76359
|
+
}
|
|
76360
|
+
if (Date.now() >= deadline) {
|
|
76361
|
+
resume2(succeed8(false));
|
|
76362
|
+
return;
|
|
76363
|
+
}
|
|
76364
|
+
setTimeout(tick2, 100);
|
|
76365
|
+
};
|
|
76366
|
+
tick2();
|
|
76367
|
+
})
|
|
76368
|
+
});
|
|
76369
|
+
|
|
75770
76370
|
// src/lib/tmux.ts
|
|
75771
|
-
import { spawn as
|
|
76371
|
+
import { spawn as spawn3, spawnSync } from "node:child_process";
|
|
75772
76372
|
function envTmuxRefreshEnabled() {
|
|
75773
76373
|
const raw4 = String(process.env.REMNOTE_TMUX_REFRESH || process.env.TMUX_REFRESH || "").trim().toLowerCase();
|
|
75774
76374
|
if (raw4 === "0" || raw4 === "false" || raw4 === "off" || raw4 === "no")
|
|
@@ -75805,13 +76405,13 @@ function refreshNow() {
|
|
|
75805
76405
|
try {
|
|
75806
76406
|
if (clients) {
|
|
75807
76407
|
for (const clientName of clients) {
|
|
75808
|
-
const child =
|
|
76408
|
+
const child = spawn3("tmux", ["refresh-client", "-S", "-t", clientName], { stdio: "ignore" });
|
|
75809
76409
|
child.on("error", () => {});
|
|
75810
76410
|
child.unref();
|
|
75811
76411
|
}
|
|
75812
76412
|
return;
|
|
75813
76413
|
}
|
|
75814
|
-
const fallback =
|
|
76414
|
+
const fallback = spawn3("tmux", ["refresh-client", "-S"], { stdio: "ignore" });
|
|
75815
76415
|
fallback.on("error", () => {});
|
|
75816
76416
|
fallback.unref();
|
|
75817
76417
|
} catch {}
|
|
@@ -75860,21 +76460,21 @@ function buildDbFallbackNextAction(queryText) {
|
|
|
75860
76460
|
}
|
|
75861
76461
|
|
|
75862
76462
|
// src/lib/wsDebug.ts
|
|
75863
|
-
import
|
|
75864
|
-
import
|
|
76463
|
+
import fs12 from "node:fs";
|
|
76464
|
+
import path14 from "node:path";
|
|
75865
76465
|
function envDebug() {
|
|
75866
76466
|
const v = (process.env.REMNOTE_WS_DEBUG || process.env.WS_DEBUG || "").toLowerCase();
|
|
75867
76467
|
return v === "1" || v === "true";
|
|
75868
76468
|
}
|
|
75869
76469
|
function envLogFilePath(params3) {
|
|
75870
76470
|
const p3 = process.env.REMNOTE_WS_LOGFILE || process.env.WS_LOGFILE || "";
|
|
75871
|
-
const def = params3.debug ?
|
|
76471
|
+
const def = params3.debug ? path14.join(homeDir(), ".agent-remnote", "ws-debug.log") : "";
|
|
75872
76472
|
const out = p3 && p3.trim() || def;
|
|
75873
76473
|
if (!out)
|
|
75874
76474
|
return;
|
|
75875
76475
|
try {
|
|
75876
76476
|
const resolved = resolveUserFilePath(out);
|
|
75877
|
-
|
|
76477
|
+
fs12.mkdirSync(path14.dirname(resolved), { recursive: true });
|
|
75878
76478
|
return resolved;
|
|
75879
76479
|
} catch {
|
|
75880
76480
|
return;
|
|
@@ -75906,19 +76506,19 @@ function wsLog(level, msg, ctx) {
|
|
|
75906
76506
|
if (!LOG_FILE)
|
|
75907
76507
|
return;
|
|
75908
76508
|
try {
|
|
75909
|
-
|
|
76509
|
+
fs12.appendFileSync(LOG_FILE, `${new Date().toISOString()} ${line4}
|
|
75910
76510
|
`);
|
|
75911
76511
|
} catch {}
|
|
75912
76512
|
}
|
|
75913
76513
|
|
|
75914
76514
|
// src/internal/queue/db.ts
|
|
75915
|
-
import
|
|
76515
|
+
import path16 from "node:path";
|
|
75916
76516
|
|
|
75917
76517
|
// src/internal/store/db.ts
|
|
75918
76518
|
import Database from "better-sqlite3";
|
|
75919
76519
|
import { createHash, randomUUID } from "node:crypto";
|
|
75920
76520
|
import { constants as constants2, copyFileSync, existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
75921
|
-
import
|
|
76521
|
+
import path15 from "node:path";
|
|
75922
76522
|
|
|
75923
76523
|
// src/internal/store/migrations/0001-baseline.ts
|
|
75924
76524
|
var migration = {
|
|
@@ -76439,7 +77039,7 @@ CREATE INDEX IF NOT EXISTS idx_task_runs_queue_txn_id
|
|
|
76439
77039
|
ON task_runs(queue_txn_id);
|
|
76440
77040
|
`;
|
|
76441
77041
|
function absoluteDefaultStorePath() {
|
|
76442
|
-
return
|
|
77042
|
+
return path15.join(homeDir(), ".agent-remnote", "store.sqlite");
|
|
76443
77043
|
}
|
|
76444
77044
|
function defaultStorePath() {
|
|
76445
77045
|
const env2 = process.env.REMNOTE_STORE_DB || process.env.STORE_DB;
|
|
@@ -76451,15 +77051,15 @@ function defaultLegacyQueuePath() {
|
|
|
76451
77051
|
const env2 = process.env.REMNOTE_QUEUE_DB || process.env.QUEUE_DB;
|
|
76452
77052
|
if (typeof env2 === "string" && env2.trim())
|
|
76453
77053
|
return resolveUserFilePath(env2);
|
|
76454
|
-
return
|
|
77054
|
+
return path15.join(homeDir(), ".agent-remnote", "queue.sqlite");
|
|
76455
77055
|
}
|
|
76456
|
-
function
|
|
76457
|
-
const dir2 =
|
|
77056
|
+
function ensureDir6(filePath) {
|
|
77057
|
+
const dir2 = path15.dirname(filePath);
|
|
76458
77058
|
mkdirSync(dir2, { recursive: true });
|
|
76459
77059
|
}
|
|
76460
77060
|
function openStoreDb(dbPath = defaultStorePath()) {
|
|
76461
77061
|
const resolvedPath = resolveUserFilePath(dbPath);
|
|
76462
|
-
|
|
77062
|
+
ensureDir6(resolvedPath);
|
|
76463
77063
|
maybeInitializeDefaultStoreFromLegacy(resolvedPath, { callerProvidedPath: dbPath });
|
|
76464
77064
|
const db = new Database(resolvedPath);
|
|
76465
77065
|
db.pragma("busy_timeout = 5000");
|
|
@@ -76796,7 +77396,7 @@ function maybeInitializeDefaultStoreFromLegacy(resolvedStorePath, params3) {
|
|
|
76796
77396
|
if (!existsSync(legacyPath))
|
|
76797
77397
|
return;
|
|
76798
77398
|
const tmpPath = `${resolvedStorePath}.tmp.${process.pid}.${randomUUID()}`;
|
|
76799
|
-
|
|
77399
|
+
ensureDir6(tmpPath);
|
|
76800
77400
|
try {
|
|
76801
77401
|
const source = new Database(legacyPath, { readonly: true });
|
|
76802
77402
|
try {
|
|
@@ -76931,10 +77531,10 @@ function defaultQueuePath() {
|
|
|
76931
77531
|
const env2 = process.env.REMNOTE_QUEUE_DB || process.env.QUEUE_DB;
|
|
76932
77532
|
if (typeof env2 === "string" && env2.trim())
|
|
76933
77533
|
return resolveUserFilePath(env2);
|
|
76934
|
-
return
|
|
77534
|
+
return path16.join(homeDir(), ".agent-remnote", "queue.sqlite");
|
|
76935
77535
|
}
|
|
76936
|
-
function
|
|
76937
|
-
|
|
77536
|
+
function ensureDir7(filePath) {
|
|
77537
|
+
ensureDir6(filePath);
|
|
76938
77538
|
}
|
|
76939
77539
|
function queueErrorFromStoreSchema(dbPath, error4) {
|
|
76940
77540
|
const code2 = error4.code === "STORE_SCHEMA_NEWER" ? "QUEUE_SCHEMA_NEWER" : error4.code === "STORE_SCHEMA_INVALID" ? "QUEUE_SCHEMA_INVALID" : "QUEUE_SCHEMA_UNKNOWN";
|
|
@@ -76947,7 +77547,7 @@ function queueErrorFromStoreSchema(dbPath, error4) {
|
|
|
76947
77547
|
}
|
|
76948
77548
|
function openQueueDb(dbPath = defaultQueuePath()) {
|
|
76949
77549
|
const resolvedPath = resolveUserFilePath(dbPath);
|
|
76950
|
-
|
|
77550
|
+
ensureDir7(resolvedPath);
|
|
76951
77551
|
try {
|
|
76952
77552
|
return openStoreDb(resolvedPath);
|
|
76953
77553
|
} catch (e) {
|
|
@@ -77305,18 +77905,18 @@ function getFirstString(payload, keys8) {
|
|
|
77305
77905
|
}
|
|
77306
77906
|
return null;
|
|
77307
77907
|
}
|
|
77308
|
-
function getFirstStringFromNested(payload,
|
|
77908
|
+
function getFirstStringFromNested(payload, path17) {
|
|
77309
77909
|
let cur = payload;
|
|
77310
|
-
for (const k of
|
|
77910
|
+
for (const k of path17) {
|
|
77311
77911
|
if (!cur || typeof cur !== "object")
|
|
77312
77912
|
return null;
|
|
77313
77913
|
cur = cur[k];
|
|
77314
77914
|
}
|
|
77315
77915
|
return asNonEmptyString(cur);
|
|
77316
77916
|
}
|
|
77317
|
-
function getStringArrayFromNested(payload,
|
|
77917
|
+
function getStringArrayFromNested(payload, path17) {
|
|
77318
77918
|
let cur = payload;
|
|
77319
|
-
for (const k of
|
|
77919
|
+
for (const k of path17) {
|
|
77320
77920
|
if (!cur || typeof cur !== "object")
|
|
77321
77921
|
return [];
|
|
77322
77922
|
cur = cur[k];
|
|
@@ -78660,38 +79260,38 @@ function idFieldPathsForOpType(opTypeRaw) {
|
|
|
78660
79260
|
return Array.isArray(entry.id_fields) ? entry.id_fields : [];
|
|
78661
79261
|
}
|
|
78662
79262
|
// src/kernel/op-catalog/pathWalk.ts
|
|
78663
|
-
function parsePathTokens(
|
|
78664
|
-
return
|
|
79263
|
+
function parsePathTokens(path17) {
|
|
79264
|
+
return path17.split(".").map((part) => part.trim()).filter(Boolean).map((part) => {
|
|
78665
79265
|
const isArray2 = part.endsWith("[]");
|
|
78666
79266
|
const key = isArray2 ? part.slice(0, -2).trim() : part;
|
|
78667
79267
|
return { key, isArray: isArray2 };
|
|
78668
79268
|
}).filter((token) => token.key.length > 0);
|
|
78669
79269
|
}
|
|
78670
|
-
function collectLeafValues(value8,
|
|
78671
|
-
if (idx >=
|
|
79270
|
+
function collectLeafValues(value8, path17, idx = 0) {
|
|
79271
|
+
if (idx >= path17.length)
|
|
78672
79272
|
return [value8];
|
|
78673
79273
|
if (!value8 || typeof value8 !== "object")
|
|
78674
79274
|
return [];
|
|
78675
|
-
const token =
|
|
79275
|
+
const token = path17[idx];
|
|
78676
79276
|
const next4 = value8[token.key];
|
|
78677
79277
|
if (token.isArray) {
|
|
78678
79278
|
if (!Array.isArray(next4))
|
|
78679
79279
|
return [];
|
|
78680
79280
|
const out = [];
|
|
78681
79281
|
for (const item of next4) {
|
|
78682
|
-
out.push(...collectLeafValues(item,
|
|
79282
|
+
out.push(...collectLeafValues(item, path17, idx + 1));
|
|
78683
79283
|
}
|
|
78684
79284
|
return out;
|
|
78685
79285
|
}
|
|
78686
|
-
return collectLeafValues(next4,
|
|
79286
|
+
return collectLeafValues(next4, path17, idx + 1);
|
|
78687
79287
|
}
|
|
78688
|
-
function mapLeafValuesInPlace(value8,
|
|
78689
|
-
if (idx >=
|
|
79288
|
+
function mapLeafValuesInPlace(value8, path17, mapFn, idx = 0) {
|
|
79289
|
+
if (idx >= path17.length)
|
|
78690
79290
|
return;
|
|
78691
79291
|
if (!value8 || typeof value8 !== "object")
|
|
78692
79292
|
return;
|
|
78693
|
-
const token =
|
|
78694
|
-
const isLeaf = idx ===
|
|
79293
|
+
const token = path17[idx];
|
|
79294
|
+
const isLeaf = idx === path17.length - 1;
|
|
78695
79295
|
if (token.isArray) {
|
|
78696
79296
|
const next4 = value8[token.key];
|
|
78697
79297
|
if (!Array.isArray(next4))
|
|
@@ -78701,7 +79301,7 @@ function mapLeafValuesInPlace(value8, path14, mapFn, idx = 0) {
|
|
|
78701
79301
|
return;
|
|
78702
79302
|
}
|
|
78703
79303
|
for (const item of next4) {
|
|
78704
|
-
mapLeafValuesInPlace(item,
|
|
79304
|
+
mapLeafValuesInPlace(item, path17, mapFn, idx + 1);
|
|
78705
79305
|
}
|
|
78706
79306
|
return;
|
|
78707
79307
|
}
|
|
@@ -78709,7 +79309,7 @@ function mapLeafValuesInPlace(value8, path14, mapFn, idx = 0) {
|
|
|
78709
79309
|
value8[token.key] = mapFn(value8[token.key]);
|
|
78710
79310
|
return;
|
|
78711
79311
|
}
|
|
78712
|
-
mapLeafValuesInPlace(value8[token.key],
|
|
79312
|
+
mapLeafValuesInPlace(value8[token.key], path17, mapFn, idx + 1);
|
|
78713
79313
|
}
|
|
78714
79314
|
|
|
78715
79315
|
// src/kernel/op-catalog/substituteIds.ts
|
|
@@ -78731,8 +79331,8 @@ function collectTempIdsFromPayload(opTypeRaw, payload) {
|
|
|
78731
79331
|
if (!payload || typeof payload !== "object")
|
|
78732
79332
|
return [];
|
|
78733
79333
|
const out = [];
|
|
78734
|
-
for (const
|
|
78735
|
-
const tokens = parsePathTokens(
|
|
79334
|
+
for (const path17 of idFieldPathsForOpType(opTypeRaw)) {
|
|
79335
|
+
const tokens = parsePathTokens(path17);
|
|
78736
79336
|
if (tokens.length === 0)
|
|
78737
79337
|
continue;
|
|
78738
79338
|
const values5 = collectLeafValues(payload, tokens);
|
|
@@ -78747,8 +79347,8 @@ function substituteTempIdsInPayload(opTypeRaw, payload, idMap) {
|
|
|
78747
79347
|
if (!payload || typeof payload !== "object")
|
|
78748
79348
|
return payload;
|
|
78749
79349
|
const out = cloneJson(payload);
|
|
78750
|
-
for (const
|
|
78751
|
-
const tokens = parsePathTokens(
|
|
79350
|
+
for (const path17 of idFieldPathsForOpType(opTypeRaw)) {
|
|
79351
|
+
const tokens = parsePathTokens(path17);
|
|
78752
79352
|
if (tokens.length === 0)
|
|
78753
79353
|
continue;
|
|
78754
79354
|
mapLeafValuesInPlace(out, tokens, (value8) => {
|
|
@@ -80149,8 +80749,8 @@ function toWsBridgeClient2(client) {
|
|
|
80149
80749
|
var GLOBAL_BRIDGE_KEY = Symbol.for("__REMNOTE_WS_BRIDGE__");
|
|
80150
80750
|
// src/internal/remdb-tools/shared.ts
|
|
80151
80751
|
import BetterSqlite3 from "better-sqlite3";
|
|
80152
|
-
import { promises as
|
|
80153
|
-
import
|
|
80752
|
+
import { promises as fs13 } from "fs";
|
|
80753
|
+
import path17 from "path";
|
|
80154
80754
|
|
|
80155
80755
|
// ../../node_modules/date-fns/constants.js
|
|
80156
80756
|
var daysInYear = 365.2425;
|
|
@@ -81639,18 +82239,18 @@ async function withResolvedDatabase(dbPath, fn) {
|
|
|
81639
82239
|
async function resolveDatabasePath(dbPath) {
|
|
81640
82240
|
if (dbPath) {
|
|
81641
82241
|
const expanded = expandHome2(dbPath.trim());
|
|
81642
|
-
const stat3 = await
|
|
82242
|
+
const stat3 = await fs13.stat(expanded);
|
|
81643
82243
|
if (!stat3.isFile()) {
|
|
81644
82244
|
throw new Error(`${expanded} is not a file`);
|
|
81645
82245
|
}
|
|
81646
82246
|
return {
|
|
81647
82247
|
dbPath: expanded,
|
|
81648
82248
|
source: "explicit",
|
|
81649
|
-
baseDir:
|
|
82249
|
+
baseDir: path17.dirname(expanded)
|
|
81650
82250
|
};
|
|
81651
82251
|
}
|
|
81652
|
-
const baseDir =
|
|
81653
|
-
const entries2 = await
|
|
82252
|
+
const baseDir = path17.join(homeDir(), REMNOTE_RELATIVE_DIR);
|
|
82253
|
+
const entries2 = await fs13.readdir(baseDir, { withFileTypes: true }).catch(() => {
|
|
81654
82254
|
throw new Error(`RemNote directory ${baseDir} not found – please specify dbPath manually`);
|
|
81655
82255
|
});
|
|
81656
82256
|
const candidates = [];
|
|
@@ -81663,9 +82263,9 @@ async function resolveDatabasePath(dbPath) {
|
|
|
81663
82263
|
const isSecondary = SECONDARY_DIRS.has(entry.name);
|
|
81664
82264
|
if (!isPrimary && !isSecondary)
|
|
81665
82265
|
continue;
|
|
81666
|
-
const candidatePath =
|
|
82266
|
+
const candidatePath = path17.join(baseDir, entry.name, REMNOTE_DB_NAME);
|
|
81667
82267
|
try {
|
|
81668
|
-
const stat3 = await
|
|
82268
|
+
const stat3 = await fs13.stat(candidatePath);
|
|
81669
82269
|
candidates.push({
|
|
81670
82270
|
dbPath: candidatePath,
|
|
81671
82271
|
dirName: entry.name,
|
|
@@ -81696,18 +82296,18 @@ async function discoverBackups(basePath) {
|
|
|
81696
82296
|
const backups = [];
|
|
81697
82297
|
let entries2;
|
|
81698
82298
|
try {
|
|
81699
|
-
entries2 = await
|
|
82299
|
+
entries2 = await fs13.readdir(basePath, { withFileTypes: true });
|
|
81700
82300
|
} catch (error4) {
|
|
81701
82301
|
throw new Error(`Unable to read ${basePath}: ${String(error4)}`);
|
|
81702
82302
|
}
|
|
81703
82303
|
for (const entry of entries2) {
|
|
81704
82304
|
if (!entry.isDirectory())
|
|
81705
82305
|
continue;
|
|
81706
|
-
const accountDir =
|
|
81707
|
-
const backupDir =
|
|
82306
|
+
const accountDir = path17.join(basePath, entry.name);
|
|
82307
|
+
const backupDir = path17.join(accountDir, "backups");
|
|
81708
82308
|
let backupFiles;
|
|
81709
82309
|
try {
|
|
81710
|
-
backupFiles = await
|
|
82310
|
+
backupFiles = await fs13.readdir(backupDir, { withFileTypes: true });
|
|
81711
82311
|
} catch {
|
|
81712
82312
|
continue;
|
|
81713
82313
|
}
|
|
@@ -81716,8 +82316,8 @@ async function discoverBackups(basePath) {
|
|
|
81716
82316
|
continue;
|
|
81717
82317
|
if (!file6.name.endsWith(".db") && !file6.name.endsWith(".db.zip"))
|
|
81718
82318
|
continue;
|
|
81719
|
-
const fullPath =
|
|
81720
|
-
const stat3 = await
|
|
82319
|
+
const fullPath = path17.join(backupDir, file6.name);
|
|
82320
|
+
const stat3 = await fs13.stat(fullPath);
|
|
81721
82321
|
backups.push({
|
|
81722
82322
|
accountDir: entry.name,
|
|
81723
82323
|
file: file6.name,
|
|
@@ -81838,8 +82438,8 @@ function parseOrThrow(schema2, input, options6) {
|
|
|
81838
82438
|
throw new Error(prefix2 + lines3.join("; "));
|
|
81839
82439
|
}
|
|
81840
82440
|
function formatZodIssueEN(issue) {
|
|
81841
|
-
const
|
|
81842
|
-
const where =
|
|
82441
|
+
const path18 = issue.path && issue.path.length > 0 ? issue.path.join(".") : undefined;
|
|
82442
|
+
const where = path18 ? `field ${path18}: ` : "";
|
|
81843
82443
|
switch (issue.code) {
|
|
81844
82444
|
case "invalid_type": {
|
|
81845
82445
|
const expected = toENType(issue.expected);
|
|
@@ -82291,8 +82891,8 @@ function getErrorMap() {
|
|
|
82291
82891
|
return overrideErrorMap;
|
|
82292
82892
|
}
|
|
82293
82893
|
var makeIssue = (params3) => {
|
|
82294
|
-
const { data, path:
|
|
82295
|
-
const fullPath = [...
|
|
82894
|
+
const { data, path: path18, errorMaps, issueData } = params3;
|
|
82895
|
+
const fullPath = [...path18, ...issueData.path || []];
|
|
82296
82896
|
const fullIssue = {
|
|
82297
82897
|
...issueData,
|
|
82298
82898
|
path: fullPath
|
|
@@ -82420,11 +83020,11 @@ var _ZodEnum_cache;
|
|
|
82420
83020
|
var _ZodNativeEnum_cache;
|
|
82421
83021
|
|
|
82422
83022
|
class ParseInputLazyPath {
|
|
82423
|
-
constructor(parent, value8,
|
|
83023
|
+
constructor(parent, value8, path18, key) {
|
|
82424
83024
|
this._cachedPath = [];
|
|
82425
83025
|
this.parent = parent;
|
|
82426
83026
|
this.data = value8;
|
|
82427
|
-
this._path =
|
|
83027
|
+
this._path = path18;
|
|
82428
83028
|
this._key = key;
|
|
82429
83029
|
}
|
|
82430
83030
|
get path() {
|
|
@@ -85801,7 +86401,7 @@ var z = /* @__PURE__ */ Object.freeze({
|
|
|
85801
86401
|
});
|
|
85802
86402
|
|
|
85803
86403
|
// src/internal/remdb-tools/listRemBackups.ts
|
|
85804
|
-
import
|
|
86404
|
+
import path18 from "node:path";
|
|
85805
86405
|
var inputShape = {
|
|
85806
86406
|
basePath: z.string().optional().describe("RemNote base directory (default: ~/remnote)"),
|
|
85807
86407
|
limit: z.number().int().min(1).max(200).optional().describe("Max backups to return (default 50)")
|
|
@@ -85809,7 +86409,7 @@ var inputShape = {
|
|
|
85809
86409
|
var listRemBackupsSchema = z.object(inputShape);
|
|
85810
86410
|
async function executeListRemBackups(params3) {
|
|
85811
86411
|
const parsed = parseOrThrow(listRemBackupsSchema, params3, { label: "list_rem_backups" });
|
|
85812
|
-
const basePath = expandHome2(parsed.basePath ??
|
|
86412
|
+
const basePath = expandHome2(parsed.basePath ?? path18.join(homeDir(), REMNOTE_RELATIVE_DIR));
|
|
85813
86413
|
const backups = await discoverBackups(basePath);
|
|
85814
86414
|
const limit = parsed.limit ?? 50;
|
|
85815
86415
|
return {
|
|
@@ -85819,6 +86419,7 @@ async function executeListRemBackups(params3) {
|
|
|
85819
86419
|
};
|
|
85820
86420
|
}
|
|
85821
86421
|
// src/internal/remdb-tools/searchRemOverview.ts
|
|
86422
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
85822
86423
|
import { isMainThread, parentPort as parentPort2, workerData } from "node:worker_threads";
|
|
85823
86424
|
|
|
85824
86425
|
// src/internal/remdb-tools/timeFilters.ts
|
|
@@ -86098,6 +86699,21 @@ class HardTimeoutError extends Error {
|
|
|
86098
86699
|
this.timeoutMs = timeoutMs;
|
|
86099
86700
|
}
|
|
86100
86701
|
}
|
|
86702
|
+
async function runSearchRemOverviewWorkerJob(job, port3) {
|
|
86703
|
+
if (job.kind === "search_rem_overview") {
|
|
86704
|
+
try {
|
|
86705
|
+
const result = await executeSearchRemOverviewDirect(job.input);
|
|
86706
|
+
port3.postMessage({ ok: true, result });
|
|
86707
|
+
} catch (e) {
|
|
86708
|
+
port3.postMessage({
|
|
86709
|
+
ok: false,
|
|
86710
|
+
error: { message: asErrorMessage(e), stack: e?.stack }
|
|
86711
|
+
});
|
|
86712
|
+
}
|
|
86713
|
+
return;
|
|
86714
|
+
}
|
|
86715
|
+
port3.postMessage({ ok: false, error: { message: "Unknown worker job" } });
|
|
86716
|
+
}
|
|
86101
86717
|
function asErrorMessage(e) {
|
|
86102
86718
|
return String(e?.message || e || "Unknown error");
|
|
86103
86719
|
}
|
|
@@ -86108,7 +86724,8 @@ async function executeSearchRemOverviewDirect(params3) {
|
|
|
86108
86724
|
}
|
|
86109
86725
|
async function executeSearchRemOverviewWithHardTimeout(params3, timeoutMs) {
|
|
86110
86726
|
const selfUrl = new URL(import.meta.url);
|
|
86111
|
-
const
|
|
86727
|
+
const selfFilePath = selfUrl.protocol === "file:" ? fileURLToPath2(selfUrl) : "";
|
|
86728
|
+
const isSourceMode = selfFilePath.endsWith(".ts");
|
|
86112
86729
|
if (isSourceMode) {
|
|
86113
86730
|
return await executeSearchRemOverviewDirect(params3);
|
|
86114
86731
|
}
|
|
@@ -86125,18 +86742,7 @@ if (!isMainThread) {
|
|
|
86125
86742
|
throw new Error("Worker parentPort is unavailable");
|
|
86126
86743
|
}
|
|
86127
86744
|
const job = workerData ?? { kind: "unknown" };
|
|
86128
|
-
|
|
86129
|
-
executeSearchRemOverviewDirect(job.input).then((result) => {
|
|
86130
|
-
port3.postMessage({ ok: true, result });
|
|
86131
|
-
}, (e) => {
|
|
86132
|
-
port3.postMessage({
|
|
86133
|
-
ok: false,
|
|
86134
|
-
error: { message: asErrorMessage(e), stack: e?.stack }
|
|
86135
|
-
});
|
|
86136
|
-
});
|
|
86137
|
-
} else {
|
|
86138
|
-
port3.postMessage({ ok: false, error: { message: "Unknown worker job" } });
|
|
86139
|
-
}
|
|
86745
|
+
runSearchRemOverviewWorkerJob(job, port3);
|
|
86140
86746
|
}
|
|
86141
86747
|
async function executeSearchRemOverview(params3) {
|
|
86142
86748
|
const parsed = parseOrThrow(searchRemOverviewSchema, params3, { label: "search_rem_overview" });
|
|
@@ -87644,10 +88250,10 @@ function fetchDocs(db, rootId, includeDescendants, maxDepth) {
|
|
|
87644
88250
|
}
|
|
87645
88251
|
return rows.map((row) => convertRow(row.id, row.doc));
|
|
87646
88252
|
}
|
|
87647
|
-
function collectReferences(value8, remId,
|
|
88253
|
+
function collectReferences(value8, remId, path19, into3) {
|
|
87648
88254
|
if (Array.isArray(value8)) {
|
|
87649
88255
|
value8.forEach((item, index) => {
|
|
87650
|
-
collectReferences(item, remId, [...
|
|
88256
|
+
collectReferences(item, remId, [...path19, index], into3);
|
|
87651
88257
|
});
|
|
87652
88258
|
return;
|
|
87653
88259
|
}
|
|
@@ -87657,7 +88263,7 @@ function collectReferences(value8, remId, path16, into3) {
|
|
|
87657
88263
|
into3.push({
|
|
87658
88264
|
refId: maybeRef._id,
|
|
87659
88265
|
remId,
|
|
87660
|
-
path: formatPath2(
|
|
88266
|
+
path: formatPath2(path19),
|
|
87661
88267
|
tokenKind: classifyToken(maybeRef)
|
|
87662
88268
|
});
|
|
87663
88269
|
return;
|
|
@@ -87666,13 +88272,13 @@ function collectReferences(value8, remId, path16, into3) {
|
|
|
87666
88272
|
into3.push({
|
|
87667
88273
|
refId: maybeRef._id,
|
|
87668
88274
|
remId,
|
|
87669
|
-
path: formatPath2(
|
|
88275
|
+
path: formatPath2(path19),
|
|
87670
88276
|
tokenKind: classifyToken(maybeRef)
|
|
87671
88277
|
});
|
|
87672
88278
|
return;
|
|
87673
88279
|
}
|
|
87674
88280
|
for (const [key, child] of Object.entries(maybeRef)) {
|
|
87675
|
-
collectReferences(child, remId, [...
|
|
88281
|
+
collectReferences(child, remId, [...path19, key], into3);
|
|
87676
88282
|
}
|
|
87677
88283
|
}
|
|
87678
88284
|
}
|
|
@@ -87789,8 +88395,8 @@ function buildReferencesMarkdown(remId, guidance, outbound, inbound, includeInbo
|
|
|
87789
88395
|
const tokenKind = Array.isArray(ref.tokenKinds) ? `type: ${formatTokenKinds(ref.tokenKinds)}` : "";
|
|
87790
88396
|
const ancestor = ref.ancestor ? `, ancestor: ${ref.ancestor}` : "";
|
|
87791
88397
|
const count4 = typeof ref.count === "number" ? `${ref.count} occurrences` : "";
|
|
87792
|
-
const
|
|
87793
|
-
const samplePath =
|
|
88398
|
+
const path19 = ref.occurrences ? ref.occurrences[0]?.path ?? null : ref.representativePath;
|
|
88399
|
+
const samplePath = path19 ? `, sample path: ${path19}` : "";
|
|
87794
88400
|
lines3.push(`- **${name}** (ID: ${ref.refId}, ${count4}${ancestor}${samplePath}${tokenKind ? `, ${tokenKind}` : ""})`);
|
|
87795
88401
|
});
|
|
87796
88402
|
}
|
|
@@ -91737,107 +92343,559 @@ var WsClientLive = succeed10(WsClient, {
|
|
|
91737
92343
|
})
|
|
91738
92344
|
});
|
|
91739
92345
|
|
|
91740
|
-
// src/
|
|
91741
|
-
import
|
|
91742
|
-
|
|
91743
|
-
|
|
91744
|
-
|
|
91745
|
-
|
|
91746
|
-
|
|
91747
|
-
|
|
91748
|
-
}
|
|
91749
|
-
|
|
91750
|
-
|
|
92346
|
+
// src/lib/managedRuntimePaths.ts
|
|
92347
|
+
import path19 from "node:path";
|
|
92348
|
+
function resolveManagedStateFile(params3) {
|
|
92349
|
+
const defaultPath = resolveUserFilePath(params3.defaultStateFilePath);
|
|
92350
|
+
const explicitPath = params3.explicitStateFilePath ? resolveUserFilePath(params3.explicitStateFilePath) : undefined;
|
|
92351
|
+
const candidatePath = params3.candidate ? resolveUserFilePath(params3.candidate) : undefined;
|
|
92352
|
+
if (!candidatePath) {
|
|
92353
|
+
return explicitPath ?? defaultPath;
|
|
92354
|
+
}
|
|
92355
|
+
if (candidatePath === defaultPath)
|
|
92356
|
+
return candidatePath;
|
|
92357
|
+
if (explicitPath && candidatePath === explicitPath)
|
|
92358
|
+
return candidatePath;
|
|
92359
|
+
const pidRoot = path19.dirname(params3.pidFilePath);
|
|
92360
|
+
const rel = path19.relative(pidRoot, candidatePath);
|
|
92361
|
+
if (rel === "" || !rel.startsWith("..") && !path19.isAbsolute(rel)) {
|
|
92362
|
+
return candidatePath;
|
|
92363
|
+
}
|
|
92364
|
+
return explicitPath ?? defaultPath;
|
|
92365
|
+
}
|
|
92366
|
+
|
|
92367
|
+
// src/lib/pidTrust.ts
|
|
92368
|
+
import path20 from "node:path";
|
|
92369
|
+
function normalizeToken(value8) {
|
|
92370
|
+
return value8.trim().replace(/\\/g, "/").toLowerCase();
|
|
91751
92371
|
}
|
|
91752
|
-
|
|
91753
|
-
|
|
91754
|
-
|
|
92372
|
+
function collectCommandTokens(raw4) {
|
|
92373
|
+
const out = new Set;
|
|
92374
|
+
for (const item of raw4) {
|
|
92375
|
+
const normalized = normalizeToken(String(item ?? ""));
|
|
92376
|
+
if (!normalized)
|
|
92377
|
+
continue;
|
|
92378
|
+
const unquoted = normalized.replace(/^['"]|['"]$/g, "");
|
|
92379
|
+
const base = path20.basename(unquoted);
|
|
92380
|
+
if (unquoted.includes("agent-remnote") || base.includes("agent-remnote")) {
|
|
92381
|
+
out.add("agent-remnote");
|
|
92382
|
+
}
|
|
92383
|
+
if (base === "node" || base === "node.exe")
|
|
92384
|
+
out.add("node");
|
|
92385
|
+
if (base === "tsx" || base === "tsx.cmd")
|
|
92386
|
+
out.add("tsx");
|
|
92387
|
+
if (base.endsWith(".js") || base.endsWith(".ts"))
|
|
92388
|
+
out.add(base);
|
|
92389
|
+
if (!unquoted.startsWith("-") && !unquoted.includes("/"))
|
|
92390
|
+
out.add(unquoted);
|
|
92391
|
+
}
|
|
92392
|
+
out.add("agent-remnote");
|
|
92393
|
+
return Array.from(out);
|
|
92394
|
+
}
|
|
92395
|
+
function expectedTokens(record2) {
|
|
92396
|
+
const raw4 = Array.isArray(record2.cmd) ? record2.cmd : [];
|
|
92397
|
+
return collectCommandTokens(raw4);
|
|
92398
|
+
}
|
|
92399
|
+
function actualTokens(commandLine) {
|
|
92400
|
+
const parts2 = commandLine.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
|
|
92401
|
+
return new Set(collectCommandTokens(parts2));
|
|
92402
|
+
}
|
|
92403
|
+
function isTrustedPidRecord(record2) {
|
|
92404
|
+
return gen2(function* () {
|
|
92405
|
+
const proc = yield* Process;
|
|
92406
|
+
const alive = yield* proc.isPidRunning(record2.pid);
|
|
92407
|
+
if (!alive)
|
|
91755
92408
|
return false;
|
|
91756
|
-
|
|
91757
|
-
process.kill(pid, 0);
|
|
91758
|
-
return true;
|
|
91759
|
-
} catch (error4) {
|
|
91760
|
-
if (error4?.code === "EPERM")
|
|
91761
|
-
return true;
|
|
92409
|
+
if (!proc.getCommandLine)
|
|
91762
92410
|
return false;
|
|
91763
|
-
|
|
91764
|
-
|
|
91765
|
-
|
|
91766
|
-
|
|
91767
|
-
|
|
91768
|
-
|
|
91769
|
-
|
|
91770
|
-
|
|
91771
|
-
|
|
91772
|
-
|
|
91773
|
-
|
|
91774
|
-
|
|
91775
|
-
|
|
91776
|
-
|
|
92411
|
+
const commandLine = yield* proc.getCommandLine(record2.pid);
|
|
92412
|
+
if (!commandLine)
|
|
92413
|
+
return false;
|
|
92414
|
+
const expected = expectedTokens(record2);
|
|
92415
|
+
const actual = actualTokens(commandLine);
|
|
92416
|
+
return expected.every((token) => actual.has(token));
|
|
92417
|
+
});
|
|
92418
|
+
}
|
|
92419
|
+
function requireTrustedPidRecord(params3) {
|
|
92420
|
+
return gen2(function* () {
|
|
92421
|
+
const trusted = yield* isTrustedPidRecord(params3.record);
|
|
92422
|
+
if (trusted)
|
|
92423
|
+
return;
|
|
92424
|
+
return yield* fail8(new CliError({
|
|
92425
|
+
code: "INTERNAL",
|
|
92426
|
+
message: "Refusing to operate on a pidfile that does not match a live agent-remnote process",
|
|
92427
|
+
exitCode: 1,
|
|
92428
|
+
details: {
|
|
92429
|
+
pid: params3.record.pid,
|
|
92430
|
+
pid_file: params3.pidFilePath,
|
|
92431
|
+
cmd: params3.record.cmd ?? []
|
|
92432
|
+
}
|
|
92433
|
+
}));
|
|
92434
|
+
});
|
|
92435
|
+
}
|
|
92436
|
+
|
|
92437
|
+
// src/lib/statuslineArtifacts.ts
|
|
92438
|
+
import { promises as fs15 } from "node:fs";
|
|
92439
|
+
|
|
92440
|
+
// src/services/StatusLineFile.ts
|
|
92441
|
+
import { promises as fs14 } from "node:fs";
|
|
92442
|
+
import path21 from "node:path";
|
|
92443
|
+
class StatusLineFile extends Tag2("StatusLineFile")() {
|
|
92444
|
+
}
|
|
92445
|
+
function defaultTextFile() {
|
|
92446
|
+
return path21.join(homeDir(), ".agent-remnote", "status-line.txt");
|
|
92447
|
+
}
|
|
92448
|
+
function defaultJsonFile() {
|
|
92449
|
+
return path21.join(homeDir(), ".agent-remnote", "status-line.json");
|
|
92450
|
+
}
|
|
92451
|
+
function ensureDir8(p3) {
|
|
92452
|
+
return fs14.mkdir(path21.dirname(p3), { recursive: true }).then(() => {
|
|
92453
|
+
return;
|
|
92454
|
+
});
|
|
92455
|
+
}
|
|
92456
|
+
async function readFileOrEmpty(filePath) {
|
|
92457
|
+
try {
|
|
92458
|
+
return await fs14.readFile(filePath, "utf8");
|
|
92459
|
+
} catch (e) {
|
|
92460
|
+
if (e?.code === "ENOENT")
|
|
92461
|
+
return "";
|
|
92462
|
+
throw e;
|
|
92463
|
+
}
|
|
92464
|
+
}
|
|
92465
|
+
async function writeTextAtomic(filePath, content) {
|
|
92466
|
+
await ensureDir8(filePath);
|
|
92467
|
+
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
92468
|
+
await fs14.writeFile(tmp, content, "utf8");
|
|
92469
|
+
await fs14.rename(tmp, filePath);
|
|
92470
|
+
}
|
|
92471
|
+
var StatusLineFileLive = succeed10(StatusLineFile, {
|
|
92472
|
+
defaultTextFile: () => defaultTextFile(),
|
|
92473
|
+
defaultJsonFile: () => defaultJsonFile(),
|
|
92474
|
+
write: ({ text: text15, textFilePath, debug: debug2, jsonFilePath, json: json4 }) => tryPromise2({
|
|
92475
|
+
try: async () => {
|
|
92476
|
+
const resolvedTextFile = resolveUserFilePath(textFilePath ?? defaultTextFile());
|
|
92477
|
+
const normalizedText = text15.trimEnd();
|
|
92478
|
+
const desired = normalizedText.length > 0 ? `${normalizedText}
|
|
92479
|
+
` : "";
|
|
92480
|
+
const existing = await readFileOrEmpty(resolvedTextFile);
|
|
92481
|
+
if (existing === desired)
|
|
92482
|
+
return { wrote: false, textFilePath: resolvedTextFile };
|
|
92483
|
+
await writeTextAtomic(resolvedTextFile, desired);
|
|
92484
|
+
if (debug2 === true) {
|
|
92485
|
+
const resolvedJsonFile = resolveUserFilePath(jsonFilePath ?? defaultJsonFile());
|
|
92486
|
+
const payload = json4 !== undefined ? json4 : { text: normalizedText };
|
|
92487
|
+
await writeTextAtomic(resolvedJsonFile, `${JSON.stringify(payload)}
|
|
92488
|
+
`);
|
|
92489
|
+
}
|
|
92490
|
+
return { wrote: true, textFilePath: resolvedTextFile };
|
|
91777
92491
|
},
|
|
91778
92492
|
catch: (error4) => {
|
|
91779
92493
|
if (isCliError(error4))
|
|
91780
92494
|
return error4;
|
|
91781
92495
|
return new CliError({
|
|
91782
92496
|
code: "INTERNAL",
|
|
91783
|
-
message: "Failed to
|
|
92497
|
+
message: "Failed to write status line file",
|
|
91784
92498
|
exitCode: 1,
|
|
91785
92499
|
details: { error: String(error4?.message || error4) }
|
|
91786
92500
|
});
|
|
91787
92501
|
}
|
|
91788
|
-
})
|
|
91789
|
-
|
|
91790
|
-
|
|
91791
|
-
|
|
91792
|
-
|
|
91793
|
-
|
|
91794
|
-
|
|
92502
|
+
})
|
|
92503
|
+
});
|
|
92504
|
+
|
|
92505
|
+
// src/lib/statuslineArtifacts.ts
|
|
92506
|
+
function normalizeOptionalPath(value8) {
|
|
92507
|
+
if (typeof value8 !== "string")
|
|
92508
|
+
return;
|
|
92509
|
+
const t = value8.trim();
|
|
92510
|
+
return t.length > 0 ? resolveUserFilePath(t) : undefined;
|
|
92511
|
+
}
|
|
92512
|
+
function resolveStatuslineArtifactPaths(params3) {
|
|
92513
|
+
const pidInfo = params3.pidInfo;
|
|
92514
|
+
const wsBridgeStateFilePath = normalizeOptionalPath(pidInfo?.ws_bridge_state_file) ?? params3.cfg.wsStateFile.path;
|
|
92515
|
+
const statusLineFilePath = normalizeOptionalPath(pidInfo?.status_line_file) ?? params3.cfg.statusLineFile;
|
|
92516
|
+
const statusLineJsonFilePath = normalizeOptionalPath(pidInfo?.status_line_json_file) ?? params3.cfg.statusLineJsonFile;
|
|
92517
|
+
return { wsBridgeStateFilePath, statusLineFilePath, statusLineJsonFilePath };
|
|
92518
|
+
}
|
|
92519
|
+
function deleteFileIfExists(filePath) {
|
|
92520
|
+
return promise2(async () => {
|
|
92521
|
+
try {
|
|
92522
|
+
await fs15.unlink(filePath);
|
|
92523
|
+
return { action: "deleted", file: filePath };
|
|
92524
|
+
} catch (e) {
|
|
92525
|
+
if (e?.code === "ENOENT")
|
|
92526
|
+
return { action: "skipped", file: filePath };
|
|
92527
|
+
return { action: "failed", file: filePath, error: String(e?.message || e) };
|
|
91795
92528
|
}
|
|
91796
|
-
|
|
91797
|
-
|
|
91798
|
-
|
|
91799
|
-
|
|
91800
|
-
|
|
91801
|
-
|
|
91802
|
-
|
|
91803
|
-
|
|
91804
|
-
|
|
91805
|
-
|
|
91806
|
-
|
|
91807
|
-
}
|
|
91808
|
-
|
|
91809
|
-
|
|
91810
|
-
|
|
91811
|
-
|
|
91812
|
-
|
|
91813
|
-
|
|
91814
|
-
|
|
91815
|
-
|
|
91816
|
-
|
|
91817
|
-
|
|
92529
|
+
});
|
|
92530
|
+
}
|
|
92531
|
+
function cleanupStatuslineArtifacts(paths) {
|
|
92532
|
+
return gen2(function* () {
|
|
92533
|
+
const statusLineFile = yield* StatusLineFile;
|
|
92534
|
+
const wsBridgeStateFile = yield* deleteFileIfExists(paths.wsBridgeStateFilePath);
|
|
92535
|
+
const cleared = yield* statusLineFile.write({ text: "", textFilePath: paths.statusLineFilePath, debug: false }).pipe(either3);
|
|
92536
|
+
const statusLineFileOutcome = cleared._tag === "Right" ? cleared.right.wrote ? { action: "cleared", file: cleared.right.textFilePath } : { action: "skipped", file: cleared.right.textFilePath } : {
|
|
92537
|
+
action: "failed",
|
|
92538
|
+
file: paths.statusLineFilePath,
|
|
92539
|
+
error: String(cleared.left?.message || cleared.left)
|
|
92540
|
+
};
|
|
92541
|
+
const statusLineJsonFile = yield* deleteFileIfExists(paths.statusLineJsonFilePath);
|
|
92542
|
+
return { wsBridgeStateFile, statusLineFile: statusLineFileOutcome, statusLineJsonFile };
|
|
92543
|
+
});
|
|
92544
|
+
}
|
|
92545
|
+
|
|
92546
|
+
// src/lib/doctor/fixes.ts
|
|
92547
|
+
function applyDoctorFixes() {
|
|
92548
|
+
return gen2(function* () {
|
|
92549
|
+
const cfg = yield* AppConfig;
|
|
92550
|
+
const daemonFiles = yield* DaemonFiles;
|
|
92551
|
+
const apiFiles = yield* ApiDaemonFiles;
|
|
92552
|
+
const pluginFiles = yield* PluginServerFiles;
|
|
92553
|
+
const supervisorState = yield* SupervisorState;
|
|
92554
|
+
const proc = yield* Process;
|
|
92555
|
+
const userConfig = yield* UserConfigFile;
|
|
92556
|
+
let changed = false;
|
|
92557
|
+
const fixes = [];
|
|
92558
|
+
const cleaned = [];
|
|
92559
|
+
const cleanupFailures = [];
|
|
92560
|
+
const daemonPidFile = daemonFiles.defaultPidFile();
|
|
92561
|
+
const daemonPidInfo = yield* daemonFiles.readPidFile(daemonPidFile).pipe(orElseSucceed2(() => {
|
|
92562
|
+
return;
|
|
92563
|
+
}));
|
|
92564
|
+
if (daemonPidInfo?.pid && !(yield* isTrustedPidRecord(daemonPidInfo))) {
|
|
92565
|
+
const daemonStateFile = resolveManagedStateFile({
|
|
92566
|
+
pidFilePath: daemonPidFile,
|
|
92567
|
+
defaultStateFilePath: supervisorState.defaultStateFile(),
|
|
92568
|
+
candidate: daemonPidInfo.state_file
|
|
92569
|
+
});
|
|
92570
|
+
const result = yield* gen2(function* () {
|
|
92571
|
+
yield* daemonFiles.deletePidFile(daemonPidFile);
|
|
92572
|
+
yield* supervisorState.deleteStateFile(daemonStateFile);
|
|
92573
|
+
return yield* cleanupStatuslineArtifacts(resolveStatuslineArtifactPaths({ cfg, pidInfo: daemonPidInfo }));
|
|
92574
|
+
}).pipe(either3);
|
|
92575
|
+
if (result._tag === "Right") {
|
|
92576
|
+
cleaned.push({ service: "daemon", pidFile: daemonPidFile, stateFile: daemonStateFile, pid: daemonPidInfo.pid });
|
|
92577
|
+
changed = true;
|
|
92578
|
+
} else {
|
|
92579
|
+
cleanupFailures.push({
|
|
92580
|
+
service: "daemon",
|
|
92581
|
+
pidFile: daemonPidFile,
|
|
92582
|
+
stateFile: daemonStateFile,
|
|
92583
|
+
pid: daemonPidInfo.pid,
|
|
92584
|
+
error: result.left.message
|
|
92585
|
+
});
|
|
91818
92586
|
}
|
|
91819
|
-
|
|
91820
|
-
|
|
91821
|
-
|
|
92587
|
+
}
|
|
92588
|
+
const apiPidFile = apiFiles.defaultPidFile();
|
|
92589
|
+
const apiPidInfo = yield* apiFiles.readPidFile(apiPidFile).pipe(orElseSucceed2(() => {
|
|
92590
|
+
return;
|
|
92591
|
+
}));
|
|
92592
|
+
if (apiPidInfo?.pid && !(yield* isTrustedPidRecord(apiPidInfo))) {
|
|
92593
|
+
const apiStateFile = resolveManagedStateFile({
|
|
92594
|
+
pidFilePath: apiPidFile,
|
|
92595
|
+
defaultStateFilePath: apiFiles.defaultStateFile(),
|
|
92596
|
+
candidate: apiPidInfo.state_file
|
|
92597
|
+
});
|
|
92598
|
+
const result = yield* gen2(function* () {
|
|
92599
|
+
yield* apiFiles.deletePidFile(apiPidFile);
|
|
92600
|
+
yield* apiFiles.deleteStateFile(apiStateFile);
|
|
92601
|
+
}).pipe(either3);
|
|
92602
|
+
if (result._tag === "Right") {
|
|
92603
|
+
cleaned.push({ service: "api", pidFile: apiPidFile, stateFile: apiStateFile, pid: apiPidInfo.pid });
|
|
92604
|
+
changed = true;
|
|
92605
|
+
} else {
|
|
92606
|
+
cleanupFailures.push({
|
|
92607
|
+
service: "api",
|
|
92608
|
+
pidFile: apiPidFile,
|
|
92609
|
+
stateFile: apiStateFile,
|
|
92610
|
+
pid: apiPidInfo.pid,
|
|
92611
|
+
error: result.left.message
|
|
92612
|
+
});
|
|
91822
92613
|
}
|
|
91823
|
-
|
|
91824
|
-
|
|
91825
|
-
|
|
92614
|
+
}
|
|
92615
|
+
const pluginPidFile = pluginFiles.defaultPidFile();
|
|
92616
|
+
const pluginPidInfo = yield* pluginFiles.readPidFile(pluginPidFile).pipe(orElseSucceed2(() => {
|
|
92617
|
+
return;
|
|
92618
|
+
}));
|
|
92619
|
+
if (pluginPidInfo?.pid && !(yield* isTrustedPidRecord(pluginPidInfo))) {
|
|
92620
|
+
const pluginStateFile = resolveManagedStateFile({
|
|
92621
|
+
pidFilePath: pluginPidFile,
|
|
92622
|
+
defaultStateFilePath: pluginFiles.defaultStateFile(),
|
|
92623
|
+
candidate: pluginPidInfo.state_file
|
|
92624
|
+
});
|
|
92625
|
+
const result = yield* gen2(function* () {
|
|
92626
|
+
yield* pluginFiles.deletePidFile(pluginPidFile);
|
|
92627
|
+
yield* pluginFiles.deleteStateFile(pluginStateFile);
|
|
92628
|
+
}).pipe(either3);
|
|
92629
|
+
if (result._tag === "Right") {
|
|
92630
|
+
cleaned.push({ service: "plugin", pidFile: pluginPidFile, stateFile: pluginStateFile, pid: pluginPidInfo.pid });
|
|
92631
|
+
changed = true;
|
|
92632
|
+
} else {
|
|
92633
|
+
cleanupFailures.push({
|
|
92634
|
+
service: "plugin",
|
|
92635
|
+
pidFile: pluginPidFile,
|
|
92636
|
+
stateFile: pluginStateFile,
|
|
92637
|
+
pid: pluginPidInfo.pid,
|
|
92638
|
+
error: result.left.message
|
|
92639
|
+
});
|
|
91826
92640
|
}
|
|
91827
|
-
|
|
92641
|
+
}
|
|
92642
|
+
fixes.push({
|
|
92643
|
+
id: "runtime.cleanup_stale_artifacts",
|
|
92644
|
+
ok: cleanupFailures.length === 0,
|
|
92645
|
+
changed: cleaned.length > 0,
|
|
92646
|
+
summary: cleaned.length === 0 && cleanupFailures.length === 0 ? "No stale runtime artifacts needed cleanup" : cleanupFailures.length === 0 ? `Cleaned ${cleaned.length} stale runtime artifact set(s)` : `Cleaned ${cleaned.length} stale runtime artifact set(s); ${cleanupFailures.length} cleanup failure(s) need manual follow-up`,
|
|
92647
|
+
details: {
|
|
92648
|
+
cleaned,
|
|
92649
|
+
failed: cleanupFailures
|
|
92650
|
+
}
|
|
92651
|
+
});
|
|
92652
|
+
const configRepair = yield* userConfig.repair().pipe(either3);
|
|
92653
|
+
if (configRepair._tag === "Right") {
|
|
92654
|
+
if (configRepair.right.changed && configRepair.right.before.valid)
|
|
92655
|
+
changed = true;
|
|
92656
|
+
fixes.push({
|
|
92657
|
+
id: "config.rewrite_canonical_user_config",
|
|
92658
|
+
ok: configRepair.right.before.valid,
|
|
92659
|
+
changed: configRepair.right.before.valid ? configRepair.right.changed : false,
|
|
92660
|
+
summary: !configRepair.right.before.valid ? "Skipped config rewrite because the current config is invalid or conflicting" : configRepair.right.changed ? "Rewrote user config into canonical form" : "User config already canonical",
|
|
92661
|
+
details: {
|
|
92662
|
+
config_file: configRepair.right.configFile,
|
|
92663
|
+
before: configRepair.right.before,
|
|
92664
|
+
after: configRepair.right.after
|
|
92665
|
+
}
|
|
92666
|
+
});
|
|
92667
|
+
} else {
|
|
92668
|
+
fixes.push({
|
|
92669
|
+
id: "config.rewrite_canonical_user_config",
|
|
92670
|
+
ok: false,
|
|
92671
|
+
changed: false,
|
|
92672
|
+
summary: "Failed to rewrite user config",
|
|
92673
|
+
details: { error: configRepair.left.message }
|
|
92674
|
+
});
|
|
92675
|
+
}
|
|
92676
|
+
const restartSummary = {
|
|
92677
|
+
attempted: [],
|
|
92678
|
+
restarted: [],
|
|
92679
|
+
skipped: ["safe_restart_disabled"],
|
|
92680
|
+
failed: []
|
|
91828
92681
|
};
|
|
91829
|
-
|
|
91830
|
-
|
|
91831
|
-
|
|
92682
|
+
fixes.push({
|
|
92683
|
+
id: "runtime.restart_mismatched_services",
|
|
92684
|
+
ok: true,
|
|
92685
|
+
changed: false,
|
|
92686
|
+
summary: "Skipped automatic runtime restart inside doctor --fix to preserve the safe repair boundary",
|
|
92687
|
+
details: restartSummary
|
|
92688
|
+
});
|
|
92689
|
+
return { fixes, changed, restartSummary };
|
|
92690
|
+
});
|
|
92691
|
+
}
|
|
92692
|
+
|
|
92693
|
+
// src/lib/doctor/checks.ts
|
|
92694
|
+
import path26 from "node:path";
|
|
92695
|
+
|
|
92696
|
+
// src/lib/builtin-scenarios/index.ts
|
|
92697
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
92698
|
+
import path22 from "node:path";
|
|
92699
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
92700
|
+
var MODULE_DIR = path22.dirname(fileURLToPath3(import.meta.url));
|
|
92701
|
+
function locateBuiltinSourceRoot() {
|
|
92702
|
+
const packageRootCandidates = [
|
|
92703
|
+
path22.resolve(MODULE_DIR, "../../../"),
|
|
92704
|
+
path22.resolve(MODULE_DIR, "..")
|
|
92705
|
+
];
|
|
92706
|
+
for (const packageRoot of packageRootCandidates) {
|
|
92707
|
+
const builtinSourceRoot = path22.join(packageRoot, "builtin-scenarios");
|
|
92708
|
+
if (existsSync2(path22.join(builtinSourceRoot, "catalog.json"))) {
|
|
92709
|
+
return { packageRoot, builtinSourceRoot };
|
|
92710
|
+
}
|
|
92711
|
+
}
|
|
92712
|
+
throw new Error(`Unable to locate builtin-scenarios catalog from ${MODULE_DIR}`);
|
|
92713
|
+
}
|
|
92714
|
+
var { packageRoot: PACKAGE_ROOT, builtinSourceRoot: BUILTIN_SOURCE_ROOT } = locateBuiltinSourceRoot();
|
|
92715
|
+
var REPO_ROOT = path22.resolve(PACKAGE_ROOT, "../..");
|
|
92716
|
+
var BUILTIN_CATALOG_PATH = path22.join(BUILTIN_SOURCE_ROOT, "catalog.json");
|
|
92717
|
+
var BUILTIN_SOURCE_PREFIX = "packages/agent-remnote/builtin-scenarios/";
|
|
92718
|
+
function readJsonFile(filePath) {
|
|
92719
|
+
return JSON.parse(readFileSync2(filePath, "utf8"));
|
|
92720
|
+
}
|
|
92721
|
+
function resolveRepoPath(relPath) {
|
|
92722
|
+
return path22.resolve(REPO_ROOT, relPath);
|
|
92723
|
+
}
|
|
92724
|
+
function resolveBuiltinPackagePath(relPath) {
|
|
92725
|
+
const normalized = relPath.replaceAll("\\", "/");
|
|
92726
|
+
if (normalized.startsWith(BUILTIN_SOURCE_PREFIX)) {
|
|
92727
|
+
return path22.resolve(BUILTIN_SOURCE_ROOT, normalized.slice(BUILTIN_SOURCE_PREFIX.length));
|
|
92728
|
+
}
|
|
92729
|
+
return resolveRepoPath(relPath);
|
|
92730
|
+
}
|
|
92731
|
+
var builtinScenarioCatalog = readJsonFile(BUILTIN_CATALOG_PATH);
|
|
92732
|
+
var builtinScenarioPackageCache = new Map;
|
|
92733
|
+
var builtinScenarioPackagesTarget = {};
|
|
92734
|
+
function loadBuiltinScenarioPackage(entry) {
|
|
92735
|
+
const cached4 = builtinScenarioPackageCache.get(entry.package_id);
|
|
92736
|
+
if (cached4)
|
|
92737
|
+
return cached4;
|
|
92738
|
+
const loaded = readJsonFile(resolveBuiltinPackagePath(entry.package_path));
|
|
92739
|
+
builtinScenarioPackageCache.set(entry.package_id, loaded);
|
|
92740
|
+
return loaded;
|
|
92741
|
+
}
|
|
92742
|
+
for (const entry of builtinScenarioCatalog) {
|
|
92743
|
+
Object.defineProperty(builtinScenarioPackagesTarget, entry.package_id, {
|
|
92744
|
+
enumerable: true,
|
|
92745
|
+
configurable: false,
|
|
92746
|
+
get: () => loadBuiltinScenarioPackage(entry)
|
|
92747
|
+
});
|
|
92748
|
+
}
|
|
92749
|
+
var builtinScenarioPackages = Object.freeze(builtinScenarioPackagesTarget);
|
|
92750
|
+
function getBuiltinScenarioPackage(id2) {
|
|
92751
|
+
const entry = builtinScenarioCatalog.find((item) => item.package_id === id2);
|
|
92752
|
+
if (!entry) {
|
|
92753
|
+
throw new Error(`Unknown builtin scenario package: ${id2}`);
|
|
92754
|
+
}
|
|
92755
|
+
return loadBuiltinScenarioPackage(entry);
|
|
92756
|
+
}
|
|
92757
|
+
function getBuiltinScenarioPackageSourcePath(id2) {
|
|
92758
|
+
const entry = builtinScenarioCatalog.find((item) => item.package_id === id2);
|
|
92759
|
+
if (!entry) {
|
|
92760
|
+
throw new Error(`Unknown builtin scenario source: ${id2}`);
|
|
92761
|
+
}
|
|
92762
|
+
return resolveBuiltinPackagePath(entry.package_path);
|
|
92763
|
+
}
|
|
92764
|
+
|
|
92765
|
+
// src/lib/pluginBuildInfo.ts
|
|
92766
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
92767
|
+
import path24 from "node:path";
|
|
92768
|
+
|
|
92769
|
+
// src/lib/pluginArtifacts.ts
|
|
92770
|
+
import { existsSync as existsSync3, statSync } from "node:fs";
|
|
92771
|
+
import path23 from "node:path";
|
|
92772
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
92773
|
+
function currentDir(moduleUrl) {
|
|
92774
|
+
return path23.dirname(fileURLToPath4(moduleUrl));
|
|
92775
|
+
}
|
|
92776
|
+
function isDirectory(targetPath) {
|
|
92777
|
+
try {
|
|
92778
|
+
return statSync(targetPath).isDirectory();
|
|
92779
|
+
} catch {
|
|
92780
|
+
return false;
|
|
92781
|
+
}
|
|
92782
|
+
}
|
|
92783
|
+
function isFile(targetPath) {
|
|
92784
|
+
try {
|
|
92785
|
+
return statSync(targetPath).isFile();
|
|
92786
|
+
} catch {
|
|
92787
|
+
return false;
|
|
92788
|
+
}
|
|
92789
|
+
}
|
|
92790
|
+
function distCandidates(moduleUrl) {
|
|
92791
|
+
const dir2 = currentDir(moduleUrl);
|
|
92792
|
+
return [
|
|
92793
|
+
path23.resolve(dir2, "../../plugin-artifacts/dist"),
|
|
92794
|
+
path23.resolve(dir2, "../plugin-artifacts/dist"),
|
|
92795
|
+
path23.resolve(dir2, "../../../plugin/dist"),
|
|
92796
|
+
path23.resolve(dir2, "../../plugin/dist")
|
|
92797
|
+
];
|
|
92798
|
+
}
|
|
92799
|
+
function zipCandidates(moduleUrl) {
|
|
92800
|
+
const dir2 = currentDir(moduleUrl);
|
|
92801
|
+
return [
|
|
92802
|
+
path23.resolve(dir2, "../../plugin-artifacts/PluginZip.zip"),
|
|
92803
|
+
path23.resolve(dir2, "../plugin-artifacts/PluginZip.zip"),
|
|
92804
|
+
path23.resolve(dir2, "../../../plugin/PluginZip.zip"),
|
|
92805
|
+
path23.resolve(dir2, "../../plugin/PluginZip.zip")
|
|
92806
|
+
];
|
|
92807
|
+
}
|
|
92808
|
+
function validateDistPath(targetPath) {
|
|
92809
|
+
return isDirectory(targetPath) && existsSync3(path23.join(targetPath, "manifest.json"));
|
|
92810
|
+
}
|
|
92811
|
+
function hasBuildInfo(targetPath) {
|
|
92812
|
+
return isFile(path23.join(targetPath, "build-info.json"));
|
|
92813
|
+
}
|
|
92814
|
+
function resolvePluginDistPath(moduleUrl = import.meta.url) {
|
|
92815
|
+
for (const candidate of distCandidates(moduleUrl)) {
|
|
92816
|
+
if (validateDistPath(candidate) && hasBuildInfo(candidate))
|
|
92817
|
+
return candidate;
|
|
92818
|
+
}
|
|
92819
|
+
for (const candidate of distCandidates(moduleUrl)) {
|
|
92820
|
+
if (validateDistPath(candidate))
|
|
92821
|
+
return candidate;
|
|
92822
|
+
}
|
|
92823
|
+
throw new CliError({
|
|
92824
|
+
code: "DEPENDENCY_MISSING",
|
|
92825
|
+
message: "Plugin build artifacts are unavailable",
|
|
92826
|
+
exitCode: 1,
|
|
92827
|
+
details: { candidates: distCandidates(moduleUrl) },
|
|
92828
|
+
hint: [
|
|
92829
|
+
"Run npm run build --workspace @remnote/plugin in the repository checkout",
|
|
92830
|
+
"Or install a packaged agent-remnote release that includes plugin artifacts"
|
|
92831
|
+
]
|
|
92832
|
+
});
|
|
92833
|
+
}
|
|
92834
|
+
function resolvePluginZipPath(moduleUrl = import.meta.url) {
|
|
92835
|
+
for (const candidate of zipCandidates(moduleUrl)) {
|
|
92836
|
+
if (isFile(candidate))
|
|
92837
|
+
return candidate;
|
|
92838
|
+
}
|
|
92839
|
+
throw new CliError({
|
|
92840
|
+
code: "DEPENDENCY_MISSING",
|
|
92841
|
+
message: "Plugin zip artifact is unavailable",
|
|
92842
|
+
exitCode: 1,
|
|
92843
|
+
details: { candidates: zipCandidates(moduleUrl) },
|
|
92844
|
+
hint: [
|
|
92845
|
+
"Run npm run build --workspace @remnote/plugin in the repository checkout",
|
|
92846
|
+
"Or install a packaged agent-remnote release that includes plugin artifacts"
|
|
92847
|
+
]
|
|
92848
|
+
});
|
|
92849
|
+
}
|
|
92850
|
+
|
|
92851
|
+
// src/lib/pluginBuildInfo.ts
|
|
92852
|
+
function readPluginDistBuildInfo(distPath) {
|
|
92853
|
+
const normalized = typeof distPath === "string" ? distPath.trim() : "";
|
|
92854
|
+
if (!normalized)
|
|
92855
|
+
return null;
|
|
92856
|
+
const target2 = path24.join(normalized, "build-info.json");
|
|
92857
|
+
try {
|
|
92858
|
+
const raw4 = readFileSync3(target2, "utf8");
|
|
92859
|
+
const parsed = JSON.parse(raw4);
|
|
92860
|
+
if (typeof parsed?.name === "string" && typeof parsed?.version === "string" && typeof parsed?.build_id === "string" && typeof parsed?.built_at === "number" && typeof parsed?.source_stamp === "number") {
|
|
92861
|
+
return {
|
|
92862
|
+
name: parsed.name,
|
|
92863
|
+
version: parsed.version,
|
|
92864
|
+
build_id: parsed.build_id,
|
|
92865
|
+
built_at: parsed.built_at,
|
|
92866
|
+
source_stamp: parsed.source_stamp,
|
|
92867
|
+
mode: parsed.mode === "src" || parsed.mode === "dist" || parsed.mode === "unknown" ? parsed.mode : "dist"
|
|
92868
|
+
};
|
|
92869
|
+
}
|
|
92870
|
+
} catch {}
|
|
92871
|
+
return null;
|
|
92872
|
+
}
|
|
92873
|
+
function currentExpectedPluginBuildInfo() {
|
|
92874
|
+
try {
|
|
92875
|
+
const dist = resolvePluginDistPath();
|
|
92876
|
+
return readPluginDistBuildInfo(dist);
|
|
92877
|
+
} catch {
|
|
92878
|
+
return null;
|
|
92879
|
+
}
|
|
92880
|
+
}
|
|
92881
|
+
function pluginBuildWarnings(params3) {
|
|
92882
|
+
if (!params3.expected || !params3.live)
|
|
92883
|
+
return [];
|
|
92884
|
+
if (params3.expected.build_id === params3.live.build_id)
|
|
92885
|
+
return [];
|
|
92886
|
+
return [
|
|
92887
|
+
`plugin build mismatch: expected=${params3.expected.build_id} live=${params3.live.build_id}`
|
|
92888
|
+
];
|
|
92889
|
+
}
|
|
91832
92890
|
|
|
91833
92891
|
// src/lib/runtimeBuildInfo.ts
|
|
91834
92892
|
import { createHash as createHash3 } from "node:crypto";
|
|
91835
|
-
import { existsSync as
|
|
91836
|
-
import
|
|
91837
|
-
import { fileURLToPath as
|
|
92893
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync, statSync as statSync2 } from "node:fs";
|
|
92894
|
+
import path25 from "node:path";
|
|
92895
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
91838
92896
|
function packageInfo() {
|
|
91839
92897
|
try {
|
|
91840
|
-
const raw4 =
|
|
92898
|
+
const raw4 = readFileSync4(new URL("../../package.json", import.meta.url), "utf8");
|
|
91841
92899
|
const parsed = JSON.parse(raw4);
|
|
91842
92900
|
const name = typeof parsed?.name === "string" && parsed.name.trim() ? parsed.name.trim() : "agent-remnote";
|
|
91843
92901
|
const version = typeof parsed?.version === "string" && parsed.version.trim() ? parsed.version.trim() : "0.0.0";
|
|
@@ -91848,13 +92906,13 @@ function packageInfo() {
|
|
|
91848
92906
|
}
|
|
91849
92907
|
function fileMtimeMs(targetPath) {
|
|
91850
92908
|
try {
|
|
91851
|
-
return Math.floor(
|
|
92909
|
+
return Math.floor(statSync2(targetPath).mtimeMs);
|
|
91852
92910
|
} catch {
|
|
91853
92911
|
return 0;
|
|
91854
92912
|
}
|
|
91855
92913
|
}
|
|
91856
92914
|
function latestMtimeMs(dirPath) {
|
|
91857
|
-
if (!
|
|
92915
|
+
if (!existsSync4(dirPath))
|
|
91858
92916
|
return 0;
|
|
91859
92917
|
let max7 = 0;
|
|
91860
92918
|
const stack = [dirPath];
|
|
@@ -91867,10 +92925,10 @@ function latestMtimeMs(dirPath) {
|
|
|
91867
92925
|
continue;
|
|
91868
92926
|
}
|
|
91869
92927
|
for (const entry of entries2) {
|
|
91870
|
-
const full =
|
|
92928
|
+
const full = path25.join(current2, entry);
|
|
91871
92929
|
let st;
|
|
91872
92930
|
try {
|
|
91873
|
-
st =
|
|
92931
|
+
st = statSync2(full);
|
|
91874
92932
|
} catch {
|
|
91875
92933
|
continue;
|
|
91876
92934
|
}
|
|
@@ -91896,7 +92954,7 @@ function computeDefaultBuildInfo() {
|
|
|
91896
92954
|
const mode = detectMode();
|
|
91897
92955
|
const srcDir = new URL("../", import.meta.url);
|
|
91898
92956
|
const packageJson = new URL("../../package.json", import.meta.url);
|
|
91899
|
-
const sourceStamp = Math.max(latestMtimeMs(
|
|
92957
|
+
const sourceStamp = Math.max(latestMtimeMs(fileURLToPath5(srcDir)), fileMtimeMs(fileURLToPath5(packageJson)));
|
|
91900
92958
|
const buildIdInput = `${pkg.name}
|
|
91901
92959
|
${pkg.version}
|
|
91902
92960
|
${mode}
|
|
@@ -91945,7 +93003,147 @@ function runtimeVersionWarnings(params3) {
|
|
|
91945
93003
|
return warnings;
|
|
91946
93004
|
}
|
|
91947
93005
|
|
|
93006
|
+
// src/lib/doctor/checks.ts
|
|
93007
|
+
function collectDoctorChecks() {
|
|
93008
|
+
return gen2(function* () {
|
|
93009
|
+
const cfg = yield* AppConfig;
|
|
93010
|
+
const daemonFiles = yield* DaemonFiles;
|
|
93011
|
+
const apiFiles = yield* ApiDaemonFiles;
|
|
93012
|
+
const pluginFiles = yield* PluginServerFiles;
|
|
93013
|
+
const userConfig = yield* UserConfigFile;
|
|
93014
|
+
const fsAccess = yield* FsAccess;
|
|
93015
|
+
const staleArtifacts = [];
|
|
93016
|
+
const daemonPidFile = daemonFiles.defaultPidFile();
|
|
93017
|
+
const daemonPidInfo = yield* daemonFiles.readPidFile(daemonPidFile).pipe(orElseSucceed2(() => {
|
|
93018
|
+
return;
|
|
93019
|
+
}));
|
|
93020
|
+
if (daemonPidInfo?.pid && !(yield* isTrustedPidRecord(daemonPidInfo))) {
|
|
93021
|
+
staleArtifacts.push({
|
|
93022
|
+
service: "daemon",
|
|
93023
|
+
pidFile: daemonPidFile,
|
|
93024
|
+
stateFile: daemonPidInfo.state_file ?? path26.join(path26.dirname(daemonPidFile), "ws.state.json"),
|
|
93025
|
+
pid: daemonPidInfo.pid
|
|
93026
|
+
});
|
|
93027
|
+
}
|
|
93028
|
+
const apiPidFile = apiFiles.defaultPidFile();
|
|
93029
|
+
const apiPidInfo = yield* apiFiles.readPidFile(apiPidFile).pipe(orElseSucceed2(() => {
|
|
93030
|
+
return;
|
|
93031
|
+
}));
|
|
93032
|
+
if (apiPidInfo?.pid && !(yield* isTrustedPidRecord(apiPidInfo))) {
|
|
93033
|
+
staleArtifacts.push({
|
|
93034
|
+
service: "api",
|
|
93035
|
+
pidFile: apiPidFile,
|
|
93036
|
+
stateFile: apiPidInfo.state_file ?? apiFiles.defaultStateFile(),
|
|
93037
|
+
pid: apiPidInfo.pid
|
|
93038
|
+
});
|
|
93039
|
+
}
|
|
93040
|
+
const pluginPidFile = pluginFiles.defaultPidFile();
|
|
93041
|
+
const pluginPidInfo = yield* pluginFiles.readPidFile(pluginPidFile).pipe(orElseSucceed2(() => {
|
|
93042
|
+
return;
|
|
93043
|
+
}));
|
|
93044
|
+
if (pluginPidInfo?.pid && !(yield* isTrustedPidRecord(pluginPidInfo))) {
|
|
93045
|
+
staleArtifacts.push({
|
|
93046
|
+
service: "plugin",
|
|
93047
|
+
pidFile: pluginPidFile,
|
|
93048
|
+
stateFile: pluginPidInfo.state_file ?? pluginFiles.defaultStateFile(),
|
|
93049
|
+
pid: pluginPidInfo.pid
|
|
93050
|
+
});
|
|
93051
|
+
}
|
|
93052
|
+
const current2 = currentRuntimeBuildInfo();
|
|
93053
|
+
const expectedPlugin = currentExpectedPluginBuildInfo();
|
|
93054
|
+
const mismatches = [
|
|
93055
|
+
daemonPidInfo?.build?.build_id && daemonPidInfo.build.build_id !== current2.build_id ? { service: "daemon", live: daemonPidInfo.build.build_id } : null,
|
|
93056
|
+
apiPidInfo?.build?.build_id && apiPidInfo.build.build_id !== current2.build_id ? { service: "api", live: apiPidInfo.build.build_id } : null,
|
|
93057
|
+
pluginPidInfo?.build?.build_id && pluginPidInfo.build.build_id !== current2.build_id ? { service: "plugin", live: pluginPidInfo.build.build_id } : null,
|
|
93058
|
+
expectedPlugin && pluginPidInfo?.build?.build_id && pluginPidInfo.build.build_id !== expectedPlugin.build_id ? { service: "plugin-artifact", live: pluginPidInfo.build.build_id, expected: expectedPlugin.build_id } : null
|
|
93059
|
+
].filter(Boolean);
|
|
93060
|
+
const configPreview = yield* userConfig.previewRepair().pipe(either3);
|
|
93061
|
+
const configChanged = configPreview._tag === "Right" ? configPreview.right.changed : false;
|
|
93062
|
+
const configValid = configPreview._tag === "Right" ? configPreview.right.before.valid : false;
|
|
93063
|
+
const configRepairable = configPreview._tag === "Right" ? configPreview.right.before.valid && configPreview.right.changed : false;
|
|
93064
|
+
const configDetails = configPreview._tag === "Right" ? configPreview.right : { error: configPreview.left.message };
|
|
93065
|
+
const packageCheck = yield* sync3(() => {
|
|
93066
|
+
try {
|
|
93067
|
+
getBuiltinScenarioPackage("dn_recent_todos_to_today_move");
|
|
93068
|
+
getBuiltinScenarioPackage("dn_recent_todos_to_today_portal");
|
|
93069
|
+
return { ok: true, details: undefined };
|
|
93070
|
+
} catch (error4) {
|
|
93071
|
+
return { ok: false, details: { error: String(error4?.message || error4) } };
|
|
93072
|
+
}
|
|
93073
|
+
});
|
|
93074
|
+
const pluginArtifactsCheck = yield* sync3(() => {
|
|
93075
|
+
try {
|
|
93076
|
+
return { ok: true, details: { distPath: resolvePluginDistPath(), zipPath: resolvePluginZipPath() } };
|
|
93077
|
+
} catch (error4) {
|
|
93078
|
+
return { ok: false, details: { error: String(error4?.message || error4) } };
|
|
93079
|
+
}
|
|
93080
|
+
});
|
|
93081
|
+
const pidWritable = yield* fsAccess.canWritePath(daemonPidFile);
|
|
93082
|
+
const logWritable = yield* fsAccess.canWritePath(daemonFiles.defaultLogFile());
|
|
93083
|
+
const storeWritable = yield* fsAccess.checkWritableFile(cfg.storeDb);
|
|
93084
|
+
const pathOk = pidWritable && logWritable && storeWritable.ok;
|
|
93085
|
+
return [
|
|
93086
|
+
{
|
|
93087
|
+
id: "runtime.stale_pid_or_state",
|
|
93088
|
+
ok: staleArtifacts.length === 0,
|
|
93089
|
+
severity: staleArtifacts.length === 0 ? "info" : "warning",
|
|
93090
|
+
summary: staleArtifacts.length === 0 ? "No stale runtime pid/state artifacts" : `Found ${staleArtifacts.length} stale runtime artifact set(s)`,
|
|
93091
|
+
details: staleArtifacts,
|
|
93092
|
+
repairable: staleArtifacts.length > 0
|
|
93093
|
+
},
|
|
93094
|
+
{
|
|
93095
|
+
id: "runtime.version_mismatch",
|
|
93096
|
+
ok: mismatches.length === 0,
|
|
93097
|
+
severity: mismatches.length === 0 ? "info" : "warning",
|
|
93098
|
+
summary: mismatches.length === 0 ? "No runtime build mismatch detected" : `Found ${mismatches.length} runtime build mismatch(es)`,
|
|
93099
|
+
details: mismatches,
|
|
93100
|
+
repairable: mismatches.length > 0
|
|
93101
|
+
},
|
|
93102
|
+
{
|
|
93103
|
+
id: "config.migration_needed",
|
|
93104
|
+
ok: configValid && !configChanged,
|
|
93105
|
+
severity: !configValid ? "error" : configChanged ? "warning" : "info",
|
|
93106
|
+
summary: !configValid ? "User config is invalid or conflicting" : configChanged ? "User config can be canonicalized" : "User config already canonical",
|
|
93107
|
+
details: configDetails,
|
|
93108
|
+
repairable: configRepairable
|
|
93109
|
+
},
|
|
93110
|
+
{
|
|
93111
|
+
id: "package.builtin_scenarios_broken",
|
|
93112
|
+
ok: packageCheck.ok,
|
|
93113
|
+
severity: packageCheck.ok ? "info" : "error",
|
|
93114
|
+
summary: packageCheck.ok ? "Builtin scenarios are loadable" : "Builtin scenario package loading failed",
|
|
93115
|
+
details: packageCheck.details,
|
|
93116
|
+
repairable: !packageCheck.ok
|
|
93117
|
+
},
|
|
93118
|
+
{
|
|
93119
|
+
id: "package.plugin_artifacts_unavailable",
|
|
93120
|
+
ok: pluginArtifactsCheck.ok,
|
|
93121
|
+
severity: pluginArtifactsCheck.ok ? "info" : "error",
|
|
93122
|
+
summary: pluginArtifactsCheck.ok ? "Plugin artifacts are available" : "Plugin artifacts are unavailable",
|
|
93123
|
+
details: pluginArtifactsCheck.details,
|
|
93124
|
+
repairable: false
|
|
93125
|
+
},
|
|
93126
|
+
{
|
|
93127
|
+
id: "env.path_or_permission_problem",
|
|
93128
|
+
ok: pathOk,
|
|
93129
|
+
severity: pathOk ? "info" : "error",
|
|
93130
|
+
summary: pathOk ? "Required writable paths are available" : "One or more required paths are not writable",
|
|
93131
|
+
details: {
|
|
93132
|
+
daemon_pid_file: daemonPidFile,
|
|
93133
|
+
daemon_log_file: daemonFiles.defaultLogFile(),
|
|
93134
|
+
pid_writable: pidWritable,
|
|
93135
|
+
log_writable: logWritable,
|
|
93136
|
+
store_db: cfg.storeDb,
|
|
93137
|
+
store_writable: storeWritable
|
|
93138
|
+
},
|
|
93139
|
+
repairable: false
|
|
93140
|
+
}
|
|
93141
|
+
];
|
|
93142
|
+
});
|
|
93143
|
+
}
|
|
93144
|
+
|
|
91948
93145
|
// src/commands/ws/_shared.ts
|
|
93146
|
+
import path27 from "node:path";
|
|
91949
93147
|
var WS_HEALTH_TIMEOUT_MS = 2000;
|
|
91950
93148
|
var WS_START_WAIT_DEFAULT_MS = 15000;
|
|
91951
93149
|
var WS_STOP_WAIT_DEFAULT_MS = 5000;
|
|
@@ -92035,7 +93233,7 @@ function toInitialSupervisorState(now2) {
|
|
|
92035
93233
|
};
|
|
92036
93234
|
}
|
|
92037
93235
|
function defaultStateFilePathFromPidFile(pidFilePath) {
|
|
92038
|
-
return
|
|
93236
|
+
return path27.join(path27.dirname(pidFilePath), "ws.state.json");
|
|
92039
93237
|
}
|
|
92040
93238
|
function startWsSupervisor(params3) {
|
|
92041
93239
|
return gen2(function* () {
|
|
@@ -92054,6 +93252,7 @@ function startWsSupervisor(params3) {
|
|
|
92054
93252
|
yield* daemonFiles.deletePidFile(pidFilePath);
|
|
92055
93253
|
yield* supervisorState.deleteStateFile(stateFilePath);
|
|
92056
93254
|
} else {
|
|
93255
|
+
yield* requireTrustedPidRecord({ record: existingPidFile, pidFilePath });
|
|
92057
93256
|
return {
|
|
92058
93257
|
started: false,
|
|
92059
93258
|
pid: existingPidFile.pid,
|
|
@@ -92117,6 +93316,7 @@ function ensureWsSupervisor(params3) {
|
|
|
92117
93316
|
if (existingPidFile) {
|
|
92118
93317
|
const alive = yield* proc.isPidRunning(existingPidFile.pid);
|
|
92119
93318
|
if (alive) {
|
|
93319
|
+
yield* requireTrustedPidRecord({ record: existingPidFile, pidFilePath });
|
|
92120
93320
|
return {
|
|
92121
93321
|
started: false,
|
|
92122
93322
|
pid: existingPidFile.pid,
|
|
@@ -92136,75 +93336,99 @@ function ensureWsSupervisor(params3) {
|
|
|
92136
93336
|
}
|
|
92137
93337
|
|
|
92138
93338
|
// src/commands/doctor.ts
|
|
92139
|
-
var doctorCommand = exports_Command.make("doctor", {}, () => gen2(function* () {
|
|
93339
|
+
var doctorCommand = exports_Command.make("doctor", { fix: boolean8("fix") }, ({ fix }) => gen2(function* () {
|
|
92140
93340
|
const cfg = yield* AppConfig;
|
|
92141
93341
|
const queue = yield* Queue;
|
|
92142
93342
|
const remDb = yield* RemDb;
|
|
92143
93343
|
const ws = yield* WsClient;
|
|
92144
93344
|
const daemonFiles = yield* DaemonFiles;
|
|
92145
93345
|
const fsAccess = yield* FsAccess;
|
|
92146
|
-
|
|
92147
|
-
|
|
92148
|
-
|
|
92149
|
-
|
|
92150
|
-
|
|
92151
|
-
|
|
92152
|
-
|
|
92153
|
-
|
|
92154
|
-
|
|
92155
|
-
const db =
|
|
92156
|
-
|
|
92157
|
-
|
|
92158
|
-
|
|
92159
|
-
|
|
93346
|
+
yield* ApiDaemonFiles;
|
|
93347
|
+
yield* PluginServerFiles;
|
|
93348
|
+
yield* Process;
|
|
93349
|
+
yield* SupervisorState;
|
|
93350
|
+
yield* UserConfigFile;
|
|
93351
|
+
const collectSnapshot = () => gen2(function* () {
|
|
93352
|
+
const queueStats2 = yield* queue.stats({ dbPath: cfg.storeDb }).pipe(either3);
|
|
93353
|
+
const remnote = yield* remDb.withDb(cfg.remnoteDb, (db) => {
|
|
93354
|
+
db.prepare("SELECT 1 FROM quanta LIMIT 1").get();
|
|
93355
|
+
const hasSearchInfos = !!db.prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name='remsSearchInfos' LIMIT 1`).get();
|
|
93356
|
+
const hasContents = !!db.prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name='remsContents' LIMIT 1`).get();
|
|
93357
|
+
return { has_search_index: hasSearchInfos && hasContents };
|
|
93358
|
+
}).pipe(either3);
|
|
93359
|
+
const schema2 = yield* try_3({
|
|
93360
|
+
try: () => {
|
|
93361
|
+
const db = openStoreDb(cfg.storeDb);
|
|
93362
|
+
try {
|
|
93363
|
+
return readStoreSchemaStatus(db);
|
|
93364
|
+
} finally {
|
|
93365
|
+
db.close();
|
|
93366
|
+
}
|
|
93367
|
+
},
|
|
93368
|
+
catch: (error4) => new CliError({
|
|
93369
|
+
code: "DB_UNAVAILABLE",
|
|
93370
|
+
message: `Failed to read store schema: ${String(error4?.message || error4)}`,
|
|
93371
|
+
exitCode: 1
|
|
93372
|
+
})
|
|
93373
|
+
}).pipe(either3);
|
|
93374
|
+
const wsHealth = yield* ws.health({ url: cfg.wsUrl, timeoutMs: WS_HEALTH_TIMEOUT_MS }).pipe(either3);
|
|
93375
|
+
const wsClients = yield* ws.queryClients({ url: cfg.wsUrl, timeoutMs: WS_HEALTH_TIMEOUT_MS }).pipe(either3);
|
|
93376
|
+
const pidFilePath = daemonFiles.defaultPidFile();
|
|
93377
|
+
const logFilePath = daemonFiles.defaultLogFile();
|
|
93378
|
+
const pidWritable = yield* fsAccess.canWritePath(pidFilePath);
|
|
93379
|
+
const logWritable = yield* fsAccess.canWritePath(logFilePath);
|
|
93380
|
+
const storeDbWritable = yield* fsAccess.checkWritableFile(cfg.storeDb);
|
|
93381
|
+
return {
|
|
93382
|
+
queue: {
|
|
93383
|
+
ok: queueStats2._tag === "Right",
|
|
93384
|
+
db_path: cfg.storeDb,
|
|
93385
|
+
schema: schema2._tag === "Right" ? schema2.right : undefined,
|
|
93386
|
+
schema_error: schema2._tag === "Left" ? schema2.left.message : undefined,
|
|
93387
|
+
writable: storeDbWritable.ok,
|
|
93388
|
+
writable_reason: storeDbWritable.reason,
|
|
93389
|
+
stats: queueStats2._tag === "Right" ? queueStats2.right : undefined,
|
|
93390
|
+
error: queueStats2._tag === "Left" ? queueStats2.left.message : undefined
|
|
93391
|
+
},
|
|
93392
|
+
remnote_db: {
|
|
93393
|
+
ok: remnote._tag === "Right",
|
|
93394
|
+
db_path: remnote._tag === "Right" ? remnote.right.info.dbPath : cfg.remnoteDb,
|
|
93395
|
+
resolution: remnote._tag === "Right" ? remnote.right.info.source : undefined,
|
|
93396
|
+
has_search_index: remnote._tag === "Right" ? remnote.right.result.has_search_index : undefined,
|
|
93397
|
+
error: remnote._tag === "Left" ? remnote.left.message : undefined
|
|
93398
|
+
},
|
|
93399
|
+
ws: {
|
|
93400
|
+
ok: wsHealth._tag === "Right",
|
|
93401
|
+
url: cfg.wsUrl,
|
|
93402
|
+
rtt_ms: wsHealth._tag === "Right" ? wsHealth.right.rtt_ms : undefined,
|
|
93403
|
+
error: wsHealth._tag === "Left" ? wsHealth.left.message : undefined,
|
|
93404
|
+
clients: wsClients._tag === "Right" ? wsClients.right.clients : []
|
|
93405
|
+
},
|
|
93406
|
+
daemon_files: {
|
|
93407
|
+
pid_file: pidFilePath,
|
|
93408
|
+
log_file: logFilePath,
|
|
93409
|
+
pid_writable: pidWritable,
|
|
93410
|
+
log_writable: logWritable
|
|
92160
93411
|
}
|
|
92161
|
-
}
|
|
92162
|
-
|
|
92163
|
-
|
|
92164
|
-
|
|
92165
|
-
|
|
92166
|
-
|
|
92167
|
-
|
|
92168
|
-
const wsHealth = yield* ws.health({ url: cfg.wsUrl, timeoutMs: WS_HEALTH_TIMEOUT_MS }).pipe(either3);
|
|
92169
|
-
const wsClients = yield* ws.queryClients({ url: cfg.wsUrl, timeoutMs: WS_HEALTH_TIMEOUT_MS }).pipe(either3);
|
|
92170
|
-
const pidFilePath = daemonFiles.defaultPidFile();
|
|
92171
|
-
const logFilePath = daemonFiles.defaultLogFile();
|
|
92172
|
-
const pidWritable = yield* fsAccess.canWritePath(pidFilePath);
|
|
92173
|
-
const logWritable = yield* fsAccess.canWritePath(logFilePath);
|
|
92174
|
-
const storeDbWritable = yield* fsAccess.checkWritableFile(cfg.storeDb);
|
|
93412
|
+
};
|
|
93413
|
+
});
|
|
93414
|
+
const snapshotBefore = yield* collectSnapshot();
|
|
93415
|
+
const checksBefore = yield* collectDoctorChecks();
|
|
93416
|
+
const fixResult = fix ? yield* applyDoctorFixes() : { fixes: [], changed: false, restartSummary: { attempted: [], restarted: [], skipped: [], failed: [] } };
|
|
93417
|
+
const snapshotAfter = fix ? yield* collectSnapshot() : snapshotBefore;
|
|
93418
|
+
const checks = fix ? yield* collectDoctorChecks() : checksBefore;
|
|
92175
93419
|
const data = {
|
|
92176
|
-
queue:
|
|
92177
|
-
|
|
92178
|
-
|
|
92179
|
-
|
|
92180
|
-
|
|
92181
|
-
|
|
92182
|
-
|
|
92183
|
-
|
|
92184
|
-
|
|
92185
|
-
|
|
92186
|
-
|
|
92187
|
-
|
|
92188
|
-
db_path: remnote._tag === "Right" ? remnote.right.info.dbPath : cfg.remnoteDb,
|
|
92189
|
-
resolution: remnote._tag === "Right" ? remnote.right.info.source : undefined,
|
|
92190
|
-
has_search_index: remnote._tag === "Right" ? remnote.right.result.has_search_index : undefined,
|
|
92191
|
-
error: remnote._tag === "Left" ? remnote.left.message : undefined
|
|
92192
|
-
},
|
|
92193
|
-
ws: {
|
|
92194
|
-
ok: wsHealth._tag === "Right",
|
|
92195
|
-
url: cfg.wsUrl,
|
|
92196
|
-
rtt_ms: wsHealth._tag === "Right" ? wsHealth.right.rtt_ms : undefined,
|
|
92197
|
-
error: wsHealth._tag === "Left" ? wsHealth.left.message : undefined,
|
|
92198
|
-
clients: wsClients._tag === "Right" ? wsClients.right.clients : []
|
|
92199
|
-
},
|
|
92200
|
-
daemon_files: {
|
|
92201
|
-
pid_file: pidFilePath,
|
|
92202
|
-
log_file: logFilePath,
|
|
92203
|
-
pid_writable: pidWritable,
|
|
92204
|
-
log_writable: logWritable
|
|
92205
|
-
}
|
|
92206
|
-
};
|
|
92207
|
-
const overallOk = data.queue.ok && data.remnote_db.ok && data.ws.ok && data.daemon_files.pid_writable && data.daemon_files.log_writable;
|
|
93420
|
+
queue: snapshotAfter.queue,
|
|
93421
|
+
remnote_db: snapshotAfter.remnote_db,
|
|
93422
|
+
ws: snapshotAfter.ws,
|
|
93423
|
+
daemon_files: snapshotAfter.daemon_files,
|
|
93424
|
+
before: fix ? snapshotBefore : undefined,
|
|
93425
|
+
changed: fixResult.changed,
|
|
93426
|
+
checks_before: checksBefore,
|
|
93427
|
+
checks,
|
|
93428
|
+
fixes: fixResult.fixes,
|
|
93429
|
+
restart_summary: fixResult.restartSummary
|
|
93430
|
+
};
|
|
93431
|
+
const overallOk = data.queue.ok && data.remnote_db.ok && data.ws.ok && data.daemon_files.pid_writable && data.daemon_files.log_writable && checks.every((check2) => check2.ok);
|
|
92208
93432
|
const hints = [];
|
|
92209
93433
|
if (!data.ws.ok)
|
|
92210
93434
|
hints.push("Try: agent-remnote daemon ensure / agent-remnote daemon status");
|
|
@@ -92243,6 +93467,9 @@ var doctorCommand = exports_Command.make("doctor", {}, () => gen2(function* () {
|
|
|
92243
93467
|
`- pid_file: ${data.daemon_files.pid_file}`,
|
|
92244
93468
|
`- log_file_writable: ${data.daemon_files.log_writable}`,
|
|
92245
93469
|
`- log_file: ${data.daemon_files.log_file}`,
|
|
93470
|
+
`- changed: ${data.changed}`,
|
|
93471
|
+
`- checks_total: ${data.checks.length}`,
|
|
93472
|
+
`- fixes_total: ${data.fixes.length}`,
|
|
92246
93473
|
hints.length > 0 ? `
|
|
92247
93474
|
## Hint` : "",
|
|
92248
93475
|
...hints.map((h) => `- ${h}`)
|
|
@@ -92564,121 +93791,37 @@ var wsLogsCommand = exports_Command.make("logs", {
|
|
|
92564
93791
|
}).pipe(catchAll2(writeFailure)));
|
|
92565
93792
|
|
|
92566
93793
|
// src/commands/ws/restart.ts
|
|
92567
|
-
import
|
|
92568
|
-
|
|
92569
|
-
// src/lib/statuslineArtifacts.ts
|
|
92570
|
-
import { promises as fs13 } from "node:fs";
|
|
92571
|
-
|
|
92572
|
-
// src/services/StatusLineFile.ts
|
|
92573
|
-
import { promises as fs12 } from "node:fs";
|
|
92574
|
-
import path19 from "node:path";
|
|
92575
|
-
class StatusLineFile extends Tag2("StatusLineFile")() {
|
|
92576
|
-
}
|
|
92577
|
-
function defaultTextFile() {
|
|
92578
|
-
return path19.join(homeDir(), ".agent-remnote", "status-line.txt");
|
|
92579
|
-
}
|
|
92580
|
-
function defaultJsonFile() {
|
|
92581
|
-
return path19.join(homeDir(), ".agent-remnote", "status-line.json");
|
|
92582
|
-
}
|
|
92583
|
-
function ensureDir6(p3) {
|
|
92584
|
-
return fs12.mkdir(path19.dirname(p3), { recursive: true }).then(() => {
|
|
92585
|
-
return;
|
|
92586
|
-
});
|
|
92587
|
-
}
|
|
92588
|
-
async function readFileOrEmpty(filePath) {
|
|
92589
|
-
try {
|
|
92590
|
-
return await fs12.readFile(filePath, "utf8");
|
|
92591
|
-
} catch (e) {
|
|
92592
|
-
if (e?.code === "ENOENT")
|
|
92593
|
-
return "";
|
|
92594
|
-
throw e;
|
|
92595
|
-
}
|
|
92596
|
-
}
|
|
92597
|
-
async function writeTextAtomic(filePath, content) {
|
|
92598
|
-
await ensureDir6(filePath);
|
|
92599
|
-
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
92600
|
-
await fs12.writeFile(tmp, content, "utf8");
|
|
92601
|
-
await fs12.rename(tmp, filePath);
|
|
92602
|
-
}
|
|
92603
|
-
var StatusLineFileLive = succeed10(StatusLineFile, {
|
|
92604
|
-
defaultTextFile: () => defaultTextFile(),
|
|
92605
|
-
defaultJsonFile: () => defaultJsonFile(),
|
|
92606
|
-
write: ({ text: text15, textFilePath, debug: debug2, jsonFilePath, json: json4 }) => tryPromise2({
|
|
92607
|
-
try: async () => {
|
|
92608
|
-
const resolvedTextFile = resolveUserFilePath(textFilePath ?? defaultTextFile());
|
|
92609
|
-
const normalizedText = text15.trimEnd();
|
|
92610
|
-
const desired = normalizedText.length > 0 ? `${normalizedText}
|
|
92611
|
-
` : "";
|
|
92612
|
-
const existing = await readFileOrEmpty(resolvedTextFile);
|
|
92613
|
-
if (existing === desired)
|
|
92614
|
-
return { wrote: false, textFilePath: resolvedTextFile };
|
|
92615
|
-
await writeTextAtomic(resolvedTextFile, desired);
|
|
92616
|
-
if (debug2 === true) {
|
|
92617
|
-
const resolvedJsonFile = resolveUserFilePath(jsonFilePath ?? defaultJsonFile());
|
|
92618
|
-
const payload = json4 !== undefined ? json4 : { text: normalizedText };
|
|
92619
|
-
await writeTextAtomic(resolvedJsonFile, `${JSON.stringify(payload)}
|
|
92620
|
-
`);
|
|
92621
|
-
}
|
|
92622
|
-
return { wrote: true, textFilePath: resolvedTextFile };
|
|
92623
|
-
},
|
|
92624
|
-
catch: (error4) => {
|
|
92625
|
-
if (isCliError(error4))
|
|
92626
|
-
return error4;
|
|
92627
|
-
return new CliError({
|
|
92628
|
-
code: "INTERNAL",
|
|
92629
|
-
message: "Failed to write status line file",
|
|
92630
|
-
exitCode: 1,
|
|
92631
|
-
details: { error: String(error4?.message || error4) }
|
|
92632
|
-
});
|
|
92633
|
-
}
|
|
92634
|
-
})
|
|
92635
|
-
});
|
|
92636
|
-
|
|
92637
|
-
// src/lib/statuslineArtifacts.ts
|
|
92638
|
-
function normalizeOptionalPath(value8) {
|
|
92639
|
-
if (typeof value8 !== "string")
|
|
92640
|
-
return;
|
|
92641
|
-
const t = value8.trim();
|
|
92642
|
-
return t.length > 0 ? resolveUserFilePath(t) : undefined;
|
|
92643
|
-
}
|
|
92644
|
-
function resolveStatuslineArtifactPaths(params3) {
|
|
92645
|
-
const pidInfo = params3.pidInfo;
|
|
92646
|
-
const wsBridgeStateFilePath = normalizeOptionalPath(pidInfo?.ws_bridge_state_file) ?? params3.cfg.wsStateFile.path;
|
|
92647
|
-
const statusLineFilePath = normalizeOptionalPath(pidInfo?.status_line_file) ?? params3.cfg.statusLineFile;
|
|
92648
|
-
const statusLineJsonFilePath = normalizeOptionalPath(pidInfo?.status_line_json_file) ?? params3.cfg.statusLineJsonFile;
|
|
92649
|
-
return { wsBridgeStateFilePath, statusLineFilePath, statusLineJsonFilePath };
|
|
92650
|
-
}
|
|
92651
|
-
function deleteFileIfExists(filePath) {
|
|
92652
|
-
return promise2(async () => {
|
|
92653
|
-
try {
|
|
92654
|
-
await fs13.unlink(filePath);
|
|
92655
|
-
return { action: "deleted", file: filePath };
|
|
92656
|
-
} catch (e) {
|
|
92657
|
-
if (e?.code === "ENOENT")
|
|
92658
|
-
return { action: "skipped", file: filePath };
|
|
92659
|
-
return { action: "failed", file: filePath, error: String(e?.message || e) };
|
|
92660
|
-
}
|
|
92661
|
-
});
|
|
92662
|
-
}
|
|
92663
|
-
function cleanupStatuslineArtifacts(paths) {
|
|
92664
|
-
return gen2(function* () {
|
|
92665
|
-
const statusLineFile = yield* StatusLineFile;
|
|
92666
|
-
const wsBridgeStateFile = yield* deleteFileIfExists(paths.wsBridgeStateFilePath);
|
|
92667
|
-
const cleared = yield* statusLineFile.write({ text: "", textFilePath: paths.statusLineFilePath, debug: false }).pipe(either3);
|
|
92668
|
-
const statusLineFileOutcome = cleared._tag === "Right" ? cleared.right.wrote ? { action: "cleared", file: cleared.right.textFilePath } : { action: "skipped", file: cleared.right.textFilePath } : {
|
|
92669
|
-
action: "failed",
|
|
92670
|
-
file: paths.statusLineFilePath,
|
|
92671
|
-
error: String(cleared.left?.message || cleared.left)
|
|
92672
|
-
};
|
|
92673
|
-
const statusLineJsonFile = yield* deleteFileIfExists(paths.statusLineJsonFilePath);
|
|
92674
|
-
return { wsBridgeStateFile, statusLineFile: statusLineFileOutcome, statusLineJsonFile };
|
|
92675
|
-
});
|
|
92676
|
-
}
|
|
92677
|
-
|
|
92678
|
-
// src/commands/ws/restart.ts
|
|
93794
|
+
import path28 from "node:path";
|
|
92679
93795
|
function optionToUndefined3(opt) {
|
|
92680
93796
|
return isSome2(opt) ? opt.value : undefined;
|
|
92681
93797
|
}
|
|
93798
|
+
function resolveManagedStateFile2(params3) {
|
|
93799
|
+
const candidate = params3.candidate ? resolveUserFilePath(params3.candidate) : undefined;
|
|
93800
|
+
if (!candidate)
|
|
93801
|
+
return resolveUserFilePath(params3.defaultStateFilePath);
|
|
93802
|
+
if (candidate === resolveUserFilePath(params3.defaultStateFilePath))
|
|
93803
|
+
return candidate;
|
|
93804
|
+
return path28.dirname(candidate) === path28.dirname(params3.pidFilePath) ? candidate : resolveUserFilePath(params3.defaultStateFilePath);
|
|
93805
|
+
}
|
|
93806
|
+
function isWithinRoot(rootDir, targetPath) {
|
|
93807
|
+
const rel = path28.relative(rootDir, targetPath);
|
|
93808
|
+
return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
|
|
93809
|
+
}
|
|
93810
|
+
function sanitizePidInfoForArtifacts(params3) {
|
|
93811
|
+
const rootDir = path28.dirname(params3.pidFilePath);
|
|
93812
|
+
const normalizeMaybe = (value8) => {
|
|
93813
|
+
if (typeof value8 !== "string" || !value8.trim())
|
|
93814
|
+
return;
|
|
93815
|
+
const resolved = resolveUserFilePath(value8);
|
|
93816
|
+
return isWithinRoot(rootDir, resolved) ? resolved : undefined;
|
|
93817
|
+
};
|
|
93818
|
+
return {
|
|
93819
|
+
...params3.pidInfo,
|
|
93820
|
+
ws_bridge_state_file: normalizeMaybe(params3.pidInfo.ws_bridge_state_file),
|
|
93821
|
+
status_line_file: normalizeMaybe(params3.pidInfo.status_line_file),
|
|
93822
|
+
status_line_json_file: normalizeMaybe(params3.pidInfo.status_line_json_file)
|
|
93823
|
+
};
|
|
93824
|
+
}
|
|
92682
93825
|
var pidFile3 = text10("pid-file").pipe(optional6, map34(optionToUndefined3));
|
|
92683
93826
|
var logFile2 = text10("log-file").pipe(optional6, map34(optionToUndefined3));
|
|
92684
93827
|
var wsRestartCommand = exports_Command.make("restart", {
|
|
@@ -92694,7 +93837,11 @@ var wsRestartCommand = exports_Command.make("restart", {
|
|
|
92694
93837
|
const pidFilePath = resolveUserFilePath(pidFile4 ?? daemonFiles.defaultPidFile());
|
|
92695
93838
|
const existing = yield* daemonFiles.readPidFile(pidFilePath);
|
|
92696
93839
|
let stopResult = { stopped: true, pid_file: pidFilePath };
|
|
92697
|
-
const stateFilePath =
|
|
93840
|
+
const stateFilePath = resolveManagedStateFile2({
|
|
93841
|
+
pidFilePath,
|
|
93842
|
+
defaultStateFilePath: supervisorState.defaultStateFile(),
|
|
93843
|
+
candidate: existing?.state_file
|
|
93844
|
+
});
|
|
92698
93845
|
if (existing) {
|
|
92699
93846
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
92700
93847
|
if (!alive) {
|
|
@@ -92702,6 +93849,7 @@ var wsRestartCommand = exports_Command.make("restart", {
|
|
|
92702
93849
|
yield* supervisorState.deleteStateFile(stateFilePath);
|
|
92703
93850
|
stopResult = { stopped: true, stale: true, pid: existing.pid, pid_file: pidFilePath };
|
|
92704
93851
|
} else {
|
|
93852
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
92705
93853
|
yield* proc.kill(existing.pid, "SIGTERM");
|
|
92706
93854
|
const exited = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: WS_STOP_WAIT_DEFAULT_MS });
|
|
92707
93855
|
if (!exited) {
|
|
@@ -92729,7 +93877,10 @@ var wsRestartCommand = exports_Command.make("restart", {
|
|
|
92729
93877
|
stopResult = { stopped: true, pid: existing.pid, pid_file: pidFilePath };
|
|
92730
93878
|
}
|
|
92731
93879
|
}
|
|
92732
|
-
const cleanup = yield* cleanupStatuslineArtifacts(resolveStatuslineArtifactPaths({
|
|
93880
|
+
const cleanup = yield* cleanupStatuslineArtifacts(resolveStatuslineArtifactPaths({
|
|
93881
|
+
cfg,
|
|
93882
|
+
pidInfo: existing ? sanitizePidInfoForArtifacts({ pidFilePath, pidInfo: existing }) : undefined
|
|
93883
|
+
}));
|
|
92733
93884
|
yield* sync3(() => refreshTmuxStatusLine());
|
|
92734
93885
|
stopResult = { ...stopResult, cleanup };
|
|
92735
93886
|
const startResult = yield* startWsSupervisor({ waitMs: wait, pidFile: pidFile4, logFile: logFile3 });
|
|
@@ -92766,10 +93917,10 @@ function safeJsonParse2(text15) {
|
|
|
92766
93917
|
}
|
|
92767
93918
|
}
|
|
92768
93919
|
var WsBridgeServerLive = succeed10(WsBridgeServer, {
|
|
92769
|
-
listen: ({ port: port3, path:
|
|
93920
|
+
listen: ({ port: port3, path: path29, host }) => acquireRelease2(gen2(function* () {
|
|
92770
93921
|
const events = yield* unbounded5();
|
|
92771
93922
|
const sockets = new Map;
|
|
92772
|
-
const wss = new import_websocket_server.default({ port: port3, host, path:
|
|
93923
|
+
const wss = new import_websocket_server.default({ port: port3, host, path: path29 });
|
|
92773
93924
|
wss.on("connection", (ws, req) => {
|
|
92774
93925
|
const connId = randomUUID4();
|
|
92775
93926
|
const remoteAddr = safeStringHeader(req?.socket?.remoteAddress);
|
|
@@ -92803,7 +93954,7 @@ var WsBridgeServerLive = succeed10(WsBridgeServer, {
|
|
|
92803
93954
|
});
|
|
92804
93955
|
const handle = {
|
|
92805
93956
|
events,
|
|
92806
|
-
serverInfo: { port: port3, path:
|
|
93957
|
+
serverInfo: { port: port3, path: path29 },
|
|
92807
93958
|
sendText: (connId, text15) => sync3(() => {
|
|
92808
93959
|
const ws = sockets.get(connId);
|
|
92809
93960
|
if (!ws)
|
|
@@ -92865,23 +94016,23 @@ var WsBridgeServerLive = succeed10(WsBridgeServer, {
|
|
|
92865
94016
|
code: "WS_UNAVAILABLE",
|
|
92866
94017
|
message: "Failed to start ws bridge server",
|
|
92867
94018
|
exitCode: 1,
|
|
92868
|
-
details: { error: String(error4?.message || error4), port: port3, path:
|
|
94019
|
+
details: { error: String(error4?.message || error4), port: port3, path: path29, host }
|
|
92869
94020
|
}))))
|
|
92870
94021
|
});
|
|
92871
94022
|
|
|
92872
94023
|
// src/services/WsBridgeStateFile.ts
|
|
92873
|
-
import { promises as
|
|
92874
|
-
import
|
|
94024
|
+
import { promises as fs16 } from "node:fs";
|
|
94025
|
+
import path29 from "node:path";
|
|
92875
94026
|
class WsBridgeStateFile extends Tag2("WsBridgeStateFile")() {
|
|
92876
94027
|
}
|
|
92877
|
-
async function
|
|
92878
|
-
await
|
|
94028
|
+
async function ensureDir9(filePath) {
|
|
94029
|
+
await fs16.mkdir(path29.dirname(filePath), { recursive: true });
|
|
92879
94030
|
}
|
|
92880
94031
|
async function writeTextAtomic2(filePath, content) {
|
|
92881
|
-
await
|
|
94032
|
+
await ensureDir9(filePath);
|
|
92882
94033
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
92883
|
-
await
|
|
92884
|
-
await
|
|
94034
|
+
await fs16.writeFile(tmp, content, "utf8");
|
|
94035
|
+
await fs16.rename(tmp, filePath);
|
|
92885
94036
|
}
|
|
92886
94037
|
var WsBridgeStateFileLive = succeed10(WsBridgeStateFile, {
|
|
92887
94038
|
write: ({ filePath, json: json4 }) => tryPromise2({
|
|
@@ -92987,7 +94138,7 @@ var TmuxLive = scoped3(Tmux, gen2(function* () {
|
|
|
92987
94138
|
}));
|
|
92988
94139
|
|
|
92989
94140
|
// src/services/WsBridgeState.ts
|
|
92990
|
-
import { promises as
|
|
94141
|
+
import { promises as fs17 } from "node:fs";
|
|
92991
94142
|
class WsBridgeState extends Tag2("WsBridgeState")() {
|
|
92992
94143
|
}
|
|
92993
94144
|
function toNonNegativeInt3(value8) {
|
|
@@ -93013,7 +94164,7 @@ var WsBridgeStateLive = succeed10(WsBridgeState, {
|
|
|
93013
94164
|
return { connection: "off", selection: { kind: "none" } };
|
|
93014
94165
|
}
|
|
93015
94166
|
const raw4 = yield* tryPromise2({
|
|
93016
|
-
try: async () => await
|
|
94167
|
+
try: async () => await fs17.readFile(cfg.wsStateFile.path, "utf8"),
|
|
93017
94168
|
catch: (e) => {
|
|
93018
94169
|
if (e?.code === "ENOENT")
|
|
93019
94170
|
return null;
|
|
@@ -93427,18 +94578,18 @@ function parseWsUrl(url2) {
|
|
|
93427
94578
|
}
|
|
93428
94579
|
const port3 = u.port ? Number(u.port) : u.protocol === "wss:" ? 443 : 80;
|
|
93429
94580
|
const host = u.hostname && u.hostname.length > 0 ? u.hostname : "localhost";
|
|
93430
|
-
const
|
|
94581
|
+
const path30 = u.pathname && u.pathname.length > 0 ? u.pathname : "/ws";
|
|
93431
94582
|
if (!Number.isFinite(port3) || port3 <= 0) {
|
|
93432
94583
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl port: ${url2}`, exitCode: 2 });
|
|
93433
94584
|
}
|
|
93434
|
-
if (!
|
|
94585
|
+
if (!path30.startsWith("/")) {
|
|
93435
94586
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl path: ${url2}`, exitCode: 2 });
|
|
93436
94587
|
}
|
|
93437
|
-
return { host, port: port3, path:
|
|
94588
|
+
return { host, port: port3, path: path30 };
|
|
93438
94589
|
}
|
|
93439
94590
|
var wsServeCommand = exports_Command.make("serve", {}, () => gen2(function* () {
|
|
93440
94591
|
const cfg = yield* AppConfig;
|
|
93441
|
-
const { host, port: port3, path:
|
|
94592
|
+
const { host, port: port3, path: path30 } = yield* try_3({
|
|
93442
94593
|
try: () => parseWsUrl(cfg.wsUrl),
|
|
93443
94594
|
catch: (e) => isCliError(e) ? e : new CliError({
|
|
93444
94595
|
code: "INVALID_ARGS",
|
|
@@ -93447,7 +94598,7 @@ var wsServeCommand = exports_Command.make("serve", {}, () => gen2(function* () {
|
|
|
93447
94598
|
details: { ws_url: cfg.wsUrl, error: String(e?.message || e) }
|
|
93448
94599
|
})
|
|
93449
94600
|
});
|
|
93450
|
-
yield* runWsBridgeRuntime({ host, port: port3, path:
|
|
94601
|
+
yield* runWsBridgeRuntime({ host, port: port3, path: path30 });
|
|
93451
94602
|
}).pipe(catchAll2(writeFailure)));
|
|
93452
94603
|
|
|
93453
94604
|
// src/commands/ws/start.ts
|
|
@@ -93463,14 +94614,14 @@ function parseWsUrl2(url2) {
|
|
|
93463
94614
|
}
|
|
93464
94615
|
const port3 = u.port ? Number(u.port) : u.protocol === "wss:" ? 443 : 80;
|
|
93465
94616
|
const host = u.hostname && u.hostname.length > 0 ? u.hostname : "localhost";
|
|
93466
|
-
const
|
|
94617
|
+
const path30 = u.pathname && u.pathname.length > 0 ? u.pathname : "/ws";
|
|
93467
94618
|
if (!Number.isFinite(port3) || port3 <= 0) {
|
|
93468
94619
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl port: ${url2}`, exitCode: 2 });
|
|
93469
94620
|
}
|
|
93470
|
-
if (!
|
|
94621
|
+
if (!path30.startsWith("/")) {
|
|
93471
94622
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl path: ${url2}`, exitCode: 2 });
|
|
93472
94623
|
}
|
|
93473
|
-
return { host, port: port3, path:
|
|
94624
|
+
return { host, port: port3, path: path30 };
|
|
93474
94625
|
}
|
|
93475
94626
|
var pidFile4 = text10("pid-file").pipe(optional6, map34(optionToUndefined4));
|
|
93476
94627
|
var logFile3 = text10("log-file").pipe(optional6, map34(optionToUndefined4));
|
|
@@ -93482,7 +94633,7 @@ var wsStartCommand = exports_Command.make("start", {
|
|
|
93482
94633
|
}, ({ foreground, wait, pidFile: pidFile5, logFile: logFile4 }) => gen2(function* () {
|
|
93483
94634
|
const cfg = yield* AppConfig;
|
|
93484
94635
|
if (foreground) {
|
|
93485
|
-
const { host, port: port3, path:
|
|
94636
|
+
const { host, port: port3, path: path30 } = yield* try_3({
|
|
93486
94637
|
try: () => parseWsUrl2(cfg.wsUrl),
|
|
93487
94638
|
catch: (e) => isCliError(e) ? e : new CliError({
|
|
93488
94639
|
code: "INVALID_ARGS",
|
|
@@ -93491,7 +94642,7 @@ var wsStartCommand = exports_Command.make("start", {
|
|
|
93491
94642
|
details: { ws_url: cfg.wsUrl, error: String(e?.message || e) }
|
|
93492
94643
|
})
|
|
93493
94644
|
});
|
|
93494
|
-
yield* runWsBridgeRuntime({ host, port: port3, path:
|
|
94645
|
+
yield* runWsBridgeRuntime({ host, port: port3, path: path30 });
|
|
93495
94646
|
return;
|
|
93496
94647
|
}
|
|
93497
94648
|
const result = yield* startWsSupervisor({ waitMs: wait, pidFile: pidFile5, logFile: logFile4 });
|
|
@@ -93506,110 +94657,7 @@ var wsStartCommand = exports_Command.make("start", {
|
|
|
93506
94657
|
}).pipe(catchAll2(writeFailure)));
|
|
93507
94658
|
|
|
93508
94659
|
// src/commands/ws/status.ts
|
|
93509
|
-
import
|
|
93510
|
-
|
|
93511
|
-
// src/lib/pluginBuildInfo.ts
|
|
93512
|
-
import { readFileSync as readFileSync3 } from "node:fs";
|
|
93513
|
-
import path23 from "node:path";
|
|
93514
|
-
|
|
93515
|
-
// src/lib/pluginArtifacts.ts
|
|
93516
|
-
import { existsSync as existsSync3, statSync as statSync2 } from "node:fs";
|
|
93517
|
-
import path22 from "node:path";
|
|
93518
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
93519
|
-
function currentDir(moduleUrl) {
|
|
93520
|
-
return path22.dirname(fileURLToPath3(moduleUrl));
|
|
93521
|
-
}
|
|
93522
|
-
function isDirectory(targetPath) {
|
|
93523
|
-
try {
|
|
93524
|
-
return statSync2(targetPath).isDirectory();
|
|
93525
|
-
} catch {
|
|
93526
|
-
return false;
|
|
93527
|
-
}
|
|
93528
|
-
}
|
|
93529
|
-
function isFile(targetPath) {
|
|
93530
|
-
try {
|
|
93531
|
-
return statSync2(targetPath).isFile();
|
|
93532
|
-
} catch {
|
|
93533
|
-
return false;
|
|
93534
|
-
}
|
|
93535
|
-
}
|
|
93536
|
-
function distCandidates(moduleUrl) {
|
|
93537
|
-
const dir2 = currentDir(moduleUrl);
|
|
93538
|
-
return [
|
|
93539
|
-
path22.resolve(dir2, "../../plugin-artifacts/dist"),
|
|
93540
|
-
path22.resolve(dir2, "../plugin-artifacts/dist"),
|
|
93541
|
-
path22.resolve(dir2, "../../../plugin/dist"),
|
|
93542
|
-
path22.resolve(dir2, "../../plugin/dist")
|
|
93543
|
-
];
|
|
93544
|
-
}
|
|
93545
|
-
function validateDistPath(targetPath) {
|
|
93546
|
-
return isDirectory(targetPath) && existsSync3(path22.join(targetPath, "manifest.json"));
|
|
93547
|
-
}
|
|
93548
|
-
function hasBuildInfo(targetPath) {
|
|
93549
|
-
return isFile(path22.join(targetPath, "build-info.json"));
|
|
93550
|
-
}
|
|
93551
|
-
function resolvePluginDistPath(moduleUrl = import.meta.url) {
|
|
93552
|
-
for (const candidate of distCandidates(moduleUrl)) {
|
|
93553
|
-
if (validateDistPath(candidate) && hasBuildInfo(candidate))
|
|
93554
|
-
return candidate;
|
|
93555
|
-
}
|
|
93556
|
-
for (const candidate of distCandidates(moduleUrl)) {
|
|
93557
|
-
if (validateDistPath(candidate))
|
|
93558
|
-
return candidate;
|
|
93559
|
-
}
|
|
93560
|
-
throw new CliError({
|
|
93561
|
-
code: "DEPENDENCY_MISSING",
|
|
93562
|
-
message: "Plugin build artifacts are unavailable",
|
|
93563
|
-
exitCode: 1,
|
|
93564
|
-
details: { candidates: distCandidates(moduleUrl) },
|
|
93565
|
-
hint: [
|
|
93566
|
-
"Run npm run build --workspace @remnote/plugin in the repository checkout",
|
|
93567
|
-
"Or install a packaged agent-remnote release that includes plugin artifacts"
|
|
93568
|
-
]
|
|
93569
|
-
});
|
|
93570
|
-
}
|
|
93571
|
-
|
|
93572
|
-
// src/lib/pluginBuildInfo.ts
|
|
93573
|
-
function readPluginDistBuildInfo(distPath) {
|
|
93574
|
-
const normalized = typeof distPath === "string" ? distPath.trim() : "";
|
|
93575
|
-
if (!normalized)
|
|
93576
|
-
return null;
|
|
93577
|
-
const target2 = path23.join(normalized, "build-info.json");
|
|
93578
|
-
try {
|
|
93579
|
-
const raw4 = readFileSync3(target2, "utf8");
|
|
93580
|
-
const parsed = JSON.parse(raw4);
|
|
93581
|
-
if (typeof parsed?.name === "string" && typeof parsed?.version === "string" && typeof parsed?.build_id === "string" && typeof parsed?.built_at === "number" && typeof parsed?.source_stamp === "number") {
|
|
93582
|
-
return {
|
|
93583
|
-
name: parsed.name,
|
|
93584
|
-
version: parsed.version,
|
|
93585
|
-
build_id: parsed.build_id,
|
|
93586
|
-
built_at: parsed.built_at,
|
|
93587
|
-
source_stamp: parsed.source_stamp,
|
|
93588
|
-
mode: parsed.mode === "src" || parsed.mode === "dist" || parsed.mode === "unknown" ? parsed.mode : "dist"
|
|
93589
|
-
};
|
|
93590
|
-
}
|
|
93591
|
-
} catch {}
|
|
93592
|
-
return null;
|
|
93593
|
-
}
|
|
93594
|
-
function currentExpectedPluginBuildInfo() {
|
|
93595
|
-
try {
|
|
93596
|
-
const dist = resolvePluginDistPath();
|
|
93597
|
-
return readPluginDistBuildInfo(dist);
|
|
93598
|
-
} catch {
|
|
93599
|
-
return null;
|
|
93600
|
-
}
|
|
93601
|
-
}
|
|
93602
|
-
function pluginBuildWarnings(params3) {
|
|
93603
|
-
if (!params3.expected || !params3.live)
|
|
93604
|
-
return [];
|
|
93605
|
-
if (params3.expected.build_id === params3.live.build_id)
|
|
93606
|
-
return [];
|
|
93607
|
-
return [
|
|
93608
|
-
`plugin build mismatch: expected=${params3.expected.build_id} live=${params3.live.build_id}`
|
|
93609
|
-
];
|
|
93610
|
-
}
|
|
93611
|
-
|
|
93612
|
-
// src/commands/ws/status.ts
|
|
94660
|
+
import path30 from "node:path";
|
|
93613
94661
|
function optionToUndefined5(opt) {
|
|
93614
94662
|
return isSome2(opt) ? opt.value : undefined;
|
|
93615
94663
|
}
|
|
@@ -93628,14 +94676,14 @@ var wsStatusCommand = exports_Command.make("status", { pidFile: pidFile5 }, ({ p
|
|
|
93628
94676
|
if (!alive) {
|
|
93629
94677
|
const stalePidInfo = pidInfo;
|
|
93630
94678
|
yield* daemonFiles.deletePidFile(pidFilePath);
|
|
93631
|
-
const staleStateFilePath = resolveUserFilePath(pidInfo.state_file ??
|
|
94679
|
+
const staleStateFilePath = resolveUserFilePath(pidInfo.state_file ?? path30.join(path30.dirname(pidFilePath), "ws.state.json"));
|
|
93632
94680
|
yield* supervisorState.deleteStateFile(staleStateFilePath);
|
|
93633
94681
|
selfHealCleanup = yield* cleanupStatuslineArtifacts(resolveStatuslineArtifactPaths({ cfg, pidInfo: stalePidInfo }));
|
|
93634
94682
|
yield* sync3(() => refreshTmuxStatusLine());
|
|
93635
94683
|
pidInfo = undefined;
|
|
93636
94684
|
}
|
|
93637
94685
|
}
|
|
93638
|
-
const stateFilePath = resolveUserFilePath(pidInfo?.state_file ??
|
|
94686
|
+
const stateFilePath = resolveUserFilePath(pidInfo?.state_file ?? path30.join(path30.dirname(pidFilePath), "ws.state.json"));
|
|
93639
94687
|
const state = yield* supervisorState.readStateFile(stateFilePath);
|
|
93640
94688
|
const mode = pidInfo ? pidInfo.mode ?? "legacy" : "supervisor";
|
|
93641
94689
|
const supervisorPid = pidInfo?.pid;
|
|
@@ -93818,10 +94866,37 @@ var wsStatusLineCommand = exports_Command.make("status-line", { stateFile, stale
|
|
|
93818
94866
|
}).pipe(catchAll2(writeFailure)));
|
|
93819
94867
|
|
|
93820
94868
|
// src/commands/ws/stop.ts
|
|
93821
|
-
import
|
|
94869
|
+
import path31 from "node:path";
|
|
93822
94870
|
function optionToUndefined7(opt) {
|
|
93823
94871
|
return isSome2(opt) ? opt.value : undefined;
|
|
93824
94872
|
}
|
|
94873
|
+
function resolveManagedStateFile3(params3) {
|
|
94874
|
+
const candidate = params3.candidate ? resolveUserFilePath(params3.candidate) : undefined;
|
|
94875
|
+
if (!candidate)
|
|
94876
|
+
return resolveUserFilePath(params3.defaultStateFilePath);
|
|
94877
|
+
if (candidate === resolveUserFilePath(params3.defaultStateFilePath))
|
|
94878
|
+
return candidate;
|
|
94879
|
+
return path31.dirname(candidate) === path31.dirname(params3.pidFilePath) ? candidate : resolveUserFilePath(params3.defaultStateFilePath);
|
|
94880
|
+
}
|
|
94881
|
+
function isWithinRoot2(rootDir, targetPath) {
|
|
94882
|
+
const rel = path31.relative(rootDir, targetPath);
|
|
94883
|
+
return rel === "" || !rel.startsWith("..") && !path31.isAbsolute(rel);
|
|
94884
|
+
}
|
|
94885
|
+
function sanitizePidInfoForArtifacts2(params3) {
|
|
94886
|
+
const rootDir = path31.dirname(params3.pidFilePath);
|
|
94887
|
+
const normalizeMaybe = (value8) => {
|
|
94888
|
+
if (typeof value8 !== "string" || !value8.trim())
|
|
94889
|
+
return;
|
|
94890
|
+
const resolved = resolveUserFilePath(value8);
|
|
94891
|
+
return isWithinRoot2(rootDir, resolved) ? resolved : undefined;
|
|
94892
|
+
};
|
|
94893
|
+
return {
|
|
94894
|
+
...params3.pidInfo,
|
|
94895
|
+
ws_bridge_state_file: normalizeMaybe(params3.pidInfo.ws_bridge_state_file),
|
|
94896
|
+
status_line_file: normalizeMaybe(params3.pidInfo.status_line_file),
|
|
94897
|
+
status_line_json_file: normalizeMaybe(params3.pidInfo.status_line_json_file)
|
|
94898
|
+
};
|
|
94899
|
+
}
|
|
93825
94900
|
var pidFile6 = text10("pid-file").pipe(optional6, map34(optionToUndefined7));
|
|
93826
94901
|
var wsStopCommand = exports_Command.make("stop", { force: boolean8("force"), pidFile: pidFile6 }, ({ force, pidFile: pidFile7 }) => gen2(function* () {
|
|
93827
94902
|
const cfg = yield* AppConfig;
|
|
@@ -93831,7 +94906,10 @@ var wsStopCommand = exports_Command.make("stop", { force: boolean8("force"), pid
|
|
|
93831
94906
|
const pidFilePath = resolveUserFilePath(pidFile7 ?? daemonFiles.defaultPidFile());
|
|
93832
94907
|
const existing = yield* daemonFiles.readPidFile(pidFilePath);
|
|
93833
94908
|
const cleanupDisplayArtifacts = (pidInfo) => gen2(function* () {
|
|
93834
|
-
const paths = resolveStatuslineArtifactPaths({
|
|
94909
|
+
const paths = resolveStatuslineArtifactPaths({
|
|
94910
|
+
cfg,
|
|
94911
|
+
pidInfo: pidInfo ? sanitizePidInfoForArtifacts2({ pidFilePath, pidInfo }) : undefined
|
|
94912
|
+
});
|
|
93835
94913
|
const cleanup2 = yield* cleanupStatuslineArtifacts(paths);
|
|
93836
94914
|
yield* sync3(() => refreshTmuxStatusLine());
|
|
93837
94915
|
return cleanup2;
|
|
@@ -93846,7 +94924,11 @@ var wsStopCommand = exports_Command.make("stop", { force: boolean8("force"), pid
|
|
|
93846
94924
|
});
|
|
93847
94925
|
return;
|
|
93848
94926
|
}
|
|
93849
|
-
const stateFilePath =
|
|
94927
|
+
const stateFilePath = resolveManagedStateFile3({
|
|
94928
|
+
pidFilePath,
|
|
94929
|
+
defaultStateFilePath: supervisorState.defaultStateFile(),
|
|
94930
|
+
candidate: existing.state_file
|
|
94931
|
+
});
|
|
93850
94932
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
93851
94933
|
if (!alive) {
|
|
93852
94934
|
yield* daemonFiles.deletePidFile(pidFilePath);
|
|
@@ -93862,6 +94944,7 @@ var wsStopCommand = exports_Command.make("stop", { force: boolean8("force"), pid
|
|
|
93862
94944
|
});
|
|
93863
94945
|
return;
|
|
93864
94946
|
}
|
|
94947
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
93865
94948
|
yield* proc.kill(existing.pid, "SIGTERM");
|
|
93866
94949
|
const exited = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: WS_STOP_WAIT_DEFAULT_MS });
|
|
93867
94950
|
if (!exited) {
|
|
@@ -94040,8 +95123,8 @@ var ChildProcessLive = succeed10(ChildProcess2, {
|
|
|
94040
95123
|
});
|
|
94041
95124
|
|
|
94042
95125
|
// src/services/LogWriter.ts
|
|
94043
|
-
import { promises as
|
|
94044
|
-
import
|
|
95126
|
+
import { promises as fs18 } from "node:fs";
|
|
95127
|
+
import path32 from "node:path";
|
|
94045
95128
|
class LogWriterFactory extends Tag2("LogWriterFactory")() {
|
|
94046
95129
|
}
|
|
94047
95130
|
function sanitizePositiveInt(value8, fallback) {
|
|
@@ -94052,12 +95135,12 @@ function sanitizeMaxBytes(value8, fallback) {
|
|
|
94052
95135
|
return null;
|
|
94053
95136
|
return Number.isFinite(value8) && value8 > 0 ? Math.floor(value8) : fallback;
|
|
94054
95137
|
}
|
|
94055
|
-
async function
|
|
94056
|
-
await
|
|
95138
|
+
async function ensureDir10(filePath) {
|
|
95139
|
+
await fs18.mkdir(path32.dirname(filePath), { recursive: true });
|
|
94057
95140
|
}
|
|
94058
95141
|
async function safeStat(filePath) {
|
|
94059
95142
|
try {
|
|
94060
|
-
const s = await
|
|
95143
|
+
const s = await fs18.stat(filePath);
|
|
94061
95144
|
return { size: s.size };
|
|
94062
95145
|
} catch {
|
|
94063
95146
|
return;
|
|
@@ -94066,25 +95149,25 @@ async function safeStat(filePath) {
|
|
|
94066
95149
|
async function rotateFiles(filePath, keep) {
|
|
94067
95150
|
if (keep <= 0)
|
|
94068
95151
|
return;
|
|
94069
|
-
const dir2 =
|
|
94070
|
-
const base =
|
|
95152
|
+
const dir2 = path32.dirname(filePath);
|
|
95153
|
+
const base = path32.basename(filePath);
|
|
94071
95154
|
let entries2 = [];
|
|
94072
95155
|
try {
|
|
94073
|
-
entries2 = await
|
|
95156
|
+
entries2 = await fs18.readdir(dir2);
|
|
94074
95157
|
} catch {
|
|
94075
95158
|
return;
|
|
94076
95159
|
}
|
|
94077
|
-
const rotated = entries2.filter((name) => name.startsWith(`${base}.`)).map((name) =>
|
|
95160
|
+
const rotated = entries2.filter((name) => name.startsWith(`${base}.`)).map((name) => path32.join(dir2, name)).sort().reverse();
|
|
94078
95161
|
for (const p3 of rotated.slice(keep)) {
|
|
94079
95162
|
try {
|
|
94080
|
-
await
|
|
95163
|
+
await fs18.unlink(p3);
|
|
94081
95164
|
} catch {}
|
|
94082
95165
|
}
|
|
94083
95166
|
}
|
|
94084
95167
|
async function createLogWriter(filePath, options6) {
|
|
94085
95168
|
const maxBytes = sanitizeMaxBytes(options6.maxBytes, 20 * 1024 * 1024);
|
|
94086
95169
|
const keep = sanitizePositiveInt(options6.keep, 5);
|
|
94087
|
-
await
|
|
95170
|
+
await ensureDir10(filePath);
|
|
94088
95171
|
let currentSize = (await safeStat(filePath))?.size ?? 0;
|
|
94089
95172
|
let handle;
|
|
94090
95173
|
let closing = false;
|
|
@@ -94093,7 +95176,7 @@ async function createLogWriter(filePath, options6) {
|
|
|
94093
95176
|
async function openIfNeeded() {
|
|
94094
95177
|
if (handle)
|
|
94095
95178
|
return handle;
|
|
94096
|
-
handle = await
|
|
95179
|
+
handle = await fs18.open(filePath, "a");
|
|
94097
95180
|
return handle;
|
|
94098
95181
|
}
|
|
94099
95182
|
async function rotateIfNeeded(nextBytes) {
|
|
@@ -94107,7 +95190,7 @@ async function createLogWriter(filePath, options6) {
|
|
|
94107
95190
|
handle = undefined;
|
|
94108
95191
|
const rotatedPath = `${filePath}.${Date.now()}`;
|
|
94109
95192
|
try {
|
|
94110
|
-
await
|
|
95193
|
+
await fs18.rename(filePath, rotatedPath);
|
|
94111
95194
|
} catch {}
|
|
94112
95195
|
currentSize = 0;
|
|
94113
95196
|
await rotateFiles(filePath, keep);
|
|
@@ -94920,7 +96003,7 @@ var HostApiClientLive = effect(HostApiClient, gen2(function* () {
|
|
|
94920
96003
|
}));
|
|
94921
96004
|
|
|
94922
96005
|
// src/lib/workspaceResolver.ts
|
|
94923
|
-
import
|
|
96006
|
+
import fs19 from "node:fs";
|
|
94924
96007
|
|
|
94925
96008
|
// src/lib/business-semantics/uiContextResolution.ts
|
|
94926
96009
|
function loadBridgeUiContextSnapshot(params3) {
|
|
@@ -95226,7 +96309,7 @@ function pathExists(filePath) {
|
|
|
95226
96309
|
if (!filePath)
|
|
95227
96310
|
return false;
|
|
95228
96311
|
try {
|
|
95229
|
-
return
|
|
96312
|
+
return fs19.statSync(filePath).isFile();
|
|
95230
96313
|
} catch {
|
|
95231
96314
|
return false;
|
|
95232
96315
|
}
|
|
@@ -96727,7 +97810,7 @@ function isSingleRootOutlineMarkdown(input) {
|
|
|
96727
97810
|
}
|
|
96728
97811
|
|
|
96729
97812
|
// src/services/Payload.ts
|
|
96730
|
-
import { promises as
|
|
97813
|
+
import { promises as fs20 } from "node:fs";
|
|
96731
97814
|
class Payload extends Tag2("Payload")() {
|
|
96732
97815
|
}
|
|
96733
97816
|
var MAX_PAYLOAD_BYTES = 5 * 1024 * 1024;
|
|
@@ -96768,7 +97851,7 @@ async function readPayloadSpec(spec) {
|
|
|
96768
97851
|
if (!filePath) {
|
|
96769
97852
|
throw new CliError({ code: "INVALID_ARGS", message: "Payload file path cannot be empty", exitCode: 2 });
|
|
96770
97853
|
}
|
|
96771
|
-
return await
|
|
97854
|
+
return await fs20.readFile(filePath, "utf8");
|
|
96772
97855
|
}
|
|
96773
97856
|
return spec;
|
|
96774
97857
|
}
|
|
@@ -97078,8 +98161,8 @@ function resolveRefsInPayload(params3) {
|
|
|
97078
98161
|
const out = structuredClone(params3.payload);
|
|
97079
98162
|
const resolvedRefCache = new Map;
|
|
97080
98163
|
const idPaths = idFieldPathsForOpType(params3.opType);
|
|
97081
|
-
for (const
|
|
97082
|
-
const tokens = parsePathTokens(
|
|
98164
|
+
for (const path33 of idPaths) {
|
|
98165
|
+
const tokens = parsePathTokens(path33);
|
|
97083
98166
|
if (tokens.length === 0)
|
|
97084
98167
|
continue;
|
|
97085
98168
|
const leaves = collectLeafValues(out, tokens);
|
|
@@ -97698,7 +98781,7 @@ function validateOptionMutationOps(params3) {
|
|
|
97698
98781
|
|
|
97699
98782
|
// src/services/RefResolver.ts
|
|
97700
98783
|
import { homedir } from "node:os";
|
|
97701
|
-
import
|
|
98784
|
+
import path33 from "node:path";
|
|
97702
98785
|
class RefResolver extends Tag2("RefResolver")() {
|
|
97703
98786
|
}
|
|
97704
98787
|
function stripQuotes(s) {
|
|
@@ -97778,8 +98861,8 @@ function normalizeDbPathInput(dbPath) {
|
|
|
97778
98861
|
const raw4 = typeof dbPath === "string" ? dbPath.trim() : "";
|
|
97779
98862
|
if (!raw4)
|
|
97780
98863
|
return;
|
|
97781
|
-
const expanded = raw4 === "~" ? homedir() : raw4.startsWith("~/") || raw4.startsWith("~\\") ?
|
|
97782
|
-
return
|
|
98864
|
+
const expanded = raw4 === "~" ? homedir() : raw4.startsWith("~/") || raw4.startsWith("~\\") ? path33.join(homedir(), raw4.slice(2)) : raw4;
|
|
98865
|
+
return path33.resolve(path33.normalize(expanded));
|
|
97783
98866
|
}
|
|
97784
98867
|
var RefResolverLive = succeed10(RefResolver, {
|
|
97785
98868
|
resolve: (ref, options6) => gen2(function* () {
|
|
@@ -100378,152 +101461,6 @@ var applyCommand = exports_Command.make("apply", {
|
|
|
100378
101461
|
});
|
|
100379
101462
|
}).pipe(catchAll2(writeFailure)));
|
|
100380
101463
|
|
|
100381
|
-
// src/services/ApiDaemonFiles.ts
|
|
100382
|
-
import { promises as fs19 } from "node:fs";
|
|
100383
|
-
import path28 from "node:path";
|
|
100384
|
-
class ApiDaemonFiles extends Tag2("ApiDaemonFiles")() {
|
|
100385
|
-
}
|
|
100386
|
-
function ensureDir9(p3) {
|
|
100387
|
-
return fs19.mkdir(path28.dirname(p3), { recursive: true }).then(() => {
|
|
100388
|
-
return;
|
|
100389
|
-
});
|
|
100390
|
-
}
|
|
100391
|
-
function defaultPidFile2() {
|
|
100392
|
-
const envPidFile = process.env.REMNOTE_API_PID_FILE;
|
|
100393
|
-
if (typeof envPidFile === "string" && envPidFile.trim())
|
|
100394
|
-
return resolveUserFilePath(envPidFile);
|
|
100395
|
-
return path28.join(homeDir(), ".agent-remnote", "api.pid");
|
|
100396
|
-
}
|
|
100397
|
-
function defaultLogFile2() {
|
|
100398
|
-
const envLogFile = process.env.REMNOTE_API_LOG_FILE;
|
|
100399
|
-
if (typeof envLogFile === "string" && envLogFile.trim())
|
|
100400
|
-
return resolveUserFilePath(envLogFile);
|
|
100401
|
-
return path28.join(homeDir(), ".agent-remnote", "api.log");
|
|
100402
|
-
}
|
|
100403
|
-
function defaultStateFile2() {
|
|
100404
|
-
const envStateFile = process.env.REMNOTE_API_STATE_FILE;
|
|
100405
|
-
if (typeof envStateFile === "string" && envStateFile.trim())
|
|
100406
|
-
return resolveUserFilePath(envStateFile);
|
|
100407
|
-
return path28.join(homeDir(), ".agent-remnote", "api.state.json");
|
|
100408
|
-
}
|
|
100409
|
-
function parseJson2(raw4, filePath) {
|
|
100410
|
-
try {
|
|
100411
|
-
return JSON.parse(raw4);
|
|
100412
|
-
} catch (error4) {
|
|
100413
|
-
throw new CliError({
|
|
100414
|
-
code: "INTERNAL",
|
|
100415
|
-
message: `Failed to parse JSON file: ${filePath}`,
|
|
100416
|
-
exitCode: 1,
|
|
100417
|
-
details: { file_path: filePath, error: String(error4?.message || error4) }
|
|
100418
|
-
});
|
|
100419
|
-
}
|
|
100420
|
-
}
|
|
100421
|
-
var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
100422
|
-
defaultPidFile: defaultPidFile2,
|
|
100423
|
-
defaultLogFile: defaultLogFile2,
|
|
100424
|
-
defaultStateFile: defaultStateFile2,
|
|
100425
|
-
readPidFile: (pidFilePath) => tryPromise2({
|
|
100426
|
-
try: async () => {
|
|
100427
|
-
const resolved = resolveUserFilePath(pidFilePath);
|
|
100428
|
-
const raw4 = await fs19.readFile(resolved, "utf8");
|
|
100429
|
-
return parseJson2(raw4, resolved);
|
|
100430
|
-
},
|
|
100431
|
-
catch: (error4) => {
|
|
100432
|
-
const code2 = error4?.code;
|
|
100433
|
-
if (code2 === "ENOENT")
|
|
100434
|
-
return;
|
|
100435
|
-
if (isCliError(error4))
|
|
100436
|
-
return error4;
|
|
100437
|
-
return new CliError({
|
|
100438
|
-
code: "INTERNAL",
|
|
100439
|
-
message: "Failed to read api pid file",
|
|
100440
|
-
exitCode: 1,
|
|
100441
|
-
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
100442
|
-
});
|
|
100443
|
-
}
|
|
100444
|
-
}).pipe(catchAll2((error4) => {
|
|
100445
|
-
if (error4 === undefined)
|
|
100446
|
-
return succeed8(undefined);
|
|
100447
|
-
return fail8(error4);
|
|
100448
|
-
})),
|
|
100449
|
-
writePidFile: (pidFilePath, value8) => tryPromise2({
|
|
100450
|
-
try: async () => {
|
|
100451
|
-
const resolved = resolveUserFilePath(pidFilePath);
|
|
100452
|
-
await ensureDir9(resolved);
|
|
100453
|
-
await fs19.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
100454
|
-
`, "utf8");
|
|
100455
|
-
},
|
|
100456
|
-
catch: (error4) => new CliError({
|
|
100457
|
-
code: "INTERNAL",
|
|
100458
|
-
message: "Failed to write api pid file",
|
|
100459
|
-
exitCode: 1,
|
|
100460
|
-
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
100461
|
-
})
|
|
100462
|
-
}),
|
|
100463
|
-
deletePidFile: (pidFilePath) => tryPromise2({
|
|
100464
|
-
try: async () => {
|
|
100465
|
-
const resolved = resolveUserFilePath(pidFilePath);
|
|
100466
|
-
await fs19.rm(resolved, { force: true });
|
|
100467
|
-
},
|
|
100468
|
-
catch: (error4) => new CliError({
|
|
100469
|
-
code: "INTERNAL",
|
|
100470
|
-
message: "Failed to delete api pid file",
|
|
100471
|
-
exitCode: 1,
|
|
100472
|
-
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
100473
|
-
})
|
|
100474
|
-
}),
|
|
100475
|
-
readStateFile: (stateFilePath) => tryPromise2({
|
|
100476
|
-
try: async () => {
|
|
100477
|
-
const resolved = resolveUserFilePath(stateFilePath);
|
|
100478
|
-
const raw4 = await fs19.readFile(resolved, "utf8");
|
|
100479
|
-
return parseJson2(raw4, resolved);
|
|
100480
|
-
},
|
|
100481
|
-
catch: (error4) => {
|
|
100482
|
-
const code2 = error4?.code;
|
|
100483
|
-
if (code2 === "ENOENT")
|
|
100484
|
-
return;
|
|
100485
|
-
if (isCliError(error4))
|
|
100486
|
-
return error4;
|
|
100487
|
-
return new CliError({
|
|
100488
|
-
code: "INTERNAL",
|
|
100489
|
-
message: "Failed to read api state file",
|
|
100490
|
-
exitCode: 1,
|
|
100491
|
-
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
100492
|
-
});
|
|
100493
|
-
}
|
|
100494
|
-
}).pipe(catchAll2((error4) => {
|
|
100495
|
-
if (error4 === undefined)
|
|
100496
|
-
return succeed8(undefined);
|
|
100497
|
-
return fail8(error4);
|
|
100498
|
-
})),
|
|
100499
|
-
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
100500
|
-
try: async () => {
|
|
100501
|
-
const resolved = resolveUserFilePath(stateFilePath);
|
|
100502
|
-
await ensureDir9(resolved);
|
|
100503
|
-
await fs19.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
100504
|
-
`, "utf8");
|
|
100505
|
-
},
|
|
100506
|
-
catch: (error4) => new CliError({
|
|
100507
|
-
code: "INTERNAL",
|
|
100508
|
-
message: "Failed to write api state file",
|
|
100509
|
-
exitCode: 1,
|
|
100510
|
-
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
100511
|
-
})
|
|
100512
|
-
}),
|
|
100513
|
-
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
100514
|
-
try: async () => {
|
|
100515
|
-
const resolved = resolveUserFilePath(stateFilePath);
|
|
100516
|
-
await fs19.rm(resolved, { force: true });
|
|
100517
|
-
},
|
|
100518
|
-
catch: (error4) => new CliError({
|
|
100519
|
-
code: "INTERNAL",
|
|
100520
|
-
message: "Failed to delete api state file",
|
|
100521
|
-
exitCode: 1,
|
|
100522
|
-
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
100523
|
-
})
|
|
100524
|
-
})
|
|
100525
|
-
});
|
|
100526
|
-
|
|
100527
101464
|
// src/commands/api/_shared.ts
|
|
100528
101465
|
var API_HEALTH_TIMEOUT_MS = 2000;
|
|
100529
101466
|
var API_START_WAIT_DEFAULT_MS = 15000;
|
|
@@ -100609,6 +101546,7 @@ function startApiDaemon(params3) {
|
|
|
100609
101546
|
if (!alive) {
|
|
100610
101547
|
yield* apiFiles.deletePidFile(pidFilePath);
|
|
100611
101548
|
} else {
|
|
101549
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
100612
101550
|
return {
|
|
100613
101551
|
started: false,
|
|
100614
101552
|
pid: existing.pid,
|
|
@@ -100686,6 +101624,7 @@ function ensureApiDaemon(params3) {
|
|
|
100686
101624
|
if (existing) {
|
|
100687
101625
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
100688
101626
|
if (alive) {
|
|
101627
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
100689
101628
|
return {
|
|
100690
101629
|
started: false,
|
|
100691
101630
|
pid: existing.pid,
|
|
@@ -100817,20 +101756,43 @@ var apiRestartCommand = exports_Command.make("restart", {
|
|
|
100817
101756
|
const proc = yield* Process;
|
|
100818
101757
|
const pidFilePath = resolveUserFilePath(pidFile11 ?? apiFiles.defaultPidFile());
|
|
100819
101758
|
const existing = yield* apiFiles.readPidFile(pidFilePath);
|
|
101759
|
+
const stateFilePath = resolveManagedStateFile({
|
|
101760
|
+
pidFilePath,
|
|
101761
|
+
defaultStateFilePath: apiFiles.defaultStateFile(),
|
|
101762
|
+
explicitStateFilePath: stateFile5,
|
|
101763
|
+
candidate: existing?.state_file
|
|
101764
|
+
});
|
|
100820
101765
|
let stoppedPid;
|
|
100821
101766
|
if (existing) {
|
|
100822
101767
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
100823
101768
|
if (alive) {
|
|
101769
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
100824
101770
|
yield* proc.kill(existing.pid, "SIGTERM");
|
|
100825
101771
|
const exited = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: API_STOP_WAIT_DEFAULT_MS });
|
|
100826
|
-
if (!exited
|
|
101772
|
+
if (!exited) {
|
|
101773
|
+
if (!force) {
|
|
101774
|
+
return yield* fail8(new CliError({
|
|
101775
|
+
code: "INTERNAL",
|
|
101776
|
+
message: `Host API did not exit within ${API_STOP_WAIT_DEFAULT_MS}ms; use --force`,
|
|
101777
|
+
exitCode: 1,
|
|
101778
|
+
details: { pid: existing.pid, pid_file: pidFilePath }
|
|
101779
|
+
}));
|
|
101780
|
+
}
|
|
100827
101781
|
yield* proc.kill(existing.pid, "SIGKILL");
|
|
100828
|
-
yield* proc.waitForExit({ pid: existing.pid, timeoutMs: API_STOP_WAIT_DEFAULT_MS });
|
|
101782
|
+
const killed = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: API_STOP_WAIT_DEFAULT_MS });
|
|
101783
|
+
if (!killed) {
|
|
101784
|
+
return yield* fail8(new CliError({
|
|
101785
|
+
code: "INTERNAL",
|
|
101786
|
+
message: "Force stop failed (process is still alive)",
|
|
101787
|
+
exitCode: 1,
|
|
101788
|
+
details: { pid: existing.pid, pid_file: pidFilePath }
|
|
101789
|
+
}));
|
|
101790
|
+
}
|
|
100829
101791
|
}
|
|
100830
101792
|
stoppedPid = existing.pid;
|
|
100831
101793
|
}
|
|
100832
101794
|
yield* apiFiles.deletePidFile(pidFilePath).pipe(catchAll2(() => _void));
|
|
100833
|
-
yield* apiFiles.deleteStateFile(
|
|
101795
|
+
yield* apiFiles.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
100834
101796
|
}
|
|
100835
101797
|
const started = yield* startApiDaemon({ host: host3, port: port5, waitMs: wait3, pidFile: pidFile11, logFile: logFile7, stateFile: stateFile5 });
|
|
100836
101798
|
yield* writeSuccess({
|
|
@@ -101647,8 +102609,13 @@ var apiStopCommand = exports_Command.make("stop", { force: boolean8("force"), pi
|
|
|
101647
102609
|
const apiFiles = yield* ApiDaemonFiles;
|
|
101648
102610
|
const proc = yield* Process;
|
|
101649
102611
|
const pidFilePath = resolveUserFilePath(pidFile14 ?? apiFiles.defaultPidFile());
|
|
101650
|
-
const stateFilePath = resolveUserFilePath(stateFile9 ?? apiFiles.defaultStateFile());
|
|
101651
102612
|
const existing = yield* apiFiles.readPidFile(pidFilePath);
|
|
102613
|
+
const stateFilePath = resolveManagedStateFile({
|
|
102614
|
+
pidFilePath,
|
|
102615
|
+
defaultStateFilePath: apiFiles.defaultStateFile(),
|
|
102616
|
+
explicitStateFilePath: stateFile9,
|
|
102617
|
+
candidate: existing?.state_file
|
|
102618
|
+
});
|
|
101652
102619
|
if (!existing) {
|
|
101653
102620
|
yield* apiFiles.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
101654
102621
|
yield* writeSuccess({
|
|
@@ -101662,7 +102629,7 @@ var apiStopCommand = exports_Command.make("stop", { force: boolean8("force"), pi
|
|
|
101662
102629
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
101663
102630
|
if (!alive) {
|
|
101664
102631
|
yield* apiFiles.deletePidFile(pidFilePath);
|
|
101665
|
-
yield* apiFiles.deleteStateFile(
|
|
102632
|
+
yield* apiFiles.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
101666
102633
|
yield* writeSuccess({
|
|
101667
102634
|
data: { stopped: true, stale: true, pid: existing.pid, pid_file: pidFilePath },
|
|
101668
102635
|
md: `- stopped: true
|
|
@@ -101673,6 +102640,7 @@ var apiStopCommand = exports_Command.make("stop", { force: boolean8("force"), pi
|
|
|
101673
102640
|
});
|
|
101674
102641
|
return;
|
|
101675
102642
|
}
|
|
102643
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
101676
102644
|
yield* proc.kill(existing.pid, "SIGTERM");
|
|
101677
102645
|
const exited = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: API_STOP_WAIT_DEFAULT_MS });
|
|
101678
102646
|
if (!exited) {
|
|
@@ -101696,7 +102664,7 @@ var apiStopCommand = exports_Command.make("stop", { force: boolean8("force"), pi
|
|
|
101696
102664
|
}
|
|
101697
102665
|
}
|
|
101698
102666
|
yield* apiFiles.deletePidFile(pidFilePath);
|
|
101699
|
-
yield* apiFiles.deleteStateFile(
|
|
102667
|
+
yield* apiFiles.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
101700
102668
|
yield* writeSuccess({
|
|
101701
102669
|
data: { stopped: true, pid: existing.pid, pid_file: pidFilePath },
|
|
101702
102670
|
md: `- stopped: true
|
|
@@ -101753,13 +102721,13 @@ var readSelectionCurrentCommand = exports_Command.make("current", { stateFile: s
|
|
|
101753
102721
|
}).pipe(catchAll2(writeFailure)));
|
|
101754
102722
|
|
|
101755
102723
|
// src/commands/read/selection/outline.ts
|
|
101756
|
-
import
|
|
102724
|
+
import path34 from "node:path";
|
|
101757
102725
|
function optionToUndefined25(opt) {
|
|
101758
102726
|
return isSome2(opt) ? opt.value : undefined;
|
|
101759
102727
|
}
|
|
101760
102728
|
function normalizeOptionalStateFile(stateFile10) {
|
|
101761
102729
|
const trimmed2 = typeof stateFile10 === "string" ? stateFile10.trim() : "";
|
|
101762
|
-
return trimmed2 ?
|
|
102730
|
+
return trimmed2 ? path34.resolve(resolveUserFilePath(trimmed2)) : undefined;
|
|
101763
102731
|
}
|
|
101764
102732
|
var stateFile10 = text10("state-file").pipe(optional6, map34(optionToUndefined25));
|
|
101765
102733
|
var staleMs3 = integer7("stale-ms").pipe(optional6, map34(optionToUndefined25));
|
|
@@ -102103,152 +103071,6 @@ function waitForPluginServerHealth(baseUrl, waitMs, timeoutMs3) {
|
|
|
102103
103071
|
});
|
|
102104
103072
|
}
|
|
102105
103073
|
|
|
102106
|
-
// src/services/PluginServerFiles.ts
|
|
102107
|
-
import { promises as fs20 } from "node:fs";
|
|
102108
|
-
import path30 from "node:path";
|
|
102109
|
-
class PluginServerFiles extends Tag2("PluginServerFiles")() {
|
|
102110
|
-
}
|
|
102111
|
-
function ensureDir10(p3) {
|
|
102112
|
-
return fs20.mkdir(path30.dirname(p3), { recursive: true }).then(() => {
|
|
102113
|
-
return;
|
|
102114
|
-
});
|
|
102115
|
-
}
|
|
102116
|
-
function defaultPidFile3() {
|
|
102117
|
-
const envPidFile = process.env.REMNOTE_PLUGIN_SERVER_PID_FILE;
|
|
102118
|
-
if (typeof envPidFile === "string" && envPidFile.trim())
|
|
102119
|
-
return resolveUserFilePath(envPidFile);
|
|
102120
|
-
return path30.join(homeDir(), ".agent-remnote", "plugin-server.pid");
|
|
102121
|
-
}
|
|
102122
|
-
function defaultLogFile3() {
|
|
102123
|
-
const envLogFile = process.env.REMNOTE_PLUGIN_SERVER_LOG_FILE;
|
|
102124
|
-
if (typeof envLogFile === "string" && envLogFile.trim())
|
|
102125
|
-
return resolveUserFilePath(envLogFile);
|
|
102126
|
-
return path30.join(homeDir(), ".agent-remnote", "plugin-server.log");
|
|
102127
|
-
}
|
|
102128
|
-
function defaultStateFile3() {
|
|
102129
|
-
const envStateFile = process.env.REMNOTE_PLUGIN_SERVER_STATE_FILE;
|
|
102130
|
-
if (typeof envStateFile === "string" && envStateFile.trim())
|
|
102131
|
-
return resolveUserFilePath(envStateFile);
|
|
102132
|
-
return path30.join(homeDir(), ".agent-remnote", "plugin-server.state.json");
|
|
102133
|
-
}
|
|
102134
|
-
function parseJson3(raw4, filePath) {
|
|
102135
|
-
try {
|
|
102136
|
-
return JSON.parse(raw4);
|
|
102137
|
-
} catch (error4) {
|
|
102138
|
-
throw new CliError({
|
|
102139
|
-
code: "INTERNAL",
|
|
102140
|
-
message: `Failed to parse JSON file: ${filePath}`,
|
|
102141
|
-
exitCode: 1,
|
|
102142
|
-
details: { file_path: filePath, error: String(error4?.message || error4) }
|
|
102143
|
-
});
|
|
102144
|
-
}
|
|
102145
|
-
}
|
|
102146
|
-
var PluginServerFilesLive = succeed10(PluginServerFiles, {
|
|
102147
|
-
defaultPidFile: defaultPidFile3,
|
|
102148
|
-
defaultLogFile: defaultLogFile3,
|
|
102149
|
-
defaultStateFile: defaultStateFile3,
|
|
102150
|
-
readPidFile: (pidFilePath) => tryPromise2({
|
|
102151
|
-
try: async () => {
|
|
102152
|
-
const resolved = resolveUserFilePath(pidFilePath);
|
|
102153
|
-
const raw4 = await fs20.readFile(resolved, "utf8");
|
|
102154
|
-
return parseJson3(raw4, resolved);
|
|
102155
|
-
},
|
|
102156
|
-
catch: (error4) => {
|
|
102157
|
-
const code2 = error4?.code;
|
|
102158
|
-
if (code2 === "ENOENT")
|
|
102159
|
-
return;
|
|
102160
|
-
if (isCliError(error4))
|
|
102161
|
-
return error4;
|
|
102162
|
-
return new CliError({
|
|
102163
|
-
code: "INTERNAL",
|
|
102164
|
-
message: "Failed to read plugin server pid file",
|
|
102165
|
-
exitCode: 1,
|
|
102166
|
-
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
102167
|
-
});
|
|
102168
|
-
}
|
|
102169
|
-
}).pipe(catchAll2((error4) => {
|
|
102170
|
-
if (error4 === undefined)
|
|
102171
|
-
return succeed8(undefined);
|
|
102172
|
-
return fail8(error4);
|
|
102173
|
-
})),
|
|
102174
|
-
writePidFile: (pidFilePath, value8) => tryPromise2({
|
|
102175
|
-
try: async () => {
|
|
102176
|
-
const resolved = resolveUserFilePath(pidFilePath);
|
|
102177
|
-
await ensureDir10(resolved);
|
|
102178
|
-
await fs20.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
102179
|
-
`, "utf8");
|
|
102180
|
-
},
|
|
102181
|
-
catch: (error4) => new CliError({
|
|
102182
|
-
code: "INTERNAL",
|
|
102183
|
-
message: "Failed to write plugin server pid file",
|
|
102184
|
-
exitCode: 1,
|
|
102185
|
-
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
102186
|
-
})
|
|
102187
|
-
}),
|
|
102188
|
-
deletePidFile: (pidFilePath) => tryPromise2({
|
|
102189
|
-
try: async () => {
|
|
102190
|
-
const resolved = resolveUserFilePath(pidFilePath);
|
|
102191
|
-
await fs20.rm(resolved, { force: true });
|
|
102192
|
-
},
|
|
102193
|
-
catch: (error4) => new CliError({
|
|
102194
|
-
code: "INTERNAL",
|
|
102195
|
-
message: "Failed to delete plugin server pid file",
|
|
102196
|
-
exitCode: 1,
|
|
102197
|
-
details: { file_path: pidFilePath, error: String(error4?.message || error4) }
|
|
102198
|
-
})
|
|
102199
|
-
}),
|
|
102200
|
-
readStateFile: (stateFilePath) => tryPromise2({
|
|
102201
|
-
try: async () => {
|
|
102202
|
-
const resolved = resolveUserFilePath(stateFilePath);
|
|
102203
|
-
const raw4 = await fs20.readFile(resolved, "utf8");
|
|
102204
|
-
return parseJson3(raw4, resolved);
|
|
102205
|
-
},
|
|
102206
|
-
catch: (error4) => {
|
|
102207
|
-
const code2 = error4?.code;
|
|
102208
|
-
if (code2 === "ENOENT")
|
|
102209
|
-
return;
|
|
102210
|
-
if (isCliError(error4))
|
|
102211
|
-
return error4;
|
|
102212
|
-
return new CliError({
|
|
102213
|
-
code: "INTERNAL",
|
|
102214
|
-
message: "Failed to read plugin server state file",
|
|
102215
|
-
exitCode: 1,
|
|
102216
|
-
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
102217
|
-
});
|
|
102218
|
-
}
|
|
102219
|
-
}).pipe(catchAll2((error4) => {
|
|
102220
|
-
if (error4 === undefined)
|
|
102221
|
-
return succeed8(undefined);
|
|
102222
|
-
return fail8(error4);
|
|
102223
|
-
})),
|
|
102224
|
-
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
102225
|
-
try: async () => {
|
|
102226
|
-
const resolved = resolveUserFilePath(stateFilePath);
|
|
102227
|
-
await ensureDir10(resolved);
|
|
102228
|
-
await fs20.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
102229
|
-
`, "utf8");
|
|
102230
|
-
},
|
|
102231
|
-
catch: (error4) => new CliError({
|
|
102232
|
-
code: "INTERNAL",
|
|
102233
|
-
message: "Failed to write plugin server state file",
|
|
102234
|
-
exitCode: 1,
|
|
102235
|
-
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
102236
|
-
})
|
|
102237
|
-
}),
|
|
102238
|
-
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
102239
|
-
try: async () => {
|
|
102240
|
-
const resolved = resolveUserFilePath(stateFilePath);
|
|
102241
|
-
await fs20.rm(resolved, { force: true });
|
|
102242
|
-
},
|
|
102243
|
-
catch: (error4) => new CliError({
|
|
102244
|
-
code: "INTERNAL",
|
|
102245
|
-
message: "Failed to delete plugin server state file",
|
|
102246
|
-
exitCode: 1,
|
|
102247
|
-
details: { file_path: stateFilePath, error: String(error4?.message || error4) }
|
|
102248
|
-
})
|
|
102249
|
-
})
|
|
102250
|
-
});
|
|
102251
|
-
|
|
102252
103074
|
// src/commands/plugin/_shared.ts
|
|
102253
103075
|
var PLUGIN_SERVER_HEALTH_TIMEOUT_MS = 2000;
|
|
102254
103076
|
var PLUGIN_SERVER_START_WAIT_DEFAULT_MS = 15000;
|
|
@@ -102302,6 +103124,7 @@ function startPluginServer(params3) {
|
|
|
102302
103124
|
if (!alive) {
|
|
102303
103125
|
yield* files.deletePidFile(pidFilePath);
|
|
102304
103126
|
} else {
|
|
103127
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
102305
103128
|
return {
|
|
102306
103129
|
started: false,
|
|
102307
103130
|
pid: existing.pid,
|
|
@@ -102368,6 +103191,7 @@ function ensurePluginServer(params3) {
|
|
|
102368
103191
|
if (existing) {
|
|
102369
103192
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
102370
103193
|
if (alive) {
|
|
103194
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
102371
103195
|
return {
|
|
102372
103196
|
started: false,
|
|
102373
103197
|
pid: existing.pid,
|
|
@@ -102499,20 +103323,43 @@ var pluginRestartCommand = exports_Command.make("restart", {
|
|
|
102499
103323
|
const proc = yield* Process;
|
|
102500
103324
|
const pidFilePath = resolveUserFilePath(pidFile17 ?? files.defaultPidFile());
|
|
102501
103325
|
const existing = yield* files.readPidFile(pidFilePath);
|
|
103326
|
+
const stateFilePath = resolveManagedStateFile({
|
|
103327
|
+
pidFilePath,
|
|
103328
|
+
defaultStateFilePath: files.defaultStateFile(),
|
|
103329
|
+
explicitStateFilePath: stateFile20,
|
|
103330
|
+
candidate: existing?.state_file
|
|
103331
|
+
});
|
|
102502
103332
|
let stoppedPid;
|
|
102503
103333
|
if (existing) {
|
|
102504
103334
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
102505
103335
|
if (alive) {
|
|
103336
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath });
|
|
102506
103337
|
yield* proc.kill(existing.pid, "SIGTERM");
|
|
102507
103338
|
const exited = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: PLUGIN_SERVER_STOP_WAIT_DEFAULT_MS });
|
|
102508
|
-
if (!exited
|
|
103339
|
+
if (!exited) {
|
|
103340
|
+
if (!force) {
|
|
103341
|
+
return yield* fail8(new CliError({
|
|
103342
|
+
code: "INTERNAL",
|
|
103343
|
+
message: `Plugin server did not exit within ${PLUGIN_SERVER_STOP_WAIT_DEFAULT_MS}ms; use --force`,
|
|
103344
|
+
exitCode: 1,
|
|
103345
|
+
details: { pid: existing.pid, pid_file: pidFilePath }
|
|
103346
|
+
}));
|
|
103347
|
+
}
|
|
102509
103348
|
yield* proc.kill(existing.pid, "SIGKILL");
|
|
102510
|
-
yield* proc.waitForExit({ pid: existing.pid, timeoutMs: PLUGIN_SERVER_STOP_WAIT_DEFAULT_MS });
|
|
103349
|
+
const killed = yield* proc.waitForExit({ pid: existing.pid, timeoutMs: PLUGIN_SERVER_STOP_WAIT_DEFAULT_MS });
|
|
103350
|
+
if (!killed) {
|
|
103351
|
+
return yield* fail8(new CliError({
|
|
103352
|
+
code: "INTERNAL",
|
|
103353
|
+
message: "Force stop failed (process is still alive)",
|
|
103354
|
+
exitCode: 1,
|
|
103355
|
+
details: { pid: existing.pid, pid_file: pidFilePath }
|
|
103356
|
+
}));
|
|
103357
|
+
}
|
|
102511
103358
|
}
|
|
102512
103359
|
stoppedPid = existing.pid;
|
|
102513
103360
|
}
|
|
102514
103361
|
yield* files.deletePidFile(pidFilePath).pipe(catchAll2(() => _void));
|
|
102515
|
-
yield* files.deleteStateFile(
|
|
103362
|
+
yield* files.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
102516
103363
|
}
|
|
102517
103364
|
const started = yield* startPluginServer({ host: host7, port: port9, waitMs: wait3, pidFile: pidFile17, logFile: logFile10, stateFile: stateFile20 });
|
|
102518
103365
|
yield* writeSuccess({
|
|
@@ -102570,7 +103417,7 @@ import { createServer as createServer2 } from "node:http";
|
|
|
102570
103417
|
|
|
102571
103418
|
// src/lib/pluginStaticFiles.ts
|
|
102572
103419
|
import { promises as fs21 } from "node:fs";
|
|
102573
|
-
import
|
|
103420
|
+
import path35 from "node:path";
|
|
102574
103421
|
var CONTENT_TYPES = new Map([
|
|
102575
103422
|
[".css", "text/css; charset=utf-8"],
|
|
102576
103423
|
[".html", "text/html; charset=utf-8"],
|
|
@@ -102580,7 +103427,7 @@ var CONTENT_TYPES = new Map([
|
|
|
102580
103427
|
[".txt", "text/plain; charset=utf-8"]
|
|
102581
103428
|
]);
|
|
102582
103429
|
function contentTypeFor(filePath) {
|
|
102583
|
-
return CONTENT_TYPES.get(
|
|
103430
|
+
return CONTENT_TYPES.get(path35.extname(filePath).toLowerCase()) ?? "application/octet-stream";
|
|
102584
103431
|
}
|
|
102585
103432
|
function normalizeAssetPath(pathname) {
|
|
102586
103433
|
let decoded;
|
|
@@ -102590,7 +103437,7 @@ function normalizeAssetPath(pathname) {
|
|
|
102590
103437
|
return null;
|
|
102591
103438
|
}
|
|
102592
103439
|
const raw4 = decoded === "/" ? "index.html" : decoded.replace(/^\/+/, "");
|
|
102593
|
-
const normalized =
|
|
103440
|
+
const normalized = path35.posix.normalize(raw4);
|
|
102594
103441
|
if (!normalized || normalized === "." || normalized.startsWith("../") || normalized === "..")
|
|
102595
103442
|
return null;
|
|
102596
103443
|
return normalized;
|
|
@@ -102604,8 +103451,8 @@ async function readPluginStaticAsset(params3) {
|
|
|
102604
103451
|
if (!relativePath) {
|
|
102605
103452
|
return { ok: false, statusCode: 404, message: "Not found" };
|
|
102606
103453
|
}
|
|
102607
|
-
const filePath =
|
|
102608
|
-
if (filePath !== params3.distPath && !filePath.startsWith(`${params3.distPath}${
|
|
103454
|
+
const filePath = path35.resolve(params3.distPath, relativePath);
|
|
103455
|
+
if (filePath !== params3.distPath && !filePath.startsWith(`${params3.distPath}${path35.sep}`)) {
|
|
102609
103456
|
return { ok: false, statusCode: 404, message: "Not found" };
|
|
102610
103457
|
}
|
|
102611
103458
|
try {
|
|
@@ -102922,8 +103769,14 @@ function stopPluginServer(params3) {
|
|
|
102922
103769
|
const files = yield* PluginServerFiles;
|
|
102923
103770
|
const proc = yield* Process;
|
|
102924
103771
|
const existing = yield* files.readPidFile(params3.pidFilePath);
|
|
103772
|
+
const stateFilePath = resolveManagedStateFile({
|
|
103773
|
+
pidFilePath: params3.pidFilePath,
|
|
103774
|
+
defaultStateFilePath: files.defaultStateFile(),
|
|
103775
|
+
explicitStateFilePath: params3.stateFilePath,
|
|
103776
|
+
candidate: existing?.state_file
|
|
103777
|
+
});
|
|
102925
103778
|
if (!existing) {
|
|
102926
|
-
yield* files.deleteStateFile(
|
|
103779
|
+
yield* files.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
102927
103780
|
return {
|
|
102928
103781
|
stopped: true,
|
|
102929
103782
|
pid_file: params3.pidFilePath
|
|
@@ -102931,7 +103784,7 @@ function stopPluginServer(params3) {
|
|
|
102931
103784
|
}
|
|
102932
103785
|
const cleanupStale = () => gen2(function* () {
|
|
102933
103786
|
yield* files.deletePidFile(params3.pidFilePath);
|
|
102934
|
-
yield* files.deleteStateFile(
|
|
103787
|
+
yield* files.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
102935
103788
|
return {
|
|
102936
103789
|
stopped: true,
|
|
102937
103790
|
stale: true,
|
|
@@ -102943,6 +103796,7 @@ function stopPluginServer(params3) {
|
|
|
102943
103796
|
if (!alive) {
|
|
102944
103797
|
return yield* cleanupStale();
|
|
102945
103798
|
}
|
|
103799
|
+
yield* requireTrustedPidRecord({ record: existing, pidFilePath: params3.pidFilePath });
|
|
102946
103800
|
const termResult = yield* proc.kill(existing.pid, "SIGTERM").pipe(either3);
|
|
102947
103801
|
if (termResult._tag === "Left") {
|
|
102948
103802
|
if (isEsrch(termResult.left)) {
|
|
@@ -102972,7 +103826,7 @@ function stopPluginServer(params3) {
|
|
|
102972
103826
|
}
|
|
102973
103827
|
}
|
|
102974
103828
|
yield* files.deletePidFile(params3.pidFilePath);
|
|
102975
|
-
yield* files.deleteStateFile(
|
|
103829
|
+
yield* files.deleteStateFile(stateFilePath).pipe(catchAll2(() => _void));
|
|
102976
103830
|
return {
|
|
102977
103831
|
stopped: true,
|
|
102978
103832
|
pid: existing.pid,
|
|
@@ -108621,53 +109475,9 @@ var writeReplaceCommand = exports_Command.make("replace", {}).pipe(exports_Comma
|
|
|
108621
109475
|
var replaceCommand = writeReplaceCommand;
|
|
108622
109476
|
|
|
108623
109477
|
// src/lib/scenario-store/index.ts
|
|
108624
|
-
import
|
|
109478
|
+
import path36 from "node:path";
|
|
108625
109479
|
import { promises as fs22 } from "node:fs";
|
|
108626
109480
|
|
|
108627
|
-
// src/lib/builtin-scenarios/index.ts
|
|
108628
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
108629
|
-
import path32 from "node:path";
|
|
108630
|
-
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
108631
|
-
var MODULE_DIR = path32.dirname(fileURLToPath4(import.meta.url));
|
|
108632
|
-
function locateBuiltinSourceRoot() {
|
|
108633
|
-
const packageRootCandidates = [
|
|
108634
|
-
path32.resolve(MODULE_DIR, "../../../"),
|
|
108635
|
-
path32.resolve(MODULE_DIR, "..")
|
|
108636
|
-
];
|
|
108637
|
-
for (const packageRoot of packageRootCandidates) {
|
|
108638
|
-
const builtinSourceRoot = path32.join(packageRoot, "builtin-scenarios");
|
|
108639
|
-
if (existsSync4(path32.join(builtinSourceRoot, "catalog.json"))) {
|
|
108640
|
-
return { packageRoot, builtinSourceRoot };
|
|
108641
|
-
}
|
|
108642
|
-
}
|
|
108643
|
-
throw new Error(`Unable to locate builtin-scenarios catalog from ${MODULE_DIR}`);
|
|
108644
|
-
}
|
|
108645
|
-
var { packageRoot: PACKAGE_ROOT, builtinSourceRoot: BUILTIN_SOURCE_ROOT } = locateBuiltinSourceRoot();
|
|
108646
|
-
var REPO_ROOT = path32.resolve(PACKAGE_ROOT, "../..");
|
|
108647
|
-
var BUILTIN_CATALOG_PATH = path32.join(BUILTIN_SOURCE_ROOT, "catalog.json");
|
|
108648
|
-
function readJsonFile(filePath) {
|
|
108649
|
-
return JSON.parse(readFileSync4(filePath, "utf8"));
|
|
108650
|
-
}
|
|
108651
|
-
function resolveRepoPath(relPath) {
|
|
108652
|
-
return path32.resolve(REPO_ROOT, relPath);
|
|
108653
|
-
}
|
|
108654
|
-
var builtinScenarioCatalog = readJsonFile(BUILTIN_CATALOG_PATH);
|
|
108655
|
-
var builtinScenarioPackages = Object.freeze(Object.fromEntries(builtinScenarioCatalog.map((entry) => [entry.package_id, readJsonFile(resolveRepoPath(entry.package_path))])));
|
|
108656
|
-
function getBuiltinScenarioPackage(id5) {
|
|
108657
|
-
const pkg = builtinScenarioPackages[id5];
|
|
108658
|
-
if (!pkg) {
|
|
108659
|
-
throw new Error(`Unknown builtin scenario package: ${id5}`);
|
|
108660
|
-
}
|
|
108661
|
-
return pkg;
|
|
108662
|
-
}
|
|
108663
|
-
function getBuiltinScenarioPackageSourcePath(id5) {
|
|
108664
|
-
const entry = builtinScenarioCatalog.find((item) => item.package_id === id5);
|
|
108665
|
-
if (!entry) {
|
|
108666
|
-
throw new Error(`Unknown builtin scenario source: ${id5}`);
|
|
108667
|
-
}
|
|
108668
|
-
return resolveRepoPath(entry.package_path);
|
|
108669
|
-
}
|
|
108670
|
-
|
|
108671
109481
|
// src/lib/scenario-shared/index.ts
|
|
108672
109482
|
class ScenarioSharedError extends Error {
|
|
108673
109483
|
code;
|
|
@@ -108680,34 +109490,34 @@ class ScenarioSharedError extends Error {
|
|
|
108680
109490
|
function isRecord4(value8) {
|
|
108681
109491
|
return value8 !== null && typeof value8 === "object" && !Array.isArray(value8);
|
|
108682
109492
|
}
|
|
108683
|
-
function addDiagnostic(diagnostics, errors3, level,
|
|
108684
|
-
diagnostics.push({ level, path:
|
|
109493
|
+
function addDiagnostic(diagnostics, errors3, level, path36, message2) {
|
|
109494
|
+
diagnostics.push({ level, path: path36, message: message2 });
|
|
108685
109495
|
if (level === "error")
|
|
108686
109496
|
errors3.push(message2);
|
|
108687
109497
|
}
|
|
108688
|
-
function addChange(changes2,
|
|
108689
|
-
changes2.push({ path:
|
|
109498
|
+
function addChange(changes2, path36, kind2, before2, after3) {
|
|
109499
|
+
changes2.push({ path: path36, kind: kind2, before: before2, after: after3 });
|
|
108690
109500
|
}
|
|
108691
|
-
function expectRecord(value8,
|
|
109501
|
+
function expectRecord(value8, path36, diagnostics, errors3) {
|
|
108692
109502
|
if (isRecord4(value8))
|
|
108693
109503
|
return value8;
|
|
108694
|
-
addDiagnostic(diagnostics, errors3, "error",
|
|
109504
|
+
addDiagnostic(diagnostics, errors3, "error", path36, `${path36} must be an object`);
|
|
108695
109505
|
return {};
|
|
108696
109506
|
}
|
|
108697
|
-
function expectString(value8,
|
|
109507
|
+
function expectString(value8, path36, diagnostics, errors3, fallback = "") {
|
|
108698
109508
|
if (typeof value8 === "string" && value8.trim())
|
|
108699
109509
|
return value8.trim();
|
|
108700
|
-
addDiagnostic(diagnostics, errors3, "error",
|
|
109510
|
+
addDiagnostic(diagnostics, errors3, "error", path36, `${path36} must be a non-empty string`);
|
|
108701
109511
|
return fallback;
|
|
108702
109512
|
}
|
|
108703
|
-
function expectStringArray(value8,
|
|
109513
|
+
function expectStringArray(value8, path36, diagnostics, errors3) {
|
|
108704
109514
|
if (!Array.isArray(value8)) {
|
|
108705
|
-
addDiagnostic(diagnostics, errors3, "error",
|
|
109515
|
+
addDiagnostic(diagnostics, errors3, "error", path36, `${path36} must be an array`);
|
|
108706
109516
|
return [];
|
|
108707
109517
|
}
|
|
108708
109518
|
const out = value8.map((item) => typeof item === "string" ? item.trim() : "").filter((item) => item.length > 0);
|
|
108709
109519
|
if (out.length !== value8.length) {
|
|
108710
|
-
addDiagnostic(diagnostics, errors3, "error",
|
|
109520
|
+
addDiagnostic(diagnostics, errors3, "error", path36, `${path36} must contain only non-empty strings`);
|
|
108711
109521
|
}
|
|
108712
109522
|
return out;
|
|
108713
109523
|
}
|
|
@@ -108730,21 +109540,21 @@ function normalizePowerupValue2(value8) {
|
|
|
108730
109540
|
return "t";
|
|
108731
109541
|
return trimmed2;
|
|
108732
109542
|
}
|
|
108733
|
-
function normalizeQuerySelector(raw4,
|
|
108734
|
-
const input = expectRecord(raw4,
|
|
109543
|
+
function normalizeQuerySelector(raw4, path36, diagnostics, errors3, changes2) {
|
|
109544
|
+
const input = expectRecord(raw4, path36, diagnostics, errors3);
|
|
108735
109545
|
let query2 = input;
|
|
108736
109546
|
if (isRecord4(input.query)) {
|
|
108737
109547
|
query2 = input.query;
|
|
108738
109548
|
} else if (isRecord4(input.queryObj)) {
|
|
108739
109549
|
query2 = input.queryObj;
|
|
108740
|
-
addChange(changes2, `${
|
|
109550
|
+
addChange(changes2, `${path36}.queryObj`, "normalized", input.queryObj, query2);
|
|
108741
109551
|
}
|
|
108742
109552
|
if (isRecord4(query2.query)) {
|
|
108743
109553
|
query2 = query2.query;
|
|
108744
109554
|
}
|
|
108745
109555
|
const version = 2;
|
|
108746
|
-
const root = expectRecord(query2.root ?? query2, `${
|
|
108747
|
-
const normalizedRoot = normalizeQueryRoot2(root, `${
|
|
109556
|
+
const root = expectRecord(query2.root ?? query2, `${path36}.root`, diagnostics, errors3);
|
|
109557
|
+
const normalizedRoot = normalizeQueryRoot2(root, `${path36}.root`, diagnostics, errors3, changes2);
|
|
108748
109558
|
return {
|
|
108749
109559
|
version,
|
|
108750
109560
|
root: normalizedRoot,
|
|
@@ -108753,31 +109563,31 @@ function normalizeQuerySelector(raw4, path33, diagnostics, errors3, changes2) {
|
|
|
108753
109563
|
...isRecord4(query2.sort) ? { sort: query2.sort } : {}
|
|
108754
109564
|
};
|
|
108755
109565
|
}
|
|
108756
|
-
function normalizeQueryRoot2(raw4,
|
|
108757
|
-
const type2 = expectString(raw4.type, `${
|
|
109566
|
+
function normalizeQueryRoot2(raw4, path36, diagnostics, errors3, changes2) {
|
|
109567
|
+
const type2 = expectString(raw4.type, `${path36}.type`, diagnostics, errors3);
|
|
108758
109568
|
if (type2 === "text") {
|
|
108759
|
-
const value8 = expectString(raw4.value, `${
|
|
109569
|
+
const value8 = expectString(raw4.value, `${path36}.value`, diagnostics, errors3);
|
|
108760
109570
|
const mode = typeof raw4.mode === "string" && raw4.mode.trim() ? raw4.mode.trim() : "contains";
|
|
108761
109571
|
if (raw4.mode === undefined) {
|
|
108762
|
-
addChange(changes2, `${
|
|
109572
|
+
addChange(changes2, `${path36}.mode`, "defaulted", undefined, mode);
|
|
108763
109573
|
}
|
|
108764
109574
|
return { type: type2, value: value8, mode };
|
|
108765
109575
|
}
|
|
108766
109576
|
if (type2 === "powerup") {
|
|
108767
|
-
const powerup3 = expectRecord(raw4.powerup, `${
|
|
109577
|
+
const powerup3 = expectRecord(raw4.powerup, `${path36}.powerup`, diagnostics, errors3);
|
|
108768
109578
|
let by = typeof powerup3.by === "string" ? powerup3.by.trim().toLowerCase() : "";
|
|
108769
109579
|
if (by !== "id" && by !== "rcrt") {
|
|
108770
109580
|
if (!by) {
|
|
108771
109581
|
by = "rcrt";
|
|
108772
|
-
addChange(changes2, `${
|
|
109582
|
+
addChange(changes2, `${path36}.powerup.by`, "defaulted", powerup3.by, by);
|
|
108773
109583
|
} else {
|
|
108774
|
-
addDiagnostic(diagnostics, errors3, "error", `${
|
|
109584
|
+
addDiagnostic(diagnostics, errors3, "error", `${path36}.powerup.by`, "powerup.by must be one of: id, rcrt");
|
|
108775
109585
|
}
|
|
108776
109586
|
}
|
|
108777
|
-
const rawValue = expectString(powerup3.value, `${
|
|
109587
|
+
const rawValue = expectString(powerup3.value, `${path36}.powerup.value`, diagnostics, errors3);
|
|
108778
109588
|
const value8 = by === "rcrt" ? normalizePowerupValue2(rawValue) : rawValue;
|
|
108779
109589
|
if (value8 !== rawValue) {
|
|
108780
|
-
addChange(changes2, `${
|
|
109590
|
+
addChange(changes2, `${path36}.powerup.value`, "normalized", rawValue, value8);
|
|
108781
109591
|
}
|
|
108782
109592
|
return {
|
|
108783
109593
|
type: type2,
|
|
@@ -108790,45 +109600,45 @@ function normalizeQueryRoot2(raw4, path33, diagnostics, errors3, changes2) {
|
|
|
108790
109600
|
if ((type2 === "and" || type2 === "or") && Array.isArray(raw4.nodes)) {
|
|
108791
109601
|
return {
|
|
108792
109602
|
type: type2,
|
|
108793
|
-
nodes: raw4.nodes.map((child, index) => normalizeQueryRoot2(expectRecord(child, `${
|
|
109603
|
+
nodes: raw4.nodes.map((child, index) => normalizeQueryRoot2(expectRecord(child, `${path36}.nodes[${index}]`, diagnostics, errors3), `${path36}.nodes[${index}]`, diagnostics, errors3, changes2))
|
|
108794
109604
|
};
|
|
108795
109605
|
}
|
|
108796
109606
|
if (type2 === "not") {
|
|
108797
109607
|
return {
|
|
108798
109608
|
type: type2,
|
|
108799
|
-
node: normalizeQueryRoot2(expectRecord(raw4.node, `${
|
|
109609
|
+
node: normalizeQueryRoot2(expectRecord(raw4.node, `${path36}.node`, diagnostics, errors3), `${path36}.node`, diagnostics, errors3, changes2)
|
|
108800
109610
|
};
|
|
108801
109611
|
}
|
|
108802
109612
|
return raw4;
|
|
108803
109613
|
}
|
|
108804
|
-
function normalizeVars(raw4,
|
|
109614
|
+
function normalizeVars(raw4, path36, diagnostics, errors3, changes2) {
|
|
108805
109615
|
if (Array.isArray(raw4)) {
|
|
108806
|
-
return raw4.map((item, index) => normalizeVar(item, `${
|
|
109616
|
+
return raw4.map((item, index) => normalizeVar(item, `${path36}[${index}]`, diagnostics, errors3));
|
|
108807
109617
|
}
|
|
108808
109618
|
if (isRecord4(raw4)) {
|
|
108809
|
-
const vars = Object.entries(raw4).map(([name, value8]) => normalizeVar({ ...isRecord4(value8) ? value8 : {}, name }, `${
|
|
108810
|
-
addChange(changes2,
|
|
109619
|
+
const vars = Object.entries(raw4).map(([name, value8]) => normalizeVar({ ...isRecord4(value8) ? value8 : {}, name }, `${path36}.${name}`, diagnostics, errors3));
|
|
109620
|
+
addChange(changes2, path36, "normalized", raw4, vars);
|
|
108811
109621
|
return vars;
|
|
108812
109622
|
}
|
|
108813
109623
|
if (raw4 === undefined)
|
|
108814
109624
|
return [];
|
|
108815
|
-
addDiagnostic(diagnostics, errors3, "error",
|
|
109625
|
+
addDiagnostic(diagnostics, errors3, "error", path36, `${path36} must be an array or object`);
|
|
108816
109626
|
return [];
|
|
108817
109627
|
}
|
|
108818
|
-
function normalizeVar(raw4,
|
|
108819
|
-
const value8 = expectRecord(raw4,
|
|
109628
|
+
function normalizeVar(raw4, path36, diagnostics, errors3) {
|
|
109629
|
+
const value8 = expectRecord(raw4, path36, diagnostics, errors3);
|
|
108820
109630
|
return {
|
|
108821
|
-
name: expectString(value8.name, `${
|
|
108822
|
-
type: expectString(value8.type, `${
|
|
109631
|
+
name: expectString(value8.name, `${path36}.name`, diagnostics, errors3),
|
|
109632
|
+
type: expectString(value8.type, `${path36}.type`, diagnostics, errors3, "string"),
|
|
108823
109633
|
required: asBoolean(value8.required, false),
|
|
108824
109634
|
...value8.default !== undefined ? { default: value8.default } : {},
|
|
108825
109635
|
...typeof value8.description === "string" && value8.description.trim() ? { description: value8.description.trim() } : {}
|
|
108826
109636
|
};
|
|
108827
109637
|
}
|
|
108828
|
-
function normalizeCapabilities(raw4,
|
|
109638
|
+
function normalizeCapabilities(raw4, path36, changes2) {
|
|
108829
109639
|
if (Array.isArray(raw4)) {
|
|
108830
109640
|
const out = Object.fromEntries(raw4.map((item) => String(item ?? "").trim()).filter(Boolean).map((item) => [item.replace(/^requires\./, ""), true]));
|
|
108831
|
-
addChange(changes2,
|
|
109641
|
+
addChange(changes2, path36, "normalized", raw4, { requires: out });
|
|
108832
109642
|
return Object.keys(out).length > 0 ? { requires: out } : {};
|
|
108833
109643
|
}
|
|
108834
109644
|
if (!isRecord4(raw4))
|
|
@@ -108836,7 +109646,7 @@ function normalizeCapabilities(raw4, path33, changes2) {
|
|
|
108836
109646
|
const requires = raw4.requires;
|
|
108837
109647
|
if (Array.isArray(requires)) {
|
|
108838
109648
|
const out = Object.fromEntries(requires.map((item) => String(item ?? "").trim()).filter(Boolean).map((item) => [item.replace(/^requires\./, ""), true]));
|
|
108839
|
-
addChange(changes2, `${
|
|
109649
|
+
addChange(changes2, `${path36}.requires`, "normalized", requires, out);
|
|
108840
109650
|
return Object.keys(out).length > 0 ? { requires: out } : {};
|
|
108841
109651
|
}
|
|
108842
109652
|
if (isRecord4(requires)) {
|
|
@@ -108845,8 +109655,8 @@ function normalizeCapabilities(raw4, path33, changes2) {
|
|
|
108845
109655
|
}
|
|
108846
109656
|
return {};
|
|
108847
109657
|
}
|
|
108848
|
-
function normalizePolicy(raw4,
|
|
108849
|
-
const value8 = expectRecord(raw4,
|
|
109658
|
+
function normalizePolicy(raw4, path36, diagnostics, errors3) {
|
|
109659
|
+
const value8 = expectRecord(raw4, path36, diagnostics, errors3);
|
|
108850
109660
|
const fallbackStrategy = value8.fallback_strategy === "allow_empty_selection" || value8.fallback_strategy === "skip_optional_outputs" || value8.fallback_strategy === "fail" ? value8.fallback_strategy : undefined;
|
|
108851
109661
|
return {
|
|
108852
109662
|
wait: asBoolean(value8.wait, false),
|
|
@@ -108856,10 +109666,10 @@ function normalizePolicy(raw4, path33, diagnostics, errors3) {
|
|
|
108856
109666
|
...fallbackStrategy ? { fallback_strategy: fallbackStrategy } : {}
|
|
108857
109667
|
};
|
|
108858
109668
|
}
|
|
108859
|
-
function normalizeScheduling(raw4,
|
|
109669
|
+
function normalizeScheduling(raw4, path36, diagnostics, errors3) {
|
|
108860
109670
|
if (raw4 === undefined)
|
|
108861
109671
|
return;
|
|
108862
|
-
const value8 = expectRecord(raw4,
|
|
109672
|
+
const value8 = expectRecord(raw4, path36, diagnostics, errors3);
|
|
108863
109673
|
const batching = value8.batching === "off" || value8.batching === "auto" ? value8.batching : undefined;
|
|
108864
109674
|
const mergeStrategy = value8.merge_strategy === "off" || value8.merge_strategy === "safe_dedupe" ? value8.merge_strategy : undefined;
|
|
108865
109675
|
const parallelism = value8.parallelism === "serial" || value8.parallelism === "auto" ? value8.parallelism : undefined;
|
|
@@ -108873,13 +109683,13 @@ function normalizeScheduling(raw4, path33, diagnostics, errors3) {
|
|
|
108873
109683
|
...dispatchMode7 ? { dispatch_mode: dispatchMode7 } : {}
|
|
108874
109684
|
};
|
|
108875
109685
|
}
|
|
108876
|
-
function normalizeNodes(raw4,
|
|
109686
|
+
function normalizeNodes(raw4, path36, diagnostics, errors3, changes2) {
|
|
108877
109687
|
if (!Array.isArray(raw4)) {
|
|
108878
|
-
addDiagnostic(diagnostics, errors3, "error",
|
|
109688
|
+
addDiagnostic(diagnostics, errors3, "error", path36, `${path36} must be an array`);
|
|
108879
109689
|
return [];
|
|
108880
109690
|
}
|
|
108881
109691
|
return raw4.map((item, index) => {
|
|
108882
|
-
const nodePath = `${
|
|
109692
|
+
const nodePath = `${path36}[${index}]`;
|
|
108883
109693
|
const value8 = expectRecord(item, nodePath, diagnostics, errors3);
|
|
108884
109694
|
const id5 = expectString(value8.id, `${nodePath}.id`, diagnostics, errors3);
|
|
108885
109695
|
const kind2 = expectString(value8.kind, `${nodePath}.kind`, diagnostics, errors3);
|
|
@@ -108931,18 +109741,18 @@ function normalizeNodes(raw4, path33, diagnostics, errors3, changes2) {
|
|
|
108931
109741
|
};
|
|
108932
109742
|
});
|
|
108933
109743
|
}
|
|
108934
|
-
function scanStructuredReferences(value8, onRef,
|
|
109744
|
+
function scanStructuredReferences(value8, onRef, path36) {
|
|
108935
109745
|
if (Array.isArray(value8)) {
|
|
108936
|
-
value8.forEach((item, index) => scanStructuredReferences(item, onRef, `${
|
|
109746
|
+
value8.forEach((item, index) => scanStructuredReferences(item, onRef, `${path36}[${index}]`));
|
|
108937
109747
|
return;
|
|
108938
109748
|
}
|
|
108939
109749
|
if (!isRecord4(value8))
|
|
108940
109750
|
return;
|
|
108941
109751
|
if (value8.kind === "node_output" && typeof value8.node === "string" && typeof value8.output === "string") {
|
|
108942
|
-
onRef(value8,
|
|
109752
|
+
onRef(value8, path36);
|
|
108943
109753
|
}
|
|
108944
109754
|
for (const [key, child] of Object.entries(value8)) {
|
|
108945
|
-
scanStructuredReferences(child, onRef, `${
|
|
109755
|
+
scanStructuredReferences(child, onRef, `${path36}.${key}`);
|
|
108946
109756
|
}
|
|
108947
109757
|
}
|
|
108948
109758
|
function validateGraph(pkg, diagnostics, errors3) {
|
|
@@ -109250,7 +110060,7 @@ function generateScenarioPackage(input) {
|
|
|
109250
110060
|
|
|
109251
110061
|
// src/lib/scenario-store/index.ts
|
|
109252
110062
|
function defaultUserScenarioDir() {
|
|
109253
|
-
return
|
|
110063
|
+
return path36.join(homeDir(), ".agent-remnote", "scenarios");
|
|
109254
110064
|
}
|
|
109255
110065
|
function resolveUserScenarioDir(input) {
|
|
109256
110066
|
if (typeof input === "string" && input.trim()) {
|
|
@@ -109281,7 +110091,7 @@ function canonicalScenarioId(input, fieldName) {
|
|
|
109281
110091
|
return id5;
|
|
109282
110092
|
}
|
|
109283
110093
|
function userScenarioFilePath(id5, installDir) {
|
|
109284
|
-
return
|
|
110094
|
+
return path36.join(resolveUserScenarioDir(installDir), `${canonicalScenarioId(id5, "Scenario id")}.json`);
|
|
109285
110095
|
}
|
|
109286
110096
|
async function readUserScenarioPackageById(id5, installDir) {
|
|
109287
110097
|
const canonicalId = canonicalScenarioId(id5, "Scenario id");
|
|
@@ -111446,7 +112256,7 @@ var stackEnsureCommand = exports_Command.make("ensure", {
|
|
|
111446
112256
|
}).pipe(catchAll2(writeFailure)));
|
|
111447
112257
|
|
|
111448
112258
|
// src/commands/stack/status.ts
|
|
111449
|
-
import
|
|
112259
|
+
import path37 from "node:path";
|
|
111450
112260
|
var stackStatusCommand = exports_Command.make("status", {}, () => gen2(function* () {
|
|
111451
112261
|
const cfg = yield* AppConfig;
|
|
111452
112262
|
const daemonFiles = yield* DaemonFiles;
|
|
@@ -111467,7 +112277,7 @@ var stackStatusCommand = exports_Command.make("status", {}, () => gen2(function*
|
|
|
111467
112277
|
const apiBaseUrl = apiLocalBaseUrl(apiPidInfo?.port ?? cfg.apiPort ?? 3000, apiBasePath);
|
|
111468
112278
|
const apiStatus = yield* api.status({ baseUrl: apiBaseUrl, timeoutMs: 2000 }).pipe(either3);
|
|
111469
112279
|
const queueStats2 = yield* queue.stats({ dbPath: cfg.storeDb }).pipe(either3);
|
|
111470
|
-
const stateFilePath = resolveUserFilePath(daemonPidInfo?.state_file ??
|
|
112280
|
+
const stateFilePath = resolveUserFilePath(daemonPidInfo?.state_file ?? path37.join(path37.dirname(daemonPidFile), "ws.state.json"));
|
|
111471
112281
|
const activeWorkerRuntime = clients._tag === "Right" && typeof clients.right.activeWorkerConnId === "string" ? clients.right.clients.find((client) => client.connId === clients.right.activeWorkerConnId)?.runtime ?? null : null;
|
|
111472
112282
|
const data = {
|
|
111473
112283
|
runtime: currentRuntimeBuildInfo(),
|
|
@@ -111529,7 +112339,7 @@ var stackStatusCommand = exports_Command.make("status", {}, () => gen2(function*
|
|
|
111529
112339
|
}).pipe(catchAll2(writeFailure)));
|
|
111530
112340
|
|
|
111531
112341
|
// src/commands/stack/stop.ts
|
|
111532
|
-
import
|
|
112342
|
+
import path38 from "node:path";
|
|
111533
112343
|
var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* () {
|
|
111534
112344
|
const apiFiles = yield* ApiDaemonFiles;
|
|
111535
112345
|
const daemonFiles = yield* DaemonFiles;
|
|
@@ -111537,8 +112347,14 @@ var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* ()
|
|
|
111537
112347
|
const supervisorState = yield* SupervisorState;
|
|
111538
112348
|
const apiPidFile = resolveUserFilePath(apiFiles.defaultPidFile());
|
|
111539
112349
|
const apiPidInfo = yield* apiFiles.readPidFile(apiPidFile);
|
|
111540
|
-
|
|
112350
|
+
const apiStateFile = resolveManagedStateFile({
|
|
112351
|
+
pidFilePath: apiPidFile,
|
|
112352
|
+
defaultStateFilePath: apiFiles.defaultStateFile(),
|
|
112353
|
+
candidate: apiPidInfo?.state_file
|
|
112354
|
+
});
|
|
112355
|
+
let apiStopped = false;
|
|
111541
112356
|
if (apiPidInfo && (yield* proc.isPidRunning(apiPidInfo.pid))) {
|
|
112357
|
+
yield* requireTrustedPidRecord({ record: apiPidInfo, pidFilePath: apiPidFile });
|
|
111542
112358
|
yield* proc.kill(apiPidInfo.pid, "SIGTERM");
|
|
111543
112359
|
const exited = yield* proc.waitForExit({ pid: apiPidInfo.pid, timeoutMs: API_STOP_WAIT_DEFAULT_MS });
|
|
111544
112360
|
if (!exited) {
|
|
@@ -111548,13 +112364,22 @@ var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* ()
|
|
|
111548
112364
|
return yield* fail8(new CliError({ code: "INTERNAL", message: "Failed to stop api process", exitCode: 1 }));
|
|
111549
112365
|
}
|
|
111550
112366
|
}
|
|
112367
|
+
apiStopped = true;
|
|
112368
|
+
} else {
|
|
112369
|
+
apiStopped = true;
|
|
111551
112370
|
}
|
|
111552
112371
|
yield* apiFiles.deletePidFile(apiPidFile).pipe(catchAll2(() => _void));
|
|
111553
|
-
yield* apiFiles.deleteStateFile(
|
|
112372
|
+
yield* apiFiles.deleteStateFile(apiStateFile).pipe(catchAll2(() => _void));
|
|
111554
112373
|
const daemonPidFile = resolveUserFilePath(daemonFiles.defaultPidFile());
|
|
111555
112374
|
const daemonPidInfo = yield* daemonFiles.readPidFile(daemonPidFile);
|
|
111556
|
-
|
|
112375
|
+
const daemonStateFile = resolveManagedStateFile({
|
|
112376
|
+
pidFilePath: daemonPidFile,
|
|
112377
|
+
defaultStateFilePath: resolveUserFilePath(path38.join(path38.dirname(daemonPidFile), "ws.state.json")),
|
|
112378
|
+
candidate: daemonPidInfo?.state_file
|
|
112379
|
+
});
|
|
112380
|
+
let daemonStopped = false;
|
|
111557
112381
|
if (daemonPidInfo && (yield* proc.isPidRunning(daemonPidInfo.pid))) {
|
|
112382
|
+
yield* requireTrustedPidRecord({ record: daemonPidInfo, pidFilePath: daemonPidFile });
|
|
111558
112383
|
yield* proc.kill(daemonPidInfo.pid, "SIGTERM");
|
|
111559
112384
|
const exited = yield* proc.waitForExit({ pid: daemonPidInfo.pid, timeoutMs: WS_STOP_WAIT_DEFAULT_MS });
|
|
111560
112385
|
if (!exited) {
|
|
@@ -111564,9 +112389,12 @@ var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* ()
|
|
|
111564
112389
|
return yield* fail8(new CliError({ code: "INTERNAL", message: "Failed to stop daemon process", exitCode: 1 }));
|
|
111565
112390
|
}
|
|
111566
112391
|
}
|
|
112392
|
+
daemonStopped = true;
|
|
112393
|
+
} else {
|
|
112394
|
+
daemonStopped = true;
|
|
111567
112395
|
}
|
|
111568
112396
|
yield* daemonFiles.deletePidFile(daemonPidFile).pipe(catchAll2(() => _void));
|
|
111569
|
-
yield* supervisorState.deleteStateFile(
|
|
112397
|
+
yield* supervisorState.deleteStateFile(daemonStateFile).pipe(catchAll2(() => _void));
|
|
111570
112398
|
yield* writeSuccess({
|
|
111571
112399
|
data: { stopped: true, api_stopped: apiStopped, daemon_stopped: daemonStopped },
|
|
111572
112400
|
md: `- stopped: true
|
|
@@ -111769,8 +112597,6 @@ var cli = exports_Command.run(rootCommand, {
|
|
|
111769
112597
|
name: "agent-remnote",
|
|
111770
112598
|
version
|
|
111771
112599
|
});
|
|
111772
|
-
var jsonRequested = process.argv.includes("--json");
|
|
111773
|
-
var debugRequested = process.argv.includes("--debug");
|
|
111774
112600
|
function canonicalizeArgv(argv) {
|
|
111775
112601
|
const out = [...argv];
|
|
111776
112602
|
for (let i = 0;i < out.length; i += 1) {
|
|
@@ -111840,6 +112666,9 @@ var ROOT_VALUE_FLAGS2 = new Set([
|
|
|
111840
112666
|
"--config-file",
|
|
111841
112667
|
...BUILTIN_VALUE_FLAGS2
|
|
111842
112668
|
]);
|
|
112669
|
+
var rootCliConfig = parseRootConfigFromArgv(argv);
|
|
112670
|
+
var jsonRequested = rootCliConfig.get("json") === "true";
|
|
112671
|
+
var debugRequested = rootCliConfig.get("debug") === "true";
|
|
111843
112672
|
function parseRootConfigFromArgv(argv2) {
|
|
111844
112673
|
const tokens = argv2.slice(2);
|
|
111845
112674
|
const out = new Map;
|
|
@@ -112292,72 +113121,77 @@ function strictCommandPreflightOrExit(argv2) {
|
|
|
112292
113121
|
process.exit(error4.exitCode);
|
|
112293
113122
|
}
|
|
112294
113123
|
strictCommandPreflightOrExit(argv);
|
|
112295
|
-
var
|
|
112296
|
-
|
|
112297
|
-
|
|
112298
|
-
|
|
112299
|
-
|
|
112300
|
-
|
|
112301
|
-
|
|
112302
|
-
if (
|
|
112303
|
-
|
|
112304
|
-
|
|
112305
|
-
|
|
112306
|
-
|
|
112307
|
-
|
|
113124
|
+
var isSearchWorkerThread = !isMainThread2 && workerData2?.kind === "search_rem_overview";
|
|
113125
|
+
if (isSearchWorkerThread && parentPort3) {
|
|
113126
|
+
runSearchRemOverviewWorkerJob(workerData2, parentPort3);
|
|
113127
|
+
} else {
|
|
113128
|
+
const configProvider = buildCliEnvConfigProvider({ cli: parseRootConfigFromArgv(argv), env: process.env });
|
|
113129
|
+
cli(argv).pipe(withConfigProvider2(configProvider), provide2(mergeAll5(exports_NodeContext.layer, setConsole2(makeCliConsole()))), scoped2, exit2, flatMap9((exit3) => sync3(() => {
|
|
113130
|
+
process.exitCode = exitCodeFromExit(exit3);
|
|
113131
|
+
if (isSuccess(exit3))
|
|
113132
|
+
return;
|
|
113133
|
+
const failure = failureOption2(exit3.cause);
|
|
113134
|
+
if (isNone2(failure)) {
|
|
113135
|
+
if (jsonRequested) {
|
|
113136
|
+
process.stdout.write(`${JSON.stringify(fail21({
|
|
113137
|
+
code: "INTERNAL",
|
|
113138
|
+
message: "Unknown runtime error (defect)",
|
|
113139
|
+
details: debugRequested ? { cause: pretty2(exit3.cause) } : undefined
|
|
113140
|
+
}))}
|
|
112308
113141
|
`);
|
|
112309
|
-
|
|
112310
|
-
|
|
112311
|
-
|
|
113142
|
+
} else if (!globalThis.__REMNOTE_CLI_ERROR_REPORTED__) {
|
|
113143
|
+
globalThis.__REMNOTE_CLI_ERROR_REPORTED__ = true;
|
|
113144
|
+
process.stderr.write(`${formatHumanErrorLine2("Unknown runtime error (defect)")}
|
|
112312
113145
|
`);
|
|
112313
|
-
|
|
112314
|
-
|
|
113146
|
+
if (debugRequested)
|
|
113147
|
+
process.stderr.write(pretty2(exit3.cause) + `
|
|
112315
113148
|
`);
|
|
112316
|
-
|
|
112317
|
-
return;
|
|
112318
|
-
}
|
|
112319
|
-
const error4 = failure.value;
|
|
112320
|
-
if (isValidationError2(error4)) {
|
|
112321
|
-
if (!jsonRequested)
|
|
113149
|
+
}
|
|
112322
113150
|
return;
|
|
112323
|
-
|
|
112324
|
-
|
|
112325
|
-
|
|
112326
|
-
|
|
112327
|
-
|
|
112328
|
-
|
|
112329
|
-
|
|
112330
|
-
process.stdout.write(`${JSON.stringify(fail21(toJsonError(error4), error4.hint))}
|
|
113151
|
+
}
|
|
113152
|
+
const error4 = failure.value;
|
|
113153
|
+
if (isValidationError2(error4)) {
|
|
113154
|
+
if (!jsonRequested)
|
|
113155
|
+
return;
|
|
113156
|
+
const cliError = cliErrorFromValidationError(error4);
|
|
113157
|
+
process.stdout.write(`${JSON.stringify(fail21(toJsonError(cliError), cliError.hint))}
|
|
112331
113158
|
`);
|
|
112332
113159
|
return;
|
|
112333
113160
|
}
|
|
112334
|
-
if (
|
|
112335
|
-
|
|
112336
|
-
|
|
112337
|
-
`);
|
|
112338
|
-
if (debugRequested && error4.details !== undefined) {
|
|
112339
|
-
process.stderr.write(`${JSON.stringify(error4.details, null, 2)}
|
|
113161
|
+
if (isCliError(error4)) {
|
|
113162
|
+
if (jsonRequested) {
|
|
113163
|
+
process.stdout.write(`${JSON.stringify(fail21(toJsonError(error4), error4.hint))}
|
|
112340
113164
|
`);
|
|
113165
|
+
return;
|
|
112341
113166
|
}
|
|
112342
|
-
if (
|
|
112343
|
-
|
|
113167
|
+
if (!globalThis.__REMNOTE_CLI_ERROR_REPORTED__) {
|
|
113168
|
+
globalThis.__REMNOTE_CLI_ERROR_REPORTED__ = true;
|
|
113169
|
+
process.stderr.write(`${formatHumanErrorLine2(error4.message)}
|
|
113170
|
+
`);
|
|
113171
|
+
if (debugRequested && error4.details !== undefined) {
|
|
113172
|
+
process.stderr.write(`${JSON.stringify(error4.details, null, 2)}
|
|
112344
113173
|
`);
|
|
112345
|
-
|
|
112346
|
-
|
|
113174
|
+
}
|
|
113175
|
+
if (error4.hint && error4.hint.length > 0) {
|
|
113176
|
+
process.stderr.write(`Hint:
|
|
113177
|
+
`);
|
|
113178
|
+
for (const h of error4.hint)
|
|
113179
|
+
process.stderr.write(`- ${h}
|
|
112347
113180
|
`);
|
|
113181
|
+
}
|
|
112348
113182
|
}
|
|
113183
|
+
return;
|
|
112349
113184
|
}
|
|
112350
|
-
|
|
112351
|
-
|
|
112352
|
-
|
|
112353
|
-
|
|
112354
|
-
|
|
112355
|
-
message: String(error4?.message || error4 || "Unknown error")
|
|
112356
|
-
}))}
|
|
113185
|
+
if (jsonRequested) {
|
|
113186
|
+
process.stdout.write(`${JSON.stringify(fail21({
|
|
113187
|
+
code: "INTERNAL",
|
|
113188
|
+
message: String(error4?.message || error4 || "Unknown error")
|
|
113189
|
+
}))}
|
|
112357
113190
|
`);
|
|
112358
|
-
|
|
112359
|
-
|
|
112360
|
-
|
|
113191
|
+
} else if (!globalThis.__REMNOTE_CLI_ERROR_REPORTED__) {
|
|
113192
|
+
globalThis.__REMNOTE_CLI_ERROR_REPORTED__ = true;
|
|
113193
|
+
process.stderr.write(`${formatHumanErrorLine2(String(error4?.message || error4 || "Unknown error"))}
|
|
112361
113194
|
`);
|
|
112362
|
-
|
|
112363
|
-
}))).pipe(exports_NodeRuntime.runMain);
|
|
113195
|
+
}
|
|
113196
|
+
}))).pipe(exports_NodeRuntime.runMain);
|
|
113197
|
+
}
|