open-walnut 0.6.16 → 0.6.17
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/README.md +7 -0
- package/dist/actions/inbox-triage-batch.js +556 -449
- package/dist/build-info.json +3 -3
- package/dist/cli-fast.js +2 -2
- package/dist/cli.js +564 -457
- package/dist/daemon-binaries/acp-worker.js.version +1 -1
- package/dist/daemon-binaries/dtach-linux-x64 +0 -0
- package/dist/integrations/calendar/index.js +556 -449
- package/dist/integrations/jira/index.js +556 -449
- package/dist/integrations/mail/index.js +2 -2
- package/dist/integrations/ms-todo/index.js +556 -449
- package/dist/web/server.js +577 -470
- package/package.json +1 -1
|
@@ -6988,6 +6988,7 @@ function createOfflineHostCore(deps4) {
|
|
|
6988
6988
|
const MAX_ARGS_BYTES = 256 * 1024;
|
|
6989
6989
|
const WRITE_BUDGET = 30;
|
|
6990
6990
|
const WRITE_WINDOW_MS = 6e4;
|
|
6991
|
+
const LOCK_RETRY_MS = [100, 300, 900];
|
|
6991
6992
|
const DEFAULT_REPLY_SECS = 3600;
|
|
6992
6993
|
const IMPLICIT_REPLY_SECS = 6 * 3600;
|
|
6993
6994
|
const DRAIN_BATCH = 200;
|
|
@@ -7134,7 +7135,7 @@ function createOfflineHostCore(deps4) {
|
|
|
7134
7135
|
...opts2.admit ? { admit: opts2.admit } : {}
|
|
7135
7136
|
});
|
|
7136
7137
|
if (!r8.ok) {
|
|
7137
|
-
if (r8.code === "journal_unwritable") deps4.log("error", "offline host: journal write refused", { home, kind, code: r8.code, why: r8.why, error: r8.message });
|
|
7138
|
+
if (r8.code === "journal_unwritable" && r8.why !== "locked") deps4.log("error", "offline host: journal write refused", { home, kind, code: r8.code, why: r8.why, error: r8.message });
|
|
7138
7139
|
return r8;
|
|
7139
7140
|
}
|
|
7140
7141
|
if (!r8.duplicate) {
|
|
@@ -7149,6 +7150,19 @@ function createOfflineHostCore(deps4) {
|
|
|
7149
7150
|
if (r8.ok) return null;
|
|
7150
7151
|
return fail6(r8.code, r8.message, { ...r8.retryAfterMs !== void 0 ? { retryAfterMs: r8.retryAfterMs } : {}, ...r8.why ? { detail: { why: r8.why } } : {} });
|
|
7151
7152
|
}
|
|
7153
|
+
const lockRefused = (r8) => !r8.ok && r8.error.code === "journal_unwritable" && r8.error.detail?.why === "locked";
|
|
7154
|
+
async function whenUnlocked(home, op2, run13) {
|
|
7155
|
+
const t0 = Date.now();
|
|
7156
|
+
let r8 = run13();
|
|
7157
|
+
for (const ms2 of LOCK_RETRY_MS) {
|
|
7158
|
+
if (!lockRefused(r8)) return r8;
|
|
7159
|
+
deps4.log("warn", "offline host: the journal is locked by another process; trying the write again", { home, op: op2, waitedMs: Date.now() - t0, retryInMs: ms2 });
|
|
7160
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms2));
|
|
7161
|
+
r8 = run13();
|
|
7162
|
+
}
|
|
7163
|
+
if (lockRefused(r8)) deps4.log("error", "offline host: the journal stayed locked; write refused", { home, op: op2, waitedMs: Date.now() - t0 });
|
|
7164
|
+
return r8;
|
|
7165
|
+
}
|
|
7152
7166
|
function configure(slice) {
|
|
7153
7167
|
if (!slice || slice.v !== 1 || typeof slice.home !== "string" || !slice.home) throw new Error("host.slice: bad slice");
|
|
7154
7168
|
const prev = slices.get(slice.home);
|
|
@@ -7882,10 +7896,8 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
7882
7896
|
if (no) return no;
|
|
7883
7897
|
deps4.log("info", "offline host: write queued", { home, op: name, taskId: task.id, callerSid: callerSid5, kind: "task-fields", seq: saved.ok ? saved.seq : void 0 });
|
|
7884
7898
|
} else {
|
|
7885
|
-
const denied = admitWrite(callerSid5) ?? roomFor(home);
|
|
7886
|
-
if (denied) return denied;
|
|
7887
7899
|
const base = slices.get(home)?.tasks.find((t3) => t3.id === task.id)?.updated_at;
|
|
7888
|
-
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }));
|
|
7900
|
+
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }, false, { admit: () => admitWrite(callerSid5) ?? roomFor(home) }));
|
|
7889
7901
|
if (no) return no;
|
|
7890
7902
|
deps4.log("info", "offline host: write queued", { home, op: name, taskId: task.id, callerSid: callerSid5 });
|
|
7891
7903
|
}
|
|
@@ -8327,7 +8339,7 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
8327
8339
|
const fromCopy = deps4.replica ? deps4.replica.answer(home, name, args, offlineNote(home)) : null;
|
|
8328
8340
|
if (fromCopy) return fromCopy;
|
|
8329
8341
|
if (deps4.boards && deps4.boards.BOARD_OPS.indexOf(name) !== -1) return opBoard(home, callerSid5, name, args);
|
|
8330
|
-
if (QUEUED_OPS.includes(name)) return opQueued(home, callerSid5, name, args);
|
|
8342
|
+
if (QUEUED_OPS.includes(name)) return whenUnlocked(home, name, () => opQueued(home, callerSid5, name, args));
|
|
8331
8343
|
return needsServer(name ? `"${name}"` : "That call");
|
|
8332
8344
|
}
|
|
8333
8345
|
}
|
|
@@ -8840,6 +8852,10 @@ ${mid}` : "";
|
|
|
8840
8852
|
handle: handle4,
|
|
8841
8853
|
handleLocal,
|
|
8842
8854
|
handleFollower,
|
|
8855
|
+
/** handleFollower, waiting out another process's journal lock (whenUnlocked): the twins' follower.op. */
|
|
8856
|
+
handleFollowerWaiting: (home, req) => whenUnlocked(home, String(req.op ?? ""), () => handleFollower(home, req)),
|
|
8857
|
+
/** noteSession, waiting out another process's journal lock (whenUnlocked): the twins' host ask. */
|
|
8858
|
+
noteSessionWaiting: (home, rec3, opId, by) => whenUnlocked(home, "session", () => noteSession(home, rec3, opId, by)),
|
|
8843
8859
|
pendingFor,
|
|
8844
8860
|
journalStats,
|
|
8845
8861
|
onResult,
|
|
@@ -23962,7 +23978,7 @@ function dispatchCommand(ws, id, cmd) {
|
|
|
23962
23978
|
case 'follower.sessions': return cmdFollowerSessions(ws, id);
|
|
23963
23979
|
case 'follower.send': return daemonCommands.run(function () { return cmdFollowerSend(ws, id, cmd); });
|
|
23964
23980
|
case 'follower.permission': return daemonCommands.run(function () { return cmdFollowerPermission(ws, id, cmd); });
|
|
23965
|
-
case 'follower.op': return cmdFollowerOp(ws, id, cmd);
|
|
23981
|
+
case 'follower.op': return daemonCommands.run(function () { return cmdFollowerOp(ws, id, cmd); });
|
|
23966
23982
|
case 'follower.pending': return cmdFollowerPending(ws, id, cmd);
|
|
23967
23983
|
// A new ask while the Mac is away ('replica-start-v1', WP12). Twin of daemon-standalone.ts.
|
|
23968
23984
|
case 'follower.start': return daemonCommands.run(function () { return cmdFollowerStart(ws, id, cmd); });
|
|
@@ -25376,14 +25392,15 @@ async function cmdFollowerPermission(ws, id, cmd) {
|
|
|
25376
25392
|
// The replica's write while the Mac is away (replica-ops-v1, journal v2). Its own gate:
|
|
25377
25393
|
// the follower's own Walnut, the quiet window unless the Mac is still taking the
|
|
25378
25394
|
// journal, and the daemon dir's owner. Twin of daemon-standalone.ts cmdFollowerOp.
|
|
25379
|
-
function cmdFollowerOp(ws, id, cmd) {
|
|
25395
|
+
async function cmdFollowerOp(ws, id, cmd) {
|
|
25380
25396
|
var home = followerHomeOf(ws);
|
|
25381
25397
|
if (!home) return sendError(ws, id, 'follower.op: send follower.hello first');
|
|
25382
25398
|
if (!followerMayWrite(home)) return sendError(ws, id, 'follower.op: your Mac answers again; write through it', { errorKind: 'leader_answers' });
|
|
25383
25399
|
if (!ownsDaemonDir()) {
|
|
25384
25400
|
return sendError(ws, id, 'follower.op: this daemon no longer owns its directory', { errorKind: 'journal_unwritable', detail: { why: 'not_owner' } });
|
|
25385
25401
|
}
|
|
25386
|
-
|
|
25402
|
+
// Waits out another process's journal lock (about 1.3 s) before it answers.
|
|
25403
|
+
var r = await offlineHost.handleFollowerWaiting(home, { op: cmd.op, args: cmd.args, actor: cmd.actor, opId: cmd.opId, base: cmd.base });
|
|
25387
25404
|
if (r.ok) return sendOk(ws, id, r.result);
|
|
25388
25405
|
sendError(ws, id, 'follower.op: ' + r.error.message, Object.assign({ errorKind: r.error.code },
|
|
25389
25406
|
r.error.detail !== undefined ? { detail: r.error.detail } : {}, r.error.retryAfterMs !== undefined ? { retryAfterMs: r.error.retryAfterMs } : {}));
|
|
@@ -25533,7 +25550,7 @@ async function startHostAsk(home, p, cmd) {
|
|
|
25533
25550
|
throw err;
|
|
25534
25551
|
}
|
|
25535
25552
|
if (DIE_AFTER_ASK_SPAWN) process.kill(process.pid, 'SIGKILL');
|
|
25536
|
-
var saved = offlineHost.
|
|
25553
|
+
var saved = await offlineHost.noteSessionWaiting(home, p.record, opId, cmd.actor);
|
|
25537
25554
|
hostStart.releasePending(home, p.sid);
|
|
25538
25555
|
if (!saved.ok) {
|
|
25539
25556
|
// Nothing would tell the Mac about this CLI: it must not run unseen. Not stamped as an
|
|
@@ -143397,8 +143414,9 @@ async function buildCopyManifest(kind) {
|
|
|
143397
143414
|
}
|
|
143398
143415
|
return manifest;
|
|
143399
143416
|
}
|
|
143400
|
-
function keepsCopiesTarget(t3) {
|
|
143401
|
-
|
|
143417
|
+
function keepsCopiesTarget(t3, kind) {
|
|
143418
|
+
if (t3.kind === "host") return t3.program?.() === "replica";
|
|
143419
|
+
return t3.kind === "companion" && (kind === void 0 || COMPANION_COPY_KINDS.has(kind));
|
|
143402
143420
|
}
|
|
143403
143421
|
function manifestDigest(manifest, ordered = false) {
|
|
143404
143422
|
let d8 = manifestDigests.get(manifest);
|
|
@@ -143512,7 +143530,7 @@ async function choiceOf(target2) {
|
|
|
143512
143530
|
}
|
|
143513
143531
|
async function syncCopyKinds(kinds, deps4 = {}) {
|
|
143514
143532
|
const now = deps4.now ?? Date.now;
|
|
143515
|
-
const all = (deps4.targets ?? await defaultTargets())().filter(keepsCopiesTarget);
|
|
143533
|
+
const all = (deps4.targets ?? await defaultTargets())().filter((t3) => kinds.some((k8) => keepsCopiesTarget(t3, k8.kind)));
|
|
143516
143534
|
const ready2 = [];
|
|
143517
143535
|
for (const target2 of all) if (await target2.available()) ready2.push({ target: target2, choice: await choiceOf(target2) });
|
|
143518
143536
|
const results = [];
|
|
@@ -143520,7 +143538,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
143520
143538
|
const asOf2 = now();
|
|
143521
143539
|
const manifests = /* @__PURE__ */ new Map();
|
|
143522
143540
|
for (const kind of kinds) {
|
|
143523
|
-
if (!ready2.some((r8) => r8.choice[kind.choice])) continue;
|
|
143541
|
+
if (!ready2.some((r8) => r8.choice[kind.choice] && keepsCopiesTarget(r8.target, kind.kind))) continue;
|
|
143524
143542
|
try {
|
|
143525
143543
|
manifests.set(kind.kind, await buildCopyManifest(kind));
|
|
143526
143544
|
} catch (err2) {
|
|
@@ -143529,6 +143547,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
143529
143547
|
}
|
|
143530
143548
|
for (const { target: target2, choice } of ready2) {
|
|
143531
143549
|
for (const kind of kinds) {
|
|
143550
|
+
if (!keepsCopiesTarget(target2, kind.kind)) continue;
|
|
143532
143551
|
const manifest = manifests.get(kind.kind);
|
|
143533
143552
|
const st2 = kindState(target2, kind.kind);
|
|
143534
143553
|
if (!choice[kind.choice]) {
|
|
@@ -143574,7 +143593,7 @@ async function purgeKind(kind, target2, st2) {
|
|
|
143574
143593
|
async function confirmCopyKindRemoval(targetId, kind, opts2 = {}) {
|
|
143575
143594
|
const { replicaTargets: replicaTargets2 } = await Promise.resolve().then(() => (init_replica_targets(), replica_targets_exports));
|
|
143576
143595
|
const target2 = replicaTargets2().find((t3) => t3.id === targetId);
|
|
143577
|
-
if (!target2 || target2
|
|
143596
|
+
if (!target2 || !keepsCopiesTarget(target2, kind) || !peekKindState(targetId, kind)) return false;
|
|
143578
143597
|
if (!confirmKindRemoval(target2, kind, opts2)) return false;
|
|
143579
143598
|
log.session.warn("copies: the user confirmed a removal of most rows", { target: targetId, kind, entries: peekKindState(targetId, kind)?.confirmFor?.entries });
|
|
143580
143599
|
copySoon(kind);
|
|
@@ -143689,6 +143708,7 @@ var init_copy_kind = __esm({
|
|
|
143689
143708
|
init_kind_leader();
|
|
143690
143709
|
init_search_digest();
|
|
143691
143710
|
init_replica_status();
|
|
143711
|
+
init_gate();
|
|
143692
143712
|
COPY_DEBOUNCE_MS = 3e3;
|
|
143693
143713
|
COPY_SWEEP_MS = 5 * 6e4;
|
|
143694
143714
|
COPY_FIRST_ROUND_MS = 15e3;
|
|
@@ -149382,6 +149402,7 @@ var init_routines = __esm({
|
|
|
149382
149402
|
var routines_follower_exports = {};
|
|
149383
149403
|
__export(routines_follower_exports, {
|
|
149384
149404
|
_resetRoutinesCopyForTesting: () => _resetRoutinesCopyForTesting,
|
|
149405
|
+
companionRoutinesCopy: () => companionRoutinesCopy,
|
|
149385
149406
|
readRoutinesCopy: () => readRoutinesCopy,
|
|
149386
149407
|
routinesFollower: () => routinesFollower
|
|
149387
149408
|
});
|
|
@@ -149477,6 +149498,10 @@ async function readRoutinesCopy(opts2 = {}) {
|
|
|
149477
149498
|
const shown = opts2.includeDisabled ? all : all.filter((j8) => j8.enabled);
|
|
149478
149499
|
return shown.sort((a8, b8) => (a8.state.nextRunAtMs ?? 0) - (b8.state.nextRunAtMs ?? 0));
|
|
149479
149500
|
}
|
|
149501
|
+
async function companionRoutinesCopy(opts2 = {}) {
|
|
149502
|
+
if (!await copyKindHeld("routines")) return null;
|
|
149503
|
+
return await readRoutinesCopy(opts2) ?? [];
|
|
149504
|
+
}
|
|
149480
149505
|
function _resetRoutinesCopyForTesting() {
|
|
149481
149506
|
io2 = copyStateIo("routines");
|
|
149482
149507
|
serial3 = serialChain();
|
|
@@ -149492,8 +149517,8 @@ var init_routines_follower = __esm({
|
|
|
149492
149517
|
init_gate();
|
|
149493
149518
|
init_state_io();
|
|
149494
149519
|
init_routines();
|
|
149495
|
-
jobsFile = () => CRON_FILE;
|
|
149496
|
-
statesFile = () => path118.join(path118.dirname(CRON_FILE), "cron-state.json");
|
|
149520
|
+
jobsFile = () => copyPath(CRON_FILE);
|
|
149521
|
+
statesFile = () => copyPath(path118.join(path118.dirname(CRON_FILE), "cron-state.json"));
|
|
149497
149522
|
io2 = copyStateIo("routines");
|
|
149498
149523
|
serial3 = serialChain();
|
|
149499
149524
|
follower2 = null;
|
|
@@ -166069,8 +166094,8 @@ import path136 from "path";
|
|
|
166069
166094
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
166070
166095
|
function getVersion() {
|
|
166071
166096
|
if (cachedVersion) return cachedVersion;
|
|
166072
|
-
if ("0.6.
|
|
166073
|
-
cachedVersion = "0.6.
|
|
166097
|
+
if ("0.6.17") {
|
|
166098
|
+
cachedVersion = "0.6.17";
|
|
166074
166099
|
versionKnown = true;
|
|
166075
166100
|
return cachedVersion;
|
|
166076
166101
|
}
|
|
@@ -190275,6 +190300,132 @@ var init_agent_turn_queue = __esm({
|
|
|
190275
190300
|
}
|
|
190276
190301
|
});
|
|
190277
190302
|
|
|
190303
|
+
// src/core/replication/kinds/personas.ts
|
|
190304
|
+
var personas_exports = {};
|
|
190305
|
+
__export(personas_exports, {
|
|
190306
|
+
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
190307
|
+
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
190308
|
+
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
190309
|
+
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
190310
|
+
personasFollower: () => personasFollower,
|
|
190311
|
+
readPersonaCopy: () => readPersonaCopy
|
|
190312
|
+
});
|
|
190313
|
+
function tools(v3) {
|
|
190314
|
+
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
190315
|
+
}
|
|
190316
|
+
async function leaderRows() {
|
|
190317
|
+
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
190318
|
+
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
190319
|
+
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
190320
|
+
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
190321
|
+
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
190322
|
+
]);
|
|
190323
|
+
const config = await getConfig2();
|
|
190324
|
+
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
190325
|
+
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
190326
|
+
const rows = [];
|
|
190327
|
+
for (const a8 of agents) {
|
|
190328
|
+
if (!ID_RE2.test(a8.id)) continue;
|
|
190329
|
+
try {
|
|
190330
|
+
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
190331
|
+
const prompt = profile.systemPrompt ?? "";
|
|
190332
|
+
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
190333
|
+
rows.push({
|
|
190334
|
+
key: a8.id,
|
|
190335
|
+
agentId: a8.id,
|
|
190336
|
+
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
190337
|
+
systemPrompt: prompt,
|
|
190338
|
+
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
190339
|
+
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
190340
|
+
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
190341
|
+
...effort ? { effort } : {},
|
|
190342
|
+
...launch.model ? { launchModel: launch.model } : {},
|
|
190343
|
+
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
190344
|
+
});
|
|
190345
|
+
} catch (err2) {
|
|
190346
|
+
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
190347
|
+
}
|
|
190348
|
+
}
|
|
190349
|
+
return rows;
|
|
190350
|
+
}
|
|
190351
|
+
function hashOf4(row) {
|
|
190352
|
+
let h8 = hashes3.get(row);
|
|
190353
|
+
if (h8 === void 0) {
|
|
190354
|
+
h8 = sha12(JSON.stringify(row));
|
|
190355
|
+
hashes3.set(row, h8);
|
|
190356
|
+
}
|
|
190357
|
+
return h8;
|
|
190358
|
+
}
|
|
190359
|
+
function isRow3(v3) {
|
|
190360
|
+
const r8 = v3;
|
|
190361
|
+
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
190362
|
+
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
190363
|
+
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE2.test(r8.key) || typeof r8.name !== "string") return false;
|
|
190364
|
+
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
190365
|
+
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
190366
|
+
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
190367
|
+
for (const k8 of ["effort", "launchModel", "launchEffort"]) if (r8[k8] !== void 0 && (typeof r8[k8] !== "string" || !/^[A-Za-z0-9._:[\]/-]{1,128}$/.test(r8[k8]))) return false;
|
|
190368
|
+
return true;
|
|
190369
|
+
}
|
|
190370
|
+
function admit(r8) {
|
|
190371
|
+
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
190372
|
+
}
|
|
190373
|
+
async function readPersonaCopy(agentId) {
|
|
190374
|
+
const rows = await copy2.read();
|
|
190375
|
+
return rows?.[agentId] ?? null;
|
|
190376
|
+
}
|
|
190377
|
+
function _resetPersonasCopyForTesting() {
|
|
190378
|
+
copy2.reset();
|
|
190379
|
+
}
|
|
190380
|
+
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE2, TOOL_RE, hashes3, PERSONAS_KIND, ROW_KEYS, copy2, personasFollower;
|
|
190381
|
+
var init_personas = __esm({
|
|
190382
|
+
"src/core/replication/kinds/personas.ts"() {
|
|
190383
|
+
"use strict";
|
|
190384
|
+
init_logging();
|
|
190385
|
+
init_config_allowlist();
|
|
190386
|
+
init_kind();
|
|
190387
|
+
init_file_copy();
|
|
190388
|
+
PERSONAS_SCHEMA_VERSION = 1;
|
|
190389
|
+
PERSONAS_REMOVAL_FLOOR = 0;
|
|
190390
|
+
MAX_PROMPT_BYTES = 120 * 1024;
|
|
190391
|
+
ID_RE2 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
190392
|
+
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
190393
|
+
hashes3 = /* @__PURE__ */ new WeakMap();
|
|
190394
|
+
PERSONAS_KIND = {
|
|
190395
|
+
kind: "personas",
|
|
190396
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
190397
|
+
key: (r8) => r8.key,
|
|
190398
|
+
hash: hashOf4,
|
|
190399
|
+
ordered: false,
|
|
190400
|
+
digest: false,
|
|
190401
|
+
choice: "personas",
|
|
190402
|
+
rows: leaderRows,
|
|
190403
|
+
watch: (soon) => {
|
|
190404
|
+
let stop2 = null;
|
|
190405
|
+
let stopped2 = false;
|
|
190406
|
+
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
190407
|
+
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
190408
|
+
});
|
|
190409
|
+
return () => {
|
|
190410
|
+
stopped2 = true;
|
|
190411
|
+
stop2?.();
|
|
190412
|
+
};
|
|
190413
|
+
}
|
|
190414
|
+
};
|
|
190415
|
+
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
190416
|
+
copy2 = createFileCopy({
|
|
190417
|
+
kind: "personas",
|
|
190418
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
190419
|
+
label: "personas copy",
|
|
190420
|
+
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
190421
|
+
isRow: isRow3,
|
|
190422
|
+
key: (r8) => r8.key,
|
|
190423
|
+
admit
|
|
190424
|
+
});
|
|
190425
|
+
personasFollower = copy2.follower;
|
|
190426
|
+
}
|
|
190427
|
+
});
|
|
190428
|
+
|
|
190278
190429
|
// src/core/sessions/cloud-chat-lane.ts
|
|
190279
190430
|
var cloud_chat_lane_exports = {};
|
|
190280
190431
|
__export(cloud_chat_lane_exports, {
|
|
@@ -190413,7 +190564,9 @@ async function resolveCloudChatLane(lane, agentId, conversationId, cwd, firstMes
|
|
|
190413
190564
|
CATCH_UP_BANNER_CLOSE: CATCH_UP_BANNER_CLOSE2,
|
|
190414
190565
|
buildConversationSeed: buildConversationSeed2
|
|
190415
190566
|
} = await Promise.resolve().then(() => (init_chat_history(), chat_history_exports));
|
|
190416
|
-
const {
|
|
190567
|
+
const { readPersonaCopy: readPersonaCopy2 } = await Promise.resolve().then(() => (init_personas(), personas_exports));
|
|
190568
|
+
const persona = await readPersonaCopy2(agentId).catch(() => null);
|
|
190569
|
+
const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId, ...persona ? { persona } : {} });
|
|
190417
190570
|
const profile = toCloudChatProfile(base, CONVERSATION_SEED_HEADER2);
|
|
190418
190571
|
const sessionId = crypto49.randomUUID();
|
|
190419
190572
|
const seedInProfile = !!seed && (seed.text !== "" || seed.stats.turnsTotal === 0);
|
|
@@ -197382,9 +197535,9 @@ function sanitizeHealthSync(body7, now = Date.now()) {
|
|
|
197382
197535
|
const tz = isValidTz(b8.tz) ? b8.tz : "";
|
|
197383
197536
|
const spec = metricSpec(type);
|
|
197384
197537
|
const generic = isGenericType(type);
|
|
197385
|
-
const storeId = typeof b8.storeId === "string" &&
|
|
197538
|
+
const storeId = typeof b8.storeId === "string" && ID_RE3.test(b8.storeId) ? b8.storeId : void 0;
|
|
197386
197539
|
const dev = b8.device && typeof b8.device === "object" ? b8.device : {};
|
|
197387
|
-
const installId = typeof dev.installId === "string" &&
|
|
197540
|
+
const installId = typeof dev.installId === "string" && ID_RE3.test(dev.installId) ? dev.installId : void 0;
|
|
197388
197541
|
const device = { installId, model: str11(dev.model, 64), os: str11(dev.os, 64) };
|
|
197389
197542
|
const hasDevice = Object.values(device).some((v3) => v3 !== void 0);
|
|
197390
197543
|
const deleted = [...new Set(deletedIn.filter((u3) => typeof u3 === "string" && UUID_RE3.test(u3)))];
|
|
@@ -197452,14 +197605,14 @@ function relayPayload(batch) {
|
|
|
197452
197605
|
samples: batch.samples.map(({ tz, ...rest }) => tz === batch.tz ? rest : { ...rest, tz })
|
|
197453
197606
|
};
|
|
197454
197607
|
}
|
|
197455
|
-
var UUID_RE3,
|
|
197608
|
+
var UUID_RE3, ID_RE3, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
|
|
197456
197609
|
var init_sanitize = __esm({
|
|
197457
197610
|
"src/core/health/sanitize.ts"() {
|
|
197458
197611
|
"use strict";
|
|
197459
197612
|
init_catalog();
|
|
197460
197613
|
init_day_key();
|
|
197461
197614
|
UUID_RE3 = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
|
|
197462
|
-
|
|
197615
|
+
ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
|
|
197463
197616
|
MIN_INSTANT = Date.UTC(2010, 0, 1);
|
|
197464
197617
|
FUTURE_SLACK_MS2 = 36 * 36e5;
|
|
197465
197618
|
MAX_SPAN_MS = 2 * 864e5;
|
|
@@ -215063,7 +215216,7 @@ function prefAdmissible(p6) {
|
|
|
215063
215216
|
function strings(v3) {
|
|
215064
215217
|
return Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string") : [];
|
|
215065
215218
|
}
|
|
215066
|
-
async function
|
|
215219
|
+
async function leaderRows2() {
|
|
215067
215220
|
const raw = await readJsonFile(UI_PREFS_FILE, {}, { readErrors: "throw" });
|
|
215068
215221
|
const rows = [];
|
|
215069
215222
|
for (const [k8, v3] of Object.entries(raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {})) {
|
|
@@ -215075,15 +215228,15 @@ async function leaderRows() {
|
|
|
215075
215228
|
rows.push({ key: "favorites", favorites: { projects: strings(fav?.projects), notes: strings(fav?.notes) } });
|
|
215076
215229
|
return rows;
|
|
215077
215230
|
}
|
|
215078
|
-
function
|
|
215079
|
-
let h8 =
|
|
215231
|
+
function hashOf5(row) {
|
|
215232
|
+
let h8 = hashes4.get(row);
|
|
215080
215233
|
if (h8 === void 0) {
|
|
215081
215234
|
h8 = sha12(JSON.stringify(row));
|
|
215082
|
-
|
|
215235
|
+
hashes4.set(row, h8);
|
|
215083
215236
|
}
|
|
215084
215237
|
return h8;
|
|
215085
215238
|
}
|
|
215086
|
-
function
|
|
215239
|
+
function isRow4(v3) {
|
|
215087
215240
|
const r8 = v3;
|
|
215088
215241
|
if (!r8 || typeof r8 !== "object" || typeof r8.key !== "string") return false;
|
|
215089
215242
|
if (r8.key === "favorites") {
|
|
@@ -215093,27 +215246,27 @@ function isRow3(v3) {
|
|
|
215093
215246
|
const p6 = prefOf(r8.pref);
|
|
215094
215247
|
return Object.keys(r8).length === 2 && r8.key.startsWith(UI) && copyableUiPrefKey(r8.key.slice(UI.length)) && !!p6 && typeof r8.pref === "object";
|
|
215095
215248
|
}
|
|
215096
|
-
function
|
|
215249
|
+
function admit2(r8) {
|
|
215097
215250
|
if ("favorites" in r8) return [...r8.favorites.projects, ...r8.favorites.notes].every((s4) => typeof s4 === "string" && secretShapedValue(s4) === null);
|
|
215098
215251
|
return prefAdmissible(r8.pref);
|
|
215099
215252
|
}
|
|
215100
215253
|
async function readUiPrefsCopy() {
|
|
215101
|
-
const rows = await
|
|
215254
|
+
const rows = await copy3.read();
|
|
215102
215255
|
if (!rows) return null;
|
|
215103
215256
|
const out = {};
|
|
215104
215257
|
for (const r8 of Object.values(rows)) if ("pref" in r8) out[r8.key.slice(UI.length)] = r8.pref;
|
|
215105
215258
|
return out;
|
|
215106
215259
|
}
|
|
215107
215260
|
async function readFavoritesCopy() {
|
|
215108
|
-
const rows = await
|
|
215261
|
+
const rows = await copy3.read();
|
|
215109
215262
|
if (!rows) return null;
|
|
215110
215263
|
const f8 = rows.favorites;
|
|
215111
215264
|
return f8 && "favorites" in f8 ? f8.favorites : { projects: [], notes: [] };
|
|
215112
215265
|
}
|
|
215113
215266
|
function _resetPrefsCopyForTesting() {
|
|
215114
|
-
|
|
215267
|
+
copy3.reset();
|
|
215115
215268
|
}
|
|
215116
|
-
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2,
|
|
215269
|
+
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes4, PREFS_KIND, copy3, prefsFollower;
|
|
215117
215270
|
var init_prefs = __esm({
|
|
215118
215271
|
"src/core/replication/kinds/prefs.ts"() {
|
|
215119
215272
|
"use strict";
|
|
@@ -215127,16 +215280,16 @@ var init_prefs = __esm({
|
|
|
215127
215280
|
PREFS_REMOVAL_FLOOR = 0;
|
|
215128
215281
|
UI = "ui:";
|
|
215129
215282
|
MAX_VALUE_LEN2 = 8 * 1024;
|
|
215130
|
-
|
|
215283
|
+
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
215131
215284
|
PREFS_KIND = {
|
|
215132
215285
|
kind: "prefs",
|
|
215133
215286
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
215134
215287
|
key: (r8) => r8.key,
|
|
215135
|
-
hash:
|
|
215288
|
+
hash: hashOf5,
|
|
215136
215289
|
ordered: false,
|
|
215137
215290
|
digest: false,
|
|
215138
215291
|
choice: "prefs",
|
|
215139
|
-
rows:
|
|
215292
|
+
rows: leaderRows2,
|
|
215140
215293
|
watch: (soon) => {
|
|
215141
215294
|
const stops = [];
|
|
215142
215295
|
let stopped2 = false;
|
|
@@ -215149,16 +215302,16 @@ var init_prefs = __esm({
|
|
|
215149
215302
|
};
|
|
215150
215303
|
}
|
|
215151
215304
|
};
|
|
215152
|
-
|
|
215305
|
+
copy3 = createFileCopy({
|
|
215153
215306
|
kind: "prefs",
|
|
215154
215307
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
215155
215308
|
label: "prefs copy",
|
|
215156
215309
|
removalFloor: PREFS_REMOVAL_FLOOR,
|
|
215157
|
-
isRow:
|
|
215310
|
+
isRow: isRow4,
|
|
215158
215311
|
key: (r8) => r8.key,
|
|
215159
|
-
admit
|
|
215312
|
+
admit: admit2
|
|
215160
215313
|
});
|
|
215161
|
-
prefsFollower =
|
|
215314
|
+
prefsFollower = copy3.follower;
|
|
215162
215315
|
}
|
|
215163
215316
|
});
|
|
215164
215317
|
|
|
@@ -215750,7 +215903,7 @@ async function adoptDeviceRecord(input, opts2 = {}) {
|
|
|
215750
215903
|
const existing = devices.find((d8) => d8.tokenHash === tokenHash);
|
|
215751
215904
|
if (existing) return { result: { name: existing.name, adopted: false } };
|
|
215752
215905
|
const finalName = freeName(devices, name);
|
|
215753
|
-
const wanted = typeof input.id === "string" &&
|
|
215906
|
+
const wanted = typeof input.id === "string" && ID_RE4.test(input.id) ? input.id : void 0;
|
|
215754
215907
|
const idFree = wanted !== void 0 && !devices.some((d8) => d8.id === wanted || d8.ownerId === wanted);
|
|
215755
215908
|
const record2 = {
|
|
215756
215909
|
name: finalName,
|
|
@@ -215785,7 +215938,7 @@ async function revokeAdopted(tokenHash) {
|
|
|
215785
215938
|
if (out.revoked) log.web.info("device-adoption: twin pairing revoked", { name: record2.name, adoptedFrom: record2.adoptedFrom ?? null });
|
|
215786
215939
|
return out.revoked ? { name: record2.name, refused: false, push: out.push } : { name: null, refused: false, push: null };
|
|
215787
215940
|
}
|
|
215788
|
-
var AdoptionError, HASH_RE2,
|
|
215941
|
+
var AdoptionError, HASH_RE2, ID_RE4, INFO_FIELD_MAX2, NAME_MAX2;
|
|
215789
215942
|
var init_device_adoption = __esm({
|
|
215790
215943
|
"src/core/device-adoption.ts"() {
|
|
215791
215944
|
"use strict";
|
|
@@ -215803,7 +215956,7 @@ var init_device_adoption = __esm({
|
|
|
215803
215956
|
}
|
|
215804
215957
|
};
|
|
215805
215958
|
HASH_RE2 = /^[0-9a-f]{64}$/;
|
|
215806
|
-
|
|
215959
|
+
ID_RE4 = /^d[0-9a-f]{16}$/;
|
|
215807
215960
|
INFO_FIELD_MAX2 = 120;
|
|
215808
215961
|
NAME_MAX2 = 64;
|
|
215809
215962
|
}
|
|
@@ -245175,7 +245328,7 @@ async function saveRecordingAudio(audioBase64, format2) {
|
|
|
245175
245328
|
return { id, audioPath };
|
|
245176
245329
|
}
|
|
245177
245330
|
async function writeRecordingResult(id, meta) {
|
|
245178
|
-
if (!
|
|
245331
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
245179
245332
|
await mkdir7(dir3(), { recursive: true });
|
|
245180
245333
|
const stamped = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...meta };
|
|
245181
245334
|
await writeFile6(join16(dir3(), `${id}.json`), JSON.stringify(stamped, null, 2));
|
|
@@ -245184,7 +245337,7 @@ async function writeRecordingResult(id, meta) {
|
|
|
245184
245337
|
return stamped.timestamp;
|
|
245185
245338
|
}
|
|
245186
245339
|
async function writeRecordingSecondary(id, secondary, expectTimestamp) {
|
|
245187
|
-
if (!
|
|
245340
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
245188
245341
|
const path298 = join16(dir3(), `${id}.json`);
|
|
245189
245342
|
let existing;
|
|
245190
245343
|
try {
|
|
@@ -245206,7 +245359,7 @@ async function listRecordings(limit = 20) {
|
|
|
245206
245359
|
const out = [];
|
|
245207
245360
|
for (const jf of jsonFiles) {
|
|
245208
245361
|
const id = jf.slice(0, -5);
|
|
245209
|
-
if (!
|
|
245362
|
+
if (!ID_RE5.test(id)) continue;
|
|
245210
245363
|
try {
|
|
245211
245364
|
const raw = JSON.parse(await readFile8(join16(dir3(), jf), "utf-8"));
|
|
245212
245365
|
out.push({
|
|
@@ -245226,7 +245379,7 @@ async function listRecordings(limit = 20) {
|
|
|
245226
245379
|
return out;
|
|
245227
245380
|
}
|
|
245228
245381
|
async function readRecordingAudio(id) {
|
|
245229
|
-
if (!
|
|
245382
|
+
if (!ID_RE5.test(id)) return null;
|
|
245230
245383
|
let files;
|
|
245231
245384
|
try {
|
|
245232
245385
|
files = await readdir3(dir3());
|
|
@@ -245254,13 +245407,13 @@ async function pruneOldRecordings() {
|
|
|
245254
245407
|
}
|
|
245255
245408
|
}
|
|
245256
245409
|
}
|
|
245257
|
-
var MAX_RECORDINGS,
|
|
245410
|
+
var MAX_RECORDINGS, ID_RE5, AUDIO_EXTS;
|
|
245258
245411
|
var init_recordings = __esm({
|
|
245259
245412
|
"src/core/stt/recordings.ts"() {
|
|
245260
245413
|
"use strict";
|
|
245261
245414
|
init_constants();
|
|
245262
245415
|
MAX_RECORDINGS = 100;
|
|
245263
|
-
|
|
245416
|
+
ID_RE5 = /^[0-9A-Za-z-]+$/;
|
|
245264
245417
|
AUDIO_EXTS = ["webm", "mp4", "ogg", "wav", "mp3", "m4a", "flac"];
|
|
245265
245418
|
}
|
|
245266
245419
|
});
|
|
@@ -251908,6 +252061,147 @@ var init_task_v1 = __esm({
|
|
|
251908
252061
|
}
|
|
251909
252062
|
});
|
|
251910
252063
|
|
|
252064
|
+
// src/core/replication/kinds/requests.ts
|
|
252065
|
+
var requests_exports = {};
|
|
252066
|
+
__export(requests_exports, {
|
|
252067
|
+
REQUESTS_KIND: () => REQUESTS_KIND,
|
|
252068
|
+
REQUESTS_REMOVAL_FLOOR: () => REQUESTS_REMOVAL_FLOOR,
|
|
252069
|
+
REQUESTS_SCHEMA_VERSION: () => REQUESTS_SCHEMA_VERSION,
|
|
252070
|
+
_resetRequestsCopyForTesting: () => _resetRequestsCopyForTesting,
|
|
252071
|
+
forwardRequest: () => forwardRequest,
|
|
252072
|
+
readRequestCopy: () => readRequestCopy,
|
|
252073
|
+
requestsFollower: () => requestsFollower
|
|
252074
|
+
});
|
|
252075
|
+
import fsp124 from "fs/promises";
|
|
252076
|
+
import path235 from "path";
|
|
252077
|
+
function forwardRequest(local, incoming) {
|
|
252078
|
+
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
252079
|
+
return incoming;
|
|
252080
|
+
}
|
|
252081
|
+
function hashOf6(row) {
|
|
252082
|
+
let h8 = hashes5.get(row);
|
|
252083
|
+
if (h8 === void 0) {
|
|
252084
|
+
h8 = sha12(JSON.stringify(row));
|
|
252085
|
+
hashes5.set(row, h8);
|
|
252086
|
+
}
|
|
252087
|
+
return h8;
|
|
252088
|
+
}
|
|
252089
|
+
async function load6() {
|
|
252090
|
+
if (state11) return state11;
|
|
252091
|
+
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
252092
|
+
try {
|
|
252093
|
+
const raw = JSON.parse(await fsp124.readFile(STATE_FILE(), "utf8"));
|
|
252094
|
+
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: [], hashes: raw.hashes };
|
|
252095
|
+
} catch {
|
|
252096
|
+
}
|
|
252097
|
+
state11 = s4;
|
|
252098
|
+
return s4;
|
|
252099
|
+
}
|
|
252100
|
+
async function save() {
|
|
252101
|
+
if (state11) await writeCopyFile(STATE_FILE(), { v: 1, asOf: state11.asOf, at: state11.at, hashes: state11.hashes });
|
|
252102
|
+
}
|
|
252103
|
+
async function readStore8() {
|
|
252104
|
+
try {
|
|
252105
|
+
const raw = JSON.parse(await fsp124.readFile(STORE_FILE(), "utf8"));
|
|
252106
|
+
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
252107
|
+
} catch {
|
|
252108
|
+
return [];
|
|
252109
|
+
}
|
|
252110
|
+
}
|
|
252111
|
+
function isRow5(v3) {
|
|
252112
|
+
const r8 = v3;
|
|
252113
|
+
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
252114
|
+
}
|
|
252115
|
+
function requestsFollower() {
|
|
252116
|
+
follower3 ??= createRowSetFollower({
|
|
252117
|
+
kind: "requests",
|
|
252118
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
252119
|
+
label: "requests copy",
|
|
252120
|
+
log: log.session,
|
|
252121
|
+
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
252122
|
+
ordered: false,
|
|
252123
|
+
serial: (fn) => serial4(fn),
|
|
252124
|
+
refuse: copyRefusal,
|
|
252125
|
+
load: load6,
|
|
252126
|
+
save,
|
|
252127
|
+
isRow: isRow5,
|
|
252128
|
+
key: (r8) => r8.id,
|
|
252129
|
+
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
252130
|
+
apply: async ({ rows, removeIds }) => {
|
|
252131
|
+
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
252132
|
+
for (const id of removeIds ?? []) byId.delete(id);
|
|
252133
|
+
for (const r8 of rows ?? []) {
|
|
252134
|
+
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
252135
|
+
if (kept !== r8) log.session.info("requests copy: kept a settled request the leader has not settled yet", { requestId: r8.id, local: kept.status, leader: r8.status });
|
|
252136
|
+
byId.set(r8.id, kept);
|
|
252137
|
+
}
|
|
252138
|
+
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
252139
|
+
return { skipped: [] };
|
|
252140
|
+
},
|
|
252141
|
+
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
252142
|
+
changed: () => {
|
|
252143
|
+
},
|
|
252144
|
+
purge: async () => {
|
|
252145
|
+
const removed = (await readStore8()).length;
|
|
252146
|
+
await fsp124.rm(STORE_FILE(), { force: true });
|
|
252147
|
+
await markCopyOff("requests");
|
|
252148
|
+
state11 = null;
|
|
252149
|
+
return { removed };
|
|
252150
|
+
}
|
|
252151
|
+
});
|
|
252152
|
+
return follower3;
|
|
252153
|
+
}
|
|
252154
|
+
async function readRequestCopy(id) {
|
|
252155
|
+
if (!await copyKindHeld("requests")) return null;
|
|
252156
|
+
return (await readStore8()).find((r8) => r8.id === id) ?? null;
|
|
252157
|
+
}
|
|
252158
|
+
function _resetRequestsCopyForTesting() {
|
|
252159
|
+
state11 = null;
|
|
252160
|
+
follower3 = null;
|
|
252161
|
+
serial4 = serialChain();
|
|
252162
|
+
}
|
|
252163
|
+
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes5, REQUESTS_KIND, STATE_FILE, STORE_FILE, state11, serial4, follower3;
|
|
252164
|
+
var init_requests = __esm({
|
|
252165
|
+
"src/core/replication/kinds/requests.ts"() {
|
|
252166
|
+
"use strict";
|
|
252167
|
+
init_constants();
|
|
252168
|
+
init_logging();
|
|
252169
|
+
init_kind();
|
|
252170
|
+
init_kind_follower();
|
|
252171
|
+
init_gate();
|
|
252172
|
+
REQUESTS_SCHEMA_VERSION = 1;
|
|
252173
|
+
REQUESTS_REMOVAL_FLOOR = 50;
|
|
252174
|
+
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
252175
|
+
hashes5 = /* @__PURE__ */ new WeakMap();
|
|
252176
|
+
REQUESTS_KIND = {
|
|
252177
|
+
kind: "requests",
|
|
252178
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
252179
|
+
key: (r8) => r8.id,
|
|
252180
|
+
hash: hashOf6,
|
|
252181
|
+
ordered: false,
|
|
252182
|
+
digest: false,
|
|
252183
|
+
choice: "requests",
|
|
252184
|
+
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
252185
|
+
watch: (soon) => {
|
|
252186
|
+
let stop2 = null;
|
|
252187
|
+
let stopped2 = false;
|
|
252188
|
+
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
252189
|
+
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
252190
|
+
});
|
|
252191
|
+
return () => {
|
|
252192
|
+
stopped2 = true;
|
|
252193
|
+
stop2?.();
|
|
252194
|
+
};
|
|
252195
|
+
}
|
|
252196
|
+
};
|
|
252197
|
+
STATE_FILE = () => path235.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
252198
|
+
STORE_FILE = () => copyPath(path235.join(WALNUT_HOME, "session-requests.json"));
|
|
252199
|
+
state11 = null;
|
|
252200
|
+
serial4 = serialChain();
|
|
252201
|
+
follower3 = null;
|
|
252202
|
+
}
|
|
252203
|
+
});
|
|
252204
|
+
|
|
251911
252205
|
// src/web/routes/messages-v1.ts
|
|
251912
252206
|
import { Router as Router82 } from "express";
|
|
251913
252207
|
function header(req, name) {
|
|
@@ -251968,7 +252262,15 @@ var init_messages_v1 = __esm({
|
|
|
251968
252262
|
return;
|
|
251969
252263
|
}
|
|
251970
252264
|
const { getSessionRequest: getSessionRequest2 } = await Promise.resolve().then(() => (init_session_requests(), session_requests_exports));
|
|
251971
|
-
|
|
252265
|
+
let request3 = await getSessionRequest2(id);
|
|
252266
|
+
if (!request3) {
|
|
252267
|
+
const [{ readRequestCopy: readRequestCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
252268
|
+
Promise.resolve().then(() => (init_requests(), requests_exports)),
|
|
252269
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
252270
|
+
]);
|
|
252271
|
+
request3 = await readRequestCopy2(id) ?? void 0;
|
|
252272
|
+
if (request3) res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("requests") ?? 0));
|
|
252273
|
+
}
|
|
251972
252274
|
if (!request3) {
|
|
251973
252275
|
sendV1Error(res, 404, "not_found", `No such request: ${id}`);
|
|
251974
252276
|
return;
|
|
@@ -253643,6 +253945,17 @@ var init_search_memory_v1 = __esm({
|
|
|
253643
253945
|
});
|
|
253644
253946
|
searchMemoryV1Router.get("/favorites", async (_req, res, next) => {
|
|
253645
253947
|
try {
|
|
253948
|
+
const [{ readFavoritesCopy: readFavoritesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
253949
|
+
Promise.resolve().then(() => (init_prefs(), prefs_exports)),
|
|
253950
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
253951
|
+
]);
|
|
253952
|
+
const asOf2 = await copyKindAsOf2("prefs");
|
|
253953
|
+
const fav = asOf2 === null ? null : await readFavoritesCopy2();
|
|
253954
|
+
if (fav) {
|
|
253955
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(asOf2));
|
|
253956
|
+
res.json({ projects: fav.projects ?? [], notes: fav.notes ?? [] });
|
|
253957
|
+
return;
|
|
253958
|
+
}
|
|
253646
253959
|
const { readFavorites: readFavorites2 } = await Promise.resolve().then(() => (init_favorites(), favorites_exports));
|
|
253647
253960
|
res.json(await readFavorites2());
|
|
253648
253961
|
} catch (err2) {
|
|
@@ -254675,9 +254988,9 @@ var init_stt_v1 = __esm({
|
|
|
254675
254988
|
|
|
254676
254989
|
// src/web/routes/pastes.ts
|
|
254677
254990
|
import { Router as Router89 } from "express";
|
|
254678
|
-
import
|
|
254991
|
+
import path236 from "path";
|
|
254679
254992
|
import { createHash as createHash38 } from "crypto";
|
|
254680
|
-
import
|
|
254993
|
+
import fsp125 from "fs/promises";
|
|
254681
254994
|
var pastesRouter, MAX_PASTE_CHARS;
|
|
254682
254995
|
var init_pastes = __esm({
|
|
254683
254996
|
"src/web/routes/pastes.ts"() {
|
|
@@ -254697,11 +255010,11 @@ var init_pastes = __esm({
|
|
|
254697
255010
|
res.status(413).json({ error: `Paste too large (max ${MAX_PASTE_CHARS} chars)` });
|
|
254698
255011
|
return;
|
|
254699
255012
|
}
|
|
254700
|
-
await
|
|
255013
|
+
await fsp125.mkdir(PASTES_DIR, { recursive: true });
|
|
254701
255014
|
const hash3 = createHash38("sha256").update(text5).digest("hex").slice(0, 12);
|
|
254702
255015
|
const filename = `${Date.now()}-${hash3}.txt`;
|
|
254703
|
-
const filePath =
|
|
254704
|
-
await
|
|
255016
|
+
const filePath = path236.join(PASTES_DIR, filename);
|
|
255017
|
+
await fsp125.writeFile(filePath, text5, "utf8");
|
|
254705
255018
|
log.web.info("paste spilled to disk", { filePath, chars: text5.length });
|
|
254706
255019
|
res.json({ path: filePath, filename, chars: text5.length });
|
|
254707
255020
|
} catch (err2) {
|
|
@@ -254717,8 +255030,8 @@ __export(file_content_replica_copy_exports, {
|
|
|
254717
255030
|
primaryDataDirRelPath: () => primaryDataDirRelPath,
|
|
254718
255031
|
resolveReplicaCopy: () => resolveReplicaCopy
|
|
254719
255032
|
});
|
|
254720
|
-
import
|
|
254721
|
-
import
|
|
255033
|
+
import path237 from "path";
|
|
255034
|
+
import fsp126 from "fs/promises";
|
|
254722
255035
|
function dataDirIndex(parts, tilde) {
|
|
254723
255036
|
if (tilde) return parts[1] === DATA_DIR_NAME ? 1 : -1;
|
|
254724
255037
|
if ((parts[0] === "Users" || parts[0] === "home") && parts[2] === DATA_DIR_NAME) return 2;
|
|
@@ -254748,12 +255061,12 @@ async function resolveReplicaCopy(requestPath) {
|
|
|
254748
255061
|
const rel = primaryDataDirRelPath(requestPath);
|
|
254749
255062
|
if (rel === null || deniedName(rel)) return null;
|
|
254750
255063
|
try {
|
|
254751
|
-
const root6 = await
|
|
254752
|
-
const real = await
|
|
254753
|
-
if (!real.startsWith(root6 +
|
|
254754
|
-
const realRel =
|
|
254755
|
-
if (isSecretPath(
|
|
254756
|
-
const st2 = await
|
|
255064
|
+
const root6 = await fsp126.realpath(WALNUT_HOME);
|
|
255065
|
+
const real = await fsp126.realpath(path237.join(WALNUT_HOME, rel));
|
|
255066
|
+
if (!real.startsWith(root6 + path237.sep)) return null;
|
|
255067
|
+
const realRel = path237.relative(root6, real).split(path237.sep).join("/");
|
|
255068
|
+
if (isSecretPath(path237.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
|
|
255069
|
+
const st2 = await fsp126.stat(real);
|
|
254757
255070
|
if (!st2.isFile()) return null;
|
|
254758
255071
|
if (!await isTracked(root6, realRel)) return null;
|
|
254759
255072
|
return { localPath: real, size: st2.size };
|
|
@@ -254793,11 +255106,11 @@ var init_file_content_replica_copy = __esm({
|
|
|
254793
255106
|
// src/web/routes/media-v1.ts
|
|
254794
255107
|
import { Router as Router90 } from "express";
|
|
254795
255108
|
import crypto67 from "crypto";
|
|
254796
|
-
import
|
|
254797
|
-
import
|
|
255109
|
+
import path238 from "path";
|
|
255110
|
+
import fsp127 from "fs/promises";
|
|
254798
255111
|
function cachePathFor(host, filePath) {
|
|
254799
255112
|
const hash3 = crypto67.createHash("sha256").update(filePath).digest("hex").slice(0, 16);
|
|
254800
|
-
return
|
|
255113
|
+
return path238.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path238.basename(filePath)}`);
|
|
254801
255114
|
}
|
|
254802
255115
|
async function hostForSession(sessionId) {
|
|
254803
255116
|
if (CLOUD_MODE) {
|
|
@@ -254862,11 +255175,11 @@ var init_media_v1 = __esm({
|
|
|
254862
255175
|
try {
|
|
254863
255176
|
const filePath = req.query.path;
|
|
254864
255177
|
const session2 = typeof req.query.session === "string" && SID_RE6.test(req.query.session) ? req.query.session : void 0;
|
|
254865
|
-
if (!filePath || typeof filePath !== "string" || !
|
|
255178
|
+
if (!filePath || typeof filePath !== "string" || !path238.isAbsolute(filePath) || filePath.includes("..")) {
|
|
254866
255179
|
res.status(400).json({ error: { code: "bad_request", message: "path must be an absolute file path" } });
|
|
254867
255180
|
return;
|
|
254868
255181
|
}
|
|
254869
|
-
const ext2 =
|
|
255182
|
+
const ext2 = path238.extname(filePath).slice(1).toLowerCase();
|
|
254870
255183
|
const mime = EXT_TO_MIME3[ext2];
|
|
254871
255184
|
if (!mime) {
|
|
254872
255185
|
res.status(400).json({ error: { code: "bad_request", message: "file type not allowed" } });
|
|
@@ -254874,8 +255187,8 @@ var init_media_v1 = __esm({
|
|
|
254874
255187
|
}
|
|
254875
255188
|
let buffer2 = null;
|
|
254876
255189
|
try {
|
|
254877
|
-
const st2 = await
|
|
254878
|
-
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
255190
|
+
const st2 = await fsp127.stat(filePath);
|
|
255191
|
+
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(filePath);
|
|
254879
255192
|
} catch {
|
|
254880
255193
|
}
|
|
254881
255194
|
let waitedOnPending = false;
|
|
@@ -254896,8 +255209,8 @@ var init_media_v1 = __esm({
|
|
|
254896
255209
|
if (buffer2) {
|
|
254897
255210
|
try {
|
|
254898
255211
|
const cachePath3 = cachePathFor(host, filePath);
|
|
254899
|
-
await
|
|
254900
|
-
await
|
|
255212
|
+
await fsp127.mkdir(path238.dirname(cachePath3), { recursive: true });
|
|
255213
|
+
await fsp127.writeFile(cachePath3, buffer2);
|
|
254901
255214
|
} catch {
|
|
254902
255215
|
}
|
|
254903
255216
|
break;
|
|
@@ -254907,9 +255220,9 @@ var init_media_v1 = __esm({
|
|
|
254907
255220
|
for (const host of hosts2) {
|
|
254908
255221
|
try {
|
|
254909
255222
|
const cached8 = cachePathFor(host, filePath);
|
|
254910
|
-
const st2 = await
|
|
255223
|
+
const st2 = await fsp127.stat(cached8);
|
|
254911
255224
|
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) {
|
|
254912
|
-
buffer2 = await
|
|
255225
|
+
buffer2 = await fsp127.readFile(cached8);
|
|
254913
255226
|
break;
|
|
254914
255227
|
}
|
|
254915
255228
|
} catch {
|
|
@@ -254919,7 +255232,7 @@ var init_media_v1 = __esm({
|
|
|
254919
255232
|
if (!buffer2 && hosts2.length > 0 && hosts2.every((h8) => h8 === "__local__") && !(await Promise.resolve().then(() => (init_bridge_registry(), bridge_registry_exports))).bridgeForHost("__local__").connected) {
|
|
254920
255233
|
const { resolveReplicaCopy: resolveReplicaCopy2 } = await Promise.resolve().then(() => (init_file_content_replica_copy(), file_content_replica_copy_exports));
|
|
254921
255234
|
const copy5 = await resolveReplicaCopy2(filePath);
|
|
254922
|
-
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
255235
|
+
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(copy5.localPath);
|
|
254923
255236
|
}
|
|
254924
255237
|
}
|
|
254925
255238
|
if (!buffer2) {
|
|
@@ -254944,6 +255257,19 @@ var init_media_v1 = __esm({
|
|
|
254944
255257
|
|
|
254945
255258
|
// src/web/routes/routines-v1.ts
|
|
254946
255259
|
import { Router as Router91 } from "express";
|
|
255260
|
+
async function answeredFromCopy(res, includeDisabled, answer5) {
|
|
255261
|
+
const [{ companionRoutinesCopy: companionRoutinesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
255262
|
+
Promise.resolve().then(() => (init_routines_follower(), routines_follower_exports)),
|
|
255263
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
255264
|
+
]);
|
|
255265
|
+
const jobs2 = await companionRoutinesCopy2({ includeDisabled });
|
|
255266
|
+
if (!jobs2) return false;
|
|
255267
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("routines") ?? 0));
|
|
255268
|
+
const body7 = answer5(jobs2);
|
|
255269
|
+
if (body7 === null) sendV1Error(res, 404, "not_found", "No such routine in the copy of your Mac's routines");
|
|
255270
|
+
else res.json(body7);
|
|
255271
|
+
return true;
|
|
255272
|
+
}
|
|
254947
255273
|
function validRid(req, res) {
|
|
254948
255274
|
const id = String(req.params.id ?? "");
|
|
254949
255275
|
if (!RID_RE.test(id)) {
|
|
@@ -254990,6 +255316,7 @@ var init_routines_v1 = __esm({
|
|
|
254990
255316
|
try {
|
|
254991
255317
|
const includeDisabled = req.query.includeDisabled === "true";
|
|
254992
255318
|
if (CLOUD_MODE) {
|
|
255319
|
+
if (await answeredFromCopy(res, includeDisabled, (jobs2) => ({ jobs: jobs2 }))) return;
|
|
254993
255320
|
await relayControlAction(res, "server.routines", SERVER_RELAY_SID14, { includeDisabled }, 200);
|
|
254994
255321
|
return;
|
|
254995
255322
|
}
|
|
@@ -255014,6 +255341,7 @@ var init_routines_v1 = __esm({
|
|
|
255014
255341
|
routinesV1Router.get("/routines/status", async (_req, res, next) => {
|
|
255015
255342
|
try {
|
|
255016
255343
|
if (CLOUD_MODE) {
|
|
255344
|
+
if (await answeredFromCopy(res, true, (jobs2) => ({ enabled: false, storePath: "", jobs: jobs2.length, nextWakeAtMs: null }))) return;
|
|
255017
255345
|
await relayControlAction(res, "server.routines.status", SERVER_RELAY_SID14, void 0, 200);
|
|
255018
255346
|
return;
|
|
255019
255347
|
}
|
|
@@ -255085,6 +255413,10 @@ var init_routines_v1 = __esm({
|
|
|
255085
255413
|
const id = validRid(req, res);
|
|
255086
255414
|
if (!id) return;
|
|
255087
255415
|
if (CLOUD_MODE) {
|
|
255416
|
+
if (await answeredFromCopy(res, true, (jobs2) => {
|
|
255417
|
+
const job2 = jobs2.find((j8) => j8.id === id);
|
|
255418
|
+
return job2 ? { job: job2 } : null;
|
|
255419
|
+
})) return;
|
|
255088
255420
|
await relayControlAction(res, "server.routines.get", SERVER_RELAY_SID14, { id }, 200);
|
|
255089
255421
|
return;
|
|
255090
255422
|
}
|
|
@@ -256279,8 +256611,8 @@ __export(file_content_bridge_exports, {
|
|
|
256279
256611
|
resolveBridgeHost: () => resolveBridgeHost,
|
|
256280
256612
|
serveCloudFileContent: () => serveCloudFileContent
|
|
256281
256613
|
});
|
|
256282
|
-
import
|
|
256283
|
-
import
|
|
256614
|
+
import path239 from "path";
|
|
256615
|
+
import fsp128 from "fs/promises";
|
|
256284
256616
|
function resolveBridgeHost(host) {
|
|
256285
256617
|
return typeof host === "string" && host.length > 0 ? host : PRIMARY_BRIDGE_ALIAS4;
|
|
256286
256618
|
}
|
|
@@ -256351,7 +256683,7 @@ function precheckPath(res, rawPath) {
|
|
|
256351
256683
|
sendV1Error(res, 400, "bad_request", "Invalid path");
|
|
256352
256684
|
return null;
|
|
256353
256685
|
}
|
|
256354
|
-
if (rawPath !== "~" && !rawPath.startsWith("~/") && !
|
|
256686
|
+
if (rawPath !== "~" && !rawPath.startsWith("~/") && !path239.isAbsolute(rawPath)) {
|
|
256355
256687
|
sendV1Error(res, 400, "bad_request", "Path must be absolute");
|
|
256356
256688
|
return null;
|
|
256357
256689
|
}
|
|
@@ -256395,7 +256727,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
256395
256727
|
const hostAlias2 = resolveBridgeHost(req.query.host);
|
|
256396
256728
|
const raw = req.query.raw === "1" || req.query.raw === "true";
|
|
256397
256729
|
const download = req.query.download === "1" || req.query.download === "true";
|
|
256398
|
-
const ext2 =
|
|
256730
|
+
const ext2 = path239.extname(filePath).slice(1).toLowerCase();
|
|
256399
256731
|
const {
|
|
256400
256732
|
assertPathAllowed: assertPathAllowed2,
|
|
256401
256733
|
isSecretPath: isSecretPath2,
|
|
@@ -256405,7 +256737,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
256405
256737
|
FileContentError: FileContentError2
|
|
256406
256738
|
} = await Promise.resolve().then(() => (init_file_content(), file_content_exports));
|
|
256407
256739
|
const explicitHost = typeof req.query.host === "string" && req.query.host.length > 0;
|
|
256408
|
-
const locallyPresent = await
|
|
256740
|
+
const locallyPresent = await fsp128.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
|
|
256409
256741
|
if (!explicitHost && locallyPresent && cloudLocalReadAllowed2(filePath) && !isSecretPath2(filePath)) {
|
|
256410
256742
|
try {
|
|
256411
256743
|
if (raw) {
|
|
@@ -256503,10 +256835,10 @@ async function serveReplicaCopy(req, res, requestPath, copy5, opts2) {
|
|
|
256503
256835
|
return;
|
|
256504
256836
|
}
|
|
256505
256837
|
if (copy5.size <= MAX_BRIDGE_FILE_BYTES) {
|
|
256506
|
-
res.json(jsonPayloadFromBuffer(await
|
|
256838
|
+
res.json(jsonPayloadFromBuffer(await fsp128.readFile(copy5.localPath), opts2.ext, false));
|
|
256507
256839
|
return;
|
|
256508
256840
|
}
|
|
256509
|
-
const fh = await
|
|
256841
|
+
const fh = await fsp128.open(copy5.localPath, "r");
|
|
256510
256842
|
try {
|
|
256511
256843
|
const head2 = Buffer.alloc(MAX_TEXT_PAYLOAD);
|
|
256512
256844
|
const { bytesRead } = await fh.read(head2, 0, head2.length, 0);
|
|
@@ -257580,17 +257912,17 @@ __export(checklist_io_exports, {
|
|
|
257580
257912
|
readHeartbeatChecklist: () => readHeartbeatChecklist,
|
|
257581
257913
|
writeHeartbeatChecklist: () => writeHeartbeatChecklist
|
|
257582
257914
|
});
|
|
257583
|
-
import
|
|
257915
|
+
import fsp129 from "fs/promises";
|
|
257584
257916
|
async function readHeartbeatChecklist() {
|
|
257585
257917
|
try {
|
|
257586
|
-
return await
|
|
257918
|
+
return await fsp129.readFile(HEARTBEAT_FILE, "utf-8");
|
|
257587
257919
|
} catch (err2) {
|
|
257588
257920
|
if (err2.code === "ENOENT") return "";
|
|
257589
257921
|
throw err2;
|
|
257590
257922
|
}
|
|
257591
257923
|
}
|
|
257592
257924
|
async function writeHeartbeatChecklist(content) {
|
|
257593
|
-
await
|
|
257925
|
+
await fsp129.writeFile(HEARTBEAT_FILE, content, "utf-8");
|
|
257594
257926
|
}
|
|
257595
257927
|
var init_checklist_io = __esm({
|
|
257596
257928
|
"src/heartbeat/checklist-io.ts"() {
|
|
@@ -259509,11 +259841,11 @@ __export(ephemeral_guard_exports, {
|
|
|
259509
259841
|
});
|
|
259510
259842
|
import fs127 from "fs";
|
|
259511
259843
|
import os60 from "os";
|
|
259512
|
-
import
|
|
259844
|
+
import path240 from "path";
|
|
259513
259845
|
function productionWalnutHomes() {
|
|
259514
259846
|
const homes = /* @__PURE__ */ new Set();
|
|
259515
259847
|
const add3 = (home) => {
|
|
259516
|
-
if (home) homes.add(
|
|
259848
|
+
if (home) homes.add(path240.join(home, ".open-walnut"));
|
|
259517
259849
|
};
|
|
259518
259850
|
add3(os60.homedir());
|
|
259519
259851
|
try {
|
|
@@ -259523,7 +259855,7 @@ function productionWalnutHomes() {
|
|
|
259523
259855
|
return [...homes];
|
|
259524
259856
|
}
|
|
259525
259857
|
function canonical2(dir4) {
|
|
259526
|
-
const resolved =
|
|
259858
|
+
const resolved = path240.resolve(dir4);
|
|
259527
259859
|
try {
|
|
259528
259860
|
return fs127.realpathSync(resolved);
|
|
259529
259861
|
} catch {
|
|
@@ -259559,28 +259891,28 @@ __export(boot_guard_exports, {
|
|
|
259559
259891
|
});
|
|
259560
259892
|
import fs128 from "fs";
|
|
259561
259893
|
import os61 from "os";
|
|
259562
|
-
import
|
|
259894
|
+
import path241 from "path";
|
|
259563
259895
|
function canonical3(dir4) {
|
|
259564
|
-
let head2 =
|
|
259896
|
+
let head2 = path241.resolve(dir4);
|
|
259565
259897
|
const rest = [];
|
|
259566
259898
|
for (; ; ) {
|
|
259567
259899
|
try {
|
|
259568
|
-
return
|
|
259900
|
+
return path241.join(fs128.realpathSync(head2), ...rest);
|
|
259569
259901
|
} catch {
|
|
259570
259902
|
}
|
|
259571
|
-
const up =
|
|
259572
|
-
if (up === head2) return
|
|
259573
|
-
rest.unshift(
|
|
259903
|
+
const up = path241.dirname(head2);
|
|
259904
|
+
if (up === head2) return path241.resolve(dir4);
|
|
259905
|
+
rest.unshift(path241.basename(head2));
|
|
259574
259906
|
head2 = up;
|
|
259575
259907
|
}
|
|
259576
259908
|
}
|
|
259577
259909
|
function spellings(dir4) {
|
|
259578
|
-
const resolved =
|
|
259910
|
+
const resolved = path241.resolve(dir4);
|
|
259579
259911
|
return [.../* @__PURE__ */ new Set([resolved, canonical3(resolved), `/private${resolved}`])];
|
|
259580
259912
|
}
|
|
259581
259913
|
function within5(child2, parent) {
|
|
259582
|
-
const rel =
|
|
259583
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
259914
|
+
const rel = path241.relative(parent, child2);
|
|
259915
|
+
return rel === "" || !rel.startsWith("..") && !path241.isAbsolute(rel);
|
|
259584
259916
|
}
|
|
259585
259917
|
function overlaps(a8, b8) {
|
|
259586
259918
|
return spellings(a8).some((x3) => spellings(b8).some((y3) => within5(x3, y3) || within5(y3, x3)));
|
|
@@ -259591,7 +259923,7 @@ function holdsOrIs(outer, inner2) {
|
|
|
259591
259923
|
function accountHomes(env3) {
|
|
259592
259924
|
const homes = /* @__PURE__ */ new Set();
|
|
259593
259925
|
const add3 = (h8) => {
|
|
259594
|
-
if (h8 && h8.trim()) homes.add(
|
|
259926
|
+
if (h8 && h8.trim()) homes.add(path241.resolve(h8.trim()));
|
|
259595
259927
|
};
|
|
259596
259928
|
add3(env3.HOME);
|
|
259597
259929
|
add3(os61.homedir());
|
|
@@ -259649,7 +259981,7 @@ function assertReplicaBootSafe(input) {
|
|
|
259649
259981
|
if (why2) throw new Error(`Host replica refused to start: ${why2}.`);
|
|
259650
259982
|
}
|
|
259651
259983
|
function claimReplicaDir(dir4) {
|
|
259652
|
-
const marker =
|
|
259984
|
+
const marker = path241.join(dir4, REPLICA_DIR_MARKER);
|
|
259653
259985
|
try {
|
|
259654
259986
|
return fs128.lstatSync(marker).isFile();
|
|
259655
259987
|
} catch {
|
|
@@ -259674,7 +260006,7 @@ function claimReplicaDir(dir4) {
|
|
|
259674
260006
|
function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
259675
260007
|
const marked = dirs2.filter((d8) => {
|
|
259676
260008
|
try {
|
|
259677
|
-
return fs128.lstatSync(
|
|
260009
|
+
return fs128.lstatSync(path241.join(d8, REPLICA_DIR_MARKER)).isFile();
|
|
259678
260010
|
} catch {
|
|
259679
260011
|
return false;
|
|
259680
260012
|
}
|
|
@@ -259704,7 +260036,7 @@ function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
|
259704
260036
|
} catch {
|
|
259705
260037
|
return;
|
|
259706
260038
|
}
|
|
259707
|
-
for (const n6 of names2) visit(
|
|
260039
|
+
for (const n6 of names2) visit(path241.join(p6, n6));
|
|
259708
260040
|
} else if (st2.isFile() && (st2.mode & 63) !== 0) {
|
|
259709
260041
|
try {
|
|
259710
260042
|
fs128.chmodSync(p6, st2.mode & 448 | 384);
|
|
@@ -259891,29 +260223,29 @@ __export(search_replica_store_exports, {
|
|
|
259891
260223
|
searchReplicaSync: () => searchReplicaSync,
|
|
259892
260224
|
startSearchReplicaStore: () => startSearchReplicaStore
|
|
259893
260225
|
});
|
|
259894
|
-
import
|
|
260226
|
+
import fsp130 from "fs/promises";
|
|
259895
260227
|
import os62 from "os";
|
|
259896
|
-
import
|
|
260228
|
+
import path242 from "path";
|
|
259897
260229
|
async function wiring() {
|
|
259898
260230
|
return Promise.resolve().then(() => (init_wiring(), wiring_exports));
|
|
259899
260231
|
}
|
|
259900
260232
|
async function loadState() {
|
|
259901
|
-
if (
|
|
260233
|
+
if (state12) return state12;
|
|
259902
260234
|
let s4 = { v: 1, mode: null, syncedAt: null };
|
|
259903
260235
|
try {
|
|
259904
|
-
const raw = JSON.parse(await
|
|
260236
|
+
const raw = JSON.parse(await fsp130.readFile(STATE_FILE2(), "utf8"));
|
|
259905
260237
|
if (raw && raw.v === 1) {
|
|
259906
260238
|
s4 = { v: 1, mode: raw.mode ? companionSearchMode(raw.mode) : null, syncedAt: typeof raw.syncedAt === "number" ? raw.syncedAt : null };
|
|
259907
260239
|
}
|
|
259908
260240
|
} catch {
|
|
259909
260241
|
}
|
|
259910
|
-
|
|
260242
|
+
state12 = s4;
|
|
259911
260243
|
return s4;
|
|
259912
260244
|
}
|
|
259913
260245
|
async function saveState() {
|
|
259914
|
-
if (
|
|
260246
|
+
if (state12) await writeJsonFile(STATE_FILE2(), state12);
|
|
259915
260247
|
}
|
|
259916
|
-
function
|
|
260248
|
+
function serial5(fn) {
|
|
259917
260249
|
const run13 = chain4.then(fn, fn);
|
|
259918
260250
|
chain4 = run13.catch(() => {
|
|
259919
260251
|
});
|
|
@@ -259977,8 +260309,8 @@ async function closeIndex() {
|
|
|
259977
260309
|
allDirty2 = true;
|
|
259978
260310
|
}
|
|
259979
260311
|
function publishReady() {
|
|
259980
|
-
const ready2 = enabled && mapBuilt && map3.size > 0 &&
|
|
259981
|
-
setCompanionSearchReady(ready2, ready2 ?
|
|
260312
|
+
const ready2 = enabled && mapBuilt && map3.size > 0 && state12?.syncedAt != null;
|
|
260313
|
+
setCompanionSearchReady(ready2, ready2 ? state12.syncedAt : null);
|
|
259982
260314
|
}
|
|
259983
260315
|
async function markInSync() {
|
|
259984
260316
|
const s4 = await loadState();
|
|
@@ -260005,7 +260337,7 @@ async function warm(why2) {
|
|
|
260005
260337
|
}
|
|
260006
260338
|
}
|
|
260007
260339
|
function searchReplicaStatus(body7) {
|
|
260008
|
-
return
|
|
260340
|
+
return serial5(async () => {
|
|
260009
260341
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
260010
260342
|
const s4 = await loadState();
|
|
260011
260343
|
const mode = companionSearchMode(body7.mode);
|
|
@@ -260053,7 +260385,7 @@ function searchReplicaStatus(body7) {
|
|
|
260053
260385
|
});
|
|
260054
260386
|
}
|
|
260055
260387
|
function searchReplicaSync(body7) {
|
|
260056
|
-
return
|
|
260388
|
+
return serial5(async () => {
|
|
260057
260389
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
260058
260390
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
260059
260391
|
if (!Array.isArray(body7.entries)) return { ok: false, status: 400, error: "bad_entries" };
|
|
@@ -260098,7 +260430,7 @@ async function forgetSearchMemo() {
|
|
|
260098
260430
|
}
|
|
260099
260431
|
}
|
|
260100
260432
|
function searchReplicaPut(body7) {
|
|
260101
|
-
return
|
|
260433
|
+
return serial5(async () => {
|
|
260102
260434
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
260103
260435
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
260104
260436
|
if (!Array.isArray(body7.docs)) return { ok: false, status: 400, error: "bad_docs" };
|
|
@@ -260164,7 +260496,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
260164
260496
|
if (!s4.mode || stopped2) return;
|
|
260165
260497
|
const decision = companionSearchDecision(s4.mode, deps3.totalMb());
|
|
260166
260498
|
if (!decision.enabled) return;
|
|
260167
|
-
await
|
|
260499
|
+
await serial5(async () => {
|
|
260168
260500
|
enabled = true;
|
|
260169
260501
|
reason2 = decision.reason;
|
|
260170
260502
|
await refreshMap2(await openIndex());
|
|
@@ -260197,12 +260529,12 @@ function startSearchReplicaStore(options = {}) {
|
|
|
260197
260529
|
}));
|
|
260198
260530
|
}).catch((err2) => log.memory.warn("search replica: local writes not wired", { error: err2 instanceof Error ? err2.message : String(err2) }));
|
|
260199
260531
|
unsubs.push(onLeaderPresence((answers4) => {
|
|
260200
|
-
if (stopped2 || answers4 || !enabled ||
|
|
260532
|
+
if (stopped2 || answers4 || !enabled || state12?.syncedAt == null) return;
|
|
260201
260533
|
void warm("leader away");
|
|
260202
260534
|
}));
|
|
260203
260535
|
const tick = setInterval(() => {
|
|
260204
260536
|
void (async () => {
|
|
260205
|
-
if (stopped2 || !enabled ||
|
|
260537
|
+
if (stopped2 || !enabled || state12?.syncedAt == null) return;
|
|
260206
260538
|
if (Date.now() - lastWarmAt < WARM_EVERY_MS) return;
|
|
260207
260539
|
if (!await deps3.macAway()) return;
|
|
260208
260540
|
await warm("mac away");
|
|
@@ -260221,7 +260553,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
260221
260553
|
};
|
|
260222
260554
|
}
|
|
260223
260555
|
function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
260224
|
-
|
|
260556
|
+
state12 = null;
|
|
260225
260557
|
enabled = false;
|
|
260226
260558
|
reason2 = "off";
|
|
260227
260559
|
map3.clear();
|
|
@@ -260236,7 +260568,7 @@ function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
|
260236
260568
|
deps3 = { totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)), macAway: defaultMacAway, ...overrides };
|
|
260237
260569
|
setCompanionSearchReady(false, null);
|
|
260238
260570
|
}
|
|
260239
|
-
var
|
|
260571
|
+
var STATE_FILE2, MASS_REMOVE_FLOOR, SCAN_SLICE2, WARM_EVERY_MS, TICK_MS2, defaultMacAway, deps3, state12, enabled, reason2, map3, mapBuilt, allDirty2, dirty2, unlisten, lastWarmAt, warmedOnce, chain4, yieldLoop;
|
|
260240
260572
|
var init_search_replica_store = __esm({
|
|
260241
260573
|
"src/core/replication/search-replica-store.ts"() {
|
|
260242
260574
|
"use strict";
|
|
@@ -260248,7 +260580,7 @@ var init_search_replica_store = __esm({
|
|
|
260248
260580
|
init_replica_refs();
|
|
260249
260581
|
init_search_digest();
|
|
260250
260582
|
init_search_replica_wire();
|
|
260251
|
-
|
|
260583
|
+
STATE_FILE2 = () => path242.join(WALNUT_HOME, "cache", "search-replica.json");
|
|
260252
260584
|
MASS_REMOVE_FLOOR = 200;
|
|
260253
260585
|
SCAN_SLICE2 = 500;
|
|
260254
260586
|
WARM_EVERY_MS = 4 * 6e4;
|
|
@@ -260258,7 +260590,7 @@ var init_search_replica_store = __esm({
|
|
|
260258
260590
|
totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)),
|
|
260259
260591
|
macAway: defaultMacAway
|
|
260260
260592
|
};
|
|
260261
|
-
|
|
260593
|
+
state12 = null;
|
|
260262
260594
|
enabled = false;
|
|
260263
260595
|
reason2 = "off";
|
|
260264
260596
|
map3 = new DigestMap();
|
|
@@ -260274,10 +260606,10 @@ var init_search_replica_store = __esm({
|
|
|
260274
260606
|
});
|
|
260275
260607
|
|
|
260276
260608
|
// src/core/replication/kinds/boards.ts
|
|
260277
|
-
import
|
|
260278
|
-
import
|
|
260609
|
+
import fsp131 from "fs/promises";
|
|
260610
|
+
import path243 from "path";
|
|
260279
260611
|
async function leaderBoards(dir4 = boardsDir2()) {
|
|
260280
|
-
const names2 = await
|
|
260612
|
+
const names2 = await fsp131.readdir(dir4).catch(() => []);
|
|
260281
260613
|
const out = [];
|
|
260282
260614
|
const unreadable = [];
|
|
260283
260615
|
const seen2 = /* @__PURE__ */ new Set();
|
|
@@ -260286,9 +260618,9 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
260286
260618
|
const id = name.slice(0, -".json".length);
|
|
260287
260619
|
if (!TASK_ID_RE3.test(id)) continue;
|
|
260288
260620
|
seen2.add(id);
|
|
260289
|
-
const file =
|
|
260621
|
+
const file = path243.join(dir4, name);
|
|
260290
260622
|
try {
|
|
260291
|
-
const st2 = await
|
|
260623
|
+
const st2 = await fsp131.stat(file);
|
|
260292
260624
|
if (!st2.isFile()) continue;
|
|
260293
260625
|
if (st2.size > BOARD_COPY_MAX_BYTES) {
|
|
260294
260626
|
if (!warnedTooBig.has(id)) log.session.warn("boards copy: a board is too large to copy, it is read from the Mac", { taskId: id, bytes: st2.size });
|
|
@@ -260297,14 +260629,14 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
260297
260629
|
}
|
|
260298
260630
|
let c8 = cache16.get(id);
|
|
260299
260631
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
260300
|
-
const row = JSON.parse(await
|
|
260301
|
-
if (!
|
|
260632
|
+
const row = JSON.parse(await fsp131.readFile(file, "utf8"));
|
|
260633
|
+
if (!isRow6(row) || row.task_id !== id) {
|
|
260302
260634
|
unreadable.push(id);
|
|
260303
260635
|
continue;
|
|
260304
260636
|
}
|
|
260305
260637
|
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, row, hash: sha12(JSON.stringify(row)) };
|
|
260306
260638
|
cache16.set(id, c8);
|
|
260307
|
-
|
|
260639
|
+
hashOf7.set(row, c8.hash);
|
|
260308
260640
|
}
|
|
260309
260641
|
out.push(c8.row);
|
|
260310
260642
|
} catch (err2) {
|
|
@@ -260319,56 +260651,56 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
260319
260651
|
if (fresh.length > 0) log.session.warn("boards copy: a board could not be read, the host keeps its copy of it", { taskIds: fresh });
|
|
260320
260652
|
return out;
|
|
260321
260653
|
}
|
|
260322
|
-
function
|
|
260654
|
+
function isRow6(v3) {
|
|
260323
260655
|
const b8 = v3;
|
|
260324
260656
|
return !!b8 && typeof b8 === "object" && !Array.isArray(b8) && typeof b8.task_id === "string" && TASK_ID_RE3.test(b8.task_id) && typeof b8.html === "string" && typeof b8.version === "number";
|
|
260325
260657
|
}
|
|
260326
|
-
async function
|
|
260327
|
-
if (
|
|
260658
|
+
async function load7() {
|
|
260659
|
+
if (state13) return state13;
|
|
260328
260660
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
260329
260661
|
try {
|
|
260330
|
-
const raw = JSON.parse(await
|
|
260662
|
+
const raw = JSON.parse(await fsp131.readFile(STATE_FILE3(), "utf8"));
|
|
260331
260663
|
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: [], hashes: raw.hashes };
|
|
260332
260664
|
} catch {
|
|
260333
260665
|
}
|
|
260334
|
-
|
|
260666
|
+
state13 = s4;
|
|
260335
260667
|
return s4;
|
|
260336
260668
|
}
|
|
260337
|
-
async function
|
|
260338
|
-
if (
|
|
260669
|
+
async function save2() {
|
|
260670
|
+
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
260339
260671
|
}
|
|
260340
260672
|
async function localIds() {
|
|
260341
|
-
const names2 = await
|
|
260673
|
+
const names2 = await fsp131.readdir(boardsDir2()).catch(() => []);
|
|
260342
260674
|
return names2.filter((n6) => n6.endsWith(".json")).map((n6) => n6.slice(0, -".json".length)).filter((id) => TASK_ID_RE3.test(id));
|
|
260343
260675
|
}
|
|
260344
260676
|
function changed3() {
|
|
260345
260677
|
}
|
|
260346
260678
|
function boardsFollower() {
|
|
260347
|
-
|
|
260679
|
+
follower4 ??= createRowSetFollower({
|
|
260348
260680
|
kind: "boards",
|
|
260349
260681
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
260350
260682
|
label: "boards copy",
|
|
260351
260683
|
log: log.session,
|
|
260352
260684
|
removalFloor: BOARDS_REMOVAL_FLOOR,
|
|
260353
260685
|
ordered: false,
|
|
260354
|
-
serial: (fn) =>
|
|
260686
|
+
serial: (fn) => serial6(fn),
|
|
260355
260687
|
refuse: copyRefusal,
|
|
260356
|
-
load:
|
|
260357
|
-
save,
|
|
260358
|
-
isRow:
|
|
260688
|
+
load: load7,
|
|
260689
|
+
save: save2,
|
|
260690
|
+
isRow: isRow6,
|
|
260359
260691
|
key: (b8) => b8.task_id,
|
|
260360
260692
|
localKeys: localIds,
|
|
260361
260693
|
apply: async ({ rows, removeIds }) => {
|
|
260362
260694
|
const skipped = [];
|
|
260363
260695
|
for (const id of removeIds ?? []) {
|
|
260364
|
-
if (TASK_ID_RE3.test(id)) await
|
|
260696
|
+
if (TASK_ID_RE3.test(id)) await fsp131.rm(path243.join(boardsDir2(), `${id}.json`), { force: true });
|
|
260365
260697
|
}
|
|
260366
260698
|
for (const b8 of rows ?? []) {
|
|
260367
260699
|
if (Buffer.byteLength(JSON.stringify(b8)) > BOARD_COPY_MAX_BYTES) {
|
|
260368
260700
|
skipped.push(b8.task_id);
|
|
260369
260701
|
continue;
|
|
260370
260702
|
}
|
|
260371
|
-
await writeCopyFile(
|
|
260703
|
+
await writeCopyFile(path243.join(boardsDir2(), `${b8.task_id}.json`), b8);
|
|
260372
260704
|
}
|
|
260373
260705
|
return { skipped };
|
|
260374
260706
|
},
|
|
@@ -260376,15 +260708,15 @@ function boardsFollower() {
|
|
|
260376
260708
|
changed: changed3,
|
|
260377
260709
|
purge: async () => {
|
|
260378
260710
|
const ids2 = await localIds();
|
|
260379
|
-
for (const id of ids2) await
|
|
260711
|
+
for (const id of ids2) await fsp131.rm(path243.join(boardsDir2(), `${id}.json`), { force: true });
|
|
260380
260712
|
await markCopyOff("boards");
|
|
260381
|
-
|
|
260713
|
+
state13 = null;
|
|
260382
260714
|
return { removed: ids2.length };
|
|
260383
260715
|
}
|
|
260384
260716
|
});
|
|
260385
|
-
return
|
|
260717
|
+
return follower4;
|
|
260386
260718
|
}
|
|
260387
|
-
var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16,
|
|
260719
|
+
var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16, hashOf7, warnedTooBig, unreadableOf2, warnedUnreadable, BOARDS_KIND, STATE_FILE3, state13, serial6, follower4;
|
|
260388
260720
|
var init_boards2 = __esm({
|
|
260389
260721
|
"src/core/replication/kinds/boards.ts"() {
|
|
260390
260722
|
"use strict";
|
|
@@ -260397,9 +260729,9 @@ var init_boards2 = __esm({
|
|
|
260397
260729
|
BOARDS_REMOVAL_FLOOR = 20;
|
|
260398
260730
|
BOARD_COPY_MAX_BYTES = 2 * 1024 * 1024;
|
|
260399
260731
|
TASK_ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
260400
|
-
boardsDir2 = () =>
|
|
260732
|
+
boardsDir2 = () => path243.join(WALNUT_HOME, "boards");
|
|
260401
260733
|
cache16 = /* @__PURE__ */ new Map();
|
|
260402
|
-
|
|
260734
|
+
hashOf7 = /* @__PURE__ */ new WeakMap();
|
|
260403
260735
|
warnedTooBig = /* @__PURE__ */ new Set();
|
|
260404
260736
|
unreadableOf2 = /* @__PURE__ */ new WeakMap();
|
|
260405
260737
|
warnedUnreadable = /* @__PURE__ */ new Set();
|
|
@@ -260407,7 +260739,7 @@ var init_boards2 = __esm({
|
|
|
260407
260739
|
kind: "boards",
|
|
260408
260740
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
260409
260741
|
key: (b8) => b8.task_id,
|
|
260410
|
-
hash: (b8) =>
|
|
260742
|
+
hash: (b8) => hashOf7.get(b8) ?? sha12(JSON.stringify(b8)),
|
|
260411
260743
|
ordered: false,
|
|
260412
260744
|
digest: false,
|
|
260413
260745
|
choice: "boards",
|
|
@@ -260427,16 +260759,16 @@ var init_boards2 = __esm({
|
|
|
260427
260759
|
};
|
|
260428
260760
|
}
|
|
260429
260761
|
};
|
|
260430
|
-
|
|
260431
|
-
|
|
260432
|
-
|
|
260433
|
-
|
|
260762
|
+
STATE_FILE3 = () => path243.join(WALNUT_HOME, "cache", "replica", "boards.json");
|
|
260763
|
+
state13 = null;
|
|
260764
|
+
serial6 = serialChain();
|
|
260765
|
+
follower4 = null;
|
|
260434
260766
|
}
|
|
260435
260767
|
});
|
|
260436
260768
|
|
|
260437
260769
|
// src/core/replication/kinds/inbox.ts
|
|
260438
|
-
import
|
|
260439
|
-
import
|
|
260770
|
+
import fsp132 from "fs/promises";
|
|
260771
|
+
import path244 from "path";
|
|
260440
260772
|
function watchLetters(soon) {
|
|
260441
260773
|
let stop2 = null;
|
|
260442
260774
|
let stopped2 = false;
|
|
@@ -260449,18 +260781,18 @@ function watchLetters(soon) {
|
|
|
260449
260781
|
};
|
|
260450
260782
|
}
|
|
260451
260783
|
async function leaderBodies(dir4 = bodiesDir()) {
|
|
260452
|
-
const names2 = (await
|
|
260784
|
+
const names2 = (await fsp132.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
|
|
260453
260785
|
const out = [];
|
|
260454
260786
|
const unreadable = [];
|
|
260455
260787
|
const seen2 = new Set(names2);
|
|
260456
260788
|
for (const name of names2) {
|
|
260457
|
-
const file =
|
|
260789
|
+
const file = path244.join(dir4, name);
|
|
260458
260790
|
try {
|
|
260459
|
-
const st2 = await
|
|
260791
|
+
const st2 = await fsp132.stat(file);
|
|
260460
260792
|
if (!st2.isFile() || st2.size > INBOX_BODY_COPY_MAX_BYTES) continue;
|
|
260461
260793
|
let c8 = bodyCache.get(name);
|
|
260462
260794
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
260463
|
-
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await
|
|
260795
|
+
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp132.readFile(file, "utf8")) };
|
|
260464
260796
|
bodyCache.set(name, c8);
|
|
260465
260797
|
}
|
|
260466
260798
|
const row = { name };
|
|
@@ -260479,21 +260811,21 @@ async function loadBody(b8) {
|
|
|
260479
260811
|
const file = bodyFiles.get(b8);
|
|
260480
260812
|
if (!file) return typeof b8.body === "string" ? b8 : void 0;
|
|
260481
260813
|
try {
|
|
260482
|
-
const body7 = await
|
|
260814
|
+
const body7 = await fsp132.readFile(file, "utf8");
|
|
260483
260815
|
return Buffer.byteLength(body7) > INBOX_BODY_COPY_MAX_BYTES ? void 0 : { name: b8.name, body: body7 };
|
|
260484
260816
|
} catch {
|
|
260485
260817
|
return void 0;
|
|
260486
260818
|
}
|
|
260487
260819
|
}
|
|
260488
260820
|
function stateIo(name) {
|
|
260489
|
-
const file = () =>
|
|
260821
|
+
const file = () => path244.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
|
|
260490
260822
|
let state17 = null;
|
|
260491
260823
|
return {
|
|
260492
260824
|
load: async () => {
|
|
260493
260825
|
if (state17) return state17;
|
|
260494
260826
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
260495
260827
|
try {
|
|
260496
|
-
const raw = JSON.parse(await
|
|
260828
|
+
const raw = JSON.parse(await fsp132.readFile(file(), "utf8"));
|
|
260497
260829
|
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") {
|
|
260498
260830
|
s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: Array.isArray(raw.order) ? raw.order.map(String) : [], hashes: raw.hashes };
|
|
260499
260831
|
}
|
|
@@ -260512,7 +260844,7 @@ function stateIo(name) {
|
|
|
260512
260844
|
}
|
|
260513
260845
|
async function readIndex3() {
|
|
260514
260846
|
try {
|
|
260515
|
-
const raw = JSON.parse(await
|
|
260847
|
+
const raw = JSON.parse(await fsp132.readFile(indexFile3(), "utf8"));
|
|
260516
260848
|
return Array.isArray(raw?.letters) ? raw.letters.filter(isLetter) : [];
|
|
260517
260849
|
} catch {
|
|
260518
260850
|
return [];
|
|
@@ -260535,7 +260867,7 @@ function inboxFollower() {
|
|
|
260535
260867
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
260536
260868
|
ordered: true,
|
|
260537
260869
|
digest: true,
|
|
260538
|
-
serial: (fn) =>
|
|
260870
|
+
serial: (fn) => serial7(fn),
|
|
260539
260871
|
refuse: refuse14,
|
|
260540
260872
|
load: () => indexIo.load(),
|
|
260541
260873
|
save: () => indexIo.save(),
|
|
@@ -260565,7 +260897,7 @@ function inboxFollower() {
|
|
|
260565
260897
|
},
|
|
260566
260898
|
purge: async () => {
|
|
260567
260899
|
const removed = (await readIndex3()).length;
|
|
260568
|
-
await
|
|
260900
|
+
await fsp132.rm(indexFile3(), { force: true });
|
|
260569
260901
|
await markCopyOff("inbox");
|
|
260570
260902
|
indexIo.reset();
|
|
260571
260903
|
return { removed };
|
|
@@ -260581,23 +260913,23 @@ function inboxBodiesFollower() {
|
|
|
260581
260913
|
log: log.notif,
|
|
260582
260914
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
260583
260915
|
ordered: false,
|
|
260584
|
-
serial: (fn) =>
|
|
260916
|
+
serial: (fn) => serial7(fn),
|
|
260585
260917
|
refuse: refuse14,
|
|
260586
260918
|
load: () => bodiesIo.load(),
|
|
260587
260919
|
save: () => bodiesIo.save(),
|
|
260588
260920
|
isRow: isBody,
|
|
260589
260921
|
key: (b8) => b8.name,
|
|
260590
260922
|
hash: (b8) => sha12(b8.body),
|
|
260591
|
-
localKeys: async () => (await
|
|
260923
|
+
localKeys: async () => (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
|
|
260592
260924
|
apply: async ({ rows, removeIds }) => {
|
|
260593
|
-
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await
|
|
260925
|
+
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp132.rm(path244.join(bodiesDir(), name), { force: true });
|
|
260594
260926
|
const skipped = [];
|
|
260595
260927
|
for (const b8 of rows ?? []) {
|
|
260596
260928
|
if (Buffer.byteLength(b8.body) > INBOX_BODY_COPY_MAX_BYTES) {
|
|
260597
260929
|
skipped.push(b8.name);
|
|
260598
260930
|
continue;
|
|
260599
260931
|
}
|
|
260600
|
-
await writeCopyText(
|
|
260932
|
+
await writeCopyText(path244.join(bodiesDir(), b8.name), b8.body);
|
|
260601
260933
|
}
|
|
260602
260934
|
return { skipped };
|
|
260603
260935
|
},
|
|
@@ -260605,8 +260937,8 @@ function inboxBodiesFollower() {
|
|
|
260605
260937
|
changed: () => {
|
|
260606
260938
|
},
|
|
260607
260939
|
purge: async () => {
|
|
260608
|
-
const names2 = (await
|
|
260609
|
-
for (const name of names2) await
|
|
260940
|
+
const names2 = (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
|
|
260941
|
+
for (const name of names2) await fsp132.rm(path244.join(bodiesDir(), name), { force: true });
|
|
260610
260942
|
await markCopyOff("inbox-bodies");
|
|
260611
260943
|
bodiesIo.reset();
|
|
260612
260944
|
return { removed: names2.length };
|
|
@@ -260614,7 +260946,7 @@ function inboxBodiesFollower() {
|
|
|
260614
260946
|
});
|
|
260615
260947
|
return bodiesF;
|
|
260616
260948
|
}
|
|
260617
|
-
var INBOX_SCHEMA_VERSION, INBOX_REMOVAL_FLOOR, INBOX_BODY_COPY_MAX_BYTES, inboxDir, indexFile3, bodiesDir, letterHashes, INBOX_KIND, bodyCache, bodyHashes, bodyFiles, unreadableBodiesOf, INBOX_BODIES_KIND, refuse14, indexIo, bodiesIo,
|
|
260949
|
+
var INBOX_SCHEMA_VERSION, INBOX_REMOVAL_FLOOR, INBOX_BODY_COPY_MAX_BYTES, inboxDir, indexFile3, bodiesDir, letterHashes, INBOX_KIND, bodyCache, bodyHashes, bodyFiles, unreadableBodiesOf, INBOX_BODIES_KIND, refuse14, indexIo, bodiesIo, serial7, inboxF, bodiesF;
|
|
260618
260950
|
var init_inbox = __esm({
|
|
260619
260951
|
"src/core/replication/kinds/inbox.ts"() {
|
|
260620
260952
|
"use strict";
|
|
@@ -260627,9 +260959,9 @@ var init_inbox = __esm({
|
|
|
260627
260959
|
INBOX_SCHEMA_VERSION = 1;
|
|
260628
260960
|
INBOX_REMOVAL_FLOOR = 50;
|
|
260629
260961
|
INBOX_BODY_COPY_MAX_BYTES = 4 * 1024 * 1024;
|
|
260630
|
-
inboxDir = () =>
|
|
260631
|
-
indexFile3 = () =>
|
|
260632
|
-
bodiesDir = () =>
|
|
260962
|
+
inboxDir = () => path244.join(WALNUT_HOME, "human-inbox");
|
|
260963
|
+
indexFile3 = () => path244.join(inboxDir(), "index.json");
|
|
260964
|
+
bodiesDir = () => path244.join(inboxDir(), "bodies");
|
|
260633
260965
|
letterHashes = /* @__PURE__ */ new WeakMap();
|
|
260634
260966
|
INBOX_KIND = {
|
|
260635
260967
|
kind: "inbox",
|
|
@@ -260671,134 +261003,12 @@ var init_inbox = __esm({
|
|
|
260671
261003
|
refuse14 = copyRefusal;
|
|
260672
261004
|
indexIo = stateIo("inbox");
|
|
260673
261005
|
bodiesIo = stateIo("inbox-bodies");
|
|
260674
|
-
|
|
261006
|
+
serial7 = serialChain();
|
|
260675
261007
|
inboxF = null;
|
|
260676
261008
|
bodiesF = null;
|
|
260677
261009
|
}
|
|
260678
261010
|
});
|
|
260679
261011
|
|
|
260680
|
-
// src/core/replication/kinds/requests.ts
|
|
260681
|
-
import fsp132 from "fs/promises";
|
|
260682
|
-
import path244 from "path";
|
|
260683
|
-
function forwardRequest(local, incoming) {
|
|
260684
|
-
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
260685
|
-
return incoming;
|
|
260686
|
-
}
|
|
260687
|
-
function hashOf6(row) {
|
|
260688
|
-
let h8 = hashes4.get(row);
|
|
260689
|
-
if (h8 === void 0) {
|
|
260690
|
-
h8 = sha12(JSON.stringify(row));
|
|
260691
|
-
hashes4.set(row, h8);
|
|
260692
|
-
}
|
|
260693
|
-
return h8;
|
|
260694
|
-
}
|
|
260695
|
-
async function load7() {
|
|
260696
|
-
if (state13) return state13;
|
|
260697
|
-
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
260698
|
-
try {
|
|
260699
|
-
const raw = JSON.parse(await fsp132.readFile(STATE_FILE3(), "utf8"));
|
|
260700
|
-
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: [], hashes: raw.hashes };
|
|
260701
|
-
} catch {
|
|
260702
|
-
}
|
|
260703
|
-
state13 = s4;
|
|
260704
|
-
return s4;
|
|
260705
|
-
}
|
|
260706
|
-
async function save2() {
|
|
260707
|
-
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
260708
|
-
}
|
|
260709
|
-
async function readStore8() {
|
|
260710
|
-
try {
|
|
260711
|
-
const raw = JSON.parse(await fsp132.readFile(STORE_FILE(), "utf8"));
|
|
260712
|
-
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
260713
|
-
} catch {
|
|
260714
|
-
return [];
|
|
260715
|
-
}
|
|
260716
|
-
}
|
|
260717
|
-
function isRow5(v3) {
|
|
260718
|
-
const r8 = v3;
|
|
260719
|
-
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
260720
|
-
}
|
|
260721
|
-
function requestsFollower() {
|
|
260722
|
-
follower4 ??= createRowSetFollower({
|
|
260723
|
-
kind: "requests",
|
|
260724
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
260725
|
-
label: "requests copy",
|
|
260726
|
-
log: log.session,
|
|
260727
|
-
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
260728
|
-
ordered: false,
|
|
260729
|
-
serial: (fn) => serial7(fn),
|
|
260730
|
-
refuse: copyRefusal,
|
|
260731
|
-
load: load7,
|
|
260732
|
-
save: save2,
|
|
260733
|
-
isRow: isRow5,
|
|
260734
|
-
key: (r8) => r8.id,
|
|
260735
|
-
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
260736
|
-
apply: async ({ rows, removeIds }) => {
|
|
260737
|
-
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
260738
|
-
for (const id of removeIds ?? []) byId.delete(id);
|
|
260739
|
-
for (const r8 of rows ?? []) {
|
|
260740
|
-
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
260741
|
-
if (kept !== r8) log.session.info("requests copy: kept a settled request the leader has not settled yet", { requestId: r8.id, local: kept.status, leader: r8.status });
|
|
260742
|
-
byId.set(r8.id, kept);
|
|
260743
|
-
}
|
|
260744
|
-
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
260745
|
-
return { skipped: [] };
|
|
260746
|
-
},
|
|
260747
|
-
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
260748
|
-
changed: () => {
|
|
260749
|
-
},
|
|
260750
|
-
purge: async () => {
|
|
260751
|
-
const removed = (await readStore8()).length;
|
|
260752
|
-
await fsp132.rm(STORE_FILE(), { force: true });
|
|
260753
|
-
await markCopyOff("requests");
|
|
260754
|
-
state13 = null;
|
|
260755
|
-
return { removed };
|
|
260756
|
-
}
|
|
260757
|
-
});
|
|
260758
|
-
return follower4;
|
|
260759
|
-
}
|
|
260760
|
-
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes4, REQUESTS_KIND, STATE_FILE3, STORE_FILE, state13, serial7, follower4;
|
|
260761
|
-
var init_requests = __esm({
|
|
260762
|
-
"src/core/replication/kinds/requests.ts"() {
|
|
260763
|
-
"use strict";
|
|
260764
|
-
init_constants();
|
|
260765
|
-
init_logging();
|
|
260766
|
-
init_kind();
|
|
260767
|
-
init_kind_follower();
|
|
260768
|
-
init_gate();
|
|
260769
|
-
REQUESTS_SCHEMA_VERSION = 1;
|
|
260770
|
-
REQUESTS_REMOVAL_FLOOR = 50;
|
|
260771
|
-
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
260772
|
-
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
260773
|
-
REQUESTS_KIND = {
|
|
260774
|
-
kind: "requests",
|
|
260775
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
260776
|
-
key: (r8) => r8.id,
|
|
260777
|
-
hash: hashOf6,
|
|
260778
|
-
ordered: false,
|
|
260779
|
-
digest: false,
|
|
260780
|
-
choice: "requests",
|
|
260781
|
-
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
260782
|
-
watch: (soon) => {
|
|
260783
|
-
let stop2 = null;
|
|
260784
|
-
let stopped2 = false;
|
|
260785
|
-
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
260786
|
-
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
260787
|
-
});
|
|
260788
|
-
return () => {
|
|
260789
|
-
stopped2 = true;
|
|
260790
|
-
stop2?.();
|
|
260791
|
-
};
|
|
260792
|
-
}
|
|
260793
|
-
};
|
|
260794
|
-
STATE_FILE3 = () => path244.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
260795
|
-
STORE_FILE = () => path244.join(WALNUT_HOME, "session-requests.json");
|
|
260796
|
-
state13 = null;
|
|
260797
|
-
serial7 = serialChain();
|
|
260798
|
-
follower4 = null;
|
|
260799
|
-
}
|
|
260800
|
-
});
|
|
260801
|
-
|
|
260802
261012
|
// src/core/replication/kinds/sessions.ts
|
|
260803
261013
|
import fsp133 from "fs/promises";
|
|
260804
261014
|
import path245 from "path";
|
|
@@ -260829,11 +261039,11 @@ function projectedOf(row) {
|
|
|
260829
261039
|
}
|
|
260830
261040
|
return p6;
|
|
260831
261041
|
}
|
|
260832
|
-
function
|
|
260833
|
-
let h8 =
|
|
261042
|
+
function hashOf8(row) {
|
|
261043
|
+
let h8 = hashes6.get(row);
|
|
260834
261044
|
if (h8 === void 0) {
|
|
260835
261045
|
h8 = sessionCopyHash(row);
|
|
260836
|
-
|
|
261046
|
+
hashes6.set(row, h8);
|
|
260837
261047
|
}
|
|
260838
261048
|
return h8;
|
|
260839
261049
|
}
|
|
@@ -260853,7 +261063,7 @@ async function load8() {
|
|
|
260853
261063
|
async function save3() {
|
|
260854
261064
|
if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
|
|
260855
261065
|
}
|
|
260856
|
-
function
|
|
261066
|
+
function isRow7(v3) {
|
|
260857
261067
|
const r8 = v3;
|
|
260858
261068
|
return !!r8 && typeof r8 === "object" && !Array.isArray(r8) && typeof r8.claudeSessionId === "string" && r8.claudeSessionId.length > 0 && r8.claudeSessionId.length <= 200;
|
|
260859
261069
|
}
|
|
@@ -260873,7 +261083,7 @@ function sessionsFollower() {
|
|
|
260873
261083
|
refuse: copyRefusal,
|
|
260874
261084
|
load: load8,
|
|
260875
261085
|
save: save3,
|
|
260876
|
-
isRow:
|
|
261086
|
+
isRow: isRow7,
|
|
260877
261087
|
key: (r8) => r8.claudeSessionId,
|
|
260878
261088
|
hash: sessionCopyHash,
|
|
260879
261089
|
localKeys: async () => (await Promise.resolve().then(() => (init_session_db(), session_db_exports))).sessionIdsInStore(),
|
|
@@ -260895,7 +261105,7 @@ function sessionsFollower() {
|
|
|
260895
261105
|
});
|
|
260896
261106
|
return follower5;
|
|
260897
261107
|
}
|
|
260898
|
-
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected,
|
|
261108
|
+
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected, hashes6, SESSIONS_KIND, STATE_FILE4, state14, serial8, follower5;
|
|
260899
261109
|
var init_sessions2 = __esm({
|
|
260900
261110
|
"src/core/replication/kinds/sessions.ts"() {
|
|
260901
261111
|
"use strict";
|
|
@@ -260932,12 +261142,12 @@ var init_sessions2 = __esm({
|
|
|
260932
261142
|
VOLATILE_SESSION_FIELDS = ["lastActiveAt", "activity", "contextTokens"];
|
|
260933
261143
|
VOLATILE_SET = new Set(VOLATILE_SESSION_FIELDS);
|
|
260934
261144
|
projected = /* @__PURE__ */ new WeakMap();
|
|
260935
|
-
|
|
261145
|
+
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
260936
261146
|
SESSIONS_KIND = {
|
|
260937
261147
|
kind: "sessions",
|
|
260938
261148
|
schemaVersion: SESSIONS_SCHEMA_VERSION,
|
|
260939
261149
|
key: (s4) => s4.claudeSessionId,
|
|
260940
|
-
hash:
|
|
261150
|
+
hash: hashOf8,
|
|
260941
261151
|
ordered: false,
|
|
260942
261152
|
digest: true,
|
|
260943
261153
|
choice: "sessions",
|
|
@@ -260969,137 +261179,11 @@ var init_sessions2 = __esm({
|
|
|
260969
261179
|
}
|
|
260970
261180
|
});
|
|
260971
261181
|
|
|
260972
|
-
// src/core/replication/kinds/personas.ts
|
|
260973
|
-
var personas_exports = {};
|
|
260974
|
-
__export(personas_exports, {
|
|
260975
|
-
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
260976
|
-
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
260977
|
-
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
260978
|
-
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
260979
|
-
personasFollower: () => personasFollower,
|
|
260980
|
-
readPersonaCopy: () => readPersonaCopy
|
|
260981
|
-
});
|
|
260982
|
-
function tools(v3) {
|
|
260983
|
-
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
260984
|
-
}
|
|
260985
|
-
async function leaderRows2() {
|
|
260986
|
-
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
260987
|
-
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
260988
|
-
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
260989
|
-
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
260990
|
-
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
260991
|
-
]);
|
|
260992
|
-
const config = await getConfig2();
|
|
260993
|
-
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
260994
|
-
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
260995
|
-
const rows = [];
|
|
260996
|
-
for (const a8 of agents) {
|
|
260997
|
-
if (!ID_RE5.test(a8.id)) continue;
|
|
260998
|
-
try {
|
|
260999
|
-
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
261000
|
-
const prompt = profile.systemPrompt ?? "";
|
|
261001
|
-
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
261002
|
-
rows.push({
|
|
261003
|
-
key: a8.id,
|
|
261004
|
-
agentId: a8.id,
|
|
261005
|
-
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
261006
|
-
systemPrompt: prompt,
|
|
261007
|
-
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
261008
|
-
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
261009
|
-
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
261010
|
-
...effort ? { effort } : {},
|
|
261011
|
-
...launch.model ? { launchModel: launch.model } : {},
|
|
261012
|
-
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
261013
|
-
});
|
|
261014
|
-
} catch (err2) {
|
|
261015
|
-
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
261016
|
-
}
|
|
261017
|
-
}
|
|
261018
|
-
return rows;
|
|
261019
|
-
}
|
|
261020
|
-
function hashOf8(row) {
|
|
261021
|
-
let h8 = hashes6.get(row);
|
|
261022
|
-
if (h8 === void 0) {
|
|
261023
|
-
h8 = sha12(JSON.stringify(row));
|
|
261024
|
-
hashes6.set(row, h8);
|
|
261025
|
-
}
|
|
261026
|
-
return h8;
|
|
261027
|
-
}
|
|
261028
|
-
function isRow7(v3) {
|
|
261029
|
-
const r8 = v3;
|
|
261030
|
-
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
261031
|
-
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
261032
|
-
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE5.test(r8.key) || typeof r8.name !== "string") return false;
|
|
261033
|
-
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
261034
|
-
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
261035
|
-
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
261036
|
-
for (const k8 of ["effort", "launchModel", "launchEffort"]) if (r8[k8] !== void 0 && (typeof r8[k8] !== "string" || !/^[A-Za-z0-9._:[\]/-]{1,128}$/.test(r8[k8]))) return false;
|
|
261037
|
-
return true;
|
|
261038
|
-
}
|
|
261039
|
-
function admit2(r8) {
|
|
261040
|
-
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
261041
|
-
}
|
|
261042
|
-
async function readPersonaCopy(agentId) {
|
|
261043
|
-
const rows = await copy3.read();
|
|
261044
|
-
return rows?.[agentId] ?? null;
|
|
261045
|
-
}
|
|
261046
|
-
function _resetPersonasCopyForTesting() {
|
|
261047
|
-
copy3.reset();
|
|
261048
|
-
}
|
|
261049
|
-
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE5, TOOL_RE, hashes6, PERSONAS_KIND, ROW_KEYS, copy3, personasFollower;
|
|
261050
|
-
var init_personas = __esm({
|
|
261051
|
-
"src/core/replication/kinds/personas.ts"() {
|
|
261052
|
-
"use strict";
|
|
261053
|
-
init_logging();
|
|
261054
|
-
init_config_allowlist();
|
|
261055
|
-
init_kind();
|
|
261056
|
-
init_file_copy();
|
|
261057
|
-
PERSONAS_SCHEMA_VERSION = 1;
|
|
261058
|
-
PERSONAS_REMOVAL_FLOOR = 0;
|
|
261059
|
-
MAX_PROMPT_BYTES = 120 * 1024;
|
|
261060
|
-
ID_RE5 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
261061
|
-
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
261062
|
-
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
261063
|
-
PERSONAS_KIND = {
|
|
261064
|
-
kind: "personas",
|
|
261065
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
261066
|
-
key: (r8) => r8.key,
|
|
261067
|
-
hash: hashOf8,
|
|
261068
|
-
ordered: false,
|
|
261069
|
-
digest: false,
|
|
261070
|
-
choice: "personas",
|
|
261071
|
-
rows: leaderRows2,
|
|
261072
|
-
watch: (soon) => {
|
|
261073
|
-
let stop2 = null;
|
|
261074
|
-
let stopped2 = false;
|
|
261075
|
-
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
261076
|
-
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
261077
|
-
});
|
|
261078
|
-
return () => {
|
|
261079
|
-
stopped2 = true;
|
|
261080
|
-
stop2?.();
|
|
261081
|
-
};
|
|
261082
|
-
}
|
|
261083
|
-
};
|
|
261084
|
-
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
261085
|
-
copy3 = createFileCopy({
|
|
261086
|
-
kind: "personas",
|
|
261087
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
261088
|
-
label: "personas copy",
|
|
261089
|
-
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
261090
|
-
isRow: isRow7,
|
|
261091
|
-
key: (r8) => r8.key,
|
|
261092
|
-
admit: admit2
|
|
261093
|
-
});
|
|
261094
|
-
personasFollower = copy3.follower;
|
|
261095
|
-
}
|
|
261096
|
-
});
|
|
261097
|
-
|
|
261098
261182
|
// src/core/replication/kinds/index.ts
|
|
261099
261183
|
var kinds_exports = {};
|
|
261100
261184
|
__export(kinds_exports, {
|
|
261185
|
+
copyKeepersOnly: () => copyKeepersOnly,
|
|
261101
261186
|
copyKinds: () => copyKinds,
|
|
261102
|
-
hostReplicaOnly: () => hostReplicaOnly,
|
|
261103
261187
|
registerCopyFollowerKinds: () => registerCopyFollowerKinds,
|
|
261104
261188
|
startCopyKinds: () => startCopyKinds
|
|
261105
261189
|
});
|
|
@@ -261117,14 +261201,14 @@ function copyKinds() {
|
|
|
261117
261201
|
PERSONAS_KIND
|
|
261118
261202
|
];
|
|
261119
261203
|
}
|
|
261120
|
-
function
|
|
261204
|
+
function copyKeepersOnly(h8) {
|
|
261121
261205
|
return {
|
|
261122
261206
|
kind: h8.kind,
|
|
261123
|
-
// followerStep checks the version before the step: never `schema_newer`
|
|
261207
|
+
// followerStep checks the version before the step: never `schema_newer` where the kind is not kept.
|
|
261124
261208
|
get schemaVersion() {
|
|
261125
|
-
return keepsCopies() ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
261209
|
+
return keepsCopies(h8.kind) ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
261126
261210
|
},
|
|
261127
|
-
step: (op2, body7) => keepsCopies() ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
261211
|
+
step: (op2, body7) => keepsCopies(h8.kind) ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
261128
261212
|
};
|
|
261129
261213
|
}
|
|
261130
261214
|
function registerCopyFollowerKinds() {
|
|
@@ -261139,7 +261223,7 @@ function registerCopyFollowerKinds() {
|
|
|
261139
261223
|
prefsFollower(),
|
|
261140
261224
|
configFollower(),
|
|
261141
261225
|
personasFollower()
|
|
261142
|
-
].map((h8) => registerFollowerKind(
|
|
261226
|
+
].map((h8) => registerFollowerKind(copyKeepersOnly(h8)));
|
|
261143
261227
|
return () => {
|
|
261144
261228
|
for (const u3 of off) u3();
|
|
261145
261229
|
};
|
|
@@ -293249,10 +293333,13 @@ async function cleanupLaneClaudeMd(homeDir2 = WALNUT_HOME) {
|
|
|
293249
293333
|
}
|
|
293250
293334
|
}
|
|
293251
293335
|
async function buildLaneProfile(config, agentId, opts2) {
|
|
293252
|
-
const
|
|
293253
|
-
const
|
|
293336
|
+
const persona = opts2?.persona;
|
|
293337
|
+
const skillsIndex = persona ? "" : await buildSessionSkillsPrompt().catch(() => "");
|
|
293338
|
+
const memoryContext = persona ? "" : await buildLaneMemoryContext().catch(() => "");
|
|
293254
293339
|
let profile;
|
|
293255
|
-
if (
|
|
293340
|
+
if (persona) {
|
|
293341
|
+
profile = mergeProfiles({ systemPrompt: persona.systemPrompt, systemPromptMode: persona.systemPromptMode }, walnutMcpProfile());
|
|
293342
|
+
} else if (agentId === "general") {
|
|
293256
293343
|
profile = personalAiProfile(config.user?.name ?? "the user", skillsIndex, memoryContext);
|
|
293257
293344
|
} else {
|
|
293258
293345
|
const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports));
|
|
@@ -293262,7 +293349,8 @@ async function buildLaneProfile(config, agentId, opts2) {
|
|
|
293262
293349
|
const contextBlock = await loadContextSources2(agentDef, {}).catch(() => "");
|
|
293263
293350
|
profile = consoleAgentProfile(agentDef, skillsIndex, contextBlock);
|
|
293264
293351
|
}
|
|
293265
|
-
const
|
|
293352
|
+
const personaEffort = persona?.effort && LANE_EFFORTS.has(persona.effort) ? persona.effort : void 0;
|
|
293353
|
+
const effort = personaEffort ?? config.agent?.session_effort ?? "medium";
|
|
293266
293354
|
if (!opts2?.conversationId) return { profile, effort };
|
|
293267
293355
|
const base = profile.systemPrompt ?? "";
|
|
293268
293356
|
const headroom = MAX_LANE_PROMPT_BYTES - Buffer.byteLength(base, "utf-8") - LANE_SEED_RESERVE_BYTES;
|
|
@@ -293532,7 +293620,7 @@ async function resolveLane(lane, agentId, conversationId, firstMessage, engine)
|
|
|
293532
293620
|
});
|
|
293533
293621
|
return { sessionId, created: true, engine: "claude" };
|
|
293534
293622
|
}
|
|
293535
|
-
var inFlight20, LANE_MEMORY_HEADER, MANAGED_LANE_CONTEXT_MARKERS, MAX_LANE_PROMPT_BYTES, LANE_SEED_RESERVE_BYTES, LANE_SEED_MIN_BYTES, walnutProfileRefreshAt, WALNUT_PROFILE_REFRESH_TTL_MS;
|
|
293623
|
+
var LANE_EFFORTS, inFlight20, LANE_MEMORY_HEADER, MANAGED_LANE_CONTEXT_MARKERS, MAX_LANE_PROMPT_BYTES, LANE_SEED_RESERVE_BYTES, LANE_SEED_MIN_BYTES, walnutProfileRefreshAt, WALNUT_PROFILE_REFRESH_TTL_MS;
|
|
293536
293624
|
var init_personal_ai_lane = __esm({
|
|
293537
293625
|
"src/core/sessions/personal-ai-lane.ts"() {
|
|
293538
293626
|
"use strict";
|
|
@@ -293547,6 +293635,7 @@ var init_personal_ai_lane = __esm({
|
|
|
293547
293635
|
init_default_engine();
|
|
293548
293636
|
init_ask_profile_prefix();
|
|
293549
293637
|
init_logging();
|
|
293638
|
+
LANE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
293550
293639
|
inFlight20 = /* @__PURE__ */ new Map();
|
|
293551
293640
|
LANE_MEMORY_HEADER = "## Standing memory (injected by Walnut)";
|
|
293552
293641
|
MANAGED_LANE_CONTEXT_MARKERS = [
|
|
@@ -321314,9 +321403,13 @@ var init_task_replica_store = __esm({
|
|
|
321314
321403
|
// src/core/replication/kinds/gate.ts
|
|
321315
321404
|
var gate_exports = {};
|
|
321316
321405
|
__export(gate_exports, {
|
|
321406
|
+
COMPANION_COPY_KINDS: () => COMPANION_COPY_KINDS,
|
|
321407
|
+
COPY_AS_OF_HEADER: () => COPY_AS_OF_HEADER,
|
|
321317
321408
|
KIND_NOT_COPIED: () => KIND_NOT_COPIED,
|
|
321409
|
+
copyKindAsOf: () => copyKindAsOf,
|
|
321318
321410
|
copyKindHeld: () => copyKindHeld,
|
|
321319
321411
|
copyKindOff: () => copyKindOff,
|
|
321412
|
+
copyPath: () => copyPath,
|
|
321320
321413
|
copyRefusal: () => copyRefusal,
|
|
321321
321414
|
copyStateFile: () => copyStateFile,
|
|
321322
321415
|
keepsCopies: () => keepsCopies,
|
|
@@ -321324,8 +321417,16 @@ __export(gate_exports, {
|
|
|
321324
321417
|
});
|
|
321325
321418
|
import fsp152 from "fs/promises";
|
|
321326
321419
|
import path296 from "path";
|
|
321327
|
-
function keepsCopies() {
|
|
321328
|
-
|
|
321420
|
+
function keepsCopies(kind) {
|
|
321421
|
+
if (isHostReplicaProgram()) return true;
|
|
321422
|
+
if (followerKind() !== "companion") return false;
|
|
321423
|
+
return kind === void 0 || COMPANION_COPY_KINDS.has(kind);
|
|
321424
|
+
}
|
|
321425
|
+
function copyPath(live6) {
|
|
321426
|
+
if (followerKind() !== "companion") return live6;
|
|
321427
|
+
const rel = path296.relative(WALNUT_HOME, live6);
|
|
321428
|
+
if (!rel || rel.startsWith("..") || path296.isAbsolute(rel)) throw new Error(`copyPath: ${live6} is not under the data dir`);
|
|
321429
|
+
return path296.join(WALNUT_HOME, "cache", "replica", "home", rel);
|
|
321329
321430
|
}
|
|
321330
321431
|
async function copyRefusal() {
|
|
321331
321432
|
if (!keepsCopies()) return { status: 404, error: "unknown_kind" };
|
|
@@ -321346,20 +321447,26 @@ async function copyKindOff(kind) {
|
|
|
321346
321447
|
}
|
|
321347
321448
|
}
|
|
321348
321449
|
async function copyKindHeld(kind) {
|
|
321450
|
+
return await copyKindAsOf(kind) !== null;
|
|
321451
|
+
}
|
|
321452
|
+
async function copyKindAsOf(kind) {
|
|
321349
321453
|
try {
|
|
321350
321454
|
const raw = JSON.parse(await fsp152.readFile(copyStateFile(kind), "utf8"));
|
|
321351
|
-
|
|
321455
|
+
if (!(raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object")) return null;
|
|
321456
|
+
return Number(raw.asOf) || 0;
|
|
321352
321457
|
} catch {
|
|
321353
|
-
return
|
|
321458
|
+
return null;
|
|
321354
321459
|
}
|
|
321355
321460
|
}
|
|
321356
|
-
var KIND_NOT_COPIED;
|
|
321461
|
+
var COMPANION_COPY_KINDS, COPY_AS_OF_HEADER, KIND_NOT_COPIED;
|
|
321357
321462
|
var init_gate = __esm({
|
|
321358
321463
|
"src/core/replication/kinds/gate.ts"() {
|
|
321359
321464
|
"use strict";
|
|
321360
321465
|
init_constants();
|
|
321361
321466
|
init_server_role();
|
|
321362
321467
|
init_kind_follower();
|
|
321468
|
+
COMPANION_COPY_KINDS = /* @__PURE__ */ new Set(["requests", "routines", "prefs", "personas"]);
|
|
321469
|
+
COPY_AS_OF_HEADER = "x-walnut-copy-as-of";
|
|
321363
321470
|
KIND_NOT_COPIED = "kind_not_copied";
|
|
321364
321471
|
}
|
|
321365
321472
|
});
|