agent-remnote 0.2.0 → 0.3.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 +8 -0
- package/README.md +21 -2
- package/dist/main.js +1343 -778
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -73916,13 +73916,17 @@ var platformRunnerImpl = /* @__PURE__ */ PlatformRunner2.of({
|
|
|
73916
73916
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
73917
73917
|
import { format as format10 } from "node:util";
|
|
73918
73918
|
|
|
73919
|
+
// src/services/UserConfigFile.ts
|
|
73920
|
+
import { promises as fs4 } from "node:fs";
|
|
73921
|
+
import path7 from "node:path";
|
|
73922
|
+
|
|
73919
73923
|
// src/services/AppConfig.ts
|
|
73920
73924
|
class AppConfig extends Tag2("AppConfig")() {
|
|
73921
73925
|
}
|
|
73922
73926
|
|
|
73923
|
-
// src/services/
|
|
73924
|
-
import
|
|
73925
|
-
import
|
|
73927
|
+
// src/services/Config.ts
|
|
73928
|
+
import fs3 from "node:fs";
|
|
73929
|
+
import path6 from "node:path";
|
|
73926
73930
|
|
|
73927
73931
|
// src/services/Errors.ts
|
|
73928
73932
|
class CliError extends TaggedError("CliError") {
|
|
@@ -73954,52 +73958,985 @@ function cliErrorFromValidationError(err) {
|
|
|
73954
73958
|
exitCode: 2
|
|
73955
73959
|
});
|
|
73956
73960
|
}
|
|
73957
|
-
function exitCodeFromExit(exit3) {
|
|
73958
|
-
if (isSuccess(exit3))
|
|
73959
|
-
return 0;
|
|
73960
|
-
if (isInterruptedOnly2(exit3.cause))
|
|
73961
|
-
return 0;
|
|
73962
|
-
const failure = failureOption2(exit3.cause);
|
|
73963
|
-
if (isSome2(failure)) {
|
|
73964
|
-
const error4 = failure.value;
|
|
73965
|
-
if (isCliError(error4))
|
|
73966
|
-
return error4.exitCode;
|
|
73967
|
-
if (isValidationError2(error4))
|
|
73968
|
-
return 2;
|
|
73969
|
-
}
|
|
73970
|
-
return 1;
|
|
73961
|
+
function exitCodeFromExit(exit3) {
|
|
73962
|
+
if (isSuccess(exit3))
|
|
73963
|
+
return 0;
|
|
73964
|
+
if (isInterruptedOnly2(exit3.cause))
|
|
73965
|
+
return 0;
|
|
73966
|
+
const failure = failureOption2(exit3.cause);
|
|
73967
|
+
if (isSome2(failure)) {
|
|
73968
|
+
const error4 = failure.value;
|
|
73969
|
+
if (isCliError(error4))
|
|
73970
|
+
return error4.exitCode;
|
|
73971
|
+
if (isValidationError2(error4))
|
|
73972
|
+
return 2;
|
|
73973
|
+
}
|
|
73974
|
+
return 1;
|
|
73975
|
+
}
|
|
73976
|
+
|
|
73977
|
+
// src/lib/paths.ts
|
|
73978
|
+
import os from "node:os";
|
|
73979
|
+
import path3 from "node:path";
|
|
73980
|
+
function homeDir() {
|
|
73981
|
+
const h = os.homedir();
|
|
73982
|
+
if (typeof h === "string" && h.trim())
|
|
73983
|
+
return h;
|
|
73984
|
+
return process.env.HOME || process.env.USERPROFILE || ".";
|
|
73985
|
+
}
|
|
73986
|
+
function expandHome(targetPath) {
|
|
73987
|
+
const raw4 = targetPath.trim();
|
|
73988
|
+
if (!raw4.startsWith("~"))
|
|
73989
|
+
return raw4;
|
|
73990
|
+
const home = homeDir();
|
|
73991
|
+
if (raw4 === "~")
|
|
73992
|
+
return home;
|
|
73993
|
+
if (raw4.startsWith("~/") || raw4.startsWith("~\\")) {
|
|
73994
|
+
return path3.join(home, raw4.slice(2));
|
|
73995
|
+
}
|
|
73996
|
+
return raw4.replace(/^~(?=$|[\\/])/, home);
|
|
73997
|
+
}
|
|
73998
|
+
function resolveUserFilePath(filePath) {
|
|
73999
|
+
return path3.normalize(expandHome(filePath));
|
|
74000
|
+
}
|
|
74001
|
+
|
|
74002
|
+
// src/lib/wsState.ts
|
|
74003
|
+
import fs from "node:fs";
|
|
74004
|
+
import path4 from "node:path";
|
|
74005
|
+
function defaultStateFilePath() {
|
|
74006
|
+
return path4.join(homeDir(), ".agent-remnote", "ws.bridge.state.json");
|
|
74007
|
+
}
|
|
74008
|
+
function resolveStateFilePath(explicit) {
|
|
74009
|
+
if (explicit && explicit.trim())
|
|
74010
|
+
return { disabled: false, path: resolveUserFilePath(explicit) };
|
|
74011
|
+
const raw4 = String(process.env.REMNOTE_WS_STATE_FILE || process.env.WS_STATE_FILE || "").trim();
|
|
74012
|
+
if (raw4 === "0" || raw4.toLowerCase() === "false")
|
|
74013
|
+
return { disabled: true, path: defaultStateFilePath() };
|
|
74014
|
+
if (raw4)
|
|
74015
|
+
return { disabled: false, path: resolveUserFilePath(raw4) };
|
|
74016
|
+
return { disabled: false, path: defaultStateFilePath() };
|
|
74017
|
+
}
|
|
74018
|
+
function readJson(filePath) {
|
|
74019
|
+
try {
|
|
74020
|
+
const txt = fs.readFileSync(filePath, "utf8");
|
|
74021
|
+
return JSON.parse(txt);
|
|
74022
|
+
} catch {
|
|
74023
|
+
return null;
|
|
74024
|
+
}
|
|
74025
|
+
}
|
|
74026
|
+
function pickClient(clients, connId) {
|
|
74027
|
+
const target2 = (connId || "").trim();
|
|
74028
|
+
if (target2) {
|
|
74029
|
+
const found = clients.find((c) => c && typeof c === "object" && c.connId === target2);
|
|
74030
|
+
if (found)
|
|
74031
|
+
return found;
|
|
74032
|
+
}
|
|
74033
|
+
const active2 = clients.find((c) => c && typeof c === "object" && c.isActiveWorker === true);
|
|
74034
|
+
if (active2)
|
|
74035
|
+
return active2;
|
|
74036
|
+
let best = null;
|
|
74037
|
+
let bestScore = -1;
|
|
74038
|
+
for (const c of clients) {
|
|
74039
|
+
if (!c || typeof c !== "object")
|
|
74040
|
+
continue;
|
|
74041
|
+
const selAt = Number(c.selection?.updatedAt ?? 0);
|
|
74042
|
+
const ctxAt = Number(c.uiContext?.updatedAt ?? 0);
|
|
74043
|
+
const score = Math.max(selAt, ctxAt);
|
|
74044
|
+
if (score > bestScore) {
|
|
74045
|
+
bestScore = score;
|
|
74046
|
+
best = c;
|
|
74047
|
+
}
|
|
74048
|
+
}
|
|
74049
|
+
return best;
|
|
74050
|
+
}
|
|
74051
|
+
function resolveStaleMs(explicit) {
|
|
74052
|
+
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0)
|
|
74053
|
+
return Math.floor(explicit);
|
|
74054
|
+
const raw4 = process.env.REMNOTE_WS_STATE_STALE_MS || process.env.WS_STATE_STALE_MS;
|
|
74055
|
+
const n = Number(raw4);
|
|
74056
|
+
if (Number.isFinite(n) && n > 0)
|
|
74057
|
+
return Math.floor(n);
|
|
74058
|
+
return 60000;
|
|
74059
|
+
}
|
|
74060
|
+
|
|
74061
|
+
// src/lib/remnote.ts
|
|
74062
|
+
import fs2 from "node:fs";
|
|
74063
|
+
import path5 from "node:path";
|
|
74064
|
+
function tryParseRemnoteLink(input) {
|
|
74065
|
+
const raw4 = input.trim();
|
|
74066
|
+
let u;
|
|
74067
|
+
try {
|
|
74068
|
+
u = new URL(raw4);
|
|
74069
|
+
} catch {
|
|
74070
|
+
return;
|
|
74071
|
+
}
|
|
74072
|
+
if (u.protocol === "remnote:" && u.hostname === "w") {
|
|
74073
|
+
const parts2 = u.pathname.split("/").filter(Boolean);
|
|
74074
|
+
const workspaceId = parts2.length >= 1 ? parts2[0] : undefined;
|
|
74075
|
+
const remId = parts2.length >= 2 ? parts2[1] : undefined;
|
|
74076
|
+
if (workspaceId && remId) {
|
|
74077
|
+
return { workspaceId: workspaceId.trim(), remId: remId.trim() };
|
|
74078
|
+
}
|
|
74079
|
+
return;
|
|
74080
|
+
}
|
|
74081
|
+
if ((u.protocol === "https:" || u.protocol === "http:") && u.hostname.endsWith("remnote.com")) {
|
|
74082
|
+
const parts2 = u.pathname.split("/").filter(Boolean);
|
|
74083
|
+
if (parts2.length >= 3 && parts2[0] === "w") {
|
|
74084
|
+
const workspaceId = parts2[1];
|
|
74085
|
+
const remId = parts2[2];
|
|
74086
|
+
if (workspaceId && remId) {
|
|
74087
|
+
return { workspaceId: workspaceId.trim(), remId: remId.trim() };
|
|
74088
|
+
}
|
|
74089
|
+
}
|
|
74090
|
+
}
|
|
74091
|
+
return;
|
|
74092
|
+
}
|
|
74093
|
+
function tryParseRemnoteLinkFromRef(input) {
|
|
74094
|
+
const direct = tryParseRemnoteLink(input);
|
|
74095
|
+
if (direct)
|
|
74096
|
+
return direct;
|
|
74097
|
+
const raw4 = input.trim();
|
|
74098
|
+
const idx = raw4.indexOf(":");
|
|
74099
|
+
if (idx <= 0)
|
|
74100
|
+
return;
|
|
74101
|
+
const value8 = raw4.slice(idx + 1).trim();
|
|
74102
|
+
if (!value8)
|
|
74103
|
+
return;
|
|
74104
|
+
return tryParseRemnoteLink(value8);
|
|
74105
|
+
}
|
|
74106
|
+
function remnoteDbPathForWorkspaceId(workspaceId) {
|
|
74107
|
+
return path5.join(homeDir(), "remnote", `remnote-${workspaceId}`, "remnote.db");
|
|
74108
|
+
}
|
|
74109
|
+
function tryResolveRemnoteDbPathForWorkspaceIdSync(workspaceId) {
|
|
74110
|
+
const p3 = remnoteDbPathForWorkspaceId(workspaceId);
|
|
74111
|
+
try {
|
|
74112
|
+
return fs2.statSync(p3).isFile() ? p3 : undefined;
|
|
74113
|
+
} catch {
|
|
74114
|
+
return;
|
|
74115
|
+
}
|
|
74116
|
+
}
|
|
74117
|
+
|
|
74118
|
+
// src/services/Config.ts
|
|
74119
|
+
function defaultStoreDbPath() {
|
|
74120
|
+
return path6.join(homeDir(), ".agent-remnote", "store.sqlite");
|
|
74121
|
+
}
|
|
74122
|
+
function defaultUserConfigFilePath() {
|
|
74123
|
+
return path6.join(homeDir(), ".agent-remnote", "config.json");
|
|
74124
|
+
}
|
|
74125
|
+
function wsUrlFromPort(port3) {
|
|
74126
|
+
return `ws://localhost:${port3}/ws`;
|
|
74127
|
+
}
|
|
74128
|
+
function defaultWsStateFilePath() {
|
|
74129
|
+
return path6.join(homeDir(), ".agent-remnote", "ws.bridge.state.json");
|
|
74130
|
+
}
|
|
74131
|
+
function defaultStatusLineFilePath() {
|
|
74132
|
+
return path6.join(homeDir(), ".agent-remnote", "status-line.txt");
|
|
74133
|
+
}
|
|
74134
|
+
function defaultStatusLineJsonFilePath() {
|
|
74135
|
+
return path6.join(homeDir(), ".agent-remnote", "status-line.json");
|
|
74136
|
+
}
|
|
74137
|
+
function defaultApiPidFilePath() {
|
|
74138
|
+
return path6.join(homeDir(), ".agent-remnote", "api.pid");
|
|
74139
|
+
}
|
|
74140
|
+
function defaultApiLogFilePath() {
|
|
74141
|
+
return path6.join(homeDir(), ".agent-remnote", "api.log");
|
|
74142
|
+
}
|
|
74143
|
+
function defaultApiStateFilePath() {
|
|
74144
|
+
return path6.join(homeDir(), ".agent-remnote", "api.state.json");
|
|
74145
|
+
}
|
|
74146
|
+
var ROOT_BOOL_FLAGS = new Set(["--json", "--md", "--ids", "--quiet", "--debug"]);
|
|
74147
|
+
var BUILTIN_BOOL_FLAGS = new Set(["--help", "-h", "--wizard", "--version"]);
|
|
74148
|
+
var BUILTIN_VALUE_FLAGS = new Set(["--completions", "--log-level"]);
|
|
74149
|
+
var ROOT_VALUE_FLAGS = new Set([
|
|
74150
|
+
"--remnote-db",
|
|
74151
|
+
"--store-db",
|
|
74152
|
+
"--daemon-url",
|
|
74153
|
+
"--ws-port",
|
|
74154
|
+
"--repo",
|
|
74155
|
+
"--api-base-url",
|
|
74156
|
+
"--config-file",
|
|
74157
|
+
...BUILTIN_VALUE_FLAGS
|
|
74158
|
+
]);
|
|
74159
|
+
function isBooleanLiteralToken(token) {
|
|
74160
|
+
const v = token.trim().toLowerCase();
|
|
74161
|
+
return v === "true" || v === "false";
|
|
74162
|
+
}
|
|
74163
|
+
function splitFlagInlineValue(token) {
|
|
74164
|
+
if (!token.startsWith("--"))
|
|
74165
|
+
return { flag: token, inlineValue: null };
|
|
74166
|
+
const eq = token.indexOf("=");
|
|
74167
|
+
if (eq === -1)
|
|
74168
|
+
return { flag: token, inlineValue: null };
|
|
74169
|
+
return { flag: token.slice(0, eq), inlineValue: token.slice(eq + 1) };
|
|
74170
|
+
}
|
|
74171
|
+
function isConfigCommandInvocation(argv) {
|
|
74172
|
+
const tokens = argv.slice(2);
|
|
74173
|
+
let i = 0;
|
|
74174
|
+
while (i < tokens.length) {
|
|
74175
|
+
const raw4 = String(tokens[i] ?? "");
|
|
74176
|
+
if (!raw4)
|
|
74177
|
+
break;
|
|
74178
|
+
if (raw4 === "--") {
|
|
74179
|
+
i += 1;
|
|
74180
|
+
break;
|
|
74181
|
+
}
|
|
74182
|
+
if (!raw4.startsWith("-"))
|
|
74183
|
+
break;
|
|
74184
|
+
const { flag, inlineValue } = splitFlagInlineValue(raw4);
|
|
74185
|
+
if (ROOT_VALUE_FLAGS.has(flag)) {
|
|
74186
|
+
i += inlineValue !== null ? 1 : 2;
|
|
74187
|
+
continue;
|
|
74188
|
+
}
|
|
74189
|
+
if (ROOT_BOOL_FLAGS.has(flag) || BUILTIN_BOOL_FLAGS.has(flag)) {
|
|
74190
|
+
if (inlineValue !== null) {
|
|
74191
|
+
i += 1;
|
|
74192
|
+
continue;
|
|
74193
|
+
}
|
|
74194
|
+
const next4 = tokens[i + 1];
|
|
74195
|
+
if (typeof next4 === "string" && isBooleanLiteralToken(next4)) {
|
|
74196
|
+
i += 2;
|
|
74197
|
+
continue;
|
|
74198
|
+
}
|
|
74199
|
+
i += 1;
|
|
74200
|
+
continue;
|
|
74201
|
+
}
|
|
74202
|
+
break;
|
|
74203
|
+
}
|
|
74204
|
+
return tokens[i] === "config";
|
|
74205
|
+
}
|
|
74206
|
+
function normalizeApiBasePath(raw4) {
|
|
74207
|
+
const trimmed2 = raw4.trim();
|
|
74208
|
+
if (!trimmed2)
|
|
74209
|
+
return "/v1";
|
|
74210
|
+
return trimmed2.startsWith("/") ? trimmed2 : `/${trimmed2}`;
|
|
74211
|
+
}
|
|
74212
|
+
function normalizeApiBaseUrl(raw4) {
|
|
74213
|
+
const trimmed2 = raw4.trim();
|
|
74214
|
+
if (!trimmed2)
|
|
74215
|
+
return trimmed2;
|
|
74216
|
+
let parsed;
|
|
74217
|
+
try {
|
|
74218
|
+
parsed = new URL(trimmed2);
|
|
74219
|
+
} catch {
|
|
74220
|
+
throw new CliError({
|
|
74221
|
+
code: "INVALID_ARGS",
|
|
74222
|
+
message: `Invalid apiBaseUrl: ${trimmed2}`,
|
|
74223
|
+
exitCode: 2,
|
|
74224
|
+
details: { api_base_url: trimmed2 }
|
|
74225
|
+
});
|
|
74226
|
+
}
|
|
74227
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
74228
|
+
throw new CliError({
|
|
74229
|
+
code: "INVALID_ARGS",
|
|
74230
|
+
message: `apiBaseUrl protocol must be http/https: ${trimmed2}`,
|
|
74231
|
+
exitCode: 2,
|
|
74232
|
+
details: { api_base_url: trimmed2 }
|
|
74233
|
+
});
|
|
74234
|
+
}
|
|
74235
|
+
const normalized = trimmed2.replace(/\/+$/, "");
|
|
74236
|
+
return normalized;
|
|
74237
|
+
}
|
|
74238
|
+
function resolveWsStateFile(spec) {
|
|
74239
|
+
const raw4 = spec.trim();
|
|
74240
|
+
if (raw4 === "0" || raw4.toLowerCase() === "false") {
|
|
74241
|
+
return { disabled: true, path: defaultWsStateFilePath() };
|
|
74242
|
+
}
|
|
74243
|
+
if (raw4)
|
|
74244
|
+
return { disabled: false, path: resolveUserFilePath(raw4) };
|
|
74245
|
+
return { disabled: false, path: defaultWsStateFilePath() };
|
|
74246
|
+
}
|
|
74247
|
+
function inferRemnoteDbFromWsState(params3) {
|
|
74248
|
+
if (params3.wsStateFile.disabled)
|
|
74249
|
+
return;
|
|
74250
|
+
const state = readJson(params3.wsStateFile.path);
|
|
74251
|
+
if (!state)
|
|
74252
|
+
return;
|
|
74253
|
+
const now2 = Date.now();
|
|
74254
|
+
const updatedAt = Number(state.updatedAt ?? 0);
|
|
74255
|
+
const staleMs = params3.wsStateStaleMs;
|
|
74256
|
+
const stale = !Number.isFinite(updatedAt) || updatedAt <= 0 || now2 - updatedAt > staleMs;
|
|
74257
|
+
if (stale)
|
|
74258
|
+
return;
|
|
74259
|
+
const clients = Array.isArray(state.clients) ? state.clients : [];
|
|
74260
|
+
const activeConnIdRaw = typeof state.activeWorkerConnId === "string" ? state.activeWorkerConnId.trim() : "";
|
|
74261
|
+
const client = pickClient(clients, activeConnIdRaw || undefined);
|
|
74262
|
+
const kbIdRaw = typeof client?.uiContext?.kbId === "string" ? client.uiContext.kbId.trim() : "";
|
|
74263
|
+
if (!kbIdRaw)
|
|
74264
|
+
return;
|
|
74265
|
+
const dbPath = resolveUserFilePath(remnoteDbPathForWorkspaceId(kbIdRaw));
|
|
74266
|
+
try {
|
|
74267
|
+
return fs3.statSync(dbPath).isFile() ? dbPath : undefined;
|
|
74268
|
+
} catch {
|
|
74269
|
+
return;
|
|
74270
|
+
}
|
|
74271
|
+
}
|
|
74272
|
+
function pickFormat(raw4) {
|
|
74273
|
+
const json4 = raw4.json === true;
|
|
74274
|
+
const md = raw4.md === true;
|
|
74275
|
+
const ids3 = raw4.ids === true;
|
|
74276
|
+
const count4 = [json4, md, ids3].filter(Boolean).length;
|
|
74277
|
+
if (count4 > 1) {
|
|
74278
|
+
throw new CliError({
|
|
74279
|
+
code: "INVALID_ARGS",
|
|
74280
|
+
message: "Output format conflict: choose only one of --json/--md/--ids",
|
|
74281
|
+
exitCode: 2,
|
|
74282
|
+
details: { json: json4, md, ids: ids3 }
|
|
74283
|
+
});
|
|
74284
|
+
}
|
|
74285
|
+
if (json4)
|
|
74286
|
+
return "json";
|
|
74287
|
+
if (ids3)
|
|
74288
|
+
return "ids";
|
|
74289
|
+
return "md";
|
|
74290
|
+
}
|
|
74291
|
+
var rawConfigSpec = all8({
|
|
74292
|
+
json: boolean4("json").pipe(withDefault2(false)),
|
|
74293
|
+
md: boolean4("md").pipe(withDefault2(false)),
|
|
74294
|
+
ids: boolean4("ids").pipe(withDefault2(false)),
|
|
74295
|
+
quiet: boolean4("quiet").pipe(withDefault2(false)),
|
|
74296
|
+
debug: boolean4("debug").pipe(withDefault2(false)),
|
|
74297
|
+
configFile: string5("configFile").pipe(withDefault2(defaultUserConfigFilePath())),
|
|
74298
|
+
remnoteDb: string5("remnoteDb").pipe(withDefault2("")),
|
|
74299
|
+
storeDb: string5("storeDb").pipe(withDefault2(defaultStoreDbPath())),
|
|
74300
|
+
daemonUrl: string5("daemonUrl").pipe(withDefault2("")),
|
|
74301
|
+
wsPort: port2("wsPort").pipe(withDefault2(6789)),
|
|
74302
|
+
wsScheduler: boolean4("wsScheduler").pipe(withDefault2(true)),
|
|
74303
|
+
wsDispatchMaxBytes: integer2("wsDispatchMaxBytes").pipe(withDefault2(512000), validate3({
|
|
74304
|
+
message: "wsDispatchMaxBytes must be a positive integer",
|
|
74305
|
+
validation: (n) => Number.isFinite(n) && n > 0
|
|
74306
|
+
})),
|
|
74307
|
+
wsDispatchMaxOpBytes: integer2("wsDispatchMaxOpBytes").pipe(withDefault2(256000), validate3({
|
|
74308
|
+
message: "wsDispatchMaxOpBytes must be a positive integer",
|
|
74309
|
+
validation: (n) => Number.isFinite(n) && n > 0
|
|
74310
|
+
})),
|
|
74311
|
+
repo: string5("repo").pipe(withDefault2("")),
|
|
74312
|
+
wsStateFile: string5("wsStateFile").pipe(withDefault2("")),
|
|
74313
|
+
wsStateStaleMs: integer2("wsStateStaleMs").pipe(withDefault2(60000), validate3({
|
|
74314
|
+
message: "wsStateStaleMs must be a positive integer",
|
|
74315
|
+
validation: (n) => Number.isFinite(n) && n > 0
|
|
74316
|
+
})),
|
|
74317
|
+
tmuxRefresh: boolean4("tmuxRefresh").pipe(withDefault2(true)),
|
|
74318
|
+
tmuxRefreshMinIntervalMs: integer2("tmuxRefreshMinIntervalMs").pipe(withDefault2(250), validate3({
|
|
74319
|
+
message: "tmuxRefreshMinIntervalMs must be a positive integer",
|
|
74320
|
+
validation: (n) => Number.isFinite(n) && n > 0
|
|
74321
|
+
})),
|
|
74322
|
+
statusLineFile: string5("statusLineFile").pipe(withDefault2(defaultStatusLineFilePath())),
|
|
74323
|
+
statusLineMinIntervalMs: integer2("statusLineMinIntervalMs").pipe(withDefault2(250), validate3({
|
|
74324
|
+
message: "statusLineMinIntervalMs must be a positive integer",
|
|
74325
|
+
validation: (n) => Number.isFinite(n) && n > 0
|
|
74326
|
+
})),
|
|
74327
|
+
statusLineDebug: boolean4("statusLineDebug").pipe(withDefault2(false)),
|
|
74328
|
+
statusLineJsonFile: string5("statusLineJsonFile").pipe(withDefault2(defaultStatusLineJsonFilePath())),
|
|
74329
|
+
apiBaseUrl: string5("apiBaseUrl").pipe(withDefault2("")),
|
|
74330
|
+
apiHost: string5("apiHost").pipe(withDefault2("0.0.0.0")),
|
|
74331
|
+
apiPort: port2("apiPort").pipe(withDefault2(3000)),
|
|
74332
|
+
apiBasePath: string5("apiBasePath").pipe(withDefault2("/v1")),
|
|
74333
|
+
apiPidFile: string5("apiPidFile").pipe(withDefault2(defaultApiPidFilePath())),
|
|
74334
|
+
apiLogFile: string5("apiLogFile").pipe(withDefault2(defaultApiLogFilePath())),
|
|
74335
|
+
apiStateFile: string5("apiStateFile").pipe(withDefault2(defaultApiStateFilePath()))
|
|
74336
|
+
});
|
|
74337
|
+
function cliErrorFromConfigError(error4) {
|
|
74338
|
+
if (isInvalidData2(error4) || isMissingData2(error4)) {
|
|
74339
|
+
return new CliError({
|
|
74340
|
+
code: "INVALID_ARGS",
|
|
74341
|
+
message: error4.message || "Invalid configuration",
|
|
74342
|
+
exitCode: 2,
|
|
74343
|
+
details: { path: error4.path, op: error4._op }
|
|
74344
|
+
});
|
|
74345
|
+
}
|
|
74346
|
+
return new CliError({
|
|
74347
|
+
code: "INVALID_ARGS",
|
|
74348
|
+
message: error4.message || "Invalid configuration",
|
|
74349
|
+
exitCode: 2,
|
|
74350
|
+
details: { op: error4._op }
|
|
74351
|
+
});
|
|
74352
|
+
}
|
|
74353
|
+
function optionalTrimmed(s) {
|
|
74354
|
+
const t = s.trim();
|
|
74355
|
+
return t.length > 0 ? t : undefined;
|
|
74356
|
+
}
|
|
74357
|
+
function readUserConfigFile(configFile) {
|
|
74358
|
+
const file6 = resolveUserFilePath(configFile);
|
|
74359
|
+
let rawText = "";
|
|
74360
|
+
try {
|
|
74361
|
+
rawText = fs3.readFileSync(file6, "utf8");
|
|
74362
|
+
} catch (error4) {
|
|
74363
|
+
if (error4?.code === "ENOENT")
|
|
74364
|
+
return {};
|
|
74365
|
+
throw new CliError({
|
|
74366
|
+
code: "INVALID_ARGS",
|
|
74367
|
+
message: `Failed to read config file: ${file6}`,
|
|
74368
|
+
exitCode: 2,
|
|
74369
|
+
details: { config_file: file6, error: String(error4?.message || error4) }
|
|
74370
|
+
});
|
|
74371
|
+
}
|
|
74372
|
+
let parsed;
|
|
74373
|
+
try {
|
|
74374
|
+
parsed = JSON.parse(rawText);
|
|
74375
|
+
} catch (error4) {
|
|
74376
|
+
throw new CliError({
|
|
74377
|
+
code: "INVALID_ARGS",
|
|
74378
|
+
message: `Invalid JSON in config file: ${file6}`,
|
|
74379
|
+
exitCode: 2,
|
|
74380
|
+
details: { config_file: file6, error: String(error4?.message || error4) }
|
|
74381
|
+
});
|
|
74382
|
+
}
|
|
74383
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
74384
|
+
throw new CliError({
|
|
74385
|
+
code: "INVALID_ARGS",
|
|
74386
|
+
message: `Config file must contain a JSON object: ${file6}`,
|
|
74387
|
+
exitCode: 2,
|
|
74388
|
+
details: { config_file: file6 }
|
|
74389
|
+
});
|
|
74390
|
+
}
|
|
74391
|
+
const config3 = parsed;
|
|
74392
|
+
const api = config3.api;
|
|
74393
|
+
const nestedBaseUrl = api && typeof api === "object" && !Array.isArray(api) ? api.baseUrl : undefined;
|
|
74394
|
+
const apiBaseUrl = config3.apiBaseUrl ?? nestedBaseUrl;
|
|
74395
|
+
if (apiBaseUrl === undefined)
|
|
74396
|
+
return {};
|
|
74397
|
+
if (typeof apiBaseUrl !== "string") {
|
|
74398
|
+
throw new CliError({
|
|
74399
|
+
code: "INVALID_ARGS",
|
|
74400
|
+
message: `Config key apiBaseUrl must be a string: ${file6}`,
|
|
74401
|
+
exitCode: 2,
|
|
74402
|
+
details: { config_file: file6 }
|
|
74403
|
+
});
|
|
74404
|
+
}
|
|
74405
|
+
return { apiBaseUrl };
|
|
74406
|
+
}
|
|
74407
|
+
function resolveConfig() {
|
|
74408
|
+
return gen2(function* () {
|
|
74409
|
+
const raw4 = yield* rawConfigSpec;
|
|
74410
|
+
const configFile = resolveUserFilePath(raw4.configFile);
|
|
74411
|
+
const userConfigResult = yield* either3(try_3({
|
|
74412
|
+
try: () => readUserConfigFile(configFile),
|
|
74413
|
+
catch: (error4) => isCliError(error4) ? error4 : new CliError({
|
|
74414
|
+
code: "INVALID_ARGS",
|
|
74415
|
+
message: `Failed to load config file: ${configFile}`,
|
|
74416
|
+
exitCode: 2,
|
|
74417
|
+
details: { config_file: configFile, error: String(error4?.message || error4) }
|
|
74418
|
+
})
|
|
74419
|
+
}));
|
|
74420
|
+
const userConfig = userConfigResult._tag === "Right" ? userConfigResult.right : isConfigCommandInvocation(process.argv) ? {} : yield* fail8(userConfigResult.left);
|
|
74421
|
+
const wsStateFile = resolveWsStateFile(raw4.wsStateFile);
|
|
74422
|
+
const remnoteDb = optionalTrimmed(raw4.remnoteDb) ? resolveUserFilePath(raw4.remnoteDb) : inferRemnoteDbFromWsState({ wsStateFile, wsStateStaleMs: raw4.wsStateStaleMs }) || undefined;
|
|
74423
|
+
const storeDb = resolveUserFilePath(raw4.storeDb);
|
|
74424
|
+
const daemonUrl = optionalTrimmed(raw4.daemonUrl);
|
|
74425
|
+
const wsUrl = daemonUrl ? daemonUrl : wsUrlFromPort(raw4.wsPort);
|
|
74426
|
+
const format8 = yield* try_3({
|
|
74427
|
+
try: () => pickFormat(raw4),
|
|
74428
|
+
catch: (e) => isCliError(e) ? e : new CliError({
|
|
74429
|
+
code: "INVALID_ARGS",
|
|
74430
|
+
message: "Invalid output format flags",
|
|
74431
|
+
exitCode: 2,
|
|
74432
|
+
details: { error: String(e?.message || e) }
|
|
74433
|
+
})
|
|
74434
|
+
});
|
|
74435
|
+
const apiBaseUrlRaw = optionalTrimmed(raw4.apiBaseUrl) ?? optionalTrimmed(userConfig.apiBaseUrl ?? "");
|
|
74436
|
+
const apiBaseUrl = apiBaseUrlRaw ? normalizeApiBaseUrl(apiBaseUrlRaw) : undefined;
|
|
74437
|
+
return {
|
|
74438
|
+
format: format8,
|
|
74439
|
+
quiet: raw4.quiet,
|
|
74440
|
+
debug: raw4.debug,
|
|
74441
|
+
configFile,
|
|
74442
|
+
remnoteDb,
|
|
74443
|
+
storeDb,
|
|
74444
|
+
wsUrl,
|
|
74445
|
+
wsScheduler: raw4.wsScheduler,
|
|
74446
|
+
wsDispatchMaxBytes: raw4.wsDispatchMaxBytes,
|
|
74447
|
+
wsDispatchMaxOpBytes: raw4.wsDispatchMaxOpBytes,
|
|
74448
|
+
repo: optionalTrimmed(raw4.repo) ? resolveUserFilePath(raw4.repo) : undefined,
|
|
74449
|
+
wsStateFile,
|
|
74450
|
+
wsStateStaleMs: raw4.wsStateStaleMs,
|
|
74451
|
+
tmuxRefresh: raw4.tmuxRefresh,
|
|
74452
|
+
tmuxRefreshMinIntervalMs: raw4.tmuxRefreshMinIntervalMs,
|
|
74453
|
+
statusLineFile: resolveUserFilePath(raw4.statusLineFile),
|
|
74454
|
+
statusLineMinIntervalMs: raw4.statusLineMinIntervalMs,
|
|
74455
|
+
statusLineDebug: raw4.statusLineDebug,
|
|
74456
|
+
statusLineJsonFile: resolveUserFilePath(raw4.statusLineJsonFile),
|
|
74457
|
+
apiBaseUrl,
|
|
74458
|
+
apiHost: raw4.apiHost.trim() || "0.0.0.0",
|
|
74459
|
+
apiPort: raw4.apiPort,
|
|
74460
|
+
apiBasePath: normalizeApiBasePath(raw4.apiBasePath),
|
|
74461
|
+
apiPidFile: resolveUserFilePath(raw4.apiPidFile),
|
|
74462
|
+
apiLogFile: resolveUserFilePath(raw4.apiLogFile),
|
|
74463
|
+
apiStateFile: resolveUserFilePath(raw4.apiStateFile)
|
|
74464
|
+
};
|
|
74465
|
+
}).pipe(catchAll2((error4) => {
|
|
74466
|
+
if (isCliError(error4))
|
|
74467
|
+
return fail8(error4);
|
|
74468
|
+
if (isConfigError2(error4))
|
|
74469
|
+
return fail8(cliErrorFromConfigError(error4));
|
|
74470
|
+
return fail8(new CliError({
|
|
74471
|
+
code: "INTERNAL",
|
|
74472
|
+
message: "Failed to parse config",
|
|
74473
|
+
exitCode: 1,
|
|
74474
|
+
details: { error: String(error4?.message || error4) }
|
|
74475
|
+
}));
|
|
74476
|
+
}));
|
|
74477
|
+
}
|
|
74478
|
+
|
|
74479
|
+
// src/services/UserConfigFile.ts
|
|
74480
|
+
class UserConfigFile extends Tag2("UserConfigFile")() {
|
|
74481
|
+
}
|
|
74482
|
+
function canonicalKey(input) {
|
|
74483
|
+
const key = String(input ?? "").trim();
|
|
74484
|
+
if (!key) {
|
|
74485
|
+
throw new CliError({ code: "INVALID_ARGS", message: "Config key is required", exitCode: 2 });
|
|
74486
|
+
}
|
|
74487
|
+
if (key === "apiBaseUrl" || key === "api.baseUrl" || key === "api-base-url")
|
|
74488
|
+
return "apiBaseUrl";
|
|
74489
|
+
throw new CliError({ code: "INVALID_ARGS", message: `Unsupported config key: ${key}`, exitCode: 2 });
|
|
74490
|
+
}
|
|
74491
|
+
function isPlainObject(value8) {
|
|
74492
|
+
return typeof value8 === "object" && value8 !== null && !Array.isArray(value8);
|
|
74493
|
+
}
|
|
74494
|
+
function cloneDoc(doc) {
|
|
74495
|
+
return JSON.parse(JSON.stringify(doc));
|
|
74496
|
+
}
|
|
74497
|
+
function removeEmptyApiObject(doc) {
|
|
74498
|
+
const api = doc.api;
|
|
74499
|
+
if (!isPlainObject(api))
|
|
74500
|
+
return;
|
|
74501
|
+
if (Object.keys(api).length === 0)
|
|
74502
|
+
delete doc.api;
|
|
74503
|
+
}
|
|
74504
|
+
function readApiBaseUrl(doc) {
|
|
74505
|
+
const errors3 = [];
|
|
74506
|
+
const root = doc.apiBaseUrl;
|
|
74507
|
+
const api = doc.api;
|
|
74508
|
+
const nested4 = isPlainObject(api) ? api.baseUrl : undefined;
|
|
74509
|
+
const rootValue = root === undefined ? undefined : typeof root === "string" ? root : (errors3.push("Config key apiBaseUrl must be a string"), undefined);
|
|
74510
|
+
const nestedValue = nested4 === undefined ? undefined : typeof nested4 === "string" ? nested4 : (errors3.push("Config key api.baseUrl must be a string"), undefined);
|
|
74511
|
+
if (rootValue && nestedValue && rootValue !== nestedValue) {
|
|
74512
|
+
errors3.push("Config keys apiBaseUrl and api.baseUrl conflict");
|
|
74513
|
+
}
|
|
74514
|
+
return { value: rootValue ?? nestedValue, errors: errors3 };
|
|
74515
|
+
}
|
|
74516
|
+
function inspectDoc(configFile, exists3, doc) {
|
|
74517
|
+
const apiBaseUrl = readApiBaseUrl(doc);
|
|
74518
|
+
const unknownKeys = [];
|
|
74519
|
+
for (const key of Object.keys(doc)) {
|
|
74520
|
+
if (key === "apiBaseUrl")
|
|
74521
|
+
continue;
|
|
74522
|
+
if (key !== "api") {
|
|
74523
|
+
unknownKeys.push(key);
|
|
74524
|
+
continue;
|
|
74525
|
+
}
|
|
74526
|
+
const api = doc.api;
|
|
74527
|
+
if (!isPlainObject(api)) {
|
|
74528
|
+
continue;
|
|
74529
|
+
}
|
|
74530
|
+
for (const nestedKey of Object.keys(api)) {
|
|
74531
|
+
if (nestedKey === "baseUrl")
|
|
74532
|
+
continue;
|
|
74533
|
+
unknownKeys.push(`api.${nestedKey}`);
|
|
74534
|
+
}
|
|
74535
|
+
}
|
|
74536
|
+
return {
|
|
74537
|
+
configFile,
|
|
74538
|
+
exists: exists3,
|
|
74539
|
+
values: { apiBaseUrl: apiBaseUrl.value },
|
|
74540
|
+
unknownKeys,
|
|
74541
|
+
errors: apiBaseUrl.errors,
|
|
74542
|
+
valid: apiBaseUrl.errors.length === 0
|
|
74543
|
+
};
|
|
74544
|
+
}
|
|
74545
|
+
async function ensureDir(filePath) {
|
|
74546
|
+
await fs4.mkdir(path7.dirname(filePath), { recursive: true });
|
|
74547
|
+
}
|
|
74548
|
+
async function readDocDetailed(configFile) {
|
|
74549
|
+
const file6 = resolveUserFilePath(configFile);
|
|
74550
|
+
let rawText = "";
|
|
74551
|
+
try {
|
|
74552
|
+
rawText = await fs4.readFile(file6, "utf8");
|
|
74553
|
+
} catch (error4) {
|
|
74554
|
+
if (error4?.code === "ENOENT")
|
|
74555
|
+
return { ok: true, exists: false, configFile: file6, doc: {} };
|
|
74556
|
+
return {
|
|
74557
|
+
ok: false,
|
|
74558
|
+
exists: true,
|
|
74559
|
+
configFile: file6,
|
|
74560
|
+
errors: [`Failed to read config file: ${file6}`]
|
|
74561
|
+
};
|
|
74562
|
+
}
|
|
74563
|
+
let parsed;
|
|
74564
|
+
try {
|
|
74565
|
+
parsed = JSON.parse(rawText);
|
|
74566
|
+
} catch {
|
|
74567
|
+
return {
|
|
74568
|
+
ok: false,
|
|
74569
|
+
exists: true,
|
|
74570
|
+
configFile: file6,
|
|
74571
|
+
errors: [`Invalid JSON in config file: ${file6}`]
|
|
74572
|
+
};
|
|
74573
|
+
}
|
|
74574
|
+
if (!isPlainObject(parsed)) {
|
|
74575
|
+
return {
|
|
74576
|
+
ok: false,
|
|
74577
|
+
exists: true,
|
|
74578
|
+
configFile: file6,
|
|
74579
|
+
errors: [`Config file must contain a JSON object: ${file6}`]
|
|
74580
|
+
};
|
|
74581
|
+
}
|
|
74582
|
+
return { ok: true, exists: true, configFile: file6, doc: parsed };
|
|
74583
|
+
}
|
|
74584
|
+
function requireParsedDoc(parsed) {
|
|
74585
|
+
if (parsed.ok)
|
|
74586
|
+
return parsed;
|
|
74587
|
+
throw new CliError({
|
|
74588
|
+
code: "INVALID_ARGS",
|
|
74589
|
+
message: parsed.errors[0] || "Invalid config file",
|
|
74590
|
+
exitCode: 2,
|
|
74591
|
+
details: { config_file: parsed.configFile, errors: parsed.errors }
|
|
74592
|
+
});
|
|
74593
|
+
}
|
|
74594
|
+
async function writeDoc(configFile, doc) {
|
|
74595
|
+
const file6 = resolveUserFilePath(configFile);
|
|
74596
|
+
await ensureDir(file6);
|
|
74597
|
+
const tmp = `${file6}.tmp-${process.pid}-${Date.now()}`;
|
|
74598
|
+
await fs4.writeFile(tmp, `${JSON.stringify(doc, null, 2)}
|
|
74599
|
+
`, "utf8");
|
|
74600
|
+
await fs4.rename(tmp, file6);
|
|
74601
|
+
}
|
|
74602
|
+
async function deleteDoc(configFile) {
|
|
74603
|
+
await fs4.rm(resolveUserFilePath(configFile), { force: true });
|
|
74604
|
+
}
|
|
74605
|
+
function setApiBaseUrl(doc, value8) {
|
|
74606
|
+
const next4 = cloneDoc(doc);
|
|
74607
|
+
next4.apiBaseUrl = normalizeApiBaseUrl(value8);
|
|
74608
|
+
const api = next4.api;
|
|
74609
|
+
if (isPlainObject(api)) {
|
|
74610
|
+
delete api.baseUrl;
|
|
74611
|
+
removeEmptyApiObject(next4);
|
|
74612
|
+
}
|
|
74613
|
+
return next4;
|
|
74614
|
+
}
|
|
74615
|
+
function unsetApiBaseUrl(doc) {
|
|
74616
|
+
const next4 = cloneDoc(doc);
|
|
74617
|
+
let removed = false;
|
|
74618
|
+
if (Object.prototype.hasOwnProperty.call(next4, "apiBaseUrl")) {
|
|
74619
|
+
delete next4.apiBaseUrl;
|
|
74620
|
+
removed = true;
|
|
74621
|
+
}
|
|
74622
|
+
const api = next4.api;
|
|
74623
|
+
if (isPlainObject(api) && Object.prototype.hasOwnProperty.call(api, "baseUrl")) {
|
|
74624
|
+
delete api.baseUrl;
|
|
74625
|
+
removeEmptyApiObject(next4);
|
|
74626
|
+
removed = true;
|
|
74627
|
+
}
|
|
74628
|
+
return { next: next4, removed };
|
|
74629
|
+
}
|
|
74630
|
+
function isEmptyDoc(doc) {
|
|
74631
|
+
return Object.keys(doc).length === 0;
|
|
74632
|
+
}
|
|
74633
|
+
function toCliFailure(error4, message) {
|
|
74634
|
+
return isCliError(error4) ? error4 : new CliError({
|
|
74635
|
+
code: "INVALID_ARGS",
|
|
74636
|
+
message,
|
|
74637
|
+
exitCode: 2,
|
|
74638
|
+
details: { error: String(error4?.message || error4) }
|
|
74639
|
+
});
|
|
74640
|
+
}
|
|
74641
|
+
var UserConfigFileLive = succeed10(UserConfigFile, {
|
|
74642
|
+
path: () => gen2(function* () {
|
|
74643
|
+
const cfg = yield* AppConfig;
|
|
74644
|
+
return cfg.configFile;
|
|
74645
|
+
}),
|
|
74646
|
+
inspect: () => gen2(function* () {
|
|
74647
|
+
const cfg = yield* AppConfig;
|
|
74648
|
+
const parsed = yield* promise2(() => readDocDetailed(cfg.configFile));
|
|
74649
|
+
if (!parsed.ok) {
|
|
74650
|
+
return {
|
|
74651
|
+
configFile: parsed.configFile,
|
|
74652
|
+
exists: parsed.exists,
|
|
74653
|
+
values: {},
|
|
74654
|
+
unknownKeys: [],
|
|
74655
|
+
errors: parsed.errors,
|
|
74656
|
+
valid: false
|
|
74657
|
+
};
|
|
74658
|
+
}
|
|
74659
|
+
return inspectDoc(parsed.configFile, parsed.exists, parsed.doc);
|
|
74660
|
+
}),
|
|
74661
|
+
get: (key) => gen2(function* () {
|
|
74662
|
+
const targetKey = yield* try_3({
|
|
74663
|
+
try: () => canonicalKey(key),
|
|
74664
|
+
catch: (error4) => toCliFailure(error4, "Invalid config key")
|
|
74665
|
+
});
|
|
74666
|
+
const cfg = yield* AppConfig;
|
|
74667
|
+
const parsed = yield* promise2(() => readDocDetailed(cfg.configFile));
|
|
74668
|
+
const { configFile, doc } = yield* try_3({
|
|
74669
|
+
try: () => requireParsedDoc(parsed),
|
|
74670
|
+
catch: (error4) => toCliFailure(error4, "Invalid config file")
|
|
74671
|
+
});
|
|
74672
|
+
const inspection = inspectDoc(configFile, parsed.exists, doc);
|
|
74673
|
+
const value8 = targetKey === "apiBaseUrl" ? inspection.values.apiBaseUrl ?? null : null;
|
|
74674
|
+
return {
|
|
74675
|
+
configFile,
|
|
74676
|
+
key: targetKey,
|
|
74677
|
+
exists: value8 !== null,
|
|
74678
|
+
value: value8
|
|
74679
|
+
};
|
|
74680
|
+
}),
|
|
74681
|
+
set: (key, value8) => gen2(function* () {
|
|
74682
|
+
const targetKey = yield* try_3({
|
|
74683
|
+
try: () => canonicalKey(key),
|
|
74684
|
+
catch: (error4) => toCliFailure(error4, "Invalid config key")
|
|
74685
|
+
});
|
|
74686
|
+
const cfg = yield* AppConfig;
|
|
74687
|
+
const parsed = yield* promise2(() => readDocDetailed(cfg.configFile));
|
|
74688
|
+
const { configFile, doc } = yield* try_3({
|
|
74689
|
+
try: () => requireParsedDoc(parsed),
|
|
74690
|
+
catch: (error4) => toCliFailure(error4, "Invalid config file")
|
|
74691
|
+
});
|
|
74692
|
+
const next4 = targetKey === "apiBaseUrl" ? yield* try_3({
|
|
74693
|
+
try: () => setApiBaseUrl(doc, value8),
|
|
74694
|
+
catch: (error4) => toCliFailure(error4, "Invalid config value")
|
|
74695
|
+
}) : doc;
|
|
74696
|
+
yield* tryPromise2({
|
|
74697
|
+
try: async () => await writeDoc(configFile, next4),
|
|
74698
|
+
catch: (error4) => new CliError({
|
|
74699
|
+
code: "INTERNAL",
|
|
74700
|
+
message: "Failed to write config file",
|
|
74701
|
+
exitCode: 1,
|
|
74702
|
+
details: { config_file: configFile, error: String(error4?.message || error4) }
|
|
74703
|
+
})
|
|
74704
|
+
});
|
|
74705
|
+
return {
|
|
74706
|
+
configFile,
|
|
74707
|
+
key: targetKey,
|
|
74708
|
+
value: String(next4.apiBaseUrl ?? ""),
|
|
74709
|
+
changed: true
|
|
74710
|
+
};
|
|
74711
|
+
}),
|
|
74712
|
+
unset: (key) => gen2(function* () {
|
|
74713
|
+
const targetKey = yield* try_3({
|
|
74714
|
+
try: () => canonicalKey(key),
|
|
74715
|
+
catch: (error4) => toCliFailure(error4, "Invalid config key")
|
|
74716
|
+
});
|
|
74717
|
+
const cfg = yield* AppConfig;
|
|
74718
|
+
const parsed = yield* promise2(() => readDocDetailed(cfg.configFile));
|
|
74719
|
+
const { configFile, doc, exists: exists3 } = yield* try_3({
|
|
74720
|
+
try: () => requireParsedDoc(parsed),
|
|
74721
|
+
catch: (error4) => toCliFailure(error4, "Invalid config file")
|
|
74722
|
+
});
|
|
74723
|
+
if (!exists3) {
|
|
74724
|
+
return {
|
|
74725
|
+
configFile,
|
|
74726
|
+
key: targetKey,
|
|
74727
|
+
removed: false,
|
|
74728
|
+
fileDeleted: false
|
|
74729
|
+
};
|
|
74730
|
+
}
|
|
74731
|
+
const result = targetKey === "apiBaseUrl" ? unsetApiBaseUrl(doc) : { next: doc, removed: false };
|
|
74732
|
+
if (!result.removed) {
|
|
74733
|
+
return {
|
|
74734
|
+
configFile,
|
|
74735
|
+
key: targetKey,
|
|
74736
|
+
removed: false,
|
|
74737
|
+
fileDeleted: false
|
|
74738
|
+
};
|
|
74739
|
+
}
|
|
74740
|
+
if (isEmptyDoc(result.next)) {
|
|
74741
|
+
yield* tryPromise2({
|
|
74742
|
+
try: async () => await deleteDoc(configFile),
|
|
74743
|
+
catch: (error4) => new CliError({
|
|
74744
|
+
code: "INTERNAL",
|
|
74745
|
+
message: "Failed to delete config file",
|
|
74746
|
+
exitCode: 1,
|
|
74747
|
+
details: { config_file: configFile, error: String(error4?.message || error4) }
|
|
74748
|
+
})
|
|
74749
|
+
});
|
|
74750
|
+
return {
|
|
74751
|
+
configFile,
|
|
74752
|
+
key: targetKey,
|
|
74753
|
+
removed: true,
|
|
74754
|
+
fileDeleted: true
|
|
74755
|
+
};
|
|
74756
|
+
}
|
|
74757
|
+
yield* tryPromise2({
|
|
74758
|
+
try: async () => await writeDoc(configFile, result.next),
|
|
74759
|
+
catch: (error4) => new CliError({
|
|
74760
|
+
code: "INTERNAL",
|
|
74761
|
+
message: "Failed to write config file",
|
|
74762
|
+
exitCode: 1,
|
|
74763
|
+
details: { config_file: configFile, error: String(error4?.message || error4) }
|
|
74764
|
+
})
|
|
74765
|
+
});
|
|
74766
|
+
return {
|
|
74767
|
+
configFile,
|
|
74768
|
+
key: targetKey,
|
|
74769
|
+
removed: true,
|
|
74770
|
+
fileDeleted: false
|
|
74771
|
+
};
|
|
74772
|
+
})
|
|
74773
|
+
});
|
|
74774
|
+
|
|
74775
|
+
// src/services/Output.ts
|
|
74776
|
+
class Output extends Tag2("Output")() {
|
|
74777
|
+
}
|
|
74778
|
+
var OutputLive = succeed10(Output, {
|
|
74779
|
+
stdout: (text14) => sync3(() => {
|
|
74780
|
+
process.stdout.write(text14);
|
|
74781
|
+
}),
|
|
74782
|
+
stderr: (text14) => sync3(() => {
|
|
74783
|
+
process.stderr.write(text14);
|
|
74784
|
+
}),
|
|
74785
|
+
json: (value8) => sync3(() => {
|
|
74786
|
+
process.stdout.write(`${JSON.stringify(value8)}
|
|
74787
|
+
`);
|
|
74788
|
+
})
|
|
74789
|
+
});
|
|
74790
|
+
|
|
74791
|
+
// src/commands/_shared.ts
|
|
74792
|
+
function ensureTrailingNewline(text14) {
|
|
74793
|
+
return text14.endsWith(`
|
|
74794
|
+
`) ? text14 : `${text14}
|
|
74795
|
+
`;
|
|
74796
|
+
}
|
|
74797
|
+
function formatHumanErrorLine(message) {
|
|
74798
|
+
const trimmed2 = String(message ?? "").trim();
|
|
74799
|
+
if (!trimmed2)
|
|
74800
|
+
return "Error: Unknown error";
|
|
74801
|
+
return trimmed2.startsWith("Error:") ? trimmed2 : `Error: ${trimmed2}`;
|
|
74802
|
+
}
|
|
74803
|
+
function readStringArray(value8) {
|
|
74804
|
+
if (!Array.isArray(value8))
|
|
74805
|
+
return [];
|
|
74806
|
+
return value8.map((v) => String(v ?? "").trim()).filter(Boolean);
|
|
74807
|
+
}
|
|
74808
|
+
function writeSuccess(params3) {
|
|
74809
|
+
return gen2(function* () {
|
|
74810
|
+
const config3 = yield* AppConfig;
|
|
74811
|
+
const out = yield* Output;
|
|
74812
|
+
if (config3.format === "json") {
|
|
74813
|
+
yield* out.json(ok(params3.data));
|
|
74814
|
+
return;
|
|
74815
|
+
}
|
|
74816
|
+
if (config3.quiet)
|
|
74817
|
+
return;
|
|
74818
|
+
if (config3.format === "ids") {
|
|
74819
|
+
if (!params3.ids || params3.ids.length === 0) {
|
|
74820
|
+
return yield* fail8(new CliError({
|
|
74821
|
+
code: "INVALID_ARGS",
|
|
74822
|
+
message: "This command does not support --ids output",
|
|
74823
|
+
exitCode: 2
|
|
74824
|
+
}));
|
|
74825
|
+
}
|
|
74826
|
+
yield* out.stdout(`${params3.ids.join(`
|
|
74827
|
+
`)}
|
|
74828
|
+
`);
|
|
74829
|
+
return;
|
|
74830
|
+
}
|
|
74831
|
+
if (params3.data && typeof params3.data === "object") {
|
|
74832
|
+
const anyData = params3.data;
|
|
74833
|
+
const warnings = readStringArray(anyData?.warnings);
|
|
74834
|
+
const nextActions = readStringArray(anyData?.nextActions);
|
|
74835
|
+
if (warnings.length > 0) {
|
|
74836
|
+
yield* out.stderr(`Warnings:
|
|
74837
|
+
`);
|
|
74838
|
+
for (const w of warnings)
|
|
74839
|
+
yield* out.stderr(`- ${w}
|
|
74840
|
+
`);
|
|
74841
|
+
}
|
|
74842
|
+
if (nextActions.length > 0) {
|
|
74843
|
+
yield* out.stderr(`Next actions:
|
|
74844
|
+
`);
|
|
74845
|
+
for (const a of nextActions)
|
|
74846
|
+
yield* out.stderr(`- ${a}
|
|
74847
|
+
`);
|
|
74848
|
+
}
|
|
74849
|
+
}
|
|
74850
|
+
const md = params3.md ?? "";
|
|
74851
|
+
if (md.trim().length > 0) {
|
|
74852
|
+
yield* out.stdout(ensureTrailingNewline(md));
|
|
74853
|
+
}
|
|
74854
|
+
});
|
|
74855
|
+
}
|
|
74856
|
+
function writeFailure(error4) {
|
|
74857
|
+
return gen2(function* () {
|
|
74858
|
+
const config3 = yield* AppConfig;
|
|
74859
|
+
const out = yield* Output;
|
|
74860
|
+
if (config3.format === "json") {
|
|
74861
|
+
return yield* fail8(error4);
|
|
74862
|
+
}
|
|
74863
|
+
globalThis.__REMNOTE_CLI_ERROR_REPORTED__ = true;
|
|
74864
|
+
yield* out.stderr(ensureTrailingNewline(formatHumanErrorLine(error4.message)));
|
|
74865
|
+
if (config3.debug && error4.details !== undefined) {
|
|
74866
|
+
yield* out.stderr(`${JSON.stringify(error4.details, null, 2)}
|
|
74867
|
+
`);
|
|
74868
|
+
}
|
|
74869
|
+
if (error4.hint && error4.hint.length > 0) {
|
|
74870
|
+
yield* out.stderr(`Hint:
|
|
74871
|
+
`);
|
|
74872
|
+
for (const h of error4.hint) {
|
|
74873
|
+
yield* out.stderr(`- ${h}
|
|
74874
|
+
`);
|
|
74875
|
+
}
|
|
74876
|
+
}
|
|
74877
|
+
return yield* fail8(error4);
|
|
74878
|
+
});
|
|
73971
74879
|
}
|
|
73972
74880
|
|
|
73973
|
-
// src/
|
|
73974
|
-
|
|
73975
|
-
|
|
73976
|
-
|
|
73977
|
-
|
|
73978
|
-
|
|
73979
|
-
|
|
73980
|
-
|
|
73981
|
-
|
|
73982
|
-
|
|
73983
|
-
|
|
73984
|
-
|
|
73985
|
-
|
|
73986
|
-
|
|
73987
|
-
|
|
73988
|
-
|
|
73989
|
-
|
|
73990
|
-
|
|
73991
|
-
|
|
73992
|
-
|
|
73993
|
-
|
|
73994
|
-
|
|
73995
|
-
|
|
73996
|
-
|
|
74881
|
+
// src/commands/config/get.ts
|
|
74882
|
+
var configGetCommand = exports_Command.make("get", { key: text9("key") }, ({ key }) => gen2(function* () {
|
|
74883
|
+
const userConfig = yield* UserConfigFile;
|
|
74884
|
+
const data = yield* userConfig.get(key);
|
|
74885
|
+
yield* writeSuccess({
|
|
74886
|
+
data: {
|
|
74887
|
+
config_file: data.configFile,
|
|
74888
|
+
key: data.key,
|
|
74889
|
+
exists: data.exists,
|
|
74890
|
+
value: data.value
|
|
74891
|
+
},
|
|
74892
|
+
md: data.value === null ? "" : `${data.value}
|
|
74893
|
+
`
|
|
74894
|
+
});
|
|
74895
|
+
}).pipe(catchAll2(writeFailure)));
|
|
74896
|
+
|
|
74897
|
+
// src/commands/config/list.ts
|
|
74898
|
+
var configListCommand = exports_Command.make("list", {}, () => gen2(function* () {
|
|
74899
|
+
const userConfig = yield* UserConfigFile;
|
|
74900
|
+
const inspection = yield* userConfig.inspect();
|
|
74901
|
+
const data = {
|
|
74902
|
+
config_file: inspection.configFile,
|
|
74903
|
+
exists: inspection.exists,
|
|
74904
|
+
valid: inspection.valid,
|
|
74905
|
+
values: inspection.values,
|
|
74906
|
+
unknown_keys: inspection.unknownKeys,
|
|
74907
|
+
errors: inspection.errors
|
|
74908
|
+
};
|
|
74909
|
+
const mdLines = [
|
|
74910
|
+
`- config_file: ${data.config_file}`,
|
|
74911
|
+
`- exists: ${data.exists}`,
|
|
74912
|
+
`- valid: ${data.valid}`,
|
|
74913
|
+
`- apiBaseUrl: ${data.values.apiBaseUrl ?? ""}`,
|
|
74914
|
+
`- unknown_keys: ${data.unknown_keys.join(", ")}`,
|
|
74915
|
+
`- errors: ${data.errors.join(" | ")}`
|
|
74916
|
+
];
|
|
74917
|
+
yield* writeSuccess({ data, md: `${mdLines.join(`
|
|
74918
|
+
`)}
|
|
74919
|
+
` });
|
|
74920
|
+
}).pipe(catchAll2(writeFailure)));
|
|
74921
|
+
|
|
74922
|
+
// src/commands/config/path.ts
|
|
74923
|
+
var configPathCommand = exports_Command.make("path", {}, () => gen2(function* () {
|
|
74924
|
+
const userConfig = yield* UserConfigFile;
|
|
74925
|
+
const configFile = yield* userConfig.path();
|
|
74926
|
+
yield* writeSuccess({
|
|
74927
|
+
data: { config_file: configFile },
|
|
74928
|
+
md: `${configFile}
|
|
74929
|
+
`
|
|
74930
|
+
});
|
|
74931
|
+
}).pipe(catchAll2(writeFailure)));
|
|
73997
74932
|
|
|
73998
74933
|
// src/services/DaemonFiles.ts
|
|
74934
|
+
import { promises as fs5 } from "node:fs";
|
|
74935
|
+
import path8 from "node:path";
|
|
73999
74936
|
class DaemonFiles extends Tag2("DaemonFiles")() {
|
|
74000
74937
|
}
|
|
74001
|
-
function
|
|
74002
|
-
return
|
|
74938
|
+
function ensureDir2(p3) {
|
|
74939
|
+
return fs5.mkdir(path8.dirname(p3), { recursive: true }).then(() => {
|
|
74003
74940
|
return;
|
|
74004
74941
|
});
|
|
74005
74942
|
}
|
|
@@ -74007,19 +74944,19 @@ function defaultPidFile() {
|
|
|
74007
74944
|
const envPidFile = process.env.REMNOTE_DAEMON_PID_FILE || process.env.DAEMON_PID_FILE;
|
|
74008
74945
|
if (typeof envPidFile === "string" && envPidFile.trim())
|
|
74009
74946
|
return resolveUserFilePath(envPidFile);
|
|
74010
|
-
return
|
|
74947
|
+
return path8.join(homeDir(), ".agent-remnote", "ws.pid");
|
|
74011
74948
|
}
|
|
74012
74949
|
function defaultLogFile() {
|
|
74013
74950
|
const envLogFile = process.env.REMNOTE_DAEMON_LOG_FILE || process.env.DAEMON_LOG_FILE;
|
|
74014
74951
|
if (typeof envLogFile === "string" && envLogFile.trim())
|
|
74015
74952
|
return resolveUserFilePath(envLogFile);
|
|
74016
|
-
return
|
|
74953
|
+
return path8.join(homeDir(), ".agent-remnote", "ws.log");
|
|
74017
74954
|
}
|
|
74018
74955
|
async function writeJsonAtomic(filePath, json4) {
|
|
74019
|
-
await
|
|
74956
|
+
await ensureDir2(filePath);
|
|
74020
74957
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
74021
|
-
await
|
|
74022
|
-
await
|
|
74958
|
+
await fs5.writeFile(tmp, JSON.stringify(json4), "utf8");
|
|
74959
|
+
await fs5.rename(tmp, filePath);
|
|
74023
74960
|
}
|
|
74024
74961
|
var DaemonFilesLive = succeed10(DaemonFiles, {
|
|
74025
74962
|
defaultPidFile: () => defaultPidFile(),
|
|
@@ -74027,7 +74964,7 @@ var DaemonFilesLive = succeed10(DaemonFiles, {
|
|
|
74027
74964
|
readPidFile: (pidFilePath) => tryPromise2({
|
|
74028
74965
|
try: async () => {
|
|
74029
74966
|
try {
|
|
74030
|
-
const raw4 = await
|
|
74967
|
+
const raw4 = await fs5.readFile(pidFilePath, "utf8");
|
|
74031
74968
|
const parsed = JSON.parse(raw4);
|
|
74032
74969
|
return parsed;
|
|
74033
74970
|
} catch (error4) {
|
|
@@ -74065,7 +75002,7 @@ var DaemonFilesLive = succeed10(DaemonFiles, {
|
|
|
74065
75002
|
deletePidFile: (pidFilePath) => tryPromise2({
|
|
74066
75003
|
try: async () => {
|
|
74067
75004
|
try {
|
|
74068
|
-
await
|
|
75005
|
+
await fs5.unlink(pidFilePath);
|
|
74069
75006
|
} catch (error4) {
|
|
74070
75007
|
if (error4?.code === "ENOENT")
|
|
74071
75008
|
return;
|
|
@@ -74086,30 +75023,30 @@ var DaemonFilesLive = succeed10(DaemonFiles, {
|
|
|
74086
75023
|
});
|
|
74087
75024
|
|
|
74088
75025
|
// src/services/SupervisorState.ts
|
|
74089
|
-
import { promises as
|
|
74090
|
-
import
|
|
75026
|
+
import { promises as fs6 } from "node:fs";
|
|
75027
|
+
import path9 from "node:path";
|
|
74091
75028
|
class SupervisorState extends Tag2("SupervisorState")() {
|
|
74092
75029
|
}
|
|
74093
|
-
function
|
|
74094
|
-
return
|
|
75030
|
+
function ensureDir3(p3) {
|
|
75031
|
+
return fs6.mkdir(path9.dirname(p3), { recursive: true }).then(() => {
|
|
74095
75032
|
return;
|
|
74096
75033
|
});
|
|
74097
75034
|
}
|
|
74098
75035
|
function defaultStateFile() {
|
|
74099
|
-
return
|
|
75036
|
+
return path9.join(homeDir(), ".agent-remnote", "ws.state.json");
|
|
74100
75037
|
}
|
|
74101
75038
|
async function writeJsonAtomic2(filePath, json4) {
|
|
74102
|
-
await
|
|
75039
|
+
await ensureDir3(filePath);
|
|
74103
75040
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
74104
|
-
await
|
|
74105
|
-
await
|
|
75041
|
+
await fs6.writeFile(tmp, JSON.stringify(json4), "utf8");
|
|
75042
|
+
await fs6.rename(tmp, filePath);
|
|
74106
75043
|
}
|
|
74107
75044
|
var SupervisorStateLive = succeed10(SupervisorState, {
|
|
74108
75045
|
defaultStateFile: () => defaultStateFile(),
|
|
74109
75046
|
readStateFile: (stateFilePath) => tryPromise2({
|
|
74110
75047
|
try: async () => {
|
|
74111
75048
|
try {
|
|
74112
|
-
const raw4 = await
|
|
75049
|
+
const raw4 = await fs6.readFile(stateFilePath, "utf8");
|
|
74113
75050
|
const parsed = JSON.parse(raw4);
|
|
74114
75051
|
return parsed;
|
|
74115
75052
|
} catch (error4) {
|
|
@@ -74117,161 +75054,55 @@ var SupervisorStateLive = succeed10(SupervisorState, {
|
|
|
74117
75054
|
return;
|
|
74118
75055
|
throw error4;
|
|
74119
75056
|
}
|
|
74120
|
-
},
|
|
74121
|
-
catch: (error4) => {
|
|
74122
|
-
if (isCliError(error4))
|
|
74123
|
-
return error4;
|
|
74124
|
-
return new CliError({
|
|
74125
|
-
code: "INTERNAL",
|
|
74126
|
-
message: "Failed to read supervisor state",
|
|
74127
|
-
exitCode: 1,
|
|
74128
|
-
details: { state_file: stateFilePath, error: String(error4?.message || error4) }
|
|
74129
|
-
});
|
|
74130
|
-
}
|
|
74131
|
-
}),
|
|
74132
|
-
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
74133
|
-
try: async () => {
|
|
74134
|
-
await writeJsonAtomic2(stateFilePath, value8);
|
|
74135
|
-
},
|
|
74136
|
-
catch: (error4) => {
|
|
74137
|
-
if (isCliError(error4))
|
|
74138
|
-
return error4;
|
|
74139
|
-
return new CliError({
|
|
74140
|
-
code: "INTERNAL",
|
|
74141
|
-
message: "Failed to write supervisor state",
|
|
74142
|
-
exitCode: 1,
|
|
74143
|
-
details: { state_file: stateFilePath, error: String(error4?.message || error4) }
|
|
74144
|
-
});
|
|
74145
|
-
}
|
|
74146
|
-
}),
|
|
74147
|
-
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
74148
|
-
try: async () => {
|
|
74149
|
-
try {
|
|
74150
|
-
await fs2.unlink(stateFilePath);
|
|
74151
|
-
} catch (error4) {
|
|
74152
|
-
if (error4?.code === "ENOENT")
|
|
74153
|
-
return;
|
|
74154
|
-
throw error4;
|
|
74155
|
-
}
|
|
74156
|
-
},
|
|
74157
|
-
catch: (error4) => {
|
|
74158
|
-
if (isCliError(error4))
|
|
74159
|
-
return error4;
|
|
74160
|
-
return new CliError({
|
|
74161
|
-
code: "INTERNAL",
|
|
74162
|
-
message: "Failed to delete supervisor state",
|
|
74163
|
-
exitCode: 1,
|
|
74164
|
-
details: { state_file: stateFilePath, error: String(error4?.message || error4) }
|
|
74165
|
-
});
|
|
74166
|
-
}
|
|
74167
|
-
})
|
|
74168
|
-
});
|
|
74169
|
-
|
|
74170
|
-
// src/services/Output.ts
|
|
74171
|
-
class Output extends Tag2("Output")() {
|
|
74172
|
-
}
|
|
74173
|
-
var OutputLive = succeed10(Output, {
|
|
74174
|
-
stdout: (text14) => sync3(() => {
|
|
74175
|
-
process.stdout.write(text14);
|
|
74176
|
-
}),
|
|
74177
|
-
stderr: (text14) => sync3(() => {
|
|
74178
|
-
process.stderr.write(text14);
|
|
74179
|
-
}),
|
|
74180
|
-
json: (value8) => sync3(() => {
|
|
74181
|
-
process.stdout.write(`${JSON.stringify(value8)}
|
|
74182
|
-
`);
|
|
74183
|
-
})
|
|
74184
|
-
});
|
|
74185
|
-
|
|
74186
|
-
// src/commands/_shared.ts
|
|
74187
|
-
function ensureTrailingNewline(text14) {
|
|
74188
|
-
return text14.endsWith(`
|
|
74189
|
-
`) ? text14 : `${text14}
|
|
74190
|
-
`;
|
|
74191
|
-
}
|
|
74192
|
-
function formatHumanErrorLine(message) {
|
|
74193
|
-
const trimmed2 = String(message ?? "").trim();
|
|
74194
|
-
if (!trimmed2)
|
|
74195
|
-
return "Error: Unknown error";
|
|
74196
|
-
return trimmed2.startsWith("Error:") ? trimmed2 : `Error: ${trimmed2}`;
|
|
74197
|
-
}
|
|
74198
|
-
function readStringArray(value8) {
|
|
74199
|
-
if (!Array.isArray(value8))
|
|
74200
|
-
return [];
|
|
74201
|
-
return value8.map((v) => String(v ?? "").trim()).filter(Boolean);
|
|
74202
|
-
}
|
|
74203
|
-
function writeSuccess(params3) {
|
|
74204
|
-
return gen2(function* () {
|
|
74205
|
-
const config3 = yield* AppConfig;
|
|
74206
|
-
const out = yield* Output;
|
|
74207
|
-
if (config3.format === "json") {
|
|
74208
|
-
yield* out.json(ok(params3.data));
|
|
74209
|
-
return;
|
|
74210
|
-
}
|
|
74211
|
-
if (config3.quiet)
|
|
74212
|
-
return;
|
|
74213
|
-
if (config3.format === "ids") {
|
|
74214
|
-
if (!params3.ids || params3.ids.length === 0) {
|
|
74215
|
-
return yield* fail8(new CliError({
|
|
74216
|
-
code: "INVALID_ARGS",
|
|
74217
|
-
message: "This command does not support --ids output",
|
|
74218
|
-
exitCode: 2
|
|
74219
|
-
}));
|
|
74220
|
-
}
|
|
74221
|
-
yield* out.stdout(`${params3.ids.join(`
|
|
74222
|
-
`)}
|
|
74223
|
-
`);
|
|
74224
|
-
return;
|
|
74225
|
-
}
|
|
74226
|
-
if (params3.data && typeof params3.data === "object") {
|
|
74227
|
-
const anyData = params3.data;
|
|
74228
|
-
const warnings = readStringArray(anyData?.warnings);
|
|
74229
|
-
const nextActions = readStringArray(anyData?.nextActions);
|
|
74230
|
-
if (warnings.length > 0) {
|
|
74231
|
-
yield* out.stderr(`Warnings:
|
|
74232
|
-
`);
|
|
74233
|
-
for (const w of warnings)
|
|
74234
|
-
yield* out.stderr(`- ${w}
|
|
74235
|
-
`);
|
|
74236
|
-
}
|
|
74237
|
-
if (nextActions.length > 0) {
|
|
74238
|
-
yield* out.stderr(`Next actions:
|
|
74239
|
-
`);
|
|
74240
|
-
for (const a of nextActions)
|
|
74241
|
-
yield* out.stderr(`- ${a}
|
|
74242
|
-
`);
|
|
74243
|
-
}
|
|
74244
|
-
}
|
|
74245
|
-
const md = params3.md ?? "";
|
|
74246
|
-
if (md.trim().length > 0) {
|
|
74247
|
-
yield* out.stdout(ensureTrailingNewline(md));
|
|
74248
|
-
}
|
|
74249
|
-
});
|
|
74250
|
-
}
|
|
74251
|
-
function writeFailure(error4) {
|
|
74252
|
-
return gen2(function* () {
|
|
74253
|
-
const config3 = yield* AppConfig;
|
|
74254
|
-
const out = yield* Output;
|
|
74255
|
-
if (config3.format === "json") {
|
|
74256
|
-
return yield* fail8(error4);
|
|
75057
|
+
},
|
|
75058
|
+
catch: (error4) => {
|
|
75059
|
+
if (isCliError(error4))
|
|
75060
|
+
return error4;
|
|
75061
|
+
return new CliError({
|
|
75062
|
+
code: "INTERNAL",
|
|
75063
|
+
message: "Failed to read supervisor state",
|
|
75064
|
+
exitCode: 1,
|
|
75065
|
+
details: { state_file: stateFilePath, error: String(error4?.message || error4) }
|
|
75066
|
+
});
|
|
74257
75067
|
}
|
|
74258
|
-
|
|
74259
|
-
|
|
74260
|
-
|
|
74261
|
-
|
|
74262
|
-
|
|
75068
|
+
}),
|
|
75069
|
+
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
75070
|
+
try: async () => {
|
|
75071
|
+
await writeJsonAtomic2(stateFilePath, value8);
|
|
75072
|
+
},
|
|
75073
|
+
catch: (error4) => {
|
|
75074
|
+
if (isCliError(error4))
|
|
75075
|
+
return error4;
|
|
75076
|
+
return new CliError({
|
|
75077
|
+
code: "INTERNAL",
|
|
75078
|
+
message: "Failed to write supervisor state",
|
|
75079
|
+
exitCode: 1,
|
|
75080
|
+
details: { state_file: stateFilePath, error: String(error4?.message || error4) }
|
|
75081
|
+
});
|
|
74263
75082
|
}
|
|
74264
|
-
|
|
74265
|
-
|
|
74266
|
-
|
|
74267
|
-
|
|
74268
|
-
|
|
74269
|
-
|
|
75083
|
+
}),
|
|
75084
|
+
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
75085
|
+
try: async () => {
|
|
75086
|
+
try {
|
|
75087
|
+
await fs6.unlink(stateFilePath);
|
|
75088
|
+
} catch (error4) {
|
|
75089
|
+
if (error4?.code === "ENOENT")
|
|
75090
|
+
return;
|
|
75091
|
+
throw error4;
|
|
74270
75092
|
}
|
|
75093
|
+
},
|
|
75094
|
+
catch: (error4) => {
|
|
75095
|
+
if (isCliError(error4))
|
|
75096
|
+
return error4;
|
|
75097
|
+
return new CliError({
|
|
75098
|
+
code: "INTERNAL",
|
|
75099
|
+
message: "Failed to delete supervisor state",
|
|
75100
|
+
exitCode: 1,
|
|
75101
|
+
details: { state_file: stateFilePath, error: String(error4?.message || error4) }
|
|
75102
|
+
});
|
|
74271
75103
|
}
|
|
74272
|
-
|
|
74273
|
-
|
|
74274
|
-
}
|
|
75104
|
+
})
|
|
75105
|
+
});
|
|
74275
75106
|
|
|
74276
75107
|
// src/commands/config/print.ts
|
|
74277
75108
|
var configPrintCommand = exports_Command.make("print", {}, () => gen2(function* () {
|
|
@@ -74285,6 +75116,7 @@ var configPrintCommand = exports_Command.make("print", {}, () => gen2(function*
|
|
|
74285
75116
|
format: cfg.format,
|
|
74286
75117
|
quiet: cfg.quiet,
|
|
74287
75118
|
debug: cfg.debug,
|
|
75119
|
+
config_file: cfg.configFile,
|
|
74288
75120
|
remnote_db: cfg.remnoteDb,
|
|
74289
75121
|
store_db: cfg.storeDb,
|
|
74290
75122
|
ws_url: cfg.wsUrl,
|
|
@@ -74299,6 +75131,13 @@ var configPrintCommand = exports_Command.make("print", {}, () => gen2(function*
|
|
|
74299
75131
|
status_line_min_interval_ms: cfg.statusLineMinIntervalMs,
|
|
74300
75132
|
status_line_debug: cfg.statusLineDebug,
|
|
74301
75133
|
status_line_json_file: cfg.statusLineJsonFile,
|
|
75134
|
+
api_base_url: cfg.apiBaseUrl,
|
|
75135
|
+
api_host: cfg.apiHost,
|
|
75136
|
+
api_port: cfg.apiPort,
|
|
75137
|
+
api_base_path: cfg.apiBasePath,
|
|
75138
|
+
api_pid_file: cfg.apiPidFile,
|
|
75139
|
+
api_log_file: cfg.apiLogFile,
|
|
75140
|
+
api_state_file: cfg.apiStateFile,
|
|
74302
75141
|
daemon_pid_file_default: daemonPidFile,
|
|
74303
75142
|
daemon_log_file_default: daemonLogFile,
|
|
74304
75143
|
supervisor_state_file_default: supervisorStateFile
|
|
@@ -74307,6 +75146,7 @@ var configPrintCommand = exports_Command.make("print", {}, () => gen2(function*
|
|
|
74307
75146
|
`- format: ${data.format}`,
|
|
74308
75147
|
`- quiet: ${data.quiet}`,
|
|
74309
75148
|
`- debug: ${data.debug}`,
|
|
75149
|
+
`- config_file: ${data.config_file}`,
|
|
74310
75150
|
`- remnote_db: ${data.remnote_db ?? ""}`,
|
|
74311
75151
|
`- store_db: ${data.store_db}`,
|
|
74312
75152
|
`- ws_url: ${data.ws_url}`,
|
|
@@ -74321,6 +75161,13 @@ var configPrintCommand = exports_Command.make("print", {}, () => gen2(function*
|
|
|
74321
75161
|
`- status_line_min_interval_ms: ${data.status_line_min_interval_ms}`,
|
|
74322
75162
|
`- status_line_debug: ${data.status_line_debug}`,
|
|
74323
75163
|
`- status_line_json_file: ${data.status_line_json_file}`,
|
|
75164
|
+
`- api_base_url: ${data.api_base_url ?? ""}`,
|
|
75165
|
+
`- api_host: ${data.api_host ?? ""}`,
|
|
75166
|
+
`- api_port: ${data.api_port ?? ""}`,
|
|
75167
|
+
`- api_base_path: ${data.api_base_path ?? ""}`,
|
|
75168
|
+
`- api_pid_file: ${data.api_pid_file ?? ""}`,
|
|
75169
|
+
`- api_log_file: ${data.api_log_file ?? ""}`,
|
|
75170
|
+
`- api_state_file: ${data.api_state_file ?? ""}`,
|
|
74324
75171
|
`- daemon_pid_file_default: ${data.daemon_pid_file_default}`,
|
|
74325
75172
|
`- daemon_log_file_default: ${data.daemon_log_file_default}`,
|
|
74326
75173
|
`- supervisor_state_file_default: ${data.supervisor_state_file_default}`
|
|
@@ -74329,38 +75176,102 @@ var configPrintCommand = exports_Command.make("print", {}, () => gen2(function*
|
|
|
74329
75176
|
yield* writeSuccess({ data, md });
|
|
74330
75177
|
}).pipe(catchAll2(writeFailure)));
|
|
74331
75178
|
|
|
75179
|
+
// src/commands/config/set.ts
|
|
75180
|
+
var configSetCommand = exports_Command.make("set", { key: text9("key"), value: text9("value") }, ({ key, value: value8 }) => gen2(function* () {
|
|
75181
|
+
const userConfig = yield* UserConfigFile;
|
|
75182
|
+
const data = yield* userConfig.set(key, value8);
|
|
75183
|
+
yield* writeSuccess({
|
|
75184
|
+
data: {
|
|
75185
|
+
config_file: data.configFile,
|
|
75186
|
+
key: data.key,
|
|
75187
|
+
value: data.value,
|
|
75188
|
+
changed: data.changed
|
|
75189
|
+
},
|
|
75190
|
+
md: `${data.key}=${data.value}
|
|
75191
|
+
`
|
|
75192
|
+
});
|
|
75193
|
+
}).pipe(catchAll2(writeFailure)));
|
|
75194
|
+
|
|
75195
|
+
// src/commands/config/unset.ts
|
|
75196
|
+
var configUnsetCommand = exports_Command.make("unset", { key: text9("key") }, ({ key }) => gen2(function* () {
|
|
75197
|
+
const userConfig = yield* UserConfigFile;
|
|
75198
|
+
const data = yield* userConfig.unset(key);
|
|
75199
|
+
yield* writeSuccess({
|
|
75200
|
+
data: {
|
|
75201
|
+
config_file: data.configFile,
|
|
75202
|
+
key: data.key,
|
|
75203
|
+
removed: data.removed,
|
|
75204
|
+
file_deleted: data.fileDeleted
|
|
75205
|
+
},
|
|
75206
|
+
md: `${data.key} removed=${data.removed}
|
|
75207
|
+
`
|
|
75208
|
+
});
|
|
75209
|
+
}).pipe(catchAll2(writeFailure)));
|
|
75210
|
+
|
|
75211
|
+
// src/commands/config/validate.ts
|
|
75212
|
+
var configValidateCommand = exports_Command.make("validate", {}, () => gen2(function* () {
|
|
75213
|
+
const userConfig = yield* UserConfigFile;
|
|
75214
|
+
const inspection = yield* userConfig.inspect();
|
|
75215
|
+
const data = {
|
|
75216
|
+
config_file: inspection.configFile,
|
|
75217
|
+
exists: inspection.exists,
|
|
75218
|
+
valid: inspection.valid,
|
|
75219
|
+
values: inspection.values,
|
|
75220
|
+
unknown_keys: inspection.unknownKeys,
|
|
75221
|
+
errors: inspection.errors
|
|
75222
|
+
};
|
|
75223
|
+
const mdLines = [
|
|
75224
|
+
`- config_file: ${data.config_file}`,
|
|
75225
|
+
`- exists: ${data.exists}`,
|
|
75226
|
+
`- valid: ${data.valid}`,
|
|
75227
|
+
`- unknown_keys: ${data.unknown_keys.join(", ")}`,
|
|
75228
|
+
`- errors: ${data.errors.join(" | ")}`
|
|
75229
|
+
];
|
|
75230
|
+
yield* writeSuccess({ data, md: `${mdLines.join(`
|
|
75231
|
+
`)}
|
|
75232
|
+
` });
|
|
75233
|
+
}).pipe(catchAll2(writeFailure)));
|
|
75234
|
+
|
|
74332
75235
|
// src/commands/config/index.ts
|
|
74333
|
-
var configCommand = exports_Command.make("config", {}).pipe(exports_Command.withSubcommands([
|
|
75236
|
+
var configCommand = exports_Command.make("config", {}).pipe(exports_Command.withSubcommands([
|
|
75237
|
+
configPrintCommand,
|
|
75238
|
+
configPathCommand,
|
|
75239
|
+
configListCommand,
|
|
75240
|
+
configGetCommand,
|
|
75241
|
+
configSetCommand,
|
|
75242
|
+
configUnsetCommand,
|
|
75243
|
+
configValidateCommand
|
|
75244
|
+
]));
|
|
74334
75245
|
|
|
74335
75246
|
// src/services/FsAccess.ts
|
|
74336
|
-
import { constants as FS_CONSTANTS, promises as
|
|
74337
|
-
import
|
|
75247
|
+
import { constants as FS_CONSTANTS, promises as fs7 } from "node:fs";
|
|
75248
|
+
import path10 from "node:path";
|
|
74338
75249
|
|
|
74339
75250
|
class FsAccess extends Tag2("FsAccess")() {
|
|
74340
75251
|
}
|
|
74341
75252
|
async function canWritePath(filePath) {
|
|
74342
75253
|
try {
|
|
74343
|
-
await
|
|
74344
|
-
await
|
|
75254
|
+
await fs7.mkdir(path10.dirname(filePath), { recursive: true });
|
|
75255
|
+
await fs7.access(path10.dirname(filePath), FS_CONSTANTS.W_OK);
|
|
74345
75256
|
return true;
|
|
74346
75257
|
} catch {
|
|
74347
75258
|
return false;
|
|
74348
75259
|
}
|
|
74349
75260
|
}
|
|
74350
75261
|
async function checkWritableFile(filePath) {
|
|
74351
|
-
const dir2 =
|
|
75262
|
+
const dir2 = path10.dirname(filePath);
|
|
74352
75263
|
try {
|
|
74353
|
-
await
|
|
75264
|
+
await fs7.mkdir(dir2, { recursive: true });
|
|
74354
75265
|
} catch (e) {
|
|
74355
75266
|
return { ok: false, reason: `failed_to_create_dir: ${String(e?.message || e)}` };
|
|
74356
75267
|
}
|
|
74357
75268
|
try {
|
|
74358
|
-
await
|
|
75269
|
+
await fs7.access(dir2, FS_CONSTANTS.W_OK);
|
|
74359
75270
|
} catch (e) {
|
|
74360
75271
|
return { ok: false, reason: `dir_not_writable: ${String(e?.message || e)}` };
|
|
74361
75272
|
}
|
|
74362
75273
|
try {
|
|
74363
|
-
await
|
|
75274
|
+
await fs7.access(filePath, FS_CONSTANTS.W_OK);
|
|
74364
75275
|
return { ok: true };
|
|
74365
75276
|
} catch {
|
|
74366
75277
|
return { ok: true };
|
|
@@ -74369,7 +75280,7 @@ async function checkWritableFile(filePath) {
|
|
|
74369
75280
|
var FsAccessLive = succeed10(FsAccess, {
|
|
74370
75281
|
isFile: (filePath) => tryPromise2({
|
|
74371
75282
|
try: async () => {
|
|
74372
|
-
const st = await
|
|
75283
|
+
const st = await fs7.stat(filePath);
|
|
74373
75284
|
return st.isFile();
|
|
74374
75285
|
},
|
|
74375
75286
|
catch: (e) => e
|
|
@@ -74466,65 +75377,6 @@ function refreshTmuxStatusLine() {
|
|
|
74466
75377
|
requestTmuxStatusLineRefresh("immediate");
|
|
74467
75378
|
}
|
|
74468
75379
|
|
|
74469
|
-
// src/lib/wsState.ts
|
|
74470
|
-
import fs4 from "node:fs";
|
|
74471
|
-
import path7 from "node:path";
|
|
74472
|
-
function defaultStateFilePath() {
|
|
74473
|
-
return path7.join(homeDir(), ".agent-remnote", "ws.bridge.state.json");
|
|
74474
|
-
}
|
|
74475
|
-
function resolveStateFilePath(explicit) {
|
|
74476
|
-
if (explicit && explicit.trim())
|
|
74477
|
-
return { disabled: false, path: resolveUserFilePath(explicit) };
|
|
74478
|
-
const raw4 = String(process.env.REMNOTE_WS_STATE_FILE || process.env.WS_STATE_FILE || "").trim();
|
|
74479
|
-
if (raw4 === "0" || raw4.toLowerCase() === "false")
|
|
74480
|
-
return { disabled: true, path: defaultStateFilePath() };
|
|
74481
|
-
if (raw4)
|
|
74482
|
-
return { disabled: false, path: resolveUserFilePath(raw4) };
|
|
74483
|
-
return { disabled: false, path: defaultStateFilePath() };
|
|
74484
|
-
}
|
|
74485
|
-
function readJson(filePath) {
|
|
74486
|
-
try {
|
|
74487
|
-
const txt = fs4.readFileSync(filePath, "utf8");
|
|
74488
|
-
return JSON.parse(txt);
|
|
74489
|
-
} catch {
|
|
74490
|
-
return null;
|
|
74491
|
-
}
|
|
74492
|
-
}
|
|
74493
|
-
function pickClient(clients, connId) {
|
|
74494
|
-
const target2 = (connId || "").trim();
|
|
74495
|
-
if (target2) {
|
|
74496
|
-
const found = clients.find((c) => c && typeof c === "object" && c.connId === target2);
|
|
74497
|
-
if (found)
|
|
74498
|
-
return found;
|
|
74499
|
-
}
|
|
74500
|
-
const active2 = clients.find((c) => c && typeof c === "object" && c.isActiveWorker === true);
|
|
74501
|
-
if (active2)
|
|
74502
|
-
return active2;
|
|
74503
|
-
let best = null;
|
|
74504
|
-
let bestScore = -1;
|
|
74505
|
-
for (const c of clients) {
|
|
74506
|
-
if (!c || typeof c !== "object")
|
|
74507
|
-
continue;
|
|
74508
|
-
const selAt = Number(c.selection?.updatedAt ?? 0);
|
|
74509
|
-
const ctxAt = Number(c.uiContext?.updatedAt ?? 0);
|
|
74510
|
-
const score = Math.max(selAt, ctxAt);
|
|
74511
|
-
if (score > bestScore) {
|
|
74512
|
-
bestScore = score;
|
|
74513
|
-
best = c;
|
|
74514
|
-
}
|
|
74515
|
-
}
|
|
74516
|
-
return best;
|
|
74517
|
-
}
|
|
74518
|
-
function resolveStaleMs(explicit) {
|
|
74519
|
-
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0)
|
|
74520
|
-
return Math.floor(explicit);
|
|
74521
|
-
const raw4 = process.env.REMNOTE_WS_STATE_STALE_MS || process.env.WS_STATE_STALE_MS;
|
|
74522
|
-
const n = Number(raw4);
|
|
74523
|
-
if (Number.isFinite(n) && n > 0)
|
|
74524
|
-
return Math.floor(n);
|
|
74525
|
-
return 60000;
|
|
74526
|
-
}
|
|
74527
|
-
|
|
74528
75380
|
// src/lib/wsBridgeNextActions.ts
|
|
74529
75381
|
function buildDbFallbackNextAction(queryText) {
|
|
74530
75382
|
const q = String(queryText || "").replace(/\s+/g, " ").trim();
|
|
@@ -74536,21 +75388,21 @@ function buildDbFallbackNextAction(queryText) {
|
|
|
74536
75388
|
}
|
|
74537
75389
|
|
|
74538
75390
|
// src/lib/wsDebug.ts
|
|
74539
|
-
import
|
|
74540
|
-
import
|
|
75391
|
+
import fs8 from "node:fs";
|
|
75392
|
+
import path11 from "node:path";
|
|
74541
75393
|
function envDebug() {
|
|
74542
75394
|
const v = (process.env.REMNOTE_WS_DEBUG || process.env.WS_DEBUG || "").toLowerCase();
|
|
74543
75395
|
return v === "1" || v === "true";
|
|
74544
75396
|
}
|
|
74545
75397
|
function envLogFilePath(params3) {
|
|
74546
75398
|
const p3 = process.env.REMNOTE_WS_LOGFILE || process.env.WS_LOGFILE || "";
|
|
74547
|
-
const def = params3.debug ?
|
|
75399
|
+
const def = params3.debug ? path11.join(homeDir(), ".agent-remnote", "ws-debug.log") : "";
|
|
74548
75400
|
const out = p3 && p3.trim() || def;
|
|
74549
75401
|
if (!out)
|
|
74550
75402
|
return;
|
|
74551
75403
|
try {
|
|
74552
75404
|
const resolved = resolveUserFilePath(out);
|
|
74553
|
-
|
|
75405
|
+
fs8.mkdirSync(path11.dirname(resolved), { recursive: true });
|
|
74554
75406
|
return resolved;
|
|
74555
75407
|
} catch {
|
|
74556
75408
|
return;
|
|
@@ -74582,19 +75434,19 @@ function wsLog(level, msg, ctx) {
|
|
|
74582
75434
|
if (!LOG_FILE)
|
|
74583
75435
|
return;
|
|
74584
75436
|
try {
|
|
74585
|
-
|
|
75437
|
+
fs8.appendFileSync(LOG_FILE, `${new Date().toISOString()} ${line4}
|
|
74586
75438
|
`);
|
|
74587
75439
|
} catch {}
|
|
74588
75440
|
}
|
|
74589
75441
|
|
|
74590
75442
|
// src/internal/queue/db.ts
|
|
74591
|
-
import
|
|
75443
|
+
import path13 from "node:path";
|
|
74592
75444
|
|
|
74593
75445
|
// src/internal/store/db.ts
|
|
74594
75446
|
import Database from "better-sqlite3";
|
|
74595
75447
|
import { createHash, randomUUID } from "node:crypto";
|
|
74596
75448
|
import { constants as constants2, copyFileSync, existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
74597
|
-
import
|
|
75449
|
+
import path12 from "node:path";
|
|
74598
75450
|
|
|
74599
75451
|
// src/internal/store/migrations/0001-baseline.ts
|
|
74600
75452
|
var migration = {
|
|
@@ -74831,7 +75683,7 @@ CREATE TABLE IF NOT EXISTS queue_consumers (
|
|
|
74831
75683
|
);
|
|
74832
75684
|
`;
|
|
74833
75685
|
function absoluteDefaultStorePath() {
|
|
74834
|
-
return
|
|
75686
|
+
return path12.join(homeDir(), ".agent-remnote", "store.sqlite");
|
|
74835
75687
|
}
|
|
74836
75688
|
function defaultStorePath() {
|
|
74837
75689
|
const env2 = process.env.REMNOTE_STORE_DB || process.env.STORE_DB;
|
|
@@ -74843,15 +75695,15 @@ function defaultLegacyQueuePath() {
|
|
|
74843
75695
|
const env2 = process.env.REMNOTE_QUEUE_DB || process.env.QUEUE_DB;
|
|
74844
75696
|
if (typeof env2 === "string" && env2.trim())
|
|
74845
75697
|
return resolveUserFilePath(env2);
|
|
74846
|
-
return
|
|
75698
|
+
return path12.join(homeDir(), ".agent-remnote", "queue.sqlite");
|
|
74847
75699
|
}
|
|
74848
|
-
function
|
|
74849
|
-
const dir2 =
|
|
75700
|
+
function ensureDir4(filePath) {
|
|
75701
|
+
const dir2 = path12.dirname(filePath);
|
|
74850
75702
|
mkdirSync(dir2, { recursive: true });
|
|
74851
75703
|
}
|
|
74852
75704
|
function openStoreDb(dbPath = defaultStorePath()) {
|
|
74853
75705
|
const resolvedPath = resolveUserFilePath(dbPath);
|
|
74854
|
-
|
|
75706
|
+
ensureDir4(resolvedPath);
|
|
74855
75707
|
maybeInitializeDefaultStoreFromLegacy(resolvedPath, { callerProvidedPath: dbPath });
|
|
74856
75708
|
const db = new Database(resolvedPath);
|
|
74857
75709
|
db.pragma("busy_timeout = 5000");
|
|
@@ -75176,7 +76028,7 @@ function maybeInitializeDefaultStoreFromLegacy(resolvedStorePath, params3) {
|
|
|
75176
76028
|
if (!existsSync(legacyPath))
|
|
75177
76029
|
return;
|
|
75178
76030
|
const tmpPath = `${resolvedStorePath}.tmp.${process.pid}.${randomUUID()}`;
|
|
75179
|
-
|
|
76031
|
+
ensureDir4(tmpPath);
|
|
75180
76032
|
try {
|
|
75181
76033
|
const source = new Database(legacyPath, { readonly: true });
|
|
75182
76034
|
try {
|
|
@@ -75215,10 +76067,10 @@ function defaultQueuePath() {
|
|
|
75215
76067
|
const env2 = process.env.REMNOTE_QUEUE_DB || process.env.QUEUE_DB;
|
|
75216
76068
|
if (typeof env2 === "string" && env2.trim())
|
|
75217
76069
|
return resolveUserFilePath(env2);
|
|
75218
|
-
return
|
|
76070
|
+
return path13.join(homeDir(), ".agent-remnote", "queue.sqlite");
|
|
75219
76071
|
}
|
|
75220
|
-
function
|
|
75221
|
-
|
|
76072
|
+
function ensureDir5(filePath) {
|
|
76073
|
+
ensureDir4(filePath);
|
|
75222
76074
|
}
|
|
75223
76075
|
function queueErrorFromStoreSchema(dbPath, error4) {
|
|
75224
76076
|
const code2 = error4.code === "STORE_SCHEMA_NEWER" ? "QUEUE_SCHEMA_NEWER" : error4.code === "STORE_SCHEMA_INVALID" ? "QUEUE_SCHEMA_INVALID" : "QUEUE_SCHEMA_UNKNOWN";
|
|
@@ -75231,7 +76083,7 @@ function queueErrorFromStoreSchema(dbPath, error4) {
|
|
|
75231
76083
|
}
|
|
75232
76084
|
function openQueueDb(dbPath = defaultQueuePath()) {
|
|
75233
76085
|
const resolvedPath = resolveUserFilePath(dbPath);
|
|
75234
|
-
|
|
76086
|
+
ensureDir5(resolvedPath);
|
|
75235
76087
|
try {
|
|
75236
76088
|
return openStoreDb(resolvedPath);
|
|
75237
76089
|
} catch (e) {
|
|
@@ -75523,18 +76375,18 @@ function getFirstString(payload, keys8) {
|
|
|
75523
76375
|
}
|
|
75524
76376
|
return null;
|
|
75525
76377
|
}
|
|
75526
|
-
function getFirstStringFromNested(payload,
|
|
76378
|
+
function getFirstStringFromNested(payload, path14) {
|
|
75527
76379
|
let cur = payload;
|
|
75528
|
-
for (const k of
|
|
76380
|
+
for (const k of path14) {
|
|
75529
76381
|
if (!cur || typeof cur !== "object")
|
|
75530
76382
|
return null;
|
|
75531
76383
|
cur = cur[k];
|
|
75532
76384
|
}
|
|
75533
76385
|
return asNonEmptyString(cur);
|
|
75534
76386
|
}
|
|
75535
|
-
function getStringArrayFromNested(payload,
|
|
76387
|
+
function getStringArrayFromNested(payload, path14) {
|
|
75536
76388
|
let cur = payload;
|
|
75537
|
-
for (const k of
|
|
76389
|
+
for (const k of path14) {
|
|
75538
76390
|
if (!cur || typeof cur !== "object")
|
|
75539
76391
|
return [];
|
|
75540
76392
|
cur = cur[k];
|
|
@@ -76647,38 +77499,38 @@ function idFieldPathsForOpType(opTypeRaw) {
|
|
|
76647
77499
|
return Array.isArray(entry.id_fields) ? entry.id_fields : [];
|
|
76648
77500
|
}
|
|
76649
77501
|
// src/kernel/op-catalog/pathWalk.ts
|
|
76650
|
-
function parsePathTokens(
|
|
76651
|
-
return
|
|
77502
|
+
function parsePathTokens(path14) {
|
|
77503
|
+
return path14.split(".").map((part) => part.trim()).filter(Boolean).map((part) => {
|
|
76652
77504
|
const isArray2 = part.endsWith("[]");
|
|
76653
77505
|
const key = isArray2 ? part.slice(0, -2).trim() : part;
|
|
76654
77506
|
return { key, isArray: isArray2 };
|
|
76655
77507
|
}).filter((token) => token.key.length > 0);
|
|
76656
77508
|
}
|
|
76657
|
-
function collectLeafValues(value8,
|
|
76658
|
-
if (idx >=
|
|
77509
|
+
function collectLeafValues(value8, path14, idx = 0) {
|
|
77510
|
+
if (idx >= path14.length)
|
|
76659
77511
|
return [value8];
|
|
76660
77512
|
if (!value8 || typeof value8 !== "object")
|
|
76661
77513
|
return [];
|
|
76662
|
-
const token =
|
|
77514
|
+
const token = path14[idx];
|
|
76663
77515
|
const next4 = value8[token.key];
|
|
76664
77516
|
if (token.isArray) {
|
|
76665
77517
|
if (!Array.isArray(next4))
|
|
76666
77518
|
return [];
|
|
76667
77519
|
const out = [];
|
|
76668
77520
|
for (const item of next4) {
|
|
76669
|
-
out.push(...collectLeafValues(item,
|
|
77521
|
+
out.push(...collectLeafValues(item, path14, idx + 1));
|
|
76670
77522
|
}
|
|
76671
77523
|
return out;
|
|
76672
77524
|
}
|
|
76673
|
-
return collectLeafValues(next4,
|
|
77525
|
+
return collectLeafValues(next4, path14, idx + 1);
|
|
76674
77526
|
}
|
|
76675
|
-
function mapLeafValuesInPlace(value8,
|
|
76676
|
-
if (idx >=
|
|
77527
|
+
function mapLeafValuesInPlace(value8, path14, mapFn, idx = 0) {
|
|
77528
|
+
if (idx >= path14.length)
|
|
76677
77529
|
return;
|
|
76678
77530
|
if (!value8 || typeof value8 !== "object")
|
|
76679
77531
|
return;
|
|
76680
|
-
const token =
|
|
76681
|
-
const isLeaf = idx ===
|
|
77532
|
+
const token = path14[idx];
|
|
77533
|
+
const isLeaf = idx === path14.length - 1;
|
|
76682
77534
|
if (token.isArray) {
|
|
76683
77535
|
const next4 = value8[token.key];
|
|
76684
77536
|
if (!Array.isArray(next4))
|
|
@@ -76688,7 +77540,7 @@ function mapLeafValuesInPlace(value8, path11, mapFn, idx = 0) {
|
|
|
76688
77540
|
return;
|
|
76689
77541
|
}
|
|
76690
77542
|
for (const item of next4) {
|
|
76691
|
-
mapLeafValuesInPlace(item,
|
|
77543
|
+
mapLeafValuesInPlace(item, path14, mapFn, idx + 1);
|
|
76692
77544
|
}
|
|
76693
77545
|
return;
|
|
76694
77546
|
}
|
|
@@ -76696,7 +77548,7 @@ function mapLeafValuesInPlace(value8, path11, mapFn, idx = 0) {
|
|
|
76696
77548
|
value8[token.key] = mapFn(value8[token.key]);
|
|
76697
77549
|
return;
|
|
76698
77550
|
}
|
|
76699
|
-
mapLeafValuesInPlace(value8[token.key],
|
|
77551
|
+
mapLeafValuesInPlace(value8[token.key], path14, mapFn, idx + 1);
|
|
76700
77552
|
}
|
|
76701
77553
|
|
|
76702
77554
|
// src/kernel/op-catalog/substituteIds.ts
|
|
@@ -76718,8 +77570,8 @@ function collectTempIdsFromPayload(opTypeRaw, payload) {
|
|
|
76718
77570
|
if (!payload || typeof payload !== "object")
|
|
76719
77571
|
return [];
|
|
76720
77572
|
const out = [];
|
|
76721
|
-
for (const
|
|
76722
|
-
const tokens = parsePathTokens(
|
|
77573
|
+
for (const path14 of idFieldPathsForOpType(opTypeRaw)) {
|
|
77574
|
+
const tokens = parsePathTokens(path14);
|
|
76723
77575
|
if (tokens.length === 0)
|
|
76724
77576
|
continue;
|
|
76725
77577
|
const values5 = collectLeafValues(payload, tokens);
|
|
@@ -76734,8 +77586,8 @@ function substituteTempIdsInPayload(opTypeRaw, payload, idMap) {
|
|
|
76734
77586
|
if (!payload || typeof payload !== "object")
|
|
76735
77587
|
return payload;
|
|
76736
77588
|
const out = cloneJson(payload);
|
|
76737
|
-
for (const
|
|
76738
|
-
const tokens = parsePathTokens(
|
|
77589
|
+
for (const path14 of idFieldPathsForOpType(opTypeRaw)) {
|
|
77590
|
+
const tokens = parsePathTokens(path14);
|
|
76739
77591
|
if (tokens.length === 0)
|
|
76740
77592
|
continue;
|
|
76741
77593
|
mapLeafValuesInPlace(out, tokens, (value8) => {
|
|
@@ -78006,8 +78858,8 @@ function toWsBridgeClient2(client) {
|
|
|
78006
78858
|
var GLOBAL_BRIDGE_KEY = Symbol.for("__REMNOTE_WS_BRIDGE__");
|
|
78007
78859
|
// src/internal/remdb-tools/shared.ts
|
|
78008
78860
|
import BetterSqlite3 from "better-sqlite3";
|
|
78009
|
-
import { promises as
|
|
78010
|
-
import
|
|
78861
|
+
import { promises as fs9 } from "fs";
|
|
78862
|
+
import path14 from "path";
|
|
78011
78863
|
|
|
78012
78864
|
// ../../node_modules/date-fns/constants.js
|
|
78013
78865
|
var daysInYear = 365.2425;
|
|
@@ -79496,18 +80348,18 @@ async function withResolvedDatabase(dbPath, fn) {
|
|
|
79496
80348
|
async function resolveDatabasePath(dbPath) {
|
|
79497
80349
|
if (dbPath) {
|
|
79498
80350
|
const expanded = expandHome2(dbPath.trim());
|
|
79499
|
-
const stat3 = await
|
|
80351
|
+
const stat3 = await fs9.stat(expanded);
|
|
79500
80352
|
if (!stat3.isFile()) {
|
|
79501
80353
|
throw new Error(`${expanded} is not a file`);
|
|
79502
80354
|
}
|
|
79503
80355
|
return {
|
|
79504
80356
|
dbPath: expanded,
|
|
79505
80357
|
source: "explicit",
|
|
79506
|
-
baseDir:
|
|
80358
|
+
baseDir: path14.dirname(expanded)
|
|
79507
80359
|
};
|
|
79508
80360
|
}
|
|
79509
|
-
const baseDir =
|
|
79510
|
-
const entries2 = await
|
|
80361
|
+
const baseDir = path14.join(homeDir(), REMNOTE_RELATIVE_DIR);
|
|
80362
|
+
const entries2 = await fs9.readdir(baseDir, { withFileTypes: true }).catch(() => {
|
|
79511
80363
|
throw new Error(`RemNote directory ${baseDir} not found – please specify dbPath manually`);
|
|
79512
80364
|
});
|
|
79513
80365
|
const candidates = [];
|
|
@@ -79520,9 +80372,9 @@ async function resolveDatabasePath(dbPath) {
|
|
|
79520
80372
|
const isSecondary = SECONDARY_DIRS.has(entry.name);
|
|
79521
80373
|
if (!isPrimary && !isSecondary)
|
|
79522
80374
|
continue;
|
|
79523
|
-
const candidatePath =
|
|
80375
|
+
const candidatePath = path14.join(baseDir, entry.name, REMNOTE_DB_NAME);
|
|
79524
80376
|
try {
|
|
79525
|
-
const stat3 = await
|
|
80377
|
+
const stat3 = await fs9.stat(candidatePath);
|
|
79526
80378
|
candidates.push({
|
|
79527
80379
|
dbPath: candidatePath,
|
|
79528
80380
|
dirName: entry.name,
|
|
@@ -79553,18 +80405,18 @@ async function discoverBackups(basePath) {
|
|
|
79553
80405
|
const backups = [];
|
|
79554
80406
|
let entries2;
|
|
79555
80407
|
try {
|
|
79556
|
-
entries2 = await
|
|
80408
|
+
entries2 = await fs9.readdir(basePath, { withFileTypes: true });
|
|
79557
80409
|
} catch (error4) {
|
|
79558
80410
|
throw new Error(`Unable to read ${basePath}: ${String(error4)}`);
|
|
79559
80411
|
}
|
|
79560
80412
|
for (const entry of entries2) {
|
|
79561
80413
|
if (!entry.isDirectory())
|
|
79562
80414
|
continue;
|
|
79563
|
-
const accountDir =
|
|
79564
|
-
const backupDir =
|
|
80415
|
+
const accountDir = path14.join(basePath, entry.name);
|
|
80416
|
+
const backupDir = path14.join(accountDir, "backups");
|
|
79565
80417
|
let backupFiles;
|
|
79566
80418
|
try {
|
|
79567
|
-
backupFiles = await
|
|
80419
|
+
backupFiles = await fs9.readdir(backupDir, { withFileTypes: true });
|
|
79568
80420
|
} catch {
|
|
79569
80421
|
continue;
|
|
79570
80422
|
}
|
|
@@ -79573,8 +80425,8 @@ async function discoverBackups(basePath) {
|
|
|
79573
80425
|
continue;
|
|
79574
80426
|
if (!file6.name.endsWith(".db") && !file6.name.endsWith(".db.zip"))
|
|
79575
80427
|
continue;
|
|
79576
|
-
const fullPath =
|
|
79577
|
-
const stat3 = await
|
|
80428
|
+
const fullPath = path14.join(backupDir, file6.name);
|
|
80429
|
+
const stat3 = await fs9.stat(fullPath);
|
|
79578
80430
|
backups.push({
|
|
79579
80431
|
accountDir: entry.name,
|
|
79580
80432
|
file: file6.name,
|
|
@@ -79695,8 +80547,8 @@ function parseOrThrow(schema2, input, options6) {
|
|
|
79695
80547
|
throw new Error(prefix2 + lines3.join("; "));
|
|
79696
80548
|
}
|
|
79697
80549
|
function formatZodIssueEN(issue) {
|
|
79698
|
-
const
|
|
79699
|
-
const where =
|
|
80550
|
+
const path15 = issue.path && issue.path.length > 0 ? issue.path.join(".") : undefined;
|
|
80551
|
+
const where = path15 ? `field ${path15}: ` : "";
|
|
79700
80552
|
switch (issue.code) {
|
|
79701
80553
|
case "invalid_type": {
|
|
79702
80554
|
const expected = toENType(issue.expected);
|
|
@@ -80148,8 +81000,8 @@ function getErrorMap() {
|
|
|
80148
81000
|
return overrideErrorMap;
|
|
80149
81001
|
}
|
|
80150
81002
|
var makeIssue = (params3) => {
|
|
80151
|
-
const { data, path:
|
|
80152
|
-
const fullPath = [...
|
|
81003
|
+
const { data, path: path15, errorMaps, issueData } = params3;
|
|
81004
|
+
const fullPath = [...path15, ...issueData.path || []];
|
|
80153
81005
|
const fullIssue = {
|
|
80154
81006
|
...issueData,
|
|
80155
81007
|
path: fullPath
|
|
@@ -80277,11 +81129,11 @@ var _ZodEnum_cache;
|
|
|
80277
81129
|
var _ZodNativeEnum_cache;
|
|
80278
81130
|
|
|
80279
81131
|
class ParseInputLazyPath {
|
|
80280
|
-
constructor(parent, value8,
|
|
81132
|
+
constructor(parent, value8, path15, key) {
|
|
80281
81133
|
this._cachedPath = [];
|
|
80282
81134
|
this.parent = parent;
|
|
80283
81135
|
this.data = value8;
|
|
80284
|
-
this._path =
|
|
81136
|
+
this._path = path15;
|
|
80285
81137
|
this._key = key;
|
|
80286
81138
|
}
|
|
80287
81139
|
get path() {
|
|
@@ -83658,7 +84510,7 @@ var z = /* @__PURE__ */ Object.freeze({
|
|
|
83658
84510
|
});
|
|
83659
84511
|
|
|
83660
84512
|
// src/internal/remdb-tools/listRemBackups.ts
|
|
83661
|
-
import
|
|
84513
|
+
import path15 from "node:path";
|
|
83662
84514
|
var inputShape = {
|
|
83663
84515
|
basePath: z.string().optional().describe("RemNote base directory (default: ~/remnote)"),
|
|
83664
84516
|
limit: z.number().int().min(1).max(200).optional().describe("Max backups to return (default 50)")
|
|
@@ -83666,7 +84518,7 @@ var inputShape = {
|
|
|
83666
84518
|
var listRemBackupsSchema = z.object(inputShape);
|
|
83667
84519
|
async function executeListRemBackups(params3) {
|
|
83668
84520
|
const parsed = parseOrThrow(listRemBackupsSchema, params3, { label: "list_rem_backups" });
|
|
83669
|
-
const basePath = expandHome2(parsed.basePath ??
|
|
84521
|
+
const basePath = expandHome2(parsed.basePath ?? path15.join(homeDir(), REMNOTE_RELATIVE_DIR));
|
|
83670
84522
|
const backups = await discoverBackups(basePath);
|
|
83671
84523
|
const limit = parsed.limit ?? 50;
|
|
83672
84524
|
return {
|
|
@@ -85416,10 +86268,10 @@ function fetchDocs(db, rootId, includeDescendants, maxDepth) {
|
|
|
85416
86268
|
}
|
|
85417
86269
|
return rows.map((row) => convertRow(row.id, row.doc));
|
|
85418
86270
|
}
|
|
85419
|
-
function collectReferences(value8, remId,
|
|
86271
|
+
function collectReferences(value8, remId, path16, into3) {
|
|
85420
86272
|
if (Array.isArray(value8)) {
|
|
85421
86273
|
value8.forEach((item, index) => {
|
|
85422
|
-
collectReferences(item, remId, [...
|
|
86274
|
+
collectReferences(item, remId, [...path16, index], into3);
|
|
85423
86275
|
});
|
|
85424
86276
|
return;
|
|
85425
86277
|
}
|
|
@@ -85429,7 +86281,7 @@ function collectReferences(value8, remId, path13, into3) {
|
|
|
85429
86281
|
into3.push({
|
|
85430
86282
|
refId: maybeRef._id,
|
|
85431
86283
|
remId,
|
|
85432
|
-
path: formatPath2(
|
|
86284
|
+
path: formatPath2(path16),
|
|
85433
86285
|
tokenKind: classifyToken(maybeRef)
|
|
85434
86286
|
});
|
|
85435
86287
|
return;
|
|
@@ -85438,13 +86290,13 @@ function collectReferences(value8, remId, path13, into3) {
|
|
|
85438
86290
|
into3.push({
|
|
85439
86291
|
refId: maybeRef._id,
|
|
85440
86292
|
remId,
|
|
85441
|
-
path: formatPath2(
|
|
86293
|
+
path: formatPath2(path16),
|
|
85442
86294
|
tokenKind: classifyToken(maybeRef)
|
|
85443
86295
|
});
|
|
85444
86296
|
return;
|
|
85445
86297
|
}
|
|
85446
86298
|
for (const [key, child] of Object.entries(maybeRef)) {
|
|
85447
|
-
collectReferences(child, remId, [...
|
|
86299
|
+
collectReferences(child, remId, [...path16, key], into3);
|
|
85448
86300
|
}
|
|
85449
86301
|
}
|
|
85450
86302
|
}
|
|
@@ -85561,8 +86413,8 @@ function buildReferencesMarkdown(remId, guidance, outbound, inbound, includeInbo
|
|
|
85561
86413
|
const tokenKind = Array.isArray(ref.tokenKinds) ? `type: ${formatTokenKinds(ref.tokenKinds)}` : "";
|
|
85562
86414
|
const ancestor = ref.ancestor ? `, ancestor: ${ref.ancestor}` : "";
|
|
85563
86415
|
const count4 = typeof ref.count === "number" ? `${ref.count} occurrences` : "";
|
|
85564
|
-
const
|
|
85565
|
-
const samplePath =
|
|
86416
|
+
const path16 = ref.occurrences ? ref.occurrences[0]?.path ?? null : ref.representativePath;
|
|
86417
|
+
const samplePath = path16 ? `, sample path: ${path16}` : "";
|
|
85566
86418
|
lines3.push(`- **${name}** (ID: ${ref.refId}, ${count4}${ancestor}${samplePath}${tokenKind ? `, ${tokenKind}` : ""})`);
|
|
85567
86419
|
});
|
|
85568
86420
|
}
|
|
@@ -89072,16 +89924,16 @@ var WsClientLive = succeed10(WsClient, {
|
|
|
89072
89924
|
});
|
|
89073
89925
|
|
|
89074
89926
|
// src/commands/ws/_shared.ts
|
|
89075
|
-
import
|
|
89927
|
+
import path17 from "node:path";
|
|
89076
89928
|
|
|
89077
89929
|
// src/services/Process.ts
|
|
89078
89930
|
import { spawn as spawn3 } from "node:child_process";
|
|
89079
|
-
import
|
|
89080
|
-
import
|
|
89931
|
+
import fs10 from "node:fs";
|
|
89932
|
+
import path16 from "node:path";
|
|
89081
89933
|
class Process extends Tag2("Process")() {
|
|
89082
89934
|
}
|
|
89083
89935
|
function ensureDirSync(filePath) {
|
|
89084
|
-
|
|
89936
|
+
fs10.mkdirSync(path16.dirname(filePath), { recursive: true });
|
|
89085
89937
|
}
|
|
89086
89938
|
var ProcessLive = succeed10(Process, {
|
|
89087
89939
|
isPidRunning: (pid) => sync3(() => {
|
|
@@ -89099,7 +89951,7 @@ var ProcessLive = succeed10(Process, {
|
|
|
89099
89951
|
spawnDetached: (params3) => try_3({
|
|
89100
89952
|
try: () => {
|
|
89101
89953
|
ensureDirSync(params3.logFile);
|
|
89102
|
-
const fd =
|
|
89954
|
+
const fd = fs10.openSync(params3.logFile, "a");
|
|
89103
89955
|
const child = spawn3(params3.command, [...params3.args], {
|
|
89104
89956
|
cwd: params3.cwd,
|
|
89105
89957
|
env: params3.env,
|
|
@@ -89253,7 +90105,7 @@ function toInitialSupervisorState(now2) {
|
|
|
89253
90105
|
};
|
|
89254
90106
|
}
|
|
89255
90107
|
function defaultStateFilePathFromPidFile(pidFilePath) {
|
|
89256
|
-
return
|
|
90108
|
+
return path17.join(path17.dirname(pidFilePath), "ws.state.json");
|
|
89257
90109
|
}
|
|
89258
90110
|
function startWsSupervisor(params3) {
|
|
89259
90111
|
return gen2(function* () {
|
|
@@ -89740,30 +90592,30 @@ var wsLogsCommand = exports_Command.make("logs", {
|
|
|
89740
90592
|
}).pipe(catchAll2(writeFailure)));
|
|
89741
90593
|
|
|
89742
90594
|
// src/commands/ws/restart.ts
|
|
89743
|
-
import
|
|
90595
|
+
import path19 from "node:path";
|
|
89744
90596
|
|
|
89745
90597
|
// src/lib/statuslineArtifacts.ts
|
|
89746
|
-
import { promises as
|
|
90598
|
+
import { promises as fs12 } from "node:fs";
|
|
89747
90599
|
|
|
89748
90600
|
// src/services/StatusLineFile.ts
|
|
89749
|
-
import { promises as
|
|
89750
|
-
import
|
|
90601
|
+
import { promises as fs11 } from "node:fs";
|
|
90602
|
+
import path18 from "node:path";
|
|
89751
90603
|
class StatusLineFile extends Tag2("StatusLineFile")() {
|
|
89752
90604
|
}
|
|
89753
90605
|
function defaultTextFile() {
|
|
89754
|
-
return
|
|
90606
|
+
return path18.join(homeDir(), ".agent-remnote", "status-line.txt");
|
|
89755
90607
|
}
|
|
89756
90608
|
function defaultJsonFile() {
|
|
89757
|
-
return
|
|
90609
|
+
return path18.join(homeDir(), ".agent-remnote", "status-line.json");
|
|
89758
90610
|
}
|
|
89759
|
-
function
|
|
89760
|
-
return
|
|
90611
|
+
function ensureDir6(p3) {
|
|
90612
|
+
return fs11.mkdir(path18.dirname(p3), { recursive: true }).then(() => {
|
|
89761
90613
|
return;
|
|
89762
90614
|
});
|
|
89763
90615
|
}
|
|
89764
90616
|
async function readFileOrEmpty(filePath) {
|
|
89765
90617
|
try {
|
|
89766
|
-
return await
|
|
90618
|
+
return await fs11.readFile(filePath, "utf8");
|
|
89767
90619
|
} catch (e) {
|
|
89768
90620
|
if (e?.code === "ENOENT")
|
|
89769
90621
|
return "";
|
|
@@ -89771,10 +90623,10 @@ async function readFileOrEmpty(filePath) {
|
|
|
89771
90623
|
}
|
|
89772
90624
|
}
|
|
89773
90625
|
async function writeTextAtomic(filePath, content) {
|
|
89774
|
-
await
|
|
90626
|
+
await ensureDir6(filePath);
|
|
89775
90627
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
89776
|
-
await
|
|
89777
|
-
await
|
|
90628
|
+
await fs11.writeFile(tmp, content, "utf8");
|
|
90629
|
+
await fs11.rename(tmp, filePath);
|
|
89778
90630
|
}
|
|
89779
90631
|
var StatusLineFileLive = succeed10(StatusLineFile, {
|
|
89780
90632
|
defaultTextFile: () => defaultTextFile(),
|
|
@@ -89827,7 +90679,7 @@ function resolveStatuslineArtifactPaths(params3) {
|
|
|
89827
90679
|
function deleteFileIfExists(filePath) {
|
|
89828
90680
|
return promise2(async () => {
|
|
89829
90681
|
try {
|
|
89830
|
-
await
|
|
90682
|
+
await fs12.unlink(filePath);
|
|
89831
90683
|
return { action: "deleted", file: filePath };
|
|
89832
90684
|
} catch (e) {
|
|
89833
90685
|
if (e?.code === "ENOENT")
|
|
@@ -89870,7 +90722,7 @@ var wsRestartCommand = exports_Command.make("restart", {
|
|
|
89870
90722
|
const pidFilePath = resolveUserFilePath(pidFile4 ?? daemonFiles.defaultPidFile());
|
|
89871
90723
|
const existing = yield* daemonFiles.readPidFile(pidFilePath);
|
|
89872
90724
|
let stopResult = { stopped: true, pid_file: pidFilePath };
|
|
89873
|
-
const stateFilePath = resolveUserFilePath(existing?.state_file ??
|
|
90725
|
+
const stateFilePath = resolveUserFilePath(existing?.state_file ?? path19.join(path19.dirname(pidFilePath), "ws.state.json"));
|
|
89874
90726
|
if (existing) {
|
|
89875
90727
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
89876
90728
|
if (!alive) {
|
|
@@ -89942,10 +90794,10 @@ function safeJsonParse2(text14) {
|
|
|
89942
90794
|
}
|
|
89943
90795
|
}
|
|
89944
90796
|
var WsBridgeServerLive = succeed10(WsBridgeServer, {
|
|
89945
|
-
listen: ({ port: port3, path:
|
|
90797
|
+
listen: ({ port: port3, path: path20, host }) => acquireRelease2(gen2(function* () {
|
|
89946
90798
|
const events = yield* unbounded5();
|
|
89947
90799
|
const sockets = new Map;
|
|
89948
|
-
const wss = new import_websocket_server.default({ port: port3, host, path:
|
|
90800
|
+
const wss = new import_websocket_server.default({ port: port3, host, path: path20 });
|
|
89949
90801
|
wss.on("connection", (ws, req) => {
|
|
89950
90802
|
const connId = randomUUID4();
|
|
89951
90803
|
const remoteAddr = safeStringHeader(req?.socket?.remoteAddress);
|
|
@@ -89979,7 +90831,7 @@ var WsBridgeServerLive = succeed10(WsBridgeServer, {
|
|
|
89979
90831
|
});
|
|
89980
90832
|
const handle = {
|
|
89981
90833
|
events,
|
|
89982
|
-
serverInfo: { port: port3, path:
|
|
90834
|
+
serverInfo: { port: port3, path: path20 },
|
|
89983
90835
|
sendText: (connId, text14) => sync3(() => {
|
|
89984
90836
|
const ws = sockets.get(connId);
|
|
89985
90837
|
if (!ws)
|
|
@@ -90041,23 +90893,23 @@ var WsBridgeServerLive = succeed10(WsBridgeServer, {
|
|
|
90041
90893
|
code: "WS_UNAVAILABLE",
|
|
90042
90894
|
message: "Failed to start ws bridge server",
|
|
90043
90895
|
exitCode: 1,
|
|
90044
|
-
details: { error: String(error4?.message || error4), port: port3, path:
|
|
90896
|
+
details: { error: String(error4?.message || error4), port: port3, path: path20, host }
|
|
90045
90897
|
}))))
|
|
90046
90898
|
});
|
|
90047
90899
|
|
|
90048
90900
|
// src/services/WsBridgeStateFile.ts
|
|
90049
|
-
import { promises as
|
|
90050
|
-
import
|
|
90901
|
+
import { promises as fs13 } from "node:fs";
|
|
90902
|
+
import path20 from "node:path";
|
|
90051
90903
|
class WsBridgeStateFile extends Tag2("WsBridgeStateFile")() {
|
|
90052
90904
|
}
|
|
90053
|
-
async function
|
|
90054
|
-
await
|
|
90905
|
+
async function ensureDir7(filePath) {
|
|
90906
|
+
await fs13.mkdir(path20.dirname(filePath), { recursive: true });
|
|
90055
90907
|
}
|
|
90056
90908
|
async function writeTextAtomic2(filePath, content) {
|
|
90057
|
-
await
|
|
90909
|
+
await ensureDir7(filePath);
|
|
90058
90910
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
90059
|
-
await
|
|
90060
|
-
await
|
|
90911
|
+
await fs13.writeFile(tmp, content, "utf8");
|
|
90912
|
+
await fs13.rename(tmp, filePath);
|
|
90061
90913
|
}
|
|
90062
90914
|
var WsBridgeStateFileLive = succeed10(WsBridgeStateFile, {
|
|
90063
90915
|
write: ({ filePath, json: json4 }) => tryPromise2({
|
|
@@ -90163,7 +91015,7 @@ var TmuxLive = scoped3(Tmux, gen2(function* () {
|
|
|
90163
91015
|
}));
|
|
90164
91016
|
|
|
90165
91017
|
// src/services/WsBridgeState.ts
|
|
90166
|
-
import { promises as
|
|
91018
|
+
import { promises as fs14 } from "node:fs";
|
|
90167
91019
|
class WsBridgeState extends Tag2("WsBridgeState")() {
|
|
90168
91020
|
}
|
|
90169
91021
|
function toNonNegativeInt3(value8) {
|
|
@@ -90189,7 +91041,7 @@ var WsBridgeStateLive = succeed10(WsBridgeState, {
|
|
|
90189
91041
|
return { connection: "off", selection: { kind: "none" } };
|
|
90190
91042
|
}
|
|
90191
91043
|
const raw4 = yield* tryPromise2({
|
|
90192
|
-
try: async () => await
|
|
91044
|
+
try: async () => await fs14.readFile(cfg.wsStateFile.path, "utf8"),
|
|
90193
91045
|
catch: (e) => {
|
|
90194
91046
|
if (e?.code === "ENOENT")
|
|
90195
91047
|
return null;
|
|
@@ -90602,18 +91454,18 @@ function parseWsUrl(url2) {
|
|
|
90602
91454
|
}
|
|
90603
91455
|
const port3 = u.port ? Number(u.port) : u.protocol === "wss:" ? 443 : 80;
|
|
90604
91456
|
const host = u.hostname && u.hostname.length > 0 ? u.hostname : "localhost";
|
|
90605
|
-
const
|
|
91457
|
+
const path21 = u.pathname && u.pathname.length > 0 ? u.pathname : "/ws";
|
|
90606
91458
|
if (!Number.isFinite(port3) || port3 <= 0) {
|
|
90607
91459
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl port: ${url2}`, exitCode: 2 });
|
|
90608
91460
|
}
|
|
90609
|
-
if (!
|
|
91461
|
+
if (!path21.startsWith("/")) {
|
|
90610
91462
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl path: ${url2}`, exitCode: 2 });
|
|
90611
91463
|
}
|
|
90612
|
-
return { host, port: port3, path:
|
|
91464
|
+
return { host, port: port3, path: path21 };
|
|
90613
91465
|
}
|
|
90614
91466
|
var wsServeCommand = exports_Command.make("serve", {}, () => gen2(function* () {
|
|
90615
91467
|
const cfg = yield* AppConfig;
|
|
90616
|
-
const { host, port: port3, path:
|
|
91468
|
+
const { host, port: port3, path: path21 } = yield* try_3({
|
|
90617
91469
|
try: () => parseWsUrl(cfg.wsUrl),
|
|
90618
91470
|
catch: (e) => isCliError(e) ? e : new CliError({
|
|
90619
91471
|
code: "INVALID_ARGS",
|
|
@@ -90622,7 +91474,7 @@ var wsServeCommand = exports_Command.make("serve", {}, () => gen2(function* () {
|
|
|
90622
91474
|
details: { ws_url: cfg.wsUrl, error: String(e?.message || e) }
|
|
90623
91475
|
})
|
|
90624
91476
|
});
|
|
90625
|
-
yield* runWsBridgeRuntime({ host, port: port3, path:
|
|
91477
|
+
yield* runWsBridgeRuntime({ host, port: port3, path: path21 });
|
|
90626
91478
|
}).pipe(catchAll2(writeFailure)));
|
|
90627
91479
|
|
|
90628
91480
|
// src/commands/ws/start.ts
|
|
@@ -90638,14 +91490,14 @@ function parseWsUrl2(url2) {
|
|
|
90638
91490
|
}
|
|
90639
91491
|
const port3 = u.port ? Number(u.port) : u.protocol === "wss:" ? 443 : 80;
|
|
90640
91492
|
const host = u.hostname && u.hostname.length > 0 ? u.hostname : "localhost";
|
|
90641
|
-
const
|
|
91493
|
+
const path21 = u.pathname && u.pathname.length > 0 ? u.pathname : "/ws";
|
|
90642
91494
|
if (!Number.isFinite(port3) || port3 <= 0) {
|
|
90643
91495
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl port: ${url2}`, exitCode: 2 });
|
|
90644
91496
|
}
|
|
90645
|
-
if (!
|
|
91497
|
+
if (!path21.startsWith("/")) {
|
|
90646
91498
|
throw new CliError({ code: "INVALID_ARGS", message: `Invalid wsUrl path: ${url2}`, exitCode: 2 });
|
|
90647
91499
|
}
|
|
90648
|
-
return { host, port: port3, path:
|
|
91500
|
+
return { host, port: port3, path: path21 };
|
|
90649
91501
|
}
|
|
90650
91502
|
var pidFile4 = text9("pid-file").pipe(optional5, map34(optionToUndefined4));
|
|
90651
91503
|
var logFile3 = text9("log-file").pipe(optional5, map34(optionToUndefined4));
|
|
@@ -90657,7 +91509,7 @@ var wsStartCommand = exports_Command.make("start", {
|
|
|
90657
91509
|
}, ({ foreground, wait, pidFile: pidFile5, logFile: logFile4 }) => gen2(function* () {
|
|
90658
91510
|
const cfg = yield* AppConfig;
|
|
90659
91511
|
if (foreground) {
|
|
90660
|
-
const { host, port: port3, path:
|
|
91512
|
+
const { host, port: port3, path: path21 } = yield* try_3({
|
|
90661
91513
|
try: () => parseWsUrl2(cfg.wsUrl),
|
|
90662
91514
|
catch: (e) => isCliError(e) ? e : new CliError({
|
|
90663
91515
|
code: "INVALID_ARGS",
|
|
@@ -90666,7 +91518,7 @@ var wsStartCommand = exports_Command.make("start", {
|
|
|
90666
91518
|
details: { ws_url: cfg.wsUrl, error: String(e?.message || e) }
|
|
90667
91519
|
})
|
|
90668
91520
|
});
|
|
90669
|
-
yield* runWsBridgeRuntime({ host, port: port3, path:
|
|
91521
|
+
yield* runWsBridgeRuntime({ host, port: port3, path: path21 });
|
|
90670
91522
|
return;
|
|
90671
91523
|
}
|
|
90672
91524
|
const result = yield* startWsSupervisor({ waitMs: wait, pidFile: pidFile5, logFile: logFile4 });
|
|
@@ -90681,7 +91533,7 @@ var wsStartCommand = exports_Command.make("start", {
|
|
|
90681
91533
|
}).pipe(catchAll2(writeFailure)));
|
|
90682
91534
|
|
|
90683
91535
|
// src/commands/ws/status.ts
|
|
90684
|
-
import
|
|
91536
|
+
import path21 from "node:path";
|
|
90685
91537
|
function optionToUndefined5(opt) {
|
|
90686
91538
|
return isSome2(opt) ? opt.value : undefined;
|
|
90687
91539
|
}
|
|
@@ -90700,14 +91552,14 @@ var wsStatusCommand = exports_Command.make("status", { pidFile: pidFile5 }, ({ p
|
|
|
90700
91552
|
if (!alive) {
|
|
90701
91553
|
const stalePidInfo = pidInfo;
|
|
90702
91554
|
yield* daemonFiles.deletePidFile(pidFilePath);
|
|
90703
|
-
const staleStateFilePath = resolveUserFilePath(pidInfo.state_file ??
|
|
91555
|
+
const staleStateFilePath = resolveUserFilePath(pidInfo.state_file ?? path21.join(path21.dirname(pidFilePath), "ws.state.json"));
|
|
90704
91556
|
yield* supervisorState.deleteStateFile(staleStateFilePath);
|
|
90705
91557
|
selfHealCleanup = yield* cleanupStatuslineArtifacts(resolveStatuslineArtifactPaths({ cfg, pidInfo: stalePidInfo }));
|
|
90706
91558
|
yield* sync3(() => refreshTmuxStatusLine());
|
|
90707
91559
|
pidInfo = undefined;
|
|
90708
91560
|
}
|
|
90709
91561
|
}
|
|
90710
|
-
const stateFilePath = resolveUserFilePath(pidInfo?.state_file ??
|
|
91562
|
+
const stateFilePath = resolveUserFilePath(pidInfo?.state_file ?? path21.join(path21.dirname(pidFilePath), "ws.state.json"));
|
|
90711
91563
|
const state = yield* supervisorState.readStateFile(stateFilePath);
|
|
90712
91564
|
const mode = pidInfo ? pidInfo.mode ?? "legacy" : "supervisor";
|
|
90713
91565
|
const supervisorPid = pidInfo?.pid;
|
|
@@ -90870,7 +91722,7 @@ var wsStatusLineCommand = exports_Command.make("status-line", { stateFile, stale
|
|
|
90870
91722
|
}).pipe(catchAll2(writeFailure)));
|
|
90871
91723
|
|
|
90872
91724
|
// src/commands/ws/stop.ts
|
|
90873
|
-
import
|
|
91725
|
+
import path22 from "node:path";
|
|
90874
91726
|
function optionToUndefined7(opt) {
|
|
90875
91727
|
return isSome2(opt) ? opt.value : undefined;
|
|
90876
91728
|
}
|
|
@@ -90898,7 +91750,7 @@ var wsStopCommand = exports_Command.make("stop", { force: boolean8("force"), pid
|
|
|
90898
91750
|
});
|
|
90899
91751
|
return;
|
|
90900
91752
|
}
|
|
90901
|
-
const stateFilePath = resolveUserFilePath(existing.state_file ??
|
|
91753
|
+
const stateFilePath = resolveUserFilePath(existing.state_file ?? path22.join(path22.dirname(pidFilePath), "ws.state.json"));
|
|
90902
91754
|
const alive = yield* proc.isPidRunning(existing.pid);
|
|
90903
91755
|
if (!alive) {
|
|
90904
91756
|
yield* daemonFiles.deletePidFile(pidFilePath);
|
|
@@ -91092,8 +91944,8 @@ var ChildProcessLive = succeed10(ChildProcess2, {
|
|
|
91092
91944
|
});
|
|
91093
91945
|
|
|
91094
91946
|
// src/services/LogWriter.ts
|
|
91095
|
-
import { promises as
|
|
91096
|
-
import
|
|
91947
|
+
import { promises as fs15 } from "node:fs";
|
|
91948
|
+
import path23 from "node:path";
|
|
91097
91949
|
class LogWriterFactory extends Tag2("LogWriterFactory")() {
|
|
91098
91950
|
}
|
|
91099
91951
|
function sanitizePositiveInt(value8, fallback) {
|
|
@@ -91104,12 +91956,12 @@ function sanitizeMaxBytes(value8, fallback) {
|
|
|
91104
91956
|
return null;
|
|
91105
91957
|
return Number.isFinite(value8) && value8 > 0 ? Math.floor(value8) : fallback;
|
|
91106
91958
|
}
|
|
91107
|
-
async function
|
|
91108
|
-
await
|
|
91959
|
+
async function ensureDir8(filePath) {
|
|
91960
|
+
await fs15.mkdir(path23.dirname(filePath), { recursive: true });
|
|
91109
91961
|
}
|
|
91110
91962
|
async function safeStat(filePath) {
|
|
91111
91963
|
try {
|
|
91112
|
-
const s = await
|
|
91964
|
+
const s = await fs15.stat(filePath);
|
|
91113
91965
|
return { size: s.size };
|
|
91114
91966
|
} catch {
|
|
91115
91967
|
return;
|
|
@@ -91118,25 +91970,25 @@ async function safeStat(filePath) {
|
|
|
91118
91970
|
async function rotateFiles(filePath, keep) {
|
|
91119
91971
|
if (keep <= 0)
|
|
91120
91972
|
return;
|
|
91121
|
-
const dir2 =
|
|
91122
|
-
const base =
|
|
91973
|
+
const dir2 = path23.dirname(filePath);
|
|
91974
|
+
const base = path23.basename(filePath);
|
|
91123
91975
|
let entries2 = [];
|
|
91124
91976
|
try {
|
|
91125
|
-
entries2 = await
|
|
91977
|
+
entries2 = await fs15.readdir(dir2);
|
|
91126
91978
|
} catch {
|
|
91127
91979
|
return;
|
|
91128
91980
|
}
|
|
91129
|
-
const rotated = entries2.filter((name) => name.startsWith(`${base}.`)).map((name) =>
|
|
91981
|
+
const rotated = entries2.filter((name) => name.startsWith(`${base}.`)).map((name) => path23.join(dir2, name)).sort().reverse();
|
|
91130
91982
|
for (const p3 of rotated.slice(keep)) {
|
|
91131
91983
|
try {
|
|
91132
|
-
await
|
|
91984
|
+
await fs15.unlink(p3);
|
|
91133
91985
|
} catch {}
|
|
91134
91986
|
}
|
|
91135
91987
|
}
|
|
91136
91988
|
async function createLogWriter(filePath, options6) {
|
|
91137
91989
|
const maxBytes = sanitizeMaxBytes(options6.maxBytes, 20 * 1024 * 1024);
|
|
91138
91990
|
const keep = sanitizePositiveInt(options6.keep, 5);
|
|
91139
|
-
await
|
|
91991
|
+
await ensureDir8(filePath);
|
|
91140
91992
|
let currentSize = (await safeStat(filePath))?.size ?? 0;
|
|
91141
91993
|
let handle;
|
|
91142
91994
|
let closing = false;
|
|
@@ -91145,7 +91997,7 @@ async function createLogWriter(filePath, options6) {
|
|
|
91145
91997
|
async function openIfNeeded() {
|
|
91146
91998
|
if (handle)
|
|
91147
91999
|
return handle;
|
|
91148
|
-
handle = await
|
|
92000
|
+
handle = await fs15.open(filePath, "a");
|
|
91149
92001
|
return handle;
|
|
91150
92002
|
}
|
|
91151
92003
|
async function rotateIfNeeded(nextBytes) {
|
|
@@ -91159,7 +92011,7 @@ async function createLogWriter(filePath, options6) {
|
|
|
91159
92011
|
handle = undefined;
|
|
91160
92012
|
const rotatedPath = `${filePath}.${Date.now()}`;
|
|
91161
92013
|
try {
|
|
91162
|
-
await
|
|
92014
|
+
await fs15.rename(filePath, rotatedPath);
|
|
91163
92015
|
} catch {}
|
|
91164
92016
|
currentSize = 0;
|
|
91165
92017
|
await rotateFiles(filePath, keep);
|
|
@@ -91567,7 +92419,7 @@ var dailySummaryCommand = exports_Command.make("summary", { days: days2, maxLine
|
|
|
91567
92419
|
}).pipe(catchAll2(writeFailure)));
|
|
91568
92420
|
|
|
91569
92421
|
// src/services/FileInput.ts
|
|
91570
|
-
import { promises as
|
|
92422
|
+
import { promises as fs16 } from "node:fs";
|
|
91571
92423
|
class FileInput extends Tag2("FileInput")() {
|
|
91572
92424
|
}
|
|
91573
92425
|
var DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
|
|
@@ -91603,7 +92455,7 @@ async function readTextFromFilePath(pathSpec, maxBytes) {
|
|
|
91603
92455
|
}
|
|
91604
92456
|
const resolved = resolveUserFilePath(trimmed2);
|
|
91605
92457
|
try {
|
|
91606
|
-
const stat3 = await
|
|
92458
|
+
const stat3 = await fs16.stat(resolved);
|
|
91607
92459
|
if (!stat3.isFile()) {
|
|
91608
92460
|
throw new CliError({ code: "INVALID_ARGS", message: `Not a file: ${resolved}`, exitCode: 2 });
|
|
91609
92461
|
}
|
|
@@ -91615,7 +92467,7 @@ async function readTextFromFilePath(pathSpec, maxBytes) {
|
|
|
91615
92467
|
details: { bytes: stat3.size, max_bytes: maxBytes, file: resolved }
|
|
91616
92468
|
});
|
|
91617
92469
|
}
|
|
91618
|
-
return await
|
|
92470
|
+
return await fs16.readFile(resolved, "utf8");
|
|
91619
92471
|
} catch (error4) {
|
|
91620
92472
|
if (isCliError(error4))
|
|
91621
92473
|
throw error4;
|
|
@@ -91659,7 +92511,7 @@ var FileInputLive = succeed10(FileInput, {
|
|
|
91659
92511
|
});
|
|
91660
92512
|
|
|
91661
92513
|
// src/services/Payload.ts
|
|
91662
|
-
import { promises as
|
|
92514
|
+
import { promises as fs17 } from "node:fs";
|
|
91663
92515
|
class Payload extends Tag2("Payload")() {
|
|
91664
92516
|
}
|
|
91665
92517
|
var MAX_PAYLOAD_BYTES = 5 * 1024 * 1024;
|
|
@@ -91700,7 +92552,7 @@ async function readPayloadSpec(spec) {
|
|
|
91700
92552
|
if (!filePath) {
|
|
91701
92553
|
throw new CliError({ code: "INVALID_ARGS", message: "Payload file path cannot be empty", exitCode: 2 });
|
|
91702
92554
|
}
|
|
91703
|
-
return await
|
|
92555
|
+
return await fs17.readFile(filePath, "utf8");
|
|
91704
92556
|
}
|
|
91705
92557
|
return spec;
|
|
91706
92558
|
}
|
|
@@ -92496,86 +93348,29 @@ var dbRecentCommand = exports_Command.make("recent", {
|
|
|
92496
93348
|
ids3.push(row.id);
|
|
92497
93349
|
const marker = row.edited_after_create ? " (edited after creation)" : "";
|
|
92498
93350
|
mdLines.push(`- \`${msToLocalStr(row.created_at)}\` ${row.preview} \`${row.id}\`${marker}`);
|
|
92499
|
-
}
|
|
92500
|
-
mdLines.push("");
|
|
92501
|
-
}
|
|
92502
|
-
}
|
|
92503
|
-
}
|
|
92504
|
-
const data = {
|
|
92505
|
-
db_path: dbPath,
|
|
92506
|
-
resolution: result.info.source,
|
|
92507
|
-
days: d,
|
|
92508
|
-
cutoff_ms: cutoffMs,
|
|
92509
|
-
counts: result.result.counts,
|
|
92510
|
-
items: result.result.items
|
|
92511
|
-
};
|
|
92512
|
-
yield* writeSuccess({ data, ids: ids3, md: mdLines.join(`
|
|
92513
|
-
`).trimEnd() + `
|
|
92514
|
-
` });
|
|
92515
|
-
}).pipe(catchAll2(writeFailure)));
|
|
92516
|
-
|
|
92517
|
-
// src/commands/read/db/index.ts
|
|
92518
|
-
var readDbCommand = exports_Command.make("db", {}).pipe(exports_Command.withSubcommands([dbBackupsCommand, dbRecentCommand]));
|
|
92519
|
-
|
|
92520
|
-
// src/commands/db/index.ts
|
|
92521
|
-
var dbCommand = readDbCommand;
|
|
92522
|
-
|
|
92523
|
-
// src/lib/remnote.ts
|
|
92524
|
-
import fs15 from "node:fs";
|
|
92525
|
-
import path21 from "node:path";
|
|
92526
|
-
function tryParseRemnoteLink(input) {
|
|
92527
|
-
const raw4 = input.trim();
|
|
92528
|
-
let u;
|
|
92529
|
-
try {
|
|
92530
|
-
u = new URL(raw4);
|
|
92531
|
-
} catch {
|
|
92532
|
-
return;
|
|
92533
|
-
}
|
|
92534
|
-
if (u.protocol === "remnote:" && u.hostname === "w") {
|
|
92535
|
-
const parts2 = u.pathname.split("/").filter(Boolean);
|
|
92536
|
-
const workspaceId = parts2.length >= 1 ? parts2[0] : undefined;
|
|
92537
|
-
const remId = parts2.length >= 2 ? parts2[1] : undefined;
|
|
92538
|
-
if (workspaceId && remId) {
|
|
92539
|
-
return { workspaceId: workspaceId.trim(), remId: remId.trim() };
|
|
92540
|
-
}
|
|
92541
|
-
return;
|
|
92542
|
-
}
|
|
92543
|
-
if ((u.protocol === "https:" || u.protocol === "http:") && u.hostname.endsWith("remnote.com")) {
|
|
92544
|
-
const parts2 = u.pathname.split("/").filter(Boolean);
|
|
92545
|
-
if (parts2.length >= 3 && parts2[0] === "w") {
|
|
92546
|
-
const workspaceId = parts2[1];
|
|
92547
|
-
const remId = parts2[2];
|
|
92548
|
-
if (workspaceId && remId) {
|
|
92549
|
-
return { workspaceId: workspaceId.trim(), remId: remId.trim() };
|
|
92550
|
-
}
|
|
92551
|
-
}
|
|
92552
|
-
}
|
|
92553
|
-
return;
|
|
92554
|
-
}
|
|
92555
|
-
function tryParseRemnoteLinkFromRef(input) {
|
|
92556
|
-
const direct = tryParseRemnoteLink(input);
|
|
92557
|
-
if (direct)
|
|
92558
|
-
return direct;
|
|
92559
|
-
const raw4 = input.trim();
|
|
92560
|
-
const idx = raw4.indexOf(":");
|
|
92561
|
-
if (idx <= 0)
|
|
92562
|
-
return;
|
|
92563
|
-
const value8 = raw4.slice(idx + 1).trim();
|
|
92564
|
-
if (!value8)
|
|
92565
|
-
return;
|
|
92566
|
-
return tryParseRemnoteLink(value8);
|
|
92567
|
-
}
|
|
92568
|
-
function remnoteDbPathForWorkspaceId(workspaceId) {
|
|
92569
|
-
return path21.join(homeDir(), "remnote", `remnote-${workspaceId}`, "remnote.db");
|
|
92570
|
-
}
|
|
92571
|
-
function tryResolveRemnoteDbPathForWorkspaceIdSync(workspaceId) {
|
|
92572
|
-
const p3 = remnoteDbPathForWorkspaceId(workspaceId);
|
|
92573
|
-
try {
|
|
92574
|
-
return fs15.statSync(p3).isFile() ? p3 : undefined;
|
|
92575
|
-
} catch {
|
|
92576
|
-
return;
|
|
93351
|
+
}
|
|
93352
|
+
mdLines.push("");
|
|
93353
|
+
}
|
|
93354
|
+
}
|
|
92577
93355
|
}
|
|
92578
|
-
|
|
93356
|
+
const data = {
|
|
93357
|
+
db_path: dbPath,
|
|
93358
|
+
resolution: result.info.source,
|
|
93359
|
+
days: d,
|
|
93360
|
+
cutoff_ms: cutoffMs,
|
|
93361
|
+
counts: result.result.counts,
|
|
93362
|
+
items: result.result.items
|
|
93363
|
+
};
|
|
93364
|
+
yield* writeSuccess({ data, ids: ids3, md: mdLines.join(`
|
|
93365
|
+
`).trimEnd() + `
|
|
93366
|
+
` });
|
|
93367
|
+
}).pipe(catchAll2(writeFailure)));
|
|
93368
|
+
|
|
93369
|
+
// src/commands/read/db/index.ts
|
|
93370
|
+
var readDbCommand = exports_Command.make("db", {}).pipe(exports_Command.withSubcommands([dbBackupsCommand, dbRecentCommand]));
|
|
93371
|
+
|
|
93372
|
+
// src/commands/db/index.ts
|
|
93373
|
+
var dbCommand = readDbCommand;
|
|
92579
93374
|
|
|
92580
93375
|
// src/services/RefResolver.ts
|
|
92581
93376
|
class RefResolver extends Tag2("RefResolver")() {
|
|
@@ -93713,12 +94508,12 @@ var applyCommand = exports_Command.make("apply", {
|
|
|
93713
94508
|
}).pipe(catchAll2(writeFailure)));
|
|
93714
94509
|
|
|
93715
94510
|
// src/services/ApiDaemonFiles.ts
|
|
93716
|
-
import { promises as
|
|
93717
|
-
import
|
|
94511
|
+
import { promises as fs18 } from "node:fs";
|
|
94512
|
+
import path24 from "node:path";
|
|
93718
94513
|
class ApiDaemonFiles extends Tag2("ApiDaemonFiles")() {
|
|
93719
94514
|
}
|
|
93720
|
-
function
|
|
93721
|
-
return
|
|
94515
|
+
function ensureDir9(p3) {
|
|
94516
|
+
return fs18.mkdir(path24.dirname(p3), { recursive: true }).then(() => {
|
|
93722
94517
|
return;
|
|
93723
94518
|
});
|
|
93724
94519
|
}
|
|
@@ -93726,19 +94521,19 @@ function defaultPidFile2() {
|
|
|
93726
94521
|
const envPidFile = process.env.REMNOTE_API_PID_FILE;
|
|
93727
94522
|
if (typeof envPidFile === "string" && envPidFile.trim())
|
|
93728
94523
|
return resolveUserFilePath(envPidFile);
|
|
93729
|
-
return
|
|
94524
|
+
return path24.join(homeDir(), ".agent-remnote", "api.pid");
|
|
93730
94525
|
}
|
|
93731
94526
|
function defaultLogFile2() {
|
|
93732
94527
|
const envLogFile = process.env.REMNOTE_API_LOG_FILE;
|
|
93733
94528
|
if (typeof envLogFile === "string" && envLogFile.trim())
|
|
93734
94529
|
return resolveUserFilePath(envLogFile);
|
|
93735
|
-
return
|
|
94530
|
+
return path24.join(homeDir(), ".agent-remnote", "api.log");
|
|
93736
94531
|
}
|
|
93737
94532
|
function defaultStateFile2() {
|
|
93738
94533
|
const envStateFile = process.env.REMNOTE_API_STATE_FILE;
|
|
93739
94534
|
if (typeof envStateFile === "string" && envStateFile.trim())
|
|
93740
94535
|
return resolveUserFilePath(envStateFile);
|
|
93741
|
-
return
|
|
94536
|
+
return path24.join(homeDir(), ".agent-remnote", "api.state.json");
|
|
93742
94537
|
}
|
|
93743
94538
|
function parseJson2(raw4, filePath) {
|
|
93744
94539
|
try {
|
|
@@ -93759,7 +94554,7 @@ var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
|
93759
94554
|
readPidFile: (pidFilePath) => tryPromise2({
|
|
93760
94555
|
try: async () => {
|
|
93761
94556
|
const resolved = resolveUserFilePath(pidFilePath);
|
|
93762
|
-
const raw4 = await
|
|
94557
|
+
const raw4 = await fs18.readFile(resolved, "utf8");
|
|
93763
94558
|
return parseJson2(raw4, resolved);
|
|
93764
94559
|
},
|
|
93765
94560
|
catch: (error4) => {
|
|
@@ -93783,8 +94578,8 @@ var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
|
93783
94578
|
writePidFile: (pidFilePath, value8) => tryPromise2({
|
|
93784
94579
|
try: async () => {
|
|
93785
94580
|
const resolved = resolveUserFilePath(pidFilePath);
|
|
93786
|
-
await
|
|
93787
|
-
await
|
|
94581
|
+
await ensureDir9(resolved);
|
|
94582
|
+
await fs18.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
93788
94583
|
`, "utf8");
|
|
93789
94584
|
},
|
|
93790
94585
|
catch: (error4) => new CliError({
|
|
@@ -93797,7 +94592,7 @@ var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
|
93797
94592
|
deletePidFile: (pidFilePath) => tryPromise2({
|
|
93798
94593
|
try: async () => {
|
|
93799
94594
|
const resolved = resolveUserFilePath(pidFilePath);
|
|
93800
|
-
await
|
|
94595
|
+
await fs18.rm(resolved, { force: true });
|
|
93801
94596
|
},
|
|
93802
94597
|
catch: (error4) => new CliError({
|
|
93803
94598
|
code: "INTERNAL",
|
|
@@ -93809,7 +94604,7 @@ var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
|
93809
94604
|
readStateFile: (stateFilePath) => tryPromise2({
|
|
93810
94605
|
try: async () => {
|
|
93811
94606
|
const resolved = resolveUserFilePath(stateFilePath);
|
|
93812
|
-
const raw4 = await
|
|
94607
|
+
const raw4 = await fs18.readFile(resolved, "utf8");
|
|
93813
94608
|
return parseJson2(raw4, resolved);
|
|
93814
94609
|
},
|
|
93815
94610
|
catch: (error4) => {
|
|
@@ -93833,8 +94628,8 @@ var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
|
93833
94628
|
writeStateFile: (stateFilePath, value8) => tryPromise2({
|
|
93834
94629
|
try: async () => {
|
|
93835
94630
|
const resolved = resolveUserFilePath(stateFilePath);
|
|
93836
|
-
await
|
|
93837
|
-
await
|
|
94631
|
+
await ensureDir9(resolved);
|
|
94632
|
+
await fs18.writeFile(resolved, `${JSON.stringify(value8, null, 2)}
|
|
93838
94633
|
`, "utf8");
|
|
93839
94634
|
},
|
|
93840
94635
|
catch: (error4) => new CliError({
|
|
@@ -93847,7 +94642,7 @@ var ApiDaemonFilesLive = succeed10(ApiDaemonFiles, {
|
|
|
93847
94642
|
deleteStateFile: (stateFilePath) => tryPromise2({
|
|
93848
94643
|
try: async () => {
|
|
93849
94644
|
const resolved = resolveUserFilePath(stateFilePath);
|
|
93850
|
-
await
|
|
94645
|
+
await fs18.rm(resolved, { force: true });
|
|
93851
94646
|
},
|
|
93852
94647
|
catch: (error4) => new CliError({
|
|
93853
94648
|
code: "INTERNAL",
|
|
@@ -95873,8 +96668,8 @@ function resolveRefsInPayload(params3) {
|
|
|
95873
96668
|
const out = structuredClone(params3.payload);
|
|
95874
96669
|
const resolvedRefCache = new Map;
|
|
95875
96670
|
const idPaths = idFieldPathsForOpType(params3.opType);
|
|
95876
|
-
for (const
|
|
95877
|
-
const tokens = parsePathTokens(
|
|
96671
|
+
for (const path25 of idPaths) {
|
|
96672
|
+
const tokens = parsePathTokens(path25);
|
|
95878
96673
|
if (tokens.length === 0)
|
|
95879
96674
|
continue;
|
|
95880
96675
|
const leaves = collectLeafValues(out, tokens);
|
|
@@ -102648,7 +103443,7 @@ var stackEnsureCommand = exports_Command.make("ensure", {
|
|
|
102648
103443
|
}).pipe(catchAll2(writeFailure)));
|
|
102649
103444
|
|
|
102650
103445
|
// src/commands/stack/status.ts
|
|
102651
|
-
import
|
|
103446
|
+
import path25 from "node:path";
|
|
102652
103447
|
var stackStatusCommand = exports_Command.make("status", {}, () => gen2(function* () {
|
|
102653
103448
|
const cfg = yield* AppConfig;
|
|
102654
103449
|
const daemonFiles = yield* DaemonFiles;
|
|
@@ -102668,7 +103463,7 @@ var stackStatusCommand = exports_Command.make("status", {}, () => gen2(function*
|
|
|
102668
103463
|
const apiBaseUrl = apiLocalBaseUrl(apiPidInfo?.port ?? cfg.apiPort ?? 3000);
|
|
102669
103464
|
const apiStatus = yield* api.status({ baseUrl: apiBaseUrl, timeoutMs: 2000 }).pipe(either3);
|
|
102670
103465
|
const queueStats2 = yield* queue.stats({ dbPath: cfg.storeDb }).pipe(either3);
|
|
102671
|
-
const stateFilePath = resolveUserFilePath(daemonPidInfo?.state_file ??
|
|
103466
|
+
const stateFilePath = resolveUserFilePath(daemonPidInfo?.state_file ?? path25.join(path25.dirname(daemonPidFile), "ws.state.json"));
|
|
102672
103467
|
const data = {
|
|
102673
103468
|
daemon: {
|
|
102674
103469
|
running: daemonRunning,
|
|
@@ -102706,7 +103501,7 @@ var stackStatusCommand = exports_Command.make("status", {}, () => gen2(function*
|
|
|
102706
103501
|
}).pipe(catchAll2(writeFailure)));
|
|
102707
103502
|
|
|
102708
103503
|
// src/commands/stack/stop.ts
|
|
102709
|
-
import
|
|
103504
|
+
import path26 from "node:path";
|
|
102710
103505
|
var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* () {
|
|
102711
103506
|
const apiFiles = yield* ApiDaemonFiles;
|
|
102712
103507
|
const daemonFiles = yield* DaemonFiles;
|
|
@@ -102743,7 +103538,7 @@ var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* ()
|
|
|
102743
103538
|
}
|
|
102744
103539
|
}
|
|
102745
103540
|
yield* daemonFiles.deletePidFile(daemonPidFile).pipe(catchAll2(() => _void));
|
|
102746
|
-
yield* supervisorState.deleteStateFile(resolveUserFilePath(daemonPidInfo?.state_file ??
|
|
103541
|
+
yield* supervisorState.deleteStateFile(resolveUserFilePath(daemonPidInfo?.state_file ?? path26.join(path26.dirname(daemonPidFile), "ws.state.json"))).pipe(catchAll2(() => _void));
|
|
102747
103542
|
yield* writeSuccess({
|
|
102748
103543
|
data: { stopped: true, api_stopped: apiStopped, daemon_stopped: daemonStopped },
|
|
102749
103544
|
md: `- stopped: true
|
|
@@ -102756,242 +103551,6 @@ var stackStopCommand = exports_Command.make("stop", {}, () => gen2(function* ()
|
|
|
102756
103551
|
// src/commands/stack/index.ts
|
|
102757
103552
|
var stackCommand = exports_Command.make("stack", {}).pipe(exports_Command.withSubcommands([stackEnsureCommand, stackStopCommand, stackStatusCommand]));
|
|
102758
103553
|
|
|
102759
|
-
// src/services/Config.ts
|
|
102760
|
-
import fs17 from "node:fs";
|
|
102761
|
-
import path25 from "node:path";
|
|
102762
|
-
function defaultStoreDbPath() {
|
|
102763
|
-
return path25.join(homeDir(), ".agent-remnote", "store.sqlite");
|
|
102764
|
-
}
|
|
102765
|
-
function wsUrlFromPort(port7) {
|
|
102766
|
-
return `ws://localhost:${port7}/ws`;
|
|
102767
|
-
}
|
|
102768
|
-
function defaultWsStateFilePath() {
|
|
102769
|
-
return path25.join(homeDir(), ".agent-remnote", "ws.bridge.state.json");
|
|
102770
|
-
}
|
|
102771
|
-
function defaultStatusLineFilePath() {
|
|
102772
|
-
return path25.join(homeDir(), ".agent-remnote", "status-line.txt");
|
|
102773
|
-
}
|
|
102774
|
-
function defaultStatusLineJsonFilePath() {
|
|
102775
|
-
return path25.join(homeDir(), ".agent-remnote", "status-line.json");
|
|
102776
|
-
}
|
|
102777
|
-
function defaultApiPidFilePath() {
|
|
102778
|
-
return path25.join(homeDir(), ".agent-remnote", "api.pid");
|
|
102779
|
-
}
|
|
102780
|
-
function defaultApiLogFilePath() {
|
|
102781
|
-
return path25.join(homeDir(), ".agent-remnote", "api.log");
|
|
102782
|
-
}
|
|
102783
|
-
function defaultApiStateFilePath() {
|
|
102784
|
-
return path25.join(homeDir(), ".agent-remnote", "api.state.json");
|
|
102785
|
-
}
|
|
102786
|
-
function normalizeApiBasePath(raw4) {
|
|
102787
|
-
const trimmed2 = raw4.trim();
|
|
102788
|
-
if (!trimmed2)
|
|
102789
|
-
return "/v1";
|
|
102790
|
-
return trimmed2.startsWith("/") ? trimmed2 : `/${trimmed2}`;
|
|
102791
|
-
}
|
|
102792
|
-
function normalizeApiBaseUrl(raw4) {
|
|
102793
|
-
const trimmed2 = raw4.trim();
|
|
102794
|
-
if (!trimmed2)
|
|
102795
|
-
return trimmed2;
|
|
102796
|
-
let parsed;
|
|
102797
|
-
try {
|
|
102798
|
-
parsed = new URL(trimmed2);
|
|
102799
|
-
} catch {
|
|
102800
|
-
throw new CliError({
|
|
102801
|
-
code: "INVALID_ARGS",
|
|
102802
|
-
message: `Invalid apiBaseUrl: ${trimmed2}`,
|
|
102803
|
-
exitCode: 2,
|
|
102804
|
-
details: { api_base_url: trimmed2 }
|
|
102805
|
-
});
|
|
102806
|
-
}
|
|
102807
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
102808
|
-
throw new CliError({
|
|
102809
|
-
code: "INVALID_ARGS",
|
|
102810
|
-
message: `apiBaseUrl protocol must be http/https: ${trimmed2}`,
|
|
102811
|
-
exitCode: 2,
|
|
102812
|
-
details: { api_base_url: trimmed2 }
|
|
102813
|
-
});
|
|
102814
|
-
}
|
|
102815
|
-
const normalized = trimmed2.replace(/\/+$/, "");
|
|
102816
|
-
return normalized;
|
|
102817
|
-
}
|
|
102818
|
-
function resolveWsStateFile(spec) {
|
|
102819
|
-
const raw4 = spec.trim();
|
|
102820
|
-
if (raw4 === "0" || raw4.toLowerCase() === "false") {
|
|
102821
|
-
return { disabled: true, path: defaultWsStateFilePath() };
|
|
102822
|
-
}
|
|
102823
|
-
if (raw4)
|
|
102824
|
-
return { disabled: false, path: resolveUserFilePath(raw4) };
|
|
102825
|
-
return { disabled: false, path: defaultWsStateFilePath() };
|
|
102826
|
-
}
|
|
102827
|
-
function inferRemnoteDbFromWsState(params3) {
|
|
102828
|
-
if (params3.wsStateFile.disabled)
|
|
102829
|
-
return;
|
|
102830
|
-
const state = readJson(params3.wsStateFile.path);
|
|
102831
|
-
if (!state)
|
|
102832
|
-
return;
|
|
102833
|
-
const now2 = Date.now();
|
|
102834
|
-
const updatedAt = Number(state.updatedAt ?? 0);
|
|
102835
|
-
const staleMs13 = params3.wsStateStaleMs;
|
|
102836
|
-
const stale = !Number.isFinite(updatedAt) || updatedAt <= 0 || now2 - updatedAt > staleMs13;
|
|
102837
|
-
if (stale)
|
|
102838
|
-
return;
|
|
102839
|
-
const clients = Array.isArray(state.clients) ? state.clients : [];
|
|
102840
|
-
const activeConnIdRaw = typeof state.activeWorkerConnId === "string" ? state.activeWorkerConnId.trim() : "";
|
|
102841
|
-
const client = pickClient(clients, activeConnIdRaw || undefined);
|
|
102842
|
-
const kbIdRaw = typeof client?.uiContext?.kbId === "string" ? client.uiContext.kbId.trim() : "";
|
|
102843
|
-
if (!kbIdRaw)
|
|
102844
|
-
return;
|
|
102845
|
-
const dbPath = resolveUserFilePath(remnoteDbPathForWorkspaceId(kbIdRaw));
|
|
102846
|
-
try {
|
|
102847
|
-
return fs17.statSync(dbPath).isFile() ? dbPath : undefined;
|
|
102848
|
-
} catch {
|
|
102849
|
-
return;
|
|
102850
|
-
}
|
|
102851
|
-
}
|
|
102852
|
-
function pickFormat(raw4) {
|
|
102853
|
-
const json4 = raw4.json === true;
|
|
102854
|
-
const md = raw4.md === true;
|
|
102855
|
-
const ids6 = raw4.ids === true;
|
|
102856
|
-
const count4 = [json4, md, ids6].filter(Boolean).length;
|
|
102857
|
-
if (count4 > 1) {
|
|
102858
|
-
throw new CliError({
|
|
102859
|
-
code: "INVALID_ARGS",
|
|
102860
|
-
message: "Output format conflict: choose only one of --json/--md/--ids",
|
|
102861
|
-
exitCode: 2,
|
|
102862
|
-
details: { json: json4, md, ids: ids6 }
|
|
102863
|
-
});
|
|
102864
|
-
}
|
|
102865
|
-
if (json4)
|
|
102866
|
-
return "json";
|
|
102867
|
-
if (ids6)
|
|
102868
|
-
return "ids";
|
|
102869
|
-
return "md";
|
|
102870
|
-
}
|
|
102871
|
-
var rawConfigSpec = all8({
|
|
102872
|
-
json: boolean4("json").pipe(withDefault2(false)),
|
|
102873
|
-
md: boolean4("md").pipe(withDefault2(false)),
|
|
102874
|
-
ids: boolean4("ids").pipe(withDefault2(false)),
|
|
102875
|
-
quiet: boolean4("quiet").pipe(withDefault2(false)),
|
|
102876
|
-
debug: boolean4("debug").pipe(withDefault2(false)),
|
|
102877
|
-
remnoteDb: string5("remnoteDb").pipe(withDefault2("")),
|
|
102878
|
-
storeDb: string5("storeDb").pipe(withDefault2(defaultStoreDbPath())),
|
|
102879
|
-
daemonUrl: string5("daemonUrl").pipe(withDefault2("")),
|
|
102880
|
-
wsPort: port2("wsPort").pipe(withDefault2(6789)),
|
|
102881
|
-
wsScheduler: boolean4("wsScheduler").pipe(withDefault2(true)),
|
|
102882
|
-
wsDispatchMaxBytes: integer2("wsDispatchMaxBytes").pipe(withDefault2(512000), validate3({
|
|
102883
|
-
message: "wsDispatchMaxBytes must be a positive integer",
|
|
102884
|
-
validation: (n) => Number.isFinite(n) && n > 0
|
|
102885
|
-
})),
|
|
102886
|
-
wsDispatchMaxOpBytes: integer2("wsDispatchMaxOpBytes").pipe(withDefault2(256000), validate3({
|
|
102887
|
-
message: "wsDispatchMaxOpBytes must be a positive integer",
|
|
102888
|
-
validation: (n) => Number.isFinite(n) && n > 0
|
|
102889
|
-
})),
|
|
102890
|
-
repo: string5("repo").pipe(withDefault2("")),
|
|
102891
|
-
wsStateFile: string5("wsStateFile").pipe(withDefault2("")),
|
|
102892
|
-
wsStateStaleMs: integer2("wsStateStaleMs").pipe(withDefault2(60000), validate3({
|
|
102893
|
-
message: "wsStateStaleMs must be a positive integer",
|
|
102894
|
-
validation: (n) => Number.isFinite(n) && n > 0
|
|
102895
|
-
})),
|
|
102896
|
-
tmuxRefresh: boolean4("tmuxRefresh").pipe(withDefault2(true)),
|
|
102897
|
-
tmuxRefreshMinIntervalMs: integer2("tmuxRefreshMinIntervalMs").pipe(withDefault2(250), validate3({
|
|
102898
|
-
message: "tmuxRefreshMinIntervalMs must be a positive integer",
|
|
102899
|
-
validation: (n) => Number.isFinite(n) && n > 0
|
|
102900
|
-
})),
|
|
102901
|
-
statusLineFile: string5("statusLineFile").pipe(withDefault2(defaultStatusLineFilePath())),
|
|
102902
|
-
statusLineMinIntervalMs: integer2("statusLineMinIntervalMs").pipe(withDefault2(250), validate3({
|
|
102903
|
-
message: "statusLineMinIntervalMs must be a positive integer",
|
|
102904
|
-
validation: (n) => Number.isFinite(n) && n > 0
|
|
102905
|
-
})),
|
|
102906
|
-
statusLineDebug: boolean4("statusLineDebug").pipe(withDefault2(false)),
|
|
102907
|
-
statusLineJsonFile: string5("statusLineJsonFile").pipe(withDefault2(defaultStatusLineJsonFilePath())),
|
|
102908
|
-
apiBaseUrl: string5("apiBaseUrl").pipe(withDefault2("")),
|
|
102909
|
-
apiHost: string5("apiHost").pipe(withDefault2("0.0.0.0")),
|
|
102910
|
-
apiPort: port2("apiPort").pipe(withDefault2(3000)),
|
|
102911
|
-
apiBasePath: string5("apiBasePath").pipe(withDefault2("/v1")),
|
|
102912
|
-
apiPidFile: string5("apiPidFile").pipe(withDefault2(defaultApiPidFilePath())),
|
|
102913
|
-
apiLogFile: string5("apiLogFile").pipe(withDefault2(defaultApiLogFilePath())),
|
|
102914
|
-
apiStateFile: string5("apiStateFile").pipe(withDefault2(defaultApiStateFilePath()))
|
|
102915
|
-
});
|
|
102916
|
-
function cliErrorFromConfigError(error4) {
|
|
102917
|
-
if (isInvalidData2(error4) || isMissingData2(error4)) {
|
|
102918
|
-
return new CliError({
|
|
102919
|
-
code: "INVALID_ARGS",
|
|
102920
|
-
message: error4.message || "Invalid configuration",
|
|
102921
|
-
exitCode: 2,
|
|
102922
|
-
details: { path: error4.path, op: error4._op }
|
|
102923
|
-
});
|
|
102924
|
-
}
|
|
102925
|
-
return new CliError({
|
|
102926
|
-
code: "INVALID_ARGS",
|
|
102927
|
-
message: error4.message || "Invalid configuration",
|
|
102928
|
-
exitCode: 2,
|
|
102929
|
-
details: { op: error4._op }
|
|
102930
|
-
});
|
|
102931
|
-
}
|
|
102932
|
-
function optionalTrimmed(s) {
|
|
102933
|
-
const t = s.trim();
|
|
102934
|
-
return t.length > 0 ? t : undefined;
|
|
102935
|
-
}
|
|
102936
|
-
function resolveConfig() {
|
|
102937
|
-
return gen2(function* () {
|
|
102938
|
-
const raw4 = yield* rawConfigSpec;
|
|
102939
|
-
const wsStateFile = resolveWsStateFile(raw4.wsStateFile);
|
|
102940
|
-
const remnoteDb = optionalTrimmed(raw4.remnoteDb) ? resolveUserFilePath(raw4.remnoteDb) : inferRemnoteDbFromWsState({ wsStateFile, wsStateStaleMs: raw4.wsStateStaleMs }) || undefined;
|
|
102941
|
-
const storeDb = resolveUserFilePath(raw4.storeDb);
|
|
102942
|
-
const daemonUrl = optionalTrimmed(raw4.daemonUrl);
|
|
102943
|
-
const wsUrl = daemonUrl ? daemonUrl : wsUrlFromPort(raw4.wsPort);
|
|
102944
|
-
const format10 = yield* try_3({
|
|
102945
|
-
try: () => pickFormat(raw4),
|
|
102946
|
-
catch: (e) => isCliError(e) ? e : new CliError({
|
|
102947
|
-
code: "INVALID_ARGS",
|
|
102948
|
-
message: "Invalid output format flags",
|
|
102949
|
-
exitCode: 2,
|
|
102950
|
-
details: { error: String(e?.message || e) }
|
|
102951
|
-
})
|
|
102952
|
-
});
|
|
102953
|
-
const apiBaseUrl = optionalTrimmed(raw4.apiBaseUrl) ? normalizeApiBaseUrl(raw4.apiBaseUrl) : undefined;
|
|
102954
|
-
return {
|
|
102955
|
-
format: format10,
|
|
102956
|
-
quiet: raw4.quiet,
|
|
102957
|
-
debug: raw4.debug,
|
|
102958
|
-
remnoteDb,
|
|
102959
|
-
storeDb,
|
|
102960
|
-
wsUrl,
|
|
102961
|
-
wsScheduler: raw4.wsScheduler,
|
|
102962
|
-
wsDispatchMaxBytes: raw4.wsDispatchMaxBytes,
|
|
102963
|
-
wsDispatchMaxOpBytes: raw4.wsDispatchMaxOpBytes,
|
|
102964
|
-
repo: optionalTrimmed(raw4.repo) ? resolveUserFilePath(raw4.repo) : undefined,
|
|
102965
|
-
wsStateFile,
|
|
102966
|
-
wsStateStaleMs: raw4.wsStateStaleMs,
|
|
102967
|
-
tmuxRefresh: raw4.tmuxRefresh,
|
|
102968
|
-
tmuxRefreshMinIntervalMs: raw4.tmuxRefreshMinIntervalMs,
|
|
102969
|
-
statusLineFile: resolveUserFilePath(raw4.statusLineFile),
|
|
102970
|
-
statusLineMinIntervalMs: raw4.statusLineMinIntervalMs,
|
|
102971
|
-
statusLineDebug: raw4.statusLineDebug,
|
|
102972
|
-
statusLineJsonFile: resolveUserFilePath(raw4.statusLineJsonFile),
|
|
102973
|
-
apiBaseUrl,
|
|
102974
|
-
apiHost: raw4.apiHost.trim() || "0.0.0.0",
|
|
102975
|
-
apiPort: raw4.apiPort,
|
|
102976
|
-
apiBasePath: normalizeApiBasePath(raw4.apiBasePath),
|
|
102977
|
-
apiPidFile: resolveUserFilePath(raw4.apiPidFile),
|
|
102978
|
-
apiLogFile: resolveUserFilePath(raw4.apiLogFile),
|
|
102979
|
-
apiStateFile: resolveUserFilePath(raw4.apiStateFile)
|
|
102980
|
-
};
|
|
102981
|
-
}).pipe(catchAll2((error4) => {
|
|
102982
|
-
if (isCliError(error4))
|
|
102983
|
-
return fail8(error4);
|
|
102984
|
-
if (isConfigError2(error4))
|
|
102985
|
-
return fail8(cliErrorFromConfigError(error4));
|
|
102986
|
-
return fail8(new CliError({
|
|
102987
|
-
code: "INTERNAL",
|
|
102988
|
-
message: "Failed to parse config",
|
|
102989
|
-
exitCode: 1,
|
|
102990
|
-
details: { error: String(error4?.message || error4) }
|
|
102991
|
-
}));
|
|
102992
|
-
}));
|
|
102993
|
-
}
|
|
102994
|
-
|
|
102995
103554
|
// src/commands/index.ts
|
|
102996
103555
|
function optionToUndefined51(opt) {
|
|
102997
103556
|
return isSome2(opt) ? opt.value : undefined;
|
|
@@ -103002,10 +103561,11 @@ var daemonUrl = text9("daemon-url").pipe(optional5, map34(optionToUndefined51));
|
|
|
103002
103561
|
var wsPort = integer7("ws-port").pipe(optional5, map34(optionToUndefined51));
|
|
103003
103562
|
var repo = text9("repo").pipe(optional5, map34(optionToUndefined51));
|
|
103004
103563
|
var apiBaseUrl = text9("api-base-url").pipe(optional5, map34(optionToUndefined51));
|
|
103564
|
+
var configFile = text9("config-file").pipe(optional5, map34(optionToUndefined51));
|
|
103005
103565
|
var appConfigLive = effect(AppConfig, resolveConfig());
|
|
103006
103566
|
var statusLineUpdaterLive = StatusLineUpdaterLive.pipe(provide3([appConfigLive, QueueLive, StatusLineFileLive, TmuxLive, WsBridgeStateLive]));
|
|
103007
103567
|
var statusLineLive = StatusLineControllerLive.pipe(provide3(statusLineUpdaterLive), provide3(appConfigLive));
|
|
103008
|
-
var servicesLive = mergeAll5(appConfigLive, OutputLive, FileInputLive, FsAccessLive, LogWriterFactoryLive, PayloadLive, DaemonFilesLive, ApiDaemonFilesLive, ProcessLive, ChildProcessLive, WsClientLive, HostApiClientLive, QueueLive, RefResolverLive, RemDbLive, StatusLineFileLive, SubprocessLive, SupervisorStateLive, WsBridgeServerLive, WsBridgeStateFileLive, statusLineLive);
|
|
103568
|
+
var servicesLive = mergeAll5(appConfigLive, OutputLive, FileInputLive, FsAccessLive, LogWriterFactoryLive, PayloadLive, DaemonFilesLive, ApiDaemonFilesLive, ProcessLive, ChildProcessLive, WsClientLive, HostApiClientLive, UserConfigFileLive, QueueLive, RefResolverLive, RemDbLive, StatusLineFileLive, SubprocessLive, SupervisorStateLive, WsBridgeServerLive, WsBridgeStateFileLive, statusLineLive);
|
|
103009
103569
|
var rootCommand = exports_Command.make("agent-remnote", {
|
|
103010
103570
|
json: boolean8("json"),
|
|
103011
103571
|
md: boolean8("md"),
|
|
@@ -103017,7 +103577,8 @@ var rootCommand = exports_Command.make("agent-remnote", {
|
|
|
103017
103577
|
daemonUrl,
|
|
103018
103578
|
wsPort,
|
|
103019
103579
|
repo,
|
|
103020
|
-
apiBaseUrl
|
|
103580
|
+
apiBaseUrl,
|
|
103581
|
+
configFile
|
|
103021
103582
|
}).pipe(exports_Command.withSubcommands([
|
|
103022
103583
|
daemonCommand,
|
|
103023
103584
|
apiCommand,
|
|
@@ -103119,6 +103680,9 @@ function buildCliEnvConfigProvider(params3) {
|
|
|
103119
103680
|
const envApiBaseUrl = env2.REMNOTE_API_BASE_URL;
|
|
103120
103681
|
if (typeof envApiBaseUrl === "string" && envApiBaseUrl.trim())
|
|
103121
103682
|
map39.set("apiBaseUrl", envApiBaseUrl);
|
|
103683
|
+
const envConfigFile = env2.REMNOTE_CONFIG_FILE || env2.AGENT_REMNOTE_CONFIG_FILE;
|
|
103684
|
+
if (typeof envConfigFile === "string" && envConfigFile.trim())
|
|
103685
|
+
map39.set("configFile", envConfigFile);
|
|
103122
103686
|
const envApiHost = env2.REMNOTE_API_HOST;
|
|
103123
103687
|
if (typeof envApiHost === "string" && envApiHost.trim())
|
|
103124
103688
|
map39.set("apiHost", envApiHost);
|
|
@@ -103215,17 +103779,18 @@ function buildCommandTree(desc) {
|
|
|
103215
103779
|
}
|
|
103216
103780
|
return { name, children: children2 };
|
|
103217
103781
|
}
|
|
103218
|
-
var
|
|
103219
|
-
var
|
|
103220
|
-
var
|
|
103221
|
-
var
|
|
103782
|
+
var ROOT_BOOL_FLAGS2 = new Set(["--json", "--md", "--ids", "--quiet", "--debug"]);
|
|
103783
|
+
var BUILTIN_BOOL_FLAGS2 = new Set(["--help", "-h", "--wizard", "--version"]);
|
|
103784
|
+
var BUILTIN_VALUE_FLAGS2 = new Set(["--completions", "--log-level"]);
|
|
103785
|
+
var ROOT_VALUE_FLAGS2 = new Set([
|
|
103222
103786
|
"--remnote-db",
|
|
103223
103787
|
"--store-db",
|
|
103224
103788
|
"--daemon-url",
|
|
103225
103789
|
"--ws-port",
|
|
103226
103790
|
"--repo",
|
|
103227
103791
|
"--api-base-url",
|
|
103228
|
-
|
|
103792
|
+
"--config-file",
|
|
103793
|
+
...BUILTIN_VALUE_FLAGS2
|
|
103229
103794
|
]);
|
|
103230
103795
|
function parseRootConfigFromArgv(argv2) {
|
|
103231
103796
|
const tokens = argv2.slice(2);
|
|
@@ -103239,8 +103804,8 @@ function parseRootConfigFromArgv(argv2) {
|
|
|
103239
103804
|
break;
|
|
103240
103805
|
if (!raw4.startsWith("-"))
|
|
103241
103806
|
break;
|
|
103242
|
-
const { flag, inlineValue } =
|
|
103243
|
-
if (
|
|
103807
|
+
const { flag, inlineValue } = splitFlagInlineValue2(raw4);
|
|
103808
|
+
if (ROOT_BOOL_FLAGS2.has(flag)) {
|
|
103244
103809
|
const key = flag.slice(2);
|
|
103245
103810
|
if (inlineValue !== null) {
|
|
103246
103811
|
out.set(key, inlineValue.trim().toLowerCase());
|
|
@@ -103248,7 +103813,7 @@ function parseRootConfigFromArgv(argv2) {
|
|
|
103248
103813
|
continue;
|
|
103249
103814
|
}
|
|
103250
103815
|
const next4 = tokens[i + 1];
|
|
103251
|
-
if (typeof next4 === "string" &&
|
|
103816
|
+
if (typeof next4 === "string" && isBooleanLiteralToken2(next4)) {
|
|
103252
103817
|
out.set(key, next4.trim().toLowerCase());
|
|
103253
103818
|
i += 2;
|
|
103254
103819
|
continue;
|
|
@@ -103257,8 +103822,8 @@ function parseRootConfigFromArgv(argv2) {
|
|
|
103257
103822
|
i += 1;
|
|
103258
103823
|
continue;
|
|
103259
103824
|
}
|
|
103260
|
-
if (
|
|
103261
|
-
const key = flag === "--remnote-db" ? "remnoteDb" : flag === "--store-db" ? "storeDb" : flag === "--daemon-url" ? "daemonUrl" : flag === "--ws-port" ? "wsPort" : flag === "--repo" ? "repo" : flag === "--api-base-url" ? "apiBaseUrl" : null;
|
|
103825
|
+
if (ROOT_VALUE_FLAGS2.has(flag)) {
|
|
103826
|
+
const key = flag === "--remnote-db" ? "remnoteDb" : flag === "--store-db" ? "storeDb" : flag === "--daemon-url" ? "daemonUrl" : flag === "--ws-port" ? "wsPort" : flag === "--repo" ? "repo" : flag === "--api-base-url" ? "apiBaseUrl" : flag === "--config-file" ? "configFile" : null;
|
|
103262
103827
|
if (inlineValue !== null) {
|
|
103263
103828
|
if (key)
|
|
103264
103829
|
out.set(key, inlineValue);
|
|
@@ -103273,13 +103838,13 @@ function parseRootConfigFromArgv(argv2) {
|
|
|
103273
103838
|
i += 2;
|
|
103274
103839
|
continue;
|
|
103275
103840
|
}
|
|
103276
|
-
if (
|
|
103841
|
+
if (BUILTIN_BOOL_FLAGS2.has(flag)) {
|
|
103277
103842
|
if (inlineValue !== null) {
|
|
103278
103843
|
i += 1;
|
|
103279
103844
|
continue;
|
|
103280
103845
|
}
|
|
103281
103846
|
const next4 = tokens[i + 1];
|
|
103282
|
-
if (typeof next4 === "string" &&
|
|
103847
|
+
if (typeof next4 === "string" && isBooleanLiteralToken2(next4)) {
|
|
103283
103848
|
i += 2;
|
|
103284
103849
|
continue;
|
|
103285
103850
|
}
|
|
@@ -103290,11 +103855,11 @@ function parseRootConfigFromArgv(argv2) {
|
|
|
103290
103855
|
}
|
|
103291
103856
|
return out;
|
|
103292
103857
|
}
|
|
103293
|
-
function
|
|
103858
|
+
function isBooleanLiteralToken2(token) {
|
|
103294
103859
|
const v = token.trim().toLowerCase();
|
|
103295
103860
|
return v === "true" || v === "false";
|
|
103296
103861
|
}
|
|
103297
|
-
function
|
|
103862
|
+
function splitFlagInlineValue2(token) {
|
|
103298
103863
|
if (!token.startsWith("--"))
|
|
103299
103864
|
return { flag: token, inlineValue: null };
|
|
103300
103865
|
const eq = token.indexOf("=");
|
|
@@ -103303,7 +103868,7 @@ function splitFlagInlineValue(token) {
|
|
|
103303
103868
|
return { flag: token.slice(0, eq), inlineValue: token.slice(eq + 1) };
|
|
103304
103869
|
}
|
|
103305
103870
|
function isKnownRootFlag(flag) {
|
|
103306
|
-
return
|
|
103871
|
+
return ROOT_BOOL_FLAGS2.has(flag) || ROOT_VALUE_FLAGS2.has(flag) || BUILTIN_BOOL_FLAGS2.has(flag);
|
|
103307
103872
|
}
|
|
103308
103873
|
function consumeRootFlag(tokens, index) {
|
|
103309
103874
|
const raw4 = String(tokens[index] ?? "");
|
|
@@ -103313,14 +103878,14 @@ function consumeRootFlag(tokens, index) {
|
|
|
103313
103878
|
error: new CliError({ code: "INVALID_ARGS", message: "Received unknown argument: ''", exitCode: 2 })
|
|
103314
103879
|
};
|
|
103315
103880
|
}
|
|
103316
|
-
const { flag, inlineValue } =
|
|
103881
|
+
const { flag, inlineValue } = splitFlagInlineValue2(raw4);
|
|
103317
103882
|
if (!isKnownRootFlag(flag)) {
|
|
103318
103883
|
return {
|
|
103319
103884
|
nextIndex: index + 1,
|
|
103320
103885
|
error: new CliError({ code: "INVALID_ARGS", message: `Received unknown argument: '${raw4}'`, exitCode: 2 })
|
|
103321
103886
|
};
|
|
103322
103887
|
}
|
|
103323
|
-
if (
|
|
103888
|
+
if (ROOT_VALUE_FLAGS2.has(flag)) {
|
|
103324
103889
|
if (inlineValue !== null)
|
|
103325
103890
|
return { nextIndex: index + 1, error: null };
|
|
103326
103891
|
if (index + 1 >= tokens.length) {
|
|
@@ -103335,8 +103900,8 @@ function consumeRootFlag(tokens, index) {
|
|
|
103335
103900
|
}
|
|
103336
103901
|
return { nextIndex: index + 2, error: null };
|
|
103337
103902
|
}
|
|
103338
|
-
if (
|
|
103339
|
-
if (inlineValue !== null && !
|
|
103903
|
+
if (ROOT_BOOL_FLAGS2.has(flag) || BUILTIN_BOOL_FLAGS2.has(flag)) {
|
|
103904
|
+
if (inlineValue !== null && !isBooleanLiteralToken2(inlineValue)) {
|
|
103340
103905
|
return {
|
|
103341
103906
|
nextIndex: index + 1,
|
|
103342
103907
|
error: new CliError({
|
|
@@ -103349,7 +103914,7 @@ function consumeRootFlag(tokens, index) {
|
|
|
103349
103914
|
if (inlineValue !== null)
|
|
103350
103915
|
return { nextIndex: index + 1, error: null };
|
|
103351
103916
|
const next4 = tokens[index + 1];
|
|
103352
|
-
if (typeof next4 === "string" &&
|
|
103917
|
+
if (typeof next4 === "string" && isBooleanLiteralToken2(next4))
|
|
103353
103918
|
return { nextIndex: index + 2, error: null };
|
|
103354
103919
|
return { nextIndex: index + 1, error: null };
|
|
103355
103920
|
}
|
|
@@ -103357,8 +103922,8 @@ function consumeRootFlag(tokens, index) {
|
|
|
103357
103922
|
}
|
|
103358
103923
|
function consumeBuiltInFlag(tokens, index) {
|
|
103359
103924
|
const raw4 = String(tokens[index] ?? "");
|
|
103360
|
-
const { flag, inlineValue } =
|
|
103361
|
-
if (
|
|
103925
|
+
const { flag, inlineValue } = splitFlagInlineValue2(raw4);
|
|
103926
|
+
if (BUILTIN_VALUE_FLAGS2.has(flag)) {
|
|
103362
103927
|
if (inlineValue !== null)
|
|
103363
103928
|
return { ok: true, nextIndex: index + 1, error: null };
|
|
103364
103929
|
if (index + 1 >= tokens.length) {
|
|
@@ -103374,8 +103939,8 @@ function consumeBuiltInFlag(tokens, index) {
|
|
|
103374
103939
|
}
|
|
103375
103940
|
return { ok: true, nextIndex: index + 2, error: null };
|
|
103376
103941
|
}
|
|
103377
|
-
if (
|
|
103378
|
-
if (inlineValue !== null && !
|
|
103942
|
+
if (BUILTIN_BOOL_FLAGS2.has(flag)) {
|
|
103943
|
+
if (inlineValue !== null && !isBooleanLiteralToken2(inlineValue)) {
|
|
103379
103944
|
return {
|
|
103380
103945
|
ok: true,
|
|
103381
103946
|
nextIndex: index + 1,
|
|
@@ -103389,7 +103954,7 @@ function consumeBuiltInFlag(tokens, index) {
|
|
|
103389
103954
|
if (inlineValue !== null)
|
|
103390
103955
|
return { ok: true, nextIndex: index + 1, error: null };
|
|
103391
103956
|
const next4 = tokens[index + 1];
|
|
103392
|
-
if (typeof next4 === "string" &&
|
|
103957
|
+
if (typeof next4 === "string" && isBooleanLiteralToken2(next4))
|
|
103393
103958
|
return { ok: true, nextIndex: index + 2, error: null };
|
|
103394
103959
|
return { ok: true, nextIndex: index + 1, error: null };
|
|
103395
103960
|
}
|
|
@@ -103442,8 +104007,8 @@ function strictCliPreflight(tree, argv2) {
|
|
|
103442
104007
|
i = builtIn2.nextIndex;
|
|
103443
104008
|
continue;
|
|
103444
104009
|
}
|
|
103445
|
-
const { flag } =
|
|
103446
|
-
if (isKnownRootFlag(flag) && !
|
|
104010
|
+
const { flag } = splitFlagInlineValue2(t);
|
|
104011
|
+
if (isKnownRootFlag(flag) && !BUILTIN_BOOL_FLAGS2.has(flag) && !BUILTIN_VALUE_FLAGS2.has(flag)) {
|
|
103447
104012
|
return new CliError({
|
|
103448
104013
|
code: "INVALID_ARGS",
|
|
103449
104014
|
message: `Global option '${flag}' must be specified before the first subcommand`,
|
|
@@ -103652,7 +104217,7 @@ function strictCommandPreflightOrExit(argv2) {
|
|
|
103652
104217
|
if (jsonRequested) {
|
|
103653
104218
|
const tokens = argv2.slice(2);
|
|
103654
104219
|
const outputBuiltins = new Set(["--help", "-h", "--version", "--wizard", "--completions"]);
|
|
103655
|
-
const conflict = tokens.map((t) =>
|
|
104220
|
+
const conflict = tokens.map((t) => splitFlagInlineValue2(String(t)).flag).find((flag) => outputBuiltins.has(flag));
|
|
103656
104221
|
if (conflict) {
|
|
103657
104222
|
const error5 = new CliError({
|
|
103658
104223
|
code: "INVALID_ARGS",
|