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
|
@@ -5862,6 +5862,7 @@ function createOfflineHostCore(deps4) {
|
|
|
5862
5862
|
const MAX_ARGS_BYTES = 256 * 1024;
|
|
5863
5863
|
const WRITE_BUDGET = 30;
|
|
5864
5864
|
const WRITE_WINDOW_MS = 6e4;
|
|
5865
|
+
const LOCK_RETRY_MS = [100, 300, 900];
|
|
5865
5866
|
const DEFAULT_REPLY_SECS = 3600;
|
|
5866
5867
|
const IMPLICIT_REPLY_SECS = 6 * 3600;
|
|
5867
5868
|
const DRAIN_BATCH = 200;
|
|
@@ -6008,7 +6009,7 @@ function createOfflineHostCore(deps4) {
|
|
|
6008
6009
|
...opts2.admit ? { admit: opts2.admit } : {}
|
|
6009
6010
|
});
|
|
6010
6011
|
if (!r8.ok) {
|
|
6011
|
-
if (r8.code === "journal_unwritable") deps4.log("error", "offline host: journal write refused", { home, kind, code: r8.code, why: r8.why, error: r8.message });
|
|
6012
|
+
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 });
|
|
6012
6013
|
return r8;
|
|
6013
6014
|
}
|
|
6014
6015
|
if (!r8.duplicate) {
|
|
@@ -6023,6 +6024,19 @@ function createOfflineHostCore(deps4) {
|
|
|
6023
6024
|
if (r8.ok) return null;
|
|
6024
6025
|
return fail6(r8.code, r8.message, { ...r8.retryAfterMs !== void 0 ? { retryAfterMs: r8.retryAfterMs } : {}, ...r8.why ? { detail: { why: r8.why } } : {} });
|
|
6025
6026
|
}
|
|
6027
|
+
const lockRefused = (r8) => !r8.ok && r8.error.code === "journal_unwritable" && r8.error.detail?.why === "locked";
|
|
6028
|
+
async function whenUnlocked(home, op2, run12) {
|
|
6029
|
+
const t0 = Date.now();
|
|
6030
|
+
let r8 = run12();
|
|
6031
|
+
for (const ms2 of LOCK_RETRY_MS) {
|
|
6032
|
+
if (!lockRefused(r8)) return r8;
|
|
6033
|
+
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 });
|
|
6034
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms2));
|
|
6035
|
+
r8 = run12();
|
|
6036
|
+
}
|
|
6037
|
+
if (lockRefused(r8)) deps4.log("error", "offline host: the journal stayed locked; write refused", { home, op: op2, waitedMs: Date.now() - t0 });
|
|
6038
|
+
return r8;
|
|
6039
|
+
}
|
|
6026
6040
|
function configure(slice) {
|
|
6027
6041
|
if (!slice || slice.v !== 1 || typeof slice.home !== "string" || !slice.home) throw new Error("host.slice: bad slice");
|
|
6028
6042
|
const prev = slices.get(slice.home);
|
|
@@ -6756,10 +6770,8 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
6756
6770
|
if (no) return no;
|
|
6757
6771
|
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 });
|
|
6758
6772
|
} else {
|
|
6759
|
-
const denied = admitWrite(callerSid5) ?? roomFor(home);
|
|
6760
|
-
if (denied) return denied;
|
|
6761
6773
|
const base = slices.get(home)?.tasks.find((t3) => t3.id === task.id)?.updated_at;
|
|
6762
|
-
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }));
|
|
6774
|
+
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }, false, { admit: () => admitWrite(callerSid5) ?? roomFor(home) }));
|
|
6763
6775
|
if (no) return no;
|
|
6764
6776
|
deps4.log("info", "offline host: write queued", { home, op: name, taskId: task.id, callerSid: callerSid5 });
|
|
6765
6777
|
}
|
|
@@ -7201,7 +7213,7 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
7201
7213
|
const fromCopy = deps4.replica ? deps4.replica.answer(home, name, args, offlineNote(home)) : null;
|
|
7202
7214
|
if (fromCopy) return fromCopy;
|
|
7203
7215
|
if (deps4.boards && deps4.boards.BOARD_OPS.indexOf(name) !== -1) return opBoard(home, callerSid5, name, args);
|
|
7204
|
-
if (QUEUED_OPS.includes(name)) return opQueued(home, callerSid5, name, args);
|
|
7216
|
+
if (QUEUED_OPS.includes(name)) return whenUnlocked(home, name, () => opQueued(home, callerSid5, name, args));
|
|
7205
7217
|
return needsServer(name ? `"${name}"` : "That call");
|
|
7206
7218
|
}
|
|
7207
7219
|
}
|
|
@@ -7714,6 +7726,10 @@ ${mid}` : "";
|
|
|
7714
7726
|
handle: handle4,
|
|
7715
7727
|
handleLocal,
|
|
7716
7728
|
handleFollower,
|
|
7729
|
+
/** handleFollower, waiting out another process's journal lock (whenUnlocked): the twins' follower.op. */
|
|
7730
|
+
handleFollowerWaiting: (home, req) => whenUnlocked(home, String(req.op ?? ""), () => handleFollower(home, req)),
|
|
7731
|
+
/** noteSession, waiting out another process's journal lock (whenUnlocked): the twins' host ask. */
|
|
7732
|
+
noteSessionWaiting: (home, rec3, opId, by) => whenUnlocked(home, "session", () => noteSession(home, rec3, opId, by)),
|
|
7717
7733
|
pendingFor,
|
|
7718
7734
|
journalStats,
|
|
7719
7735
|
onResult,
|
|
@@ -23253,7 +23269,7 @@ function dispatchCommand(ws, id, cmd) {
|
|
|
23253
23269
|
case 'follower.sessions': return cmdFollowerSessions(ws, id);
|
|
23254
23270
|
case 'follower.send': return daemonCommands.run(function () { return cmdFollowerSend(ws, id, cmd); });
|
|
23255
23271
|
case 'follower.permission': return daemonCommands.run(function () { return cmdFollowerPermission(ws, id, cmd); });
|
|
23256
|
-
case 'follower.op': return cmdFollowerOp(ws, id, cmd);
|
|
23272
|
+
case 'follower.op': return daemonCommands.run(function () { return cmdFollowerOp(ws, id, cmd); });
|
|
23257
23273
|
case 'follower.pending': return cmdFollowerPending(ws, id, cmd);
|
|
23258
23274
|
// A new ask while the Mac is away ('replica-start-v1', WP12). Twin of daemon-standalone.ts.
|
|
23259
23275
|
case 'follower.start': return daemonCommands.run(function () { return cmdFollowerStart(ws, id, cmd); });
|
|
@@ -24667,14 +24683,15 @@ async function cmdFollowerPermission(ws, id, cmd) {
|
|
|
24667
24683
|
// The replica's write while the Mac is away (replica-ops-v1, journal v2). Its own gate:
|
|
24668
24684
|
// the follower's own Walnut, the quiet window unless the Mac is still taking the
|
|
24669
24685
|
// journal, and the daemon dir's owner. Twin of daemon-standalone.ts cmdFollowerOp.
|
|
24670
|
-
function cmdFollowerOp(ws, id, cmd) {
|
|
24686
|
+
async function cmdFollowerOp(ws, id, cmd) {
|
|
24671
24687
|
var home = followerHomeOf(ws);
|
|
24672
24688
|
if (!home) return sendError(ws, id, 'follower.op: send follower.hello first');
|
|
24673
24689
|
if (!followerMayWrite(home)) return sendError(ws, id, 'follower.op: your Mac answers again; write through it', { errorKind: 'leader_answers' });
|
|
24674
24690
|
if (!ownsDaemonDir()) {
|
|
24675
24691
|
return sendError(ws, id, 'follower.op: this daemon no longer owns its directory', { errorKind: 'journal_unwritable', detail: { why: 'not_owner' } });
|
|
24676
24692
|
}
|
|
24677
|
-
|
|
24693
|
+
// Waits out another process's journal lock (about 1.3 s) before it answers.
|
|
24694
|
+
var r = await offlineHost.handleFollowerWaiting(home, { op: cmd.op, args: cmd.args, actor: cmd.actor, opId: cmd.opId, base: cmd.base });
|
|
24678
24695
|
if (r.ok) return sendOk(ws, id, r.result);
|
|
24679
24696
|
sendError(ws, id, 'follower.op: ' + r.error.message, Object.assign({ errorKind: r.error.code },
|
|
24680
24697
|
r.error.detail !== undefined ? { detail: r.error.detail } : {}, r.error.retryAfterMs !== undefined ? { retryAfterMs: r.error.retryAfterMs } : {}));
|
|
@@ -24824,7 +24841,7 @@ async function startHostAsk(home, p, cmd) {
|
|
|
24824
24841
|
throw err;
|
|
24825
24842
|
}
|
|
24826
24843
|
if (DIE_AFTER_ASK_SPAWN) process.kill(process.pid, 'SIGKILL');
|
|
24827
|
-
var saved = offlineHost.
|
|
24844
|
+
var saved = await offlineHost.noteSessionWaiting(home, p.record, opId, cmd.actor);
|
|
24828
24845
|
hostStart.releasePending(home, p.sid);
|
|
24829
24846
|
if (!saved.ok) {
|
|
24830
24847
|
// Nothing would tell the Mac about this CLI: it must not run unseen. Not stamped as an
|
|
@@ -142740,8 +142757,9 @@ async function buildCopyManifest(kind) {
|
|
|
142740
142757
|
}
|
|
142741
142758
|
return manifest;
|
|
142742
142759
|
}
|
|
142743
|
-
function keepsCopiesTarget(t3) {
|
|
142744
|
-
|
|
142760
|
+
function keepsCopiesTarget(t3, kind) {
|
|
142761
|
+
if (t3.kind === "host") return t3.program?.() === "replica";
|
|
142762
|
+
return t3.kind === "companion" && (kind === void 0 || COMPANION_COPY_KINDS.has(kind));
|
|
142745
142763
|
}
|
|
142746
142764
|
function manifestDigest(manifest, ordered = false) {
|
|
142747
142765
|
let d8 = manifestDigests.get(manifest);
|
|
@@ -142855,7 +142873,7 @@ async function choiceOf(target2) {
|
|
|
142855
142873
|
}
|
|
142856
142874
|
async function syncCopyKinds(kinds, deps4 = {}) {
|
|
142857
142875
|
const now = deps4.now ?? Date.now;
|
|
142858
|
-
const all = (deps4.targets ?? await defaultTargets())().filter(keepsCopiesTarget);
|
|
142876
|
+
const all = (deps4.targets ?? await defaultTargets())().filter((t3) => kinds.some((k8) => keepsCopiesTarget(t3, k8.kind)));
|
|
142859
142877
|
const ready2 = [];
|
|
142860
142878
|
for (const target2 of all) if (await target2.available()) ready2.push({ target: target2, choice: await choiceOf(target2) });
|
|
142861
142879
|
const results = [];
|
|
@@ -142863,7 +142881,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
142863
142881
|
const asOf2 = now();
|
|
142864
142882
|
const manifests = /* @__PURE__ */ new Map();
|
|
142865
142883
|
for (const kind of kinds) {
|
|
142866
|
-
if (!ready2.some((r8) => r8.choice[kind.choice])) continue;
|
|
142884
|
+
if (!ready2.some((r8) => r8.choice[kind.choice] && keepsCopiesTarget(r8.target, kind.kind))) continue;
|
|
142867
142885
|
try {
|
|
142868
142886
|
manifests.set(kind.kind, await buildCopyManifest(kind));
|
|
142869
142887
|
} catch (err2) {
|
|
@@ -142872,6 +142890,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
142872
142890
|
}
|
|
142873
142891
|
for (const { target: target2, choice } of ready2) {
|
|
142874
142892
|
for (const kind of kinds) {
|
|
142893
|
+
if (!keepsCopiesTarget(target2, kind.kind)) continue;
|
|
142875
142894
|
const manifest = manifests.get(kind.kind);
|
|
142876
142895
|
const st2 = kindState(target2, kind.kind);
|
|
142877
142896
|
if (!choice[kind.choice]) {
|
|
@@ -142917,7 +142936,7 @@ async function purgeKind(kind, target2, st2) {
|
|
|
142917
142936
|
async function confirmCopyKindRemoval(targetId, kind, opts2 = {}) {
|
|
142918
142937
|
const { replicaTargets: replicaTargets2 } = await Promise.resolve().then(() => (init_replica_targets(), replica_targets_exports));
|
|
142919
142938
|
const target2 = replicaTargets2().find((t3) => t3.id === targetId);
|
|
142920
|
-
if (!target2 || target2
|
|
142939
|
+
if (!target2 || !keepsCopiesTarget(target2, kind) || !peekKindState(targetId, kind)) return false;
|
|
142921
142940
|
if (!confirmKindRemoval(target2, kind, opts2)) return false;
|
|
142922
142941
|
log.session.warn("copies: the user confirmed a removal of most rows", { target: targetId, kind, entries: peekKindState(targetId, kind)?.confirmFor?.entries });
|
|
142923
142942
|
copySoon(kind);
|
|
@@ -143032,6 +143051,7 @@ var init_copy_kind = __esm({
|
|
|
143032
143051
|
init_kind_leader();
|
|
143033
143052
|
init_search_digest();
|
|
143034
143053
|
init_replica_status();
|
|
143054
|
+
init_gate();
|
|
143035
143055
|
COPY_DEBOUNCE_MS = 3e3;
|
|
143036
143056
|
COPY_SWEEP_MS = 5 * 6e4;
|
|
143037
143057
|
COPY_FIRST_ROUND_MS = 15e3;
|
|
@@ -148725,6 +148745,7 @@ var init_routines = __esm({
|
|
|
148725
148745
|
var routines_follower_exports = {};
|
|
148726
148746
|
__export(routines_follower_exports, {
|
|
148727
148747
|
_resetRoutinesCopyForTesting: () => _resetRoutinesCopyForTesting,
|
|
148748
|
+
companionRoutinesCopy: () => companionRoutinesCopy,
|
|
148728
148749
|
readRoutinesCopy: () => readRoutinesCopy,
|
|
148729
148750
|
routinesFollower: () => routinesFollower
|
|
148730
148751
|
});
|
|
@@ -148820,6 +148841,10 @@ async function readRoutinesCopy(opts2 = {}) {
|
|
|
148820
148841
|
const shown = opts2.includeDisabled ? all : all.filter((j8) => j8.enabled);
|
|
148821
148842
|
return shown.sort((a8, b8) => (a8.state.nextRunAtMs ?? 0) - (b8.state.nextRunAtMs ?? 0));
|
|
148822
148843
|
}
|
|
148844
|
+
async function companionRoutinesCopy(opts2 = {}) {
|
|
148845
|
+
if (!await copyKindHeld("routines")) return null;
|
|
148846
|
+
return await readRoutinesCopy(opts2) ?? [];
|
|
148847
|
+
}
|
|
148823
148848
|
function _resetRoutinesCopyForTesting() {
|
|
148824
148849
|
io2 = copyStateIo("routines");
|
|
148825
148850
|
serial3 = serialChain();
|
|
@@ -148835,8 +148860,8 @@ var init_routines_follower = __esm({
|
|
|
148835
148860
|
init_gate();
|
|
148836
148861
|
init_state_io();
|
|
148837
148862
|
init_routines();
|
|
148838
|
-
jobsFile = () => CRON_FILE;
|
|
148839
|
-
statesFile = () => path117.join(path117.dirname(CRON_FILE), "cron-state.json");
|
|
148863
|
+
jobsFile = () => copyPath(CRON_FILE);
|
|
148864
|
+
statesFile = () => copyPath(path117.join(path117.dirname(CRON_FILE), "cron-state.json"));
|
|
148840
148865
|
io2 = copyStateIo("routines");
|
|
148841
148866
|
serial3 = serialChain();
|
|
148842
148867
|
follower2 = null;
|
|
@@ -165378,8 +165403,8 @@ import path135 from "path";
|
|
|
165378
165403
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
165379
165404
|
function getVersion() {
|
|
165380
165405
|
if (cachedVersion) return cachedVersion;
|
|
165381
|
-
if ("0.6.
|
|
165382
|
-
cachedVersion = "0.6.
|
|
165406
|
+
if ("0.6.17") {
|
|
165407
|
+
cachedVersion = "0.6.17";
|
|
165383
165408
|
versionKnown = true;
|
|
165384
165409
|
return cachedVersion;
|
|
165385
165410
|
}
|
|
@@ -187587,6 +187612,132 @@ var init_agent_turn_queue = __esm({
|
|
|
187587
187612
|
}
|
|
187588
187613
|
});
|
|
187589
187614
|
|
|
187615
|
+
// src/core/replication/kinds/personas.ts
|
|
187616
|
+
var personas_exports = {};
|
|
187617
|
+
__export(personas_exports, {
|
|
187618
|
+
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
187619
|
+
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
187620
|
+
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
187621
|
+
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
187622
|
+
personasFollower: () => personasFollower,
|
|
187623
|
+
readPersonaCopy: () => readPersonaCopy
|
|
187624
|
+
});
|
|
187625
|
+
function tools(v3) {
|
|
187626
|
+
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
187627
|
+
}
|
|
187628
|
+
async function leaderRows() {
|
|
187629
|
+
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
187630
|
+
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
187631
|
+
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
187632
|
+
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
187633
|
+
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
187634
|
+
]);
|
|
187635
|
+
const config = await getConfig2();
|
|
187636
|
+
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
187637
|
+
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
187638
|
+
const rows = [];
|
|
187639
|
+
for (const a8 of agents) {
|
|
187640
|
+
if (!ID_RE2.test(a8.id)) continue;
|
|
187641
|
+
try {
|
|
187642
|
+
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
187643
|
+
const prompt = profile.systemPrompt ?? "";
|
|
187644
|
+
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
187645
|
+
rows.push({
|
|
187646
|
+
key: a8.id,
|
|
187647
|
+
agentId: a8.id,
|
|
187648
|
+
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
187649
|
+
systemPrompt: prompt,
|
|
187650
|
+
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
187651
|
+
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
187652
|
+
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
187653
|
+
...effort ? { effort } : {},
|
|
187654
|
+
...launch.model ? { launchModel: launch.model } : {},
|
|
187655
|
+
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
187656
|
+
});
|
|
187657
|
+
} catch (err2) {
|
|
187658
|
+
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
187659
|
+
}
|
|
187660
|
+
}
|
|
187661
|
+
return rows;
|
|
187662
|
+
}
|
|
187663
|
+
function hashOf4(row) {
|
|
187664
|
+
let h8 = hashes3.get(row);
|
|
187665
|
+
if (h8 === void 0) {
|
|
187666
|
+
h8 = sha12(JSON.stringify(row));
|
|
187667
|
+
hashes3.set(row, h8);
|
|
187668
|
+
}
|
|
187669
|
+
return h8;
|
|
187670
|
+
}
|
|
187671
|
+
function isRow3(v3) {
|
|
187672
|
+
const r8 = v3;
|
|
187673
|
+
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
187674
|
+
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
187675
|
+
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE2.test(r8.key) || typeof r8.name !== "string") return false;
|
|
187676
|
+
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
187677
|
+
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
187678
|
+
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
187679
|
+
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;
|
|
187680
|
+
return true;
|
|
187681
|
+
}
|
|
187682
|
+
function admit(r8) {
|
|
187683
|
+
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
187684
|
+
}
|
|
187685
|
+
async function readPersonaCopy(agentId) {
|
|
187686
|
+
const rows = await copy2.read();
|
|
187687
|
+
return rows?.[agentId] ?? null;
|
|
187688
|
+
}
|
|
187689
|
+
function _resetPersonasCopyForTesting() {
|
|
187690
|
+
copy2.reset();
|
|
187691
|
+
}
|
|
187692
|
+
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE2, TOOL_RE, hashes3, PERSONAS_KIND, ROW_KEYS, copy2, personasFollower;
|
|
187693
|
+
var init_personas = __esm({
|
|
187694
|
+
"src/core/replication/kinds/personas.ts"() {
|
|
187695
|
+
"use strict";
|
|
187696
|
+
init_logging();
|
|
187697
|
+
init_config_allowlist();
|
|
187698
|
+
init_kind();
|
|
187699
|
+
init_file_copy();
|
|
187700
|
+
PERSONAS_SCHEMA_VERSION = 1;
|
|
187701
|
+
PERSONAS_REMOVAL_FLOOR = 0;
|
|
187702
|
+
MAX_PROMPT_BYTES = 120 * 1024;
|
|
187703
|
+
ID_RE2 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
187704
|
+
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
187705
|
+
hashes3 = /* @__PURE__ */ new WeakMap();
|
|
187706
|
+
PERSONAS_KIND = {
|
|
187707
|
+
kind: "personas",
|
|
187708
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
187709
|
+
key: (r8) => r8.key,
|
|
187710
|
+
hash: hashOf4,
|
|
187711
|
+
ordered: false,
|
|
187712
|
+
digest: false,
|
|
187713
|
+
choice: "personas",
|
|
187714
|
+
rows: leaderRows,
|
|
187715
|
+
watch: (soon) => {
|
|
187716
|
+
let stop2 = null;
|
|
187717
|
+
let stopped2 = false;
|
|
187718
|
+
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
187719
|
+
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
187720
|
+
});
|
|
187721
|
+
return () => {
|
|
187722
|
+
stopped2 = true;
|
|
187723
|
+
stop2?.();
|
|
187724
|
+
};
|
|
187725
|
+
}
|
|
187726
|
+
};
|
|
187727
|
+
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
187728
|
+
copy2 = createFileCopy({
|
|
187729
|
+
kind: "personas",
|
|
187730
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
187731
|
+
label: "personas copy",
|
|
187732
|
+
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
187733
|
+
isRow: isRow3,
|
|
187734
|
+
key: (r8) => r8.key,
|
|
187735
|
+
admit
|
|
187736
|
+
});
|
|
187737
|
+
personasFollower = copy2.follower;
|
|
187738
|
+
}
|
|
187739
|
+
});
|
|
187740
|
+
|
|
187590
187741
|
// src/core/sessions/cloud-chat-lane.ts
|
|
187591
187742
|
var cloud_chat_lane_exports = {};
|
|
187592
187743
|
__export(cloud_chat_lane_exports, {
|
|
@@ -187725,7 +187876,9 @@ async function resolveCloudChatLane(lane, agentId, conversationId, cwd, firstMes
|
|
|
187725
187876
|
CATCH_UP_BANNER_CLOSE: CATCH_UP_BANNER_CLOSE2,
|
|
187726
187877
|
buildConversationSeed: buildConversationSeed2
|
|
187727
187878
|
} = await Promise.resolve().then(() => (init_chat_history(), chat_history_exports));
|
|
187728
|
-
const {
|
|
187879
|
+
const { readPersonaCopy: readPersonaCopy2 } = await Promise.resolve().then(() => (init_personas(), personas_exports));
|
|
187880
|
+
const persona = await readPersonaCopy2(agentId).catch(() => null);
|
|
187881
|
+
const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId, ...persona ? { persona } : {} });
|
|
187729
187882
|
const profile = toCloudChatProfile(base, CONVERSATION_SEED_HEADER2);
|
|
187730
187883
|
const sessionId = crypto49.randomUUID();
|
|
187731
187884
|
const seedInProfile = !!seed && (seed.text !== "" || seed.stats.turnsTotal === 0);
|
|
@@ -194694,9 +194847,9 @@ function sanitizeHealthSync(body7, now = Date.now()) {
|
|
|
194694
194847
|
const tz = isValidTz(b8.tz) ? b8.tz : "";
|
|
194695
194848
|
const spec = metricSpec(type);
|
|
194696
194849
|
const generic = isGenericType(type);
|
|
194697
|
-
const storeId = typeof b8.storeId === "string" &&
|
|
194850
|
+
const storeId = typeof b8.storeId === "string" && ID_RE3.test(b8.storeId) ? b8.storeId : void 0;
|
|
194698
194851
|
const dev = b8.device && typeof b8.device === "object" ? b8.device : {};
|
|
194699
|
-
const installId = typeof dev.installId === "string" &&
|
|
194852
|
+
const installId = typeof dev.installId === "string" && ID_RE3.test(dev.installId) ? dev.installId : void 0;
|
|
194700
194853
|
const device = { installId, model: str10(dev.model, 64), os: str10(dev.os, 64) };
|
|
194701
194854
|
const hasDevice = Object.values(device).some((v3) => v3 !== void 0);
|
|
194702
194855
|
const deleted = [...new Set(deletedIn.filter((u3) => typeof u3 === "string" && UUID_RE3.test(u3)))];
|
|
@@ -194764,14 +194917,14 @@ function relayPayload(batch) {
|
|
|
194764
194917
|
samples: batch.samples.map(({ tz, ...rest }) => tz === batch.tz ? rest : { ...rest, tz })
|
|
194765
194918
|
};
|
|
194766
194919
|
}
|
|
194767
|
-
var UUID_RE3,
|
|
194920
|
+
var UUID_RE3, ID_RE3, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
|
|
194768
194921
|
var init_sanitize = __esm({
|
|
194769
194922
|
"src/core/health/sanitize.ts"() {
|
|
194770
194923
|
"use strict";
|
|
194771
194924
|
init_catalog();
|
|
194772
194925
|
init_day_key();
|
|
194773
194926
|
UUID_RE3 = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
|
|
194774
|
-
|
|
194927
|
+
ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
|
|
194775
194928
|
MIN_INSTANT = Date.UTC(2010, 0, 1);
|
|
194776
194929
|
FUTURE_SLACK_MS2 = 36 * 36e5;
|
|
194777
194930
|
MAX_SPAN_MS = 2 * 864e5;
|
|
@@ -212375,7 +212528,7 @@ function prefAdmissible(p6) {
|
|
|
212375
212528
|
function strings(v3) {
|
|
212376
212529
|
return Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string") : [];
|
|
212377
212530
|
}
|
|
212378
|
-
async function
|
|
212531
|
+
async function leaderRows2() {
|
|
212379
212532
|
const raw = await readJsonFile(UI_PREFS_FILE, {}, { readErrors: "throw" });
|
|
212380
212533
|
const rows = [];
|
|
212381
212534
|
for (const [k8, v3] of Object.entries(raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {})) {
|
|
@@ -212387,15 +212540,15 @@ async function leaderRows() {
|
|
|
212387
212540
|
rows.push({ key: "favorites", favorites: { projects: strings(fav?.projects), notes: strings(fav?.notes) } });
|
|
212388
212541
|
return rows;
|
|
212389
212542
|
}
|
|
212390
|
-
function
|
|
212391
|
-
let h8 =
|
|
212543
|
+
function hashOf5(row) {
|
|
212544
|
+
let h8 = hashes4.get(row);
|
|
212392
212545
|
if (h8 === void 0) {
|
|
212393
212546
|
h8 = sha12(JSON.stringify(row));
|
|
212394
|
-
|
|
212547
|
+
hashes4.set(row, h8);
|
|
212395
212548
|
}
|
|
212396
212549
|
return h8;
|
|
212397
212550
|
}
|
|
212398
|
-
function
|
|
212551
|
+
function isRow4(v3) {
|
|
212399
212552
|
const r8 = v3;
|
|
212400
212553
|
if (!r8 || typeof r8 !== "object" || typeof r8.key !== "string") return false;
|
|
212401
212554
|
if (r8.key === "favorites") {
|
|
@@ -212405,27 +212558,27 @@ function isRow3(v3) {
|
|
|
212405
212558
|
const p6 = prefOf(r8.pref);
|
|
212406
212559
|
return Object.keys(r8).length === 2 && r8.key.startsWith(UI) && copyableUiPrefKey(r8.key.slice(UI.length)) && !!p6 && typeof r8.pref === "object";
|
|
212407
212560
|
}
|
|
212408
|
-
function
|
|
212561
|
+
function admit2(r8) {
|
|
212409
212562
|
if ("favorites" in r8) return [...r8.favorites.projects, ...r8.favorites.notes].every((s4) => typeof s4 === "string" && secretShapedValue(s4) === null);
|
|
212410
212563
|
return prefAdmissible(r8.pref);
|
|
212411
212564
|
}
|
|
212412
212565
|
async function readUiPrefsCopy() {
|
|
212413
|
-
const rows = await
|
|
212566
|
+
const rows = await copy3.read();
|
|
212414
212567
|
if (!rows) return null;
|
|
212415
212568
|
const out = {};
|
|
212416
212569
|
for (const r8 of Object.values(rows)) if ("pref" in r8) out[r8.key.slice(UI.length)] = r8.pref;
|
|
212417
212570
|
return out;
|
|
212418
212571
|
}
|
|
212419
212572
|
async function readFavoritesCopy() {
|
|
212420
|
-
const rows = await
|
|
212573
|
+
const rows = await copy3.read();
|
|
212421
212574
|
if (!rows) return null;
|
|
212422
212575
|
const f8 = rows.favorites;
|
|
212423
212576
|
return f8 && "favorites" in f8 ? f8.favorites : { projects: [], notes: [] };
|
|
212424
212577
|
}
|
|
212425
212578
|
function _resetPrefsCopyForTesting() {
|
|
212426
|
-
|
|
212579
|
+
copy3.reset();
|
|
212427
212580
|
}
|
|
212428
|
-
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2,
|
|
212581
|
+
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes4, PREFS_KIND, copy3, prefsFollower;
|
|
212429
212582
|
var init_prefs = __esm({
|
|
212430
212583
|
"src/core/replication/kinds/prefs.ts"() {
|
|
212431
212584
|
"use strict";
|
|
@@ -212439,16 +212592,16 @@ var init_prefs = __esm({
|
|
|
212439
212592
|
PREFS_REMOVAL_FLOOR = 0;
|
|
212440
212593
|
UI = "ui:";
|
|
212441
212594
|
MAX_VALUE_LEN2 = 8 * 1024;
|
|
212442
|
-
|
|
212595
|
+
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
212443
212596
|
PREFS_KIND = {
|
|
212444
212597
|
kind: "prefs",
|
|
212445
212598
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
212446
212599
|
key: (r8) => r8.key,
|
|
212447
|
-
hash:
|
|
212600
|
+
hash: hashOf5,
|
|
212448
212601
|
ordered: false,
|
|
212449
212602
|
digest: false,
|
|
212450
212603
|
choice: "prefs",
|
|
212451
|
-
rows:
|
|
212604
|
+
rows: leaderRows2,
|
|
212452
212605
|
watch: (soon) => {
|
|
212453
212606
|
const stops = [];
|
|
212454
212607
|
let stopped2 = false;
|
|
@@ -212461,16 +212614,16 @@ var init_prefs = __esm({
|
|
|
212461
212614
|
};
|
|
212462
212615
|
}
|
|
212463
212616
|
};
|
|
212464
|
-
|
|
212617
|
+
copy3 = createFileCopy({
|
|
212465
212618
|
kind: "prefs",
|
|
212466
212619
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
212467
212620
|
label: "prefs copy",
|
|
212468
212621
|
removalFloor: PREFS_REMOVAL_FLOOR,
|
|
212469
|
-
isRow:
|
|
212622
|
+
isRow: isRow4,
|
|
212470
212623
|
key: (r8) => r8.key,
|
|
212471
|
-
admit
|
|
212624
|
+
admit: admit2
|
|
212472
212625
|
});
|
|
212473
|
-
prefsFollower =
|
|
212626
|
+
prefsFollower = copy3.follower;
|
|
212474
212627
|
}
|
|
212475
212628
|
});
|
|
212476
212629
|
|
|
@@ -213062,7 +213215,7 @@ async function adoptDeviceRecord(input, opts2 = {}) {
|
|
|
213062
213215
|
const existing = devices.find((d8) => d8.tokenHash === tokenHash);
|
|
213063
213216
|
if (existing) return { result: { name: existing.name, adopted: false } };
|
|
213064
213217
|
const finalName = freeName(devices, name);
|
|
213065
|
-
const wanted = typeof input.id === "string" &&
|
|
213218
|
+
const wanted = typeof input.id === "string" && ID_RE4.test(input.id) ? input.id : void 0;
|
|
213066
213219
|
const idFree = wanted !== void 0 && !devices.some((d8) => d8.id === wanted || d8.ownerId === wanted);
|
|
213067
213220
|
const record2 = {
|
|
213068
213221
|
name: finalName,
|
|
@@ -213097,7 +213250,7 @@ async function revokeAdopted(tokenHash) {
|
|
|
213097
213250
|
if (out.revoked) log.web.info("device-adoption: twin pairing revoked", { name: record2.name, adoptedFrom: record2.adoptedFrom ?? null });
|
|
213098
213251
|
return out.revoked ? { name: record2.name, refused: false, push: out.push } : { name: null, refused: false, push: null };
|
|
213099
213252
|
}
|
|
213100
|
-
var AdoptionError, HASH_RE2,
|
|
213253
|
+
var AdoptionError, HASH_RE2, ID_RE4, INFO_FIELD_MAX2, NAME_MAX2;
|
|
213101
213254
|
var init_device_adoption = __esm({
|
|
213102
213255
|
"src/core/device-adoption.ts"() {
|
|
213103
213256
|
"use strict";
|
|
@@ -213115,7 +213268,7 @@ var init_device_adoption = __esm({
|
|
|
213115
213268
|
}
|
|
213116
213269
|
};
|
|
213117
213270
|
HASH_RE2 = /^[0-9a-f]{64}$/;
|
|
213118
|
-
|
|
213271
|
+
ID_RE4 = /^d[0-9a-f]{16}$/;
|
|
213119
213272
|
INFO_FIELD_MAX2 = 120;
|
|
213120
213273
|
NAME_MAX2 = 64;
|
|
213121
213274
|
}
|
|
@@ -242508,7 +242661,7 @@ async function saveRecordingAudio(audioBase64, format2) {
|
|
|
242508
242661
|
return { id, audioPath };
|
|
242509
242662
|
}
|
|
242510
242663
|
async function writeRecordingResult(id, meta) {
|
|
242511
|
-
if (!
|
|
242664
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
242512
242665
|
await mkdir7(dir3(), { recursive: true });
|
|
242513
242666
|
const stamped = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...meta };
|
|
242514
242667
|
await writeFile6(join16(dir3(), `${id}.json`), JSON.stringify(stamped, null, 2));
|
|
@@ -242517,7 +242670,7 @@ async function writeRecordingResult(id, meta) {
|
|
|
242517
242670
|
return stamped.timestamp;
|
|
242518
242671
|
}
|
|
242519
242672
|
async function writeRecordingSecondary(id, secondary, expectTimestamp) {
|
|
242520
|
-
if (!
|
|
242673
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
242521
242674
|
const path297 = join16(dir3(), `${id}.json`);
|
|
242522
242675
|
let existing;
|
|
242523
242676
|
try {
|
|
@@ -242539,7 +242692,7 @@ async function listRecordings(limit = 20) {
|
|
|
242539
242692
|
const out = [];
|
|
242540
242693
|
for (const jf of jsonFiles) {
|
|
242541
242694
|
const id = jf.slice(0, -5);
|
|
242542
|
-
if (!
|
|
242695
|
+
if (!ID_RE5.test(id)) continue;
|
|
242543
242696
|
try {
|
|
242544
242697
|
const raw = JSON.parse(await readFile8(join16(dir3(), jf), "utf-8"));
|
|
242545
242698
|
out.push({
|
|
@@ -242559,7 +242712,7 @@ async function listRecordings(limit = 20) {
|
|
|
242559
242712
|
return out;
|
|
242560
242713
|
}
|
|
242561
242714
|
async function readRecordingAudio(id) {
|
|
242562
|
-
if (!
|
|
242715
|
+
if (!ID_RE5.test(id)) return null;
|
|
242563
242716
|
let files;
|
|
242564
242717
|
try {
|
|
242565
242718
|
files = await readdir3(dir3());
|
|
@@ -242587,13 +242740,13 @@ async function pruneOldRecordings() {
|
|
|
242587
242740
|
}
|
|
242588
242741
|
}
|
|
242589
242742
|
}
|
|
242590
|
-
var MAX_RECORDINGS,
|
|
242743
|
+
var MAX_RECORDINGS, ID_RE5, AUDIO_EXTS;
|
|
242591
242744
|
var init_recordings = __esm({
|
|
242592
242745
|
"src/core/stt/recordings.ts"() {
|
|
242593
242746
|
"use strict";
|
|
242594
242747
|
init_constants();
|
|
242595
242748
|
MAX_RECORDINGS = 100;
|
|
242596
|
-
|
|
242749
|
+
ID_RE5 = /^[0-9A-Za-z-]+$/;
|
|
242597
242750
|
AUDIO_EXTS = ["webm", "mp4", "ogg", "wav", "mp3", "m4a", "flac"];
|
|
242598
242751
|
}
|
|
242599
242752
|
});
|
|
@@ -249241,6 +249394,147 @@ var init_task_v1 = __esm({
|
|
|
249241
249394
|
}
|
|
249242
249395
|
});
|
|
249243
249396
|
|
|
249397
|
+
// src/core/replication/kinds/requests.ts
|
|
249398
|
+
var requests_exports = {};
|
|
249399
|
+
__export(requests_exports, {
|
|
249400
|
+
REQUESTS_KIND: () => REQUESTS_KIND,
|
|
249401
|
+
REQUESTS_REMOVAL_FLOOR: () => REQUESTS_REMOVAL_FLOOR,
|
|
249402
|
+
REQUESTS_SCHEMA_VERSION: () => REQUESTS_SCHEMA_VERSION,
|
|
249403
|
+
_resetRequestsCopyForTesting: () => _resetRequestsCopyForTesting,
|
|
249404
|
+
forwardRequest: () => forwardRequest,
|
|
249405
|
+
readRequestCopy: () => readRequestCopy,
|
|
249406
|
+
requestsFollower: () => requestsFollower
|
|
249407
|
+
});
|
|
249408
|
+
import fsp124 from "fs/promises";
|
|
249409
|
+
import path233 from "path";
|
|
249410
|
+
function forwardRequest(local, incoming) {
|
|
249411
|
+
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
249412
|
+
return incoming;
|
|
249413
|
+
}
|
|
249414
|
+
function hashOf6(row) {
|
|
249415
|
+
let h8 = hashes5.get(row);
|
|
249416
|
+
if (h8 === void 0) {
|
|
249417
|
+
h8 = sha12(JSON.stringify(row));
|
|
249418
|
+
hashes5.set(row, h8);
|
|
249419
|
+
}
|
|
249420
|
+
return h8;
|
|
249421
|
+
}
|
|
249422
|
+
async function load6() {
|
|
249423
|
+
if (state11) return state11;
|
|
249424
|
+
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
249425
|
+
try {
|
|
249426
|
+
const raw = JSON.parse(await fsp124.readFile(STATE_FILE(), "utf8"));
|
|
249427
|
+
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 };
|
|
249428
|
+
} catch {
|
|
249429
|
+
}
|
|
249430
|
+
state11 = s4;
|
|
249431
|
+
return s4;
|
|
249432
|
+
}
|
|
249433
|
+
async function save() {
|
|
249434
|
+
if (state11) await writeCopyFile(STATE_FILE(), { v: 1, asOf: state11.asOf, at: state11.at, hashes: state11.hashes });
|
|
249435
|
+
}
|
|
249436
|
+
async function readStore8() {
|
|
249437
|
+
try {
|
|
249438
|
+
const raw = JSON.parse(await fsp124.readFile(STORE_FILE(), "utf8"));
|
|
249439
|
+
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
249440
|
+
} catch {
|
|
249441
|
+
return [];
|
|
249442
|
+
}
|
|
249443
|
+
}
|
|
249444
|
+
function isRow5(v3) {
|
|
249445
|
+
const r8 = v3;
|
|
249446
|
+
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
249447
|
+
}
|
|
249448
|
+
function requestsFollower() {
|
|
249449
|
+
follower3 ??= createRowSetFollower({
|
|
249450
|
+
kind: "requests",
|
|
249451
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
249452
|
+
label: "requests copy",
|
|
249453
|
+
log: log.session,
|
|
249454
|
+
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
249455
|
+
ordered: false,
|
|
249456
|
+
serial: (fn) => serial4(fn),
|
|
249457
|
+
refuse: copyRefusal,
|
|
249458
|
+
load: load6,
|
|
249459
|
+
save,
|
|
249460
|
+
isRow: isRow5,
|
|
249461
|
+
key: (r8) => r8.id,
|
|
249462
|
+
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
249463
|
+
apply: async ({ rows, removeIds }) => {
|
|
249464
|
+
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
249465
|
+
for (const id of removeIds ?? []) byId.delete(id);
|
|
249466
|
+
for (const r8 of rows ?? []) {
|
|
249467
|
+
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
249468
|
+
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 });
|
|
249469
|
+
byId.set(r8.id, kept);
|
|
249470
|
+
}
|
|
249471
|
+
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
249472
|
+
return { skipped: [] };
|
|
249473
|
+
},
|
|
249474
|
+
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
249475
|
+
changed: () => {
|
|
249476
|
+
},
|
|
249477
|
+
purge: async () => {
|
|
249478
|
+
const removed = (await readStore8()).length;
|
|
249479
|
+
await fsp124.rm(STORE_FILE(), { force: true });
|
|
249480
|
+
await markCopyOff("requests");
|
|
249481
|
+
state11 = null;
|
|
249482
|
+
return { removed };
|
|
249483
|
+
}
|
|
249484
|
+
});
|
|
249485
|
+
return follower3;
|
|
249486
|
+
}
|
|
249487
|
+
async function readRequestCopy(id) {
|
|
249488
|
+
if (!await copyKindHeld("requests")) return null;
|
|
249489
|
+
return (await readStore8()).find((r8) => r8.id === id) ?? null;
|
|
249490
|
+
}
|
|
249491
|
+
function _resetRequestsCopyForTesting() {
|
|
249492
|
+
state11 = null;
|
|
249493
|
+
follower3 = null;
|
|
249494
|
+
serial4 = serialChain();
|
|
249495
|
+
}
|
|
249496
|
+
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes5, REQUESTS_KIND, STATE_FILE, STORE_FILE, state11, serial4, follower3;
|
|
249497
|
+
var init_requests = __esm({
|
|
249498
|
+
"src/core/replication/kinds/requests.ts"() {
|
|
249499
|
+
"use strict";
|
|
249500
|
+
init_constants();
|
|
249501
|
+
init_logging();
|
|
249502
|
+
init_kind();
|
|
249503
|
+
init_kind_follower();
|
|
249504
|
+
init_gate();
|
|
249505
|
+
REQUESTS_SCHEMA_VERSION = 1;
|
|
249506
|
+
REQUESTS_REMOVAL_FLOOR = 50;
|
|
249507
|
+
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
249508
|
+
hashes5 = /* @__PURE__ */ new WeakMap();
|
|
249509
|
+
REQUESTS_KIND = {
|
|
249510
|
+
kind: "requests",
|
|
249511
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
249512
|
+
key: (r8) => r8.id,
|
|
249513
|
+
hash: hashOf6,
|
|
249514
|
+
ordered: false,
|
|
249515
|
+
digest: false,
|
|
249516
|
+
choice: "requests",
|
|
249517
|
+
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
249518
|
+
watch: (soon) => {
|
|
249519
|
+
let stop2 = null;
|
|
249520
|
+
let stopped2 = false;
|
|
249521
|
+
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
249522
|
+
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
249523
|
+
});
|
|
249524
|
+
return () => {
|
|
249525
|
+
stopped2 = true;
|
|
249526
|
+
stop2?.();
|
|
249527
|
+
};
|
|
249528
|
+
}
|
|
249529
|
+
};
|
|
249530
|
+
STATE_FILE = () => path233.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
249531
|
+
STORE_FILE = () => copyPath(path233.join(WALNUT_HOME, "session-requests.json"));
|
|
249532
|
+
state11 = null;
|
|
249533
|
+
serial4 = serialChain();
|
|
249534
|
+
follower3 = null;
|
|
249535
|
+
}
|
|
249536
|
+
});
|
|
249537
|
+
|
|
249244
249538
|
// src/web/routes/messages-v1.ts
|
|
249245
249539
|
import { Router as Router82 } from "express";
|
|
249246
249540
|
function header(req, name) {
|
|
@@ -249301,7 +249595,15 @@ var init_messages_v1 = __esm({
|
|
|
249301
249595
|
return;
|
|
249302
249596
|
}
|
|
249303
249597
|
const { getSessionRequest: getSessionRequest2 } = await Promise.resolve().then(() => (init_session_requests(), session_requests_exports));
|
|
249304
|
-
|
|
249598
|
+
let request3 = await getSessionRequest2(id);
|
|
249599
|
+
if (!request3) {
|
|
249600
|
+
const [{ readRequestCopy: readRequestCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
249601
|
+
Promise.resolve().then(() => (init_requests(), requests_exports)),
|
|
249602
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
249603
|
+
]);
|
|
249604
|
+
request3 = await readRequestCopy2(id) ?? void 0;
|
|
249605
|
+
if (request3) res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("requests") ?? 0));
|
|
249606
|
+
}
|
|
249305
249607
|
if (!request3) {
|
|
249306
249608
|
sendV1Error(res, 404, "not_found", `No such request: ${id}`);
|
|
249307
249609
|
return;
|
|
@@ -250976,6 +251278,17 @@ var init_search_memory_v1 = __esm({
|
|
|
250976
251278
|
});
|
|
250977
251279
|
searchMemoryV1Router.get("/favorites", async (_req, res, next) => {
|
|
250978
251280
|
try {
|
|
251281
|
+
const [{ readFavoritesCopy: readFavoritesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
251282
|
+
Promise.resolve().then(() => (init_prefs(), prefs_exports)),
|
|
251283
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
251284
|
+
]);
|
|
251285
|
+
const asOf2 = await copyKindAsOf2("prefs");
|
|
251286
|
+
const fav = asOf2 === null ? null : await readFavoritesCopy2();
|
|
251287
|
+
if (fav) {
|
|
251288
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(asOf2));
|
|
251289
|
+
res.json({ projects: fav.projects ?? [], notes: fav.notes ?? [] });
|
|
251290
|
+
return;
|
|
251291
|
+
}
|
|
250979
251292
|
const { readFavorites: readFavorites2 } = await Promise.resolve().then(() => (init_favorites(), favorites_exports));
|
|
250980
251293
|
res.json(await readFavorites2());
|
|
250981
251294
|
} catch (err2) {
|
|
@@ -252008,9 +252321,9 @@ var init_stt_v1 = __esm({
|
|
|
252008
252321
|
|
|
252009
252322
|
// src/web/routes/pastes.ts
|
|
252010
252323
|
import { Router as Router89 } from "express";
|
|
252011
|
-
import
|
|
252324
|
+
import path234 from "path";
|
|
252012
252325
|
import { createHash as createHash38 } from "crypto";
|
|
252013
|
-
import
|
|
252326
|
+
import fsp125 from "fs/promises";
|
|
252014
252327
|
var pastesRouter, MAX_PASTE_CHARS;
|
|
252015
252328
|
var init_pastes = __esm({
|
|
252016
252329
|
"src/web/routes/pastes.ts"() {
|
|
@@ -252030,11 +252343,11 @@ var init_pastes = __esm({
|
|
|
252030
252343
|
res.status(413).json({ error: `Paste too large (max ${MAX_PASTE_CHARS} chars)` });
|
|
252031
252344
|
return;
|
|
252032
252345
|
}
|
|
252033
|
-
await
|
|
252346
|
+
await fsp125.mkdir(PASTES_DIR, { recursive: true });
|
|
252034
252347
|
const hash3 = createHash38("sha256").update(text5).digest("hex").slice(0, 12);
|
|
252035
252348
|
const filename = `${Date.now()}-${hash3}.txt`;
|
|
252036
|
-
const filePath =
|
|
252037
|
-
await
|
|
252349
|
+
const filePath = path234.join(PASTES_DIR, filename);
|
|
252350
|
+
await fsp125.writeFile(filePath, text5, "utf8");
|
|
252038
252351
|
log.web.info("paste spilled to disk", { filePath, chars: text5.length });
|
|
252039
252352
|
res.json({ path: filePath, filename, chars: text5.length });
|
|
252040
252353
|
} catch (err2) {
|
|
@@ -252050,8 +252363,8 @@ __export(file_content_replica_copy_exports, {
|
|
|
252050
252363
|
primaryDataDirRelPath: () => primaryDataDirRelPath,
|
|
252051
252364
|
resolveReplicaCopy: () => resolveReplicaCopy
|
|
252052
252365
|
});
|
|
252053
|
-
import
|
|
252054
|
-
import
|
|
252366
|
+
import path235 from "path";
|
|
252367
|
+
import fsp126 from "fs/promises";
|
|
252055
252368
|
function dataDirIndex(parts, tilde) {
|
|
252056
252369
|
if (tilde) return parts[1] === DATA_DIR_NAME ? 1 : -1;
|
|
252057
252370
|
if ((parts[0] === "Users" || parts[0] === "home") && parts[2] === DATA_DIR_NAME) return 2;
|
|
@@ -252081,12 +252394,12 @@ async function resolveReplicaCopy(requestPath) {
|
|
|
252081
252394
|
const rel = primaryDataDirRelPath(requestPath);
|
|
252082
252395
|
if (rel === null || deniedName(rel)) return null;
|
|
252083
252396
|
try {
|
|
252084
|
-
const root6 = await
|
|
252085
|
-
const real = await
|
|
252086
|
-
if (!real.startsWith(root6 +
|
|
252087
|
-
const realRel =
|
|
252088
|
-
if (isSecretPath(
|
|
252089
|
-
const st2 = await
|
|
252397
|
+
const root6 = await fsp126.realpath(WALNUT_HOME);
|
|
252398
|
+
const real = await fsp126.realpath(path235.join(WALNUT_HOME, rel));
|
|
252399
|
+
if (!real.startsWith(root6 + path235.sep)) return null;
|
|
252400
|
+
const realRel = path235.relative(root6, real).split(path235.sep).join("/");
|
|
252401
|
+
if (isSecretPath(path235.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
|
|
252402
|
+
const st2 = await fsp126.stat(real);
|
|
252090
252403
|
if (!st2.isFile()) return null;
|
|
252091
252404
|
if (!await isTracked(root6, realRel)) return null;
|
|
252092
252405
|
return { localPath: real, size: st2.size };
|
|
@@ -252126,11 +252439,11 @@ var init_file_content_replica_copy = __esm({
|
|
|
252126
252439
|
// src/web/routes/media-v1.ts
|
|
252127
252440
|
import { Router as Router90 } from "express";
|
|
252128
252441
|
import crypto67 from "crypto";
|
|
252129
|
-
import
|
|
252130
|
-
import
|
|
252442
|
+
import path236 from "path";
|
|
252443
|
+
import fsp127 from "fs/promises";
|
|
252131
252444
|
function cachePathFor(host, filePath) {
|
|
252132
252445
|
const hash3 = crypto67.createHash("sha256").update(filePath).digest("hex").slice(0, 16);
|
|
252133
|
-
return
|
|
252446
|
+
return path236.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path236.basename(filePath)}`);
|
|
252134
252447
|
}
|
|
252135
252448
|
async function hostForSession(sessionId) {
|
|
252136
252449
|
if (CLOUD_MODE) {
|
|
@@ -252195,11 +252508,11 @@ var init_media_v1 = __esm({
|
|
|
252195
252508
|
try {
|
|
252196
252509
|
const filePath = req.query.path;
|
|
252197
252510
|
const session2 = typeof req.query.session === "string" && SID_RE6.test(req.query.session) ? req.query.session : void 0;
|
|
252198
|
-
if (!filePath || typeof filePath !== "string" || !
|
|
252511
|
+
if (!filePath || typeof filePath !== "string" || !path236.isAbsolute(filePath) || filePath.includes("..")) {
|
|
252199
252512
|
res.status(400).json({ error: { code: "bad_request", message: "path must be an absolute file path" } });
|
|
252200
252513
|
return;
|
|
252201
252514
|
}
|
|
252202
|
-
const ext2 =
|
|
252515
|
+
const ext2 = path236.extname(filePath).slice(1).toLowerCase();
|
|
252203
252516
|
const mime = EXT_TO_MIME3[ext2];
|
|
252204
252517
|
if (!mime) {
|
|
252205
252518
|
res.status(400).json({ error: { code: "bad_request", message: "file type not allowed" } });
|
|
@@ -252207,8 +252520,8 @@ var init_media_v1 = __esm({
|
|
|
252207
252520
|
}
|
|
252208
252521
|
let buffer2 = null;
|
|
252209
252522
|
try {
|
|
252210
|
-
const st2 = await
|
|
252211
|
-
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
252523
|
+
const st2 = await fsp127.stat(filePath);
|
|
252524
|
+
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(filePath);
|
|
252212
252525
|
} catch {
|
|
252213
252526
|
}
|
|
252214
252527
|
let waitedOnPending = false;
|
|
@@ -252229,8 +252542,8 @@ var init_media_v1 = __esm({
|
|
|
252229
252542
|
if (buffer2) {
|
|
252230
252543
|
try {
|
|
252231
252544
|
const cachePath3 = cachePathFor(host, filePath);
|
|
252232
|
-
await
|
|
252233
|
-
await
|
|
252545
|
+
await fsp127.mkdir(path236.dirname(cachePath3), { recursive: true });
|
|
252546
|
+
await fsp127.writeFile(cachePath3, buffer2);
|
|
252234
252547
|
} catch {
|
|
252235
252548
|
}
|
|
252236
252549
|
break;
|
|
@@ -252240,9 +252553,9 @@ var init_media_v1 = __esm({
|
|
|
252240
252553
|
for (const host of hosts2) {
|
|
252241
252554
|
try {
|
|
252242
252555
|
const cached8 = cachePathFor(host, filePath);
|
|
252243
|
-
const st2 = await
|
|
252556
|
+
const st2 = await fsp127.stat(cached8);
|
|
252244
252557
|
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) {
|
|
252245
|
-
buffer2 = await
|
|
252558
|
+
buffer2 = await fsp127.readFile(cached8);
|
|
252246
252559
|
break;
|
|
252247
252560
|
}
|
|
252248
252561
|
} catch {
|
|
@@ -252252,7 +252565,7 @@ var init_media_v1 = __esm({
|
|
|
252252
252565
|
if (!buffer2 && hosts2.length > 0 && hosts2.every((h8) => h8 === "__local__") && !(await Promise.resolve().then(() => (init_bridge_registry(), bridge_registry_exports))).bridgeForHost("__local__").connected) {
|
|
252253
252566
|
const { resolveReplicaCopy: resolveReplicaCopy2 } = await Promise.resolve().then(() => (init_file_content_replica_copy(), file_content_replica_copy_exports));
|
|
252254
252567
|
const copy5 = await resolveReplicaCopy2(filePath);
|
|
252255
|
-
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
252568
|
+
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(copy5.localPath);
|
|
252256
252569
|
}
|
|
252257
252570
|
}
|
|
252258
252571
|
if (!buffer2) {
|
|
@@ -252277,6 +252590,19 @@ var init_media_v1 = __esm({
|
|
|
252277
252590
|
|
|
252278
252591
|
// src/web/routes/routines-v1.ts
|
|
252279
252592
|
import { Router as Router91 } from "express";
|
|
252593
|
+
async function answeredFromCopy(res, includeDisabled, answer5) {
|
|
252594
|
+
const [{ companionRoutinesCopy: companionRoutinesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
252595
|
+
Promise.resolve().then(() => (init_routines_follower(), routines_follower_exports)),
|
|
252596
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
252597
|
+
]);
|
|
252598
|
+
const jobs2 = await companionRoutinesCopy2({ includeDisabled });
|
|
252599
|
+
if (!jobs2) return false;
|
|
252600
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("routines") ?? 0));
|
|
252601
|
+
const body7 = answer5(jobs2);
|
|
252602
|
+
if (body7 === null) sendV1Error(res, 404, "not_found", "No such routine in the copy of your Mac's routines");
|
|
252603
|
+
else res.json(body7);
|
|
252604
|
+
return true;
|
|
252605
|
+
}
|
|
252280
252606
|
function validRid(req, res) {
|
|
252281
252607
|
const id = String(req.params.id ?? "");
|
|
252282
252608
|
if (!RID_RE.test(id)) {
|
|
@@ -252323,6 +252649,7 @@ var init_routines_v1 = __esm({
|
|
|
252323
252649
|
try {
|
|
252324
252650
|
const includeDisabled = req.query.includeDisabled === "true";
|
|
252325
252651
|
if (CLOUD_MODE) {
|
|
252652
|
+
if (await answeredFromCopy(res, includeDisabled, (jobs2) => ({ jobs: jobs2 }))) return;
|
|
252326
252653
|
await relayControlAction(res, "server.routines", SERVER_RELAY_SID14, { includeDisabled }, 200);
|
|
252327
252654
|
return;
|
|
252328
252655
|
}
|
|
@@ -252347,6 +252674,7 @@ var init_routines_v1 = __esm({
|
|
|
252347
252674
|
routinesV1Router.get("/routines/status", async (_req, res, next) => {
|
|
252348
252675
|
try {
|
|
252349
252676
|
if (CLOUD_MODE) {
|
|
252677
|
+
if (await answeredFromCopy(res, true, (jobs2) => ({ enabled: false, storePath: "", jobs: jobs2.length, nextWakeAtMs: null }))) return;
|
|
252350
252678
|
await relayControlAction(res, "server.routines.status", SERVER_RELAY_SID14, void 0, 200);
|
|
252351
252679
|
return;
|
|
252352
252680
|
}
|
|
@@ -252418,6 +252746,10 @@ var init_routines_v1 = __esm({
|
|
|
252418
252746
|
const id = validRid(req, res);
|
|
252419
252747
|
if (!id) return;
|
|
252420
252748
|
if (CLOUD_MODE) {
|
|
252749
|
+
if (await answeredFromCopy(res, true, (jobs2) => {
|
|
252750
|
+
const job2 = jobs2.find((j8) => j8.id === id);
|
|
252751
|
+
return job2 ? { job: job2 } : null;
|
|
252752
|
+
})) return;
|
|
252421
252753
|
await relayControlAction(res, "server.routines.get", SERVER_RELAY_SID14, { id }, 200);
|
|
252422
252754
|
return;
|
|
252423
252755
|
}
|
|
@@ -253612,8 +253944,8 @@ __export(file_content_bridge_exports, {
|
|
|
253612
253944
|
resolveBridgeHost: () => resolveBridgeHost,
|
|
253613
253945
|
serveCloudFileContent: () => serveCloudFileContent
|
|
253614
253946
|
});
|
|
253615
|
-
import
|
|
253616
|
-
import
|
|
253947
|
+
import path237 from "path";
|
|
253948
|
+
import fsp128 from "fs/promises";
|
|
253617
253949
|
function resolveBridgeHost(host) {
|
|
253618
253950
|
return typeof host === "string" && host.length > 0 ? host : PRIMARY_BRIDGE_ALIAS4;
|
|
253619
253951
|
}
|
|
@@ -253684,7 +254016,7 @@ function precheckPath(res, rawPath) {
|
|
|
253684
254016
|
sendV1Error(res, 400, "bad_request", "Invalid path");
|
|
253685
254017
|
return null;
|
|
253686
254018
|
}
|
|
253687
|
-
if (rawPath !== "~" && !rawPath.startsWith("~/") && !
|
|
254019
|
+
if (rawPath !== "~" && !rawPath.startsWith("~/") && !path237.isAbsolute(rawPath)) {
|
|
253688
254020
|
sendV1Error(res, 400, "bad_request", "Path must be absolute");
|
|
253689
254021
|
return null;
|
|
253690
254022
|
}
|
|
@@ -253728,7 +254060,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
253728
254060
|
const hostAlias2 = resolveBridgeHost(req.query.host);
|
|
253729
254061
|
const raw = req.query.raw === "1" || req.query.raw === "true";
|
|
253730
254062
|
const download = req.query.download === "1" || req.query.download === "true";
|
|
253731
|
-
const ext2 =
|
|
254063
|
+
const ext2 = path237.extname(filePath).slice(1).toLowerCase();
|
|
253732
254064
|
const {
|
|
253733
254065
|
assertPathAllowed: assertPathAllowed2,
|
|
253734
254066
|
isSecretPath: isSecretPath2,
|
|
@@ -253738,7 +254070,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
253738
254070
|
FileContentError: FileContentError2
|
|
253739
254071
|
} = await Promise.resolve().then(() => (init_file_content(), file_content_exports));
|
|
253740
254072
|
const explicitHost = typeof req.query.host === "string" && req.query.host.length > 0;
|
|
253741
|
-
const locallyPresent = await
|
|
254073
|
+
const locallyPresent = await fsp128.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
|
|
253742
254074
|
if (!explicitHost && locallyPresent && cloudLocalReadAllowed2(filePath) && !isSecretPath2(filePath)) {
|
|
253743
254075
|
try {
|
|
253744
254076
|
if (raw) {
|
|
@@ -253836,10 +254168,10 @@ async function serveReplicaCopy(req, res, requestPath, copy5, opts2) {
|
|
|
253836
254168
|
return;
|
|
253837
254169
|
}
|
|
253838
254170
|
if (copy5.size <= MAX_BRIDGE_FILE_BYTES) {
|
|
253839
|
-
res.json(jsonPayloadFromBuffer(await
|
|
254171
|
+
res.json(jsonPayloadFromBuffer(await fsp128.readFile(copy5.localPath), opts2.ext, false));
|
|
253840
254172
|
return;
|
|
253841
254173
|
}
|
|
253842
|
-
const fh = await
|
|
254174
|
+
const fh = await fsp128.open(copy5.localPath, "r");
|
|
253843
254175
|
try {
|
|
253844
254176
|
const head2 = Buffer.alloc(MAX_TEXT_PAYLOAD);
|
|
253845
254177
|
const { bytesRead } = await fh.read(head2, 0, head2.length, 0);
|
|
@@ -254913,17 +255245,17 @@ __export(checklist_io_exports, {
|
|
|
254913
255245
|
readHeartbeatChecklist: () => readHeartbeatChecklist,
|
|
254914
255246
|
writeHeartbeatChecklist: () => writeHeartbeatChecklist
|
|
254915
255247
|
});
|
|
254916
|
-
import
|
|
255248
|
+
import fsp129 from "fs/promises";
|
|
254917
255249
|
async function readHeartbeatChecklist() {
|
|
254918
255250
|
try {
|
|
254919
|
-
return await
|
|
255251
|
+
return await fsp129.readFile(HEARTBEAT_FILE, "utf-8");
|
|
254920
255252
|
} catch (err2) {
|
|
254921
255253
|
if (err2.code === "ENOENT") return "";
|
|
254922
255254
|
throw err2;
|
|
254923
255255
|
}
|
|
254924
255256
|
}
|
|
254925
255257
|
async function writeHeartbeatChecklist(content) {
|
|
254926
|
-
await
|
|
255258
|
+
await fsp129.writeFile(HEARTBEAT_FILE, content, "utf-8");
|
|
254927
255259
|
}
|
|
254928
255260
|
var init_checklist_io = __esm({
|
|
254929
255261
|
"src/heartbeat/checklist-io.ts"() {
|
|
@@ -257063,11 +257395,11 @@ __export(ephemeral_guard_exports, {
|
|
|
257063
257395
|
});
|
|
257064
257396
|
import fs127 from "fs";
|
|
257065
257397
|
import os60 from "os";
|
|
257066
|
-
import
|
|
257398
|
+
import path238 from "path";
|
|
257067
257399
|
function productionWalnutHomes() {
|
|
257068
257400
|
const homes = /* @__PURE__ */ new Set();
|
|
257069
257401
|
const add3 = (home) => {
|
|
257070
|
-
if (home) homes.add(
|
|
257402
|
+
if (home) homes.add(path238.join(home, ".open-walnut"));
|
|
257071
257403
|
};
|
|
257072
257404
|
add3(os60.homedir());
|
|
257073
257405
|
try {
|
|
@@ -257077,7 +257409,7 @@ function productionWalnutHomes() {
|
|
|
257077
257409
|
return [...homes];
|
|
257078
257410
|
}
|
|
257079
257411
|
function canonical2(dir4) {
|
|
257080
|
-
const resolved =
|
|
257412
|
+
const resolved = path238.resolve(dir4);
|
|
257081
257413
|
try {
|
|
257082
257414
|
return fs127.realpathSync(resolved);
|
|
257083
257415
|
} catch {
|
|
@@ -257113,28 +257445,28 @@ __export(boot_guard_exports, {
|
|
|
257113
257445
|
});
|
|
257114
257446
|
import fs128 from "fs";
|
|
257115
257447
|
import os61 from "os";
|
|
257116
|
-
import
|
|
257448
|
+
import path239 from "path";
|
|
257117
257449
|
function canonical3(dir4) {
|
|
257118
|
-
let head2 =
|
|
257450
|
+
let head2 = path239.resolve(dir4);
|
|
257119
257451
|
const rest = [];
|
|
257120
257452
|
for (; ; ) {
|
|
257121
257453
|
try {
|
|
257122
|
-
return
|
|
257454
|
+
return path239.join(fs128.realpathSync(head2), ...rest);
|
|
257123
257455
|
} catch {
|
|
257124
257456
|
}
|
|
257125
|
-
const up =
|
|
257126
|
-
if (up === head2) return
|
|
257127
|
-
rest.unshift(
|
|
257457
|
+
const up = path239.dirname(head2);
|
|
257458
|
+
if (up === head2) return path239.resolve(dir4);
|
|
257459
|
+
rest.unshift(path239.basename(head2));
|
|
257128
257460
|
head2 = up;
|
|
257129
257461
|
}
|
|
257130
257462
|
}
|
|
257131
257463
|
function spellings(dir4) {
|
|
257132
|
-
const resolved =
|
|
257464
|
+
const resolved = path239.resolve(dir4);
|
|
257133
257465
|
return [.../* @__PURE__ */ new Set([resolved, canonical3(resolved), `/private${resolved}`])];
|
|
257134
257466
|
}
|
|
257135
257467
|
function within5(child2, parent) {
|
|
257136
|
-
const rel =
|
|
257137
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
257468
|
+
const rel = path239.relative(parent, child2);
|
|
257469
|
+
return rel === "" || !rel.startsWith("..") && !path239.isAbsolute(rel);
|
|
257138
257470
|
}
|
|
257139
257471
|
function overlaps(a8, b8) {
|
|
257140
257472
|
return spellings(a8).some((x3) => spellings(b8).some((y3) => within5(x3, y3) || within5(y3, x3)));
|
|
@@ -257145,7 +257477,7 @@ function holdsOrIs(outer, inner2) {
|
|
|
257145
257477
|
function accountHomes(env3) {
|
|
257146
257478
|
const homes = /* @__PURE__ */ new Set();
|
|
257147
257479
|
const add3 = (h8) => {
|
|
257148
|
-
if (h8 && h8.trim()) homes.add(
|
|
257480
|
+
if (h8 && h8.trim()) homes.add(path239.resolve(h8.trim()));
|
|
257149
257481
|
};
|
|
257150
257482
|
add3(env3.HOME);
|
|
257151
257483
|
add3(os61.homedir());
|
|
@@ -257203,7 +257535,7 @@ function assertReplicaBootSafe(input) {
|
|
|
257203
257535
|
if (why2) throw new Error(`Host replica refused to start: ${why2}.`);
|
|
257204
257536
|
}
|
|
257205
257537
|
function claimReplicaDir(dir4) {
|
|
257206
|
-
const marker =
|
|
257538
|
+
const marker = path239.join(dir4, REPLICA_DIR_MARKER);
|
|
257207
257539
|
try {
|
|
257208
257540
|
return fs128.lstatSync(marker).isFile();
|
|
257209
257541
|
} catch {
|
|
@@ -257228,7 +257560,7 @@ function claimReplicaDir(dir4) {
|
|
|
257228
257560
|
function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
257229
257561
|
const marked = dirs2.filter((d8) => {
|
|
257230
257562
|
try {
|
|
257231
|
-
return fs128.lstatSync(
|
|
257563
|
+
return fs128.lstatSync(path239.join(d8, REPLICA_DIR_MARKER)).isFile();
|
|
257232
257564
|
} catch {
|
|
257233
257565
|
return false;
|
|
257234
257566
|
}
|
|
@@ -257258,7 +257590,7 @@ function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
|
257258
257590
|
} catch {
|
|
257259
257591
|
return;
|
|
257260
257592
|
}
|
|
257261
|
-
for (const n6 of names2) visit(
|
|
257593
|
+
for (const n6 of names2) visit(path239.join(p6, n6));
|
|
257262
257594
|
} else if (st2.isFile() && (st2.mode & 63) !== 0) {
|
|
257263
257595
|
try {
|
|
257264
257596
|
fs128.chmodSync(p6, st2.mode & 448 | 384);
|
|
@@ -257445,29 +257777,29 @@ __export(search_replica_store_exports, {
|
|
|
257445
257777
|
searchReplicaSync: () => searchReplicaSync,
|
|
257446
257778
|
startSearchReplicaStore: () => startSearchReplicaStore
|
|
257447
257779
|
});
|
|
257448
|
-
import
|
|
257780
|
+
import fsp130 from "fs/promises";
|
|
257449
257781
|
import os62 from "os";
|
|
257450
|
-
import
|
|
257782
|
+
import path240 from "path";
|
|
257451
257783
|
async function wiring() {
|
|
257452
257784
|
return Promise.resolve().then(() => (init_wiring(), wiring_exports));
|
|
257453
257785
|
}
|
|
257454
257786
|
async function loadState() {
|
|
257455
|
-
if (
|
|
257787
|
+
if (state12) return state12;
|
|
257456
257788
|
let s4 = { v: 1, mode: null, syncedAt: null };
|
|
257457
257789
|
try {
|
|
257458
|
-
const raw = JSON.parse(await
|
|
257790
|
+
const raw = JSON.parse(await fsp130.readFile(STATE_FILE2(), "utf8"));
|
|
257459
257791
|
if (raw && raw.v === 1) {
|
|
257460
257792
|
s4 = { v: 1, mode: raw.mode ? companionSearchMode(raw.mode) : null, syncedAt: typeof raw.syncedAt === "number" ? raw.syncedAt : null };
|
|
257461
257793
|
}
|
|
257462
257794
|
} catch {
|
|
257463
257795
|
}
|
|
257464
|
-
|
|
257796
|
+
state12 = s4;
|
|
257465
257797
|
return s4;
|
|
257466
257798
|
}
|
|
257467
257799
|
async function saveState() {
|
|
257468
|
-
if (
|
|
257800
|
+
if (state12) await writeJsonFile(STATE_FILE2(), state12);
|
|
257469
257801
|
}
|
|
257470
|
-
function
|
|
257802
|
+
function serial5(fn) {
|
|
257471
257803
|
const run12 = chain4.then(fn, fn);
|
|
257472
257804
|
chain4 = run12.catch(() => {
|
|
257473
257805
|
});
|
|
@@ -257531,8 +257863,8 @@ async function closeIndex() {
|
|
|
257531
257863
|
allDirty2 = true;
|
|
257532
257864
|
}
|
|
257533
257865
|
function publishReady() {
|
|
257534
|
-
const ready2 = enabled && mapBuilt && map3.size > 0 &&
|
|
257535
|
-
setCompanionSearchReady(ready2, ready2 ?
|
|
257866
|
+
const ready2 = enabled && mapBuilt && map3.size > 0 && state12?.syncedAt != null;
|
|
257867
|
+
setCompanionSearchReady(ready2, ready2 ? state12.syncedAt : null);
|
|
257536
257868
|
}
|
|
257537
257869
|
async function markInSync() {
|
|
257538
257870
|
const s4 = await loadState();
|
|
@@ -257559,7 +257891,7 @@ async function warm(why2) {
|
|
|
257559
257891
|
}
|
|
257560
257892
|
}
|
|
257561
257893
|
function searchReplicaStatus(body7) {
|
|
257562
|
-
return
|
|
257894
|
+
return serial5(async () => {
|
|
257563
257895
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
257564
257896
|
const s4 = await loadState();
|
|
257565
257897
|
const mode = companionSearchMode(body7.mode);
|
|
@@ -257607,7 +257939,7 @@ function searchReplicaStatus(body7) {
|
|
|
257607
257939
|
});
|
|
257608
257940
|
}
|
|
257609
257941
|
function searchReplicaSync(body7) {
|
|
257610
|
-
return
|
|
257942
|
+
return serial5(async () => {
|
|
257611
257943
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
257612
257944
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
257613
257945
|
if (!Array.isArray(body7.entries)) return { ok: false, status: 400, error: "bad_entries" };
|
|
@@ -257652,7 +257984,7 @@ async function forgetSearchMemo() {
|
|
|
257652
257984
|
}
|
|
257653
257985
|
}
|
|
257654
257986
|
function searchReplicaPut(body7) {
|
|
257655
|
-
return
|
|
257987
|
+
return serial5(async () => {
|
|
257656
257988
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
257657
257989
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
257658
257990
|
if (!Array.isArray(body7.docs)) return { ok: false, status: 400, error: "bad_docs" };
|
|
@@ -257718,7 +258050,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
257718
258050
|
if (!s4.mode || stopped2) return;
|
|
257719
258051
|
const decision = companionSearchDecision(s4.mode, deps3.totalMb());
|
|
257720
258052
|
if (!decision.enabled) return;
|
|
257721
|
-
await
|
|
258053
|
+
await serial5(async () => {
|
|
257722
258054
|
enabled = true;
|
|
257723
258055
|
reason2 = decision.reason;
|
|
257724
258056
|
await refreshMap2(await openIndex());
|
|
@@ -257751,12 +258083,12 @@ function startSearchReplicaStore(options = {}) {
|
|
|
257751
258083
|
}));
|
|
257752
258084
|
}).catch((err2) => log.memory.warn("search replica: local writes not wired", { error: err2 instanceof Error ? err2.message : String(err2) }));
|
|
257753
258085
|
unsubs.push(onLeaderPresence((answers4) => {
|
|
257754
|
-
if (stopped2 || answers4 || !enabled ||
|
|
258086
|
+
if (stopped2 || answers4 || !enabled || state12?.syncedAt == null) return;
|
|
257755
258087
|
void warm("leader away");
|
|
257756
258088
|
}));
|
|
257757
258089
|
const tick = setInterval(() => {
|
|
257758
258090
|
void (async () => {
|
|
257759
|
-
if (stopped2 || !enabled ||
|
|
258091
|
+
if (stopped2 || !enabled || state12?.syncedAt == null) return;
|
|
257760
258092
|
if (Date.now() - lastWarmAt < WARM_EVERY_MS) return;
|
|
257761
258093
|
if (!await deps3.macAway()) return;
|
|
257762
258094
|
await warm("mac away");
|
|
@@ -257775,7 +258107,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
257775
258107
|
};
|
|
257776
258108
|
}
|
|
257777
258109
|
function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
257778
|
-
|
|
258110
|
+
state12 = null;
|
|
257779
258111
|
enabled = false;
|
|
257780
258112
|
reason2 = "off";
|
|
257781
258113
|
map3.clear();
|
|
@@ -257790,7 +258122,7 @@ function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
|
257790
258122
|
deps3 = { totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)), macAway: defaultMacAway, ...overrides };
|
|
257791
258123
|
setCompanionSearchReady(false, null);
|
|
257792
258124
|
}
|
|
257793
|
-
var
|
|
258125
|
+
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;
|
|
257794
258126
|
var init_search_replica_store = __esm({
|
|
257795
258127
|
"src/core/replication/search-replica-store.ts"() {
|
|
257796
258128
|
"use strict";
|
|
@@ -257802,7 +258134,7 @@ var init_search_replica_store = __esm({
|
|
|
257802
258134
|
init_replica_refs();
|
|
257803
258135
|
init_search_digest();
|
|
257804
258136
|
init_search_replica_wire();
|
|
257805
|
-
|
|
258137
|
+
STATE_FILE2 = () => path240.join(WALNUT_HOME, "cache", "search-replica.json");
|
|
257806
258138
|
MASS_REMOVE_FLOOR = 200;
|
|
257807
258139
|
SCAN_SLICE2 = 500;
|
|
257808
258140
|
WARM_EVERY_MS = 4 * 6e4;
|
|
@@ -257812,7 +258144,7 @@ var init_search_replica_store = __esm({
|
|
|
257812
258144
|
totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)),
|
|
257813
258145
|
macAway: defaultMacAway
|
|
257814
258146
|
};
|
|
257815
|
-
|
|
258147
|
+
state12 = null;
|
|
257816
258148
|
enabled = false;
|
|
257817
258149
|
reason2 = "off";
|
|
257818
258150
|
map3 = new DigestMap();
|
|
@@ -257828,10 +258160,10 @@ var init_search_replica_store = __esm({
|
|
|
257828
258160
|
});
|
|
257829
258161
|
|
|
257830
258162
|
// src/core/replication/kinds/boards.ts
|
|
257831
|
-
import
|
|
257832
|
-
import
|
|
258163
|
+
import fsp131 from "fs/promises";
|
|
258164
|
+
import path241 from "path";
|
|
257833
258165
|
async function leaderBoards(dir4 = boardsDir2()) {
|
|
257834
|
-
const names2 = await
|
|
258166
|
+
const names2 = await fsp131.readdir(dir4).catch(() => []);
|
|
257835
258167
|
const out = [];
|
|
257836
258168
|
const unreadable = [];
|
|
257837
258169
|
const seen2 = /* @__PURE__ */ new Set();
|
|
@@ -257840,9 +258172,9 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
257840
258172
|
const id = name.slice(0, -".json".length);
|
|
257841
258173
|
if (!TASK_ID_RE3.test(id)) continue;
|
|
257842
258174
|
seen2.add(id);
|
|
257843
|
-
const file =
|
|
258175
|
+
const file = path241.join(dir4, name);
|
|
257844
258176
|
try {
|
|
257845
|
-
const st2 = await
|
|
258177
|
+
const st2 = await fsp131.stat(file);
|
|
257846
258178
|
if (!st2.isFile()) continue;
|
|
257847
258179
|
if (st2.size > BOARD_COPY_MAX_BYTES) {
|
|
257848
258180
|
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 });
|
|
@@ -257851,14 +258183,14 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
257851
258183
|
}
|
|
257852
258184
|
let c8 = cache16.get(id);
|
|
257853
258185
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
257854
|
-
const row = JSON.parse(await
|
|
257855
|
-
if (!
|
|
258186
|
+
const row = JSON.parse(await fsp131.readFile(file, "utf8"));
|
|
258187
|
+
if (!isRow6(row) || row.task_id !== id) {
|
|
257856
258188
|
unreadable.push(id);
|
|
257857
258189
|
continue;
|
|
257858
258190
|
}
|
|
257859
258191
|
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, row, hash: sha12(JSON.stringify(row)) };
|
|
257860
258192
|
cache16.set(id, c8);
|
|
257861
|
-
|
|
258193
|
+
hashOf7.set(row, c8.hash);
|
|
257862
258194
|
}
|
|
257863
258195
|
out.push(c8.row);
|
|
257864
258196
|
} catch (err2) {
|
|
@@ -257873,56 +258205,56 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
257873
258205
|
if (fresh.length > 0) log.session.warn("boards copy: a board could not be read, the host keeps its copy of it", { taskIds: fresh });
|
|
257874
258206
|
return out;
|
|
257875
258207
|
}
|
|
257876
|
-
function
|
|
258208
|
+
function isRow6(v3) {
|
|
257877
258209
|
const b8 = v3;
|
|
257878
258210
|
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";
|
|
257879
258211
|
}
|
|
257880
|
-
async function
|
|
257881
|
-
if (
|
|
258212
|
+
async function load7() {
|
|
258213
|
+
if (state13) return state13;
|
|
257882
258214
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
257883
258215
|
try {
|
|
257884
|
-
const raw = JSON.parse(await
|
|
258216
|
+
const raw = JSON.parse(await fsp131.readFile(STATE_FILE3(), "utf8"));
|
|
257885
258217
|
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 };
|
|
257886
258218
|
} catch {
|
|
257887
258219
|
}
|
|
257888
|
-
|
|
258220
|
+
state13 = s4;
|
|
257889
258221
|
return s4;
|
|
257890
258222
|
}
|
|
257891
|
-
async function
|
|
257892
|
-
if (
|
|
258223
|
+
async function save2() {
|
|
258224
|
+
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
257893
258225
|
}
|
|
257894
258226
|
async function localIds() {
|
|
257895
|
-
const names2 = await
|
|
258227
|
+
const names2 = await fsp131.readdir(boardsDir2()).catch(() => []);
|
|
257896
258228
|
return names2.filter((n6) => n6.endsWith(".json")).map((n6) => n6.slice(0, -".json".length)).filter((id) => TASK_ID_RE3.test(id));
|
|
257897
258229
|
}
|
|
257898
258230
|
function changed3() {
|
|
257899
258231
|
}
|
|
257900
258232
|
function boardsFollower() {
|
|
257901
|
-
|
|
258233
|
+
follower4 ??= createRowSetFollower({
|
|
257902
258234
|
kind: "boards",
|
|
257903
258235
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
257904
258236
|
label: "boards copy",
|
|
257905
258237
|
log: log.session,
|
|
257906
258238
|
removalFloor: BOARDS_REMOVAL_FLOOR,
|
|
257907
258239
|
ordered: false,
|
|
257908
|
-
serial: (fn) =>
|
|
258240
|
+
serial: (fn) => serial6(fn),
|
|
257909
258241
|
refuse: copyRefusal,
|
|
257910
|
-
load:
|
|
257911
|
-
save,
|
|
257912
|
-
isRow:
|
|
258242
|
+
load: load7,
|
|
258243
|
+
save: save2,
|
|
258244
|
+
isRow: isRow6,
|
|
257913
258245
|
key: (b8) => b8.task_id,
|
|
257914
258246
|
localKeys: localIds,
|
|
257915
258247
|
apply: async ({ rows, removeIds }) => {
|
|
257916
258248
|
const skipped = [];
|
|
257917
258249
|
for (const id of removeIds ?? []) {
|
|
257918
|
-
if (TASK_ID_RE3.test(id)) await
|
|
258250
|
+
if (TASK_ID_RE3.test(id)) await fsp131.rm(path241.join(boardsDir2(), `${id}.json`), { force: true });
|
|
257919
258251
|
}
|
|
257920
258252
|
for (const b8 of rows ?? []) {
|
|
257921
258253
|
if (Buffer.byteLength(JSON.stringify(b8)) > BOARD_COPY_MAX_BYTES) {
|
|
257922
258254
|
skipped.push(b8.task_id);
|
|
257923
258255
|
continue;
|
|
257924
258256
|
}
|
|
257925
|
-
await writeCopyFile(
|
|
258257
|
+
await writeCopyFile(path241.join(boardsDir2(), `${b8.task_id}.json`), b8);
|
|
257926
258258
|
}
|
|
257927
258259
|
return { skipped };
|
|
257928
258260
|
},
|
|
@@ -257930,15 +258262,15 @@ function boardsFollower() {
|
|
|
257930
258262
|
changed: changed3,
|
|
257931
258263
|
purge: async () => {
|
|
257932
258264
|
const ids2 = await localIds();
|
|
257933
|
-
for (const id of ids2) await
|
|
258265
|
+
for (const id of ids2) await fsp131.rm(path241.join(boardsDir2(), `${id}.json`), { force: true });
|
|
257934
258266
|
await markCopyOff("boards");
|
|
257935
|
-
|
|
258267
|
+
state13 = null;
|
|
257936
258268
|
return { removed: ids2.length };
|
|
257937
258269
|
}
|
|
257938
258270
|
});
|
|
257939
|
-
return
|
|
258271
|
+
return follower4;
|
|
257940
258272
|
}
|
|
257941
|
-
var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16,
|
|
258273
|
+
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;
|
|
257942
258274
|
var init_boards2 = __esm({
|
|
257943
258275
|
"src/core/replication/kinds/boards.ts"() {
|
|
257944
258276
|
"use strict";
|
|
@@ -257951,9 +258283,9 @@ var init_boards2 = __esm({
|
|
|
257951
258283
|
BOARDS_REMOVAL_FLOOR = 20;
|
|
257952
258284
|
BOARD_COPY_MAX_BYTES = 2 * 1024 * 1024;
|
|
257953
258285
|
TASK_ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
257954
|
-
boardsDir2 = () =>
|
|
258286
|
+
boardsDir2 = () => path241.join(WALNUT_HOME, "boards");
|
|
257955
258287
|
cache16 = /* @__PURE__ */ new Map();
|
|
257956
|
-
|
|
258288
|
+
hashOf7 = /* @__PURE__ */ new WeakMap();
|
|
257957
258289
|
warnedTooBig = /* @__PURE__ */ new Set();
|
|
257958
258290
|
unreadableOf2 = /* @__PURE__ */ new WeakMap();
|
|
257959
258291
|
warnedUnreadable = /* @__PURE__ */ new Set();
|
|
@@ -257961,7 +258293,7 @@ var init_boards2 = __esm({
|
|
|
257961
258293
|
kind: "boards",
|
|
257962
258294
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
257963
258295
|
key: (b8) => b8.task_id,
|
|
257964
|
-
hash: (b8) =>
|
|
258296
|
+
hash: (b8) => hashOf7.get(b8) ?? sha12(JSON.stringify(b8)),
|
|
257965
258297
|
ordered: false,
|
|
257966
258298
|
digest: false,
|
|
257967
258299
|
choice: "boards",
|
|
@@ -257981,16 +258313,16 @@ var init_boards2 = __esm({
|
|
|
257981
258313
|
};
|
|
257982
258314
|
}
|
|
257983
258315
|
};
|
|
257984
|
-
|
|
257985
|
-
|
|
257986
|
-
|
|
257987
|
-
|
|
258316
|
+
STATE_FILE3 = () => path241.join(WALNUT_HOME, "cache", "replica", "boards.json");
|
|
258317
|
+
state13 = null;
|
|
258318
|
+
serial6 = serialChain();
|
|
258319
|
+
follower4 = null;
|
|
257988
258320
|
}
|
|
257989
258321
|
});
|
|
257990
258322
|
|
|
257991
258323
|
// src/core/replication/kinds/inbox.ts
|
|
257992
|
-
import
|
|
257993
|
-
import
|
|
258324
|
+
import fsp132 from "fs/promises";
|
|
258325
|
+
import path242 from "path";
|
|
257994
258326
|
function watchLetters(soon) {
|
|
257995
258327
|
let stop2 = null;
|
|
257996
258328
|
let stopped2 = false;
|
|
@@ -258003,18 +258335,18 @@ function watchLetters(soon) {
|
|
|
258003
258335
|
};
|
|
258004
258336
|
}
|
|
258005
258337
|
async function leaderBodies(dir4 = bodiesDir()) {
|
|
258006
|
-
const names2 = (await
|
|
258338
|
+
const names2 = (await fsp132.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
|
|
258007
258339
|
const out = [];
|
|
258008
258340
|
const unreadable = [];
|
|
258009
258341
|
const seen2 = new Set(names2);
|
|
258010
258342
|
for (const name of names2) {
|
|
258011
|
-
const file =
|
|
258343
|
+
const file = path242.join(dir4, name);
|
|
258012
258344
|
try {
|
|
258013
|
-
const st2 = await
|
|
258345
|
+
const st2 = await fsp132.stat(file);
|
|
258014
258346
|
if (!st2.isFile() || st2.size > INBOX_BODY_COPY_MAX_BYTES) continue;
|
|
258015
258347
|
let c8 = bodyCache.get(name);
|
|
258016
258348
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
258017
|
-
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await
|
|
258349
|
+
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp132.readFile(file, "utf8")) };
|
|
258018
258350
|
bodyCache.set(name, c8);
|
|
258019
258351
|
}
|
|
258020
258352
|
const row = { name };
|
|
@@ -258033,21 +258365,21 @@ async function loadBody(b8) {
|
|
|
258033
258365
|
const file = bodyFiles.get(b8);
|
|
258034
258366
|
if (!file) return typeof b8.body === "string" ? b8 : void 0;
|
|
258035
258367
|
try {
|
|
258036
|
-
const body7 = await
|
|
258368
|
+
const body7 = await fsp132.readFile(file, "utf8");
|
|
258037
258369
|
return Buffer.byteLength(body7) > INBOX_BODY_COPY_MAX_BYTES ? void 0 : { name: b8.name, body: body7 };
|
|
258038
258370
|
} catch {
|
|
258039
258371
|
return void 0;
|
|
258040
258372
|
}
|
|
258041
258373
|
}
|
|
258042
258374
|
function stateIo(name) {
|
|
258043
|
-
const file = () =>
|
|
258375
|
+
const file = () => path242.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
|
|
258044
258376
|
let state17 = null;
|
|
258045
258377
|
return {
|
|
258046
258378
|
load: async () => {
|
|
258047
258379
|
if (state17) return state17;
|
|
258048
258380
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
258049
258381
|
try {
|
|
258050
|
-
const raw = JSON.parse(await
|
|
258382
|
+
const raw = JSON.parse(await fsp132.readFile(file(), "utf8"));
|
|
258051
258383
|
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") {
|
|
258052
258384
|
s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: Array.isArray(raw.order) ? raw.order.map(String) : [], hashes: raw.hashes };
|
|
258053
258385
|
}
|
|
@@ -258066,7 +258398,7 @@ function stateIo(name) {
|
|
|
258066
258398
|
}
|
|
258067
258399
|
async function readIndex3() {
|
|
258068
258400
|
try {
|
|
258069
|
-
const raw = JSON.parse(await
|
|
258401
|
+
const raw = JSON.parse(await fsp132.readFile(indexFile3(), "utf8"));
|
|
258070
258402
|
return Array.isArray(raw?.letters) ? raw.letters.filter(isLetter) : [];
|
|
258071
258403
|
} catch {
|
|
258072
258404
|
return [];
|
|
@@ -258089,7 +258421,7 @@ function inboxFollower() {
|
|
|
258089
258421
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
258090
258422
|
ordered: true,
|
|
258091
258423
|
digest: true,
|
|
258092
|
-
serial: (fn) =>
|
|
258424
|
+
serial: (fn) => serial7(fn),
|
|
258093
258425
|
refuse: refuse14,
|
|
258094
258426
|
load: () => indexIo.load(),
|
|
258095
258427
|
save: () => indexIo.save(),
|
|
@@ -258119,7 +258451,7 @@ function inboxFollower() {
|
|
|
258119
258451
|
},
|
|
258120
258452
|
purge: async () => {
|
|
258121
258453
|
const removed = (await readIndex3()).length;
|
|
258122
|
-
await
|
|
258454
|
+
await fsp132.rm(indexFile3(), { force: true });
|
|
258123
258455
|
await markCopyOff("inbox");
|
|
258124
258456
|
indexIo.reset();
|
|
258125
258457
|
return { removed };
|
|
@@ -258135,23 +258467,23 @@ function inboxBodiesFollower() {
|
|
|
258135
258467
|
log: log.notif,
|
|
258136
258468
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
258137
258469
|
ordered: false,
|
|
258138
|
-
serial: (fn) =>
|
|
258470
|
+
serial: (fn) => serial7(fn),
|
|
258139
258471
|
refuse: refuse14,
|
|
258140
258472
|
load: () => bodiesIo.load(),
|
|
258141
258473
|
save: () => bodiesIo.save(),
|
|
258142
258474
|
isRow: isBody,
|
|
258143
258475
|
key: (b8) => b8.name,
|
|
258144
258476
|
hash: (b8) => sha12(b8.body),
|
|
258145
|
-
localKeys: async () => (await
|
|
258477
|
+
localKeys: async () => (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
|
|
258146
258478
|
apply: async ({ rows, removeIds }) => {
|
|
258147
|
-
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await
|
|
258479
|
+
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp132.rm(path242.join(bodiesDir(), name), { force: true });
|
|
258148
258480
|
const skipped = [];
|
|
258149
258481
|
for (const b8 of rows ?? []) {
|
|
258150
258482
|
if (Buffer.byteLength(b8.body) > INBOX_BODY_COPY_MAX_BYTES) {
|
|
258151
258483
|
skipped.push(b8.name);
|
|
258152
258484
|
continue;
|
|
258153
258485
|
}
|
|
258154
|
-
await writeCopyText(
|
|
258486
|
+
await writeCopyText(path242.join(bodiesDir(), b8.name), b8.body);
|
|
258155
258487
|
}
|
|
258156
258488
|
return { skipped };
|
|
258157
258489
|
},
|
|
@@ -258159,8 +258491,8 @@ function inboxBodiesFollower() {
|
|
|
258159
258491
|
changed: () => {
|
|
258160
258492
|
},
|
|
258161
258493
|
purge: async () => {
|
|
258162
|
-
const names2 = (await
|
|
258163
|
-
for (const name of names2) await
|
|
258494
|
+
const names2 = (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
|
|
258495
|
+
for (const name of names2) await fsp132.rm(path242.join(bodiesDir(), name), { force: true });
|
|
258164
258496
|
await markCopyOff("inbox-bodies");
|
|
258165
258497
|
bodiesIo.reset();
|
|
258166
258498
|
return { removed: names2.length };
|
|
@@ -258168,7 +258500,7 @@ function inboxBodiesFollower() {
|
|
|
258168
258500
|
});
|
|
258169
258501
|
return bodiesF;
|
|
258170
258502
|
}
|
|
258171
|
-
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,
|
|
258503
|
+
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;
|
|
258172
258504
|
var init_inbox = __esm({
|
|
258173
258505
|
"src/core/replication/kinds/inbox.ts"() {
|
|
258174
258506
|
"use strict";
|
|
@@ -258181,9 +258513,9 @@ var init_inbox = __esm({
|
|
|
258181
258513
|
INBOX_SCHEMA_VERSION = 1;
|
|
258182
258514
|
INBOX_REMOVAL_FLOOR = 50;
|
|
258183
258515
|
INBOX_BODY_COPY_MAX_BYTES = 4 * 1024 * 1024;
|
|
258184
|
-
inboxDir = () =>
|
|
258185
|
-
indexFile3 = () =>
|
|
258186
|
-
bodiesDir = () =>
|
|
258516
|
+
inboxDir = () => path242.join(WALNUT_HOME, "human-inbox");
|
|
258517
|
+
indexFile3 = () => path242.join(inboxDir(), "index.json");
|
|
258518
|
+
bodiesDir = () => path242.join(inboxDir(), "bodies");
|
|
258187
258519
|
letterHashes = /* @__PURE__ */ new WeakMap();
|
|
258188
258520
|
INBOX_KIND = {
|
|
258189
258521
|
kind: "inbox",
|
|
@@ -258225,134 +258557,12 @@ var init_inbox = __esm({
|
|
|
258225
258557
|
refuse14 = copyRefusal;
|
|
258226
258558
|
indexIo = stateIo("inbox");
|
|
258227
258559
|
bodiesIo = stateIo("inbox-bodies");
|
|
258228
|
-
|
|
258560
|
+
serial7 = serialChain();
|
|
258229
258561
|
inboxF = null;
|
|
258230
258562
|
bodiesF = null;
|
|
258231
258563
|
}
|
|
258232
258564
|
});
|
|
258233
258565
|
|
|
258234
|
-
// src/core/replication/kinds/requests.ts
|
|
258235
|
-
import fsp132 from "fs/promises";
|
|
258236
|
-
import path242 from "path";
|
|
258237
|
-
function forwardRequest(local, incoming) {
|
|
258238
|
-
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
258239
|
-
return incoming;
|
|
258240
|
-
}
|
|
258241
|
-
function hashOf6(row) {
|
|
258242
|
-
let h8 = hashes4.get(row);
|
|
258243
|
-
if (h8 === void 0) {
|
|
258244
|
-
h8 = sha12(JSON.stringify(row));
|
|
258245
|
-
hashes4.set(row, h8);
|
|
258246
|
-
}
|
|
258247
|
-
return h8;
|
|
258248
|
-
}
|
|
258249
|
-
async function load7() {
|
|
258250
|
-
if (state13) return state13;
|
|
258251
|
-
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
258252
|
-
try {
|
|
258253
|
-
const raw = JSON.parse(await fsp132.readFile(STATE_FILE3(), "utf8"));
|
|
258254
|
-
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 };
|
|
258255
|
-
} catch {
|
|
258256
|
-
}
|
|
258257
|
-
state13 = s4;
|
|
258258
|
-
return s4;
|
|
258259
|
-
}
|
|
258260
|
-
async function save2() {
|
|
258261
|
-
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
258262
|
-
}
|
|
258263
|
-
async function readStore8() {
|
|
258264
|
-
try {
|
|
258265
|
-
const raw = JSON.parse(await fsp132.readFile(STORE_FILE(), "utf8"));
|
|
258266
|
-
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
258267
|
-
} catch {
|
|
258268
|
-
return [];
|
|
258269
|
-
}
|
|
258270
|
-
}
|
|
258271
|
-
function isRow5(v3) {
|
|
258272
|
-
const r8 = v3;
|
|
258273
|
-
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
258274
|
-
}
|
|
258275
|
-
function requestsFollower() {
|
|
258276
|
-
follower4 ??= createRowSetFollower({
|
|
258277
|
-
kind: "requests",
|
|
258278
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
258279
|
-
label: "requests copy",
|
|
258280
|
-
log: log.session,
|
|
258281
|
-
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
258282
|
-
ordered: false,
|
|
258283
|
-
serial: (fn) => serial7(fn),
|
|
258284
|
-
refuse: copyRefusal,
|
|
258285
|
-
load: load7,
|
|
258286
|
-
save: save2,
|
|
258287
|
-
isRow: isRow5,
|
|
258288
|
-
key: (r8) => r8.id,
|
|
258289
|
-
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
258290
|
-
apply: async ({ rows, removeIds }) => {
|
|
258291
|
-
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
258292
|
-
for (const id of removeIds ?? []) byId.delete(id);
|
|
258293
|
-
for (const r8 of rows ?? []) {
|
|
258294
|
-
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
258295
|
-
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 });
|
|
258296
|
-
byId.set(r8.id, kept);
|
|
258297
|
-
}
|
|
258298
|
-
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
258299
|
-
return { skipped: [] };
|
|
258300
|
-
},
|
|
258301
|
-
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
258302
|
-
changed: () => {
|
|
258303
|
-
},
|
|
258304
|
-
purge: async () => {
|
|
258305
|
-
const removed = (await readStore8()).length;
|
|
258306
|
-
await fsp132.rm(STORE_FILE(), { force: true });
|
|
258307
|
-
await markCopyOff("requests");
|
|
258308
|
-
state13 = null;
|
|
258309
|
-
return { removed };
|
|
258310
|
-
}
|
|
258311
|
-
});
|
|
258312
|
-
return follower4;
|
|
258313
|
-
}
|
|
258314
|
-
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes4, REQUESTS_KIND, STATE_FILE3, STORE_FILE, state13, serial7, follower4;
|
|
258315
|
-
var init_requests = __esm({
|
|
258316
|
-
"src/core/replication/kinds/requests.ts"() {
|
|
258317
|
-
"use strict";
|
|
258318
|
-
init_constants();
|
|
258319
|
-
init_logging();
|
|
258320
|
-
init_kind();
|
|
258321
|
-
init_kind_follower();
|
|
258322
|
-
init_gate();
|
|
258323
|
-
REQUESTS_SCHEMA_VERSION = 1;
|
|
258324
|
-
REQUESTS_REMOVAL_FLOOR = 50;
|
|
258325
|
-
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
258326
|
-
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
258327
|
-
REQUESTS_KIND = {
|
|
258328
|
-
kind: "requests",
|
|
258329
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
258330
|
-
key: (r8) => r8.id,
|
|
258331
|
-
hash: hashOf6,
|
|
258332
|
-
ordered: false,
|
|
258333
|
-
digest: false,
|
|
258334
|
-
choice: "requests",
|
|
258335
|
-
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
258336
|
-
watch: (soon) => {
|
|
258337
|
-
let stop2 = null;
|
|
258338
|
-
let stopped2 = false;
|
|
258339
|
-
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
258340
|
-
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
258341
|
-
});
|
|
258342
|
-
return () => {
|
|
258343
|
-
stopped2 = true;
|
|
258344
|
-
stop2?.();
|
|
258345
|
-
};
|
|
258346
|
-
}
|
|
258347
|
-
};
|
|
258348
|
-
STATE_FILE3 = () => path242.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
258349
|
-
STORE_FILE = () => path242.join(WALNUT_HOME, "session-requests.json");
|
|
258350
|
-
state13 = null;
|
|
258351
|
-
serial7 = serialChain();
|
|
258352
|
-
follower4 = null;
|
|
258353
|
-
}
|
|
258354
|
-
});
|
|
258355
|
-
|
|
258356
258566
|
// src/core/replication/kinds/sessions.ts
|
|
258357
258567
|
import fsp133 from "fs/promises";
|
|
258358
258568
|
import path243 from "path";
|
|
@@ -258383,11 +258593,11 @@ function projectedOf(row) {
|
|
|
258383
258593
|
}
|
|
258384
258594
|
return p6;
|
|
258385
258595
|
}
|
|
258386
|
-
function
|
|
258387
|
-
let h8 =
|
|
258596
|
+
function hashOf8(row) {
|
|
258597
|
+
let h8 = hashes6.get(row);
|
|
258388
258598
|
if (h8 === void 0) {
|
|
258389
258599
|
h8 = sessionCopyHash(row);
|
|
258390
|
-
|
|
258600
|
+
hashes6.set(row, h8);
|
|
258391
258601
|
}
|
|
258392
258602
|
return h8;
|
|
258393
258603
|
}
|
|
@@ -258407,7 +258617,7 @@ async function load8() {
|
|
|
258407
258617
|
async function save3() {
|
|
258408
258618
|
if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
|
|
258409
258619
|
}
|
|
258410
|
-
function
|
|
258620
|
+
function isRow7(v3) {
|
|
258411
258621
|
const r8 = v3;
|
|
258412
258622
|
return !!r8 && typeof r8 === "object" && !Array.isArray(r8) && typeof r8.claudeSessionId === "string" && r8.claudeSessionId.length > 0 && r8.claudeSessionId.length <= 200;
|
|
258413
258623
|
}
|
|
@@ -258427,7 +258637,7 @@ function sessionsFollower() {
|
|
|
258427
258637
|
refuse: copyRefusal,
|
|
258428
258638
|
load: load8,
|
|
258429
258639
|
save: save3,
|
|
258430
|
-
isRow:
|
|
258640
|
+
isRow: isRow7,
|
|
258431
258641
|
key: (r8) => r8.claudeSessionId,
|
|
258432
258642
|
hash: sessionCopyHash,
|
|
258433
258643
|
localKeys: async () => (await Promise.resolve().then(() => (init_session_db(), session_db_exports))).sessionIdsInStore(),
|
|
@@ -258449,7 +258659,7 @@ function sessionsFollower() {
|
|
|
258449
258659
|
});
|
|
258450
258660
|
return follower5;
|
|
258451
258661
|
}
|
|
258452
|
-
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected,
|
|
258662
|
+
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;
|
|
258453
258663
|
var init_sessions2 = __esm({
|
|
258454
258664
|
"src/core/replication/kinds/sessions.ts"() {
|
|
258455
258665
|
"use strict";
|
|
@@ -258486,12 +258696,12 @@ var init_sessions2 = __esm({
|
|
|
258486
258696
|
VOLATILE_SESSION_FIELDS = ["lastActiveAt", "activity", "contextTokens"];
|
|
258487
258697
|
VOLATILE_SET = new Set(VOLATILE_SESSION_FIELDS);
|
|
258488
258698
|
projected = /* @__PURE__ */ new WeakMap();
|
|
258489
|
-
|
|
258699
|
+
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
258490
258700
|
SESSIONS_KIND = {
|
|
258491
258701
|
kind: "sessions",
|
|
258492
258702
|
schemaVersion: SESSIONS_SCHEMA_VERSION,
|
|
258493
258703
|
key: (s4) => s4.claudeSessionId,
|
|
258494
|
-
hash:
|
|
258704
|
+
hash: hashOf8,
|
|
258495
258705
|
ordered: false,
|
|
258496
258706
|
digest: true,
|
|
258497
258707
|
choice: "sessions",
|
|
@@ -258523,137 +258733,11 @@ var init_sessions2 = __esm({
|
|
|
258523
258733
|
}
|
|
258524
258734
|
});
|
|
258525
258735
|
|
|
258526
|
-
// src/core/replication/kinds/personas.ts
|
|
258527
|
-
var personas_exports = {};
|
|
258528
|
-
__export(personas_exports, {
|
|
258529
|
-
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
258530
|
-
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
258531
|
-
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
258532
|
-
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
258533
|
-
personasFollower: () => personasFollower,
|
|
258534
|
-
readPersonaCopy: () => readPersonaCopy
|
|
258535
|
-
});
|
|
258536
|
-
function tools(v3) {
|
|
258537
|
-
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
258538
|
-
}
|
|
258539
|
-
async function leaderRows2() {
|
|
258540
|
-
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
258541
|
-
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
258542
|
-
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
258543
|
-
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
258544
|
-
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
258545
|
-
]);
|
|
258546
|
-
const config = await getConfig2();
|
|
258547
|
-
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
258548
|
-
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
258549
|
-
const rows = [];
|
|
258550
|
-
for (const a8 of agents) {
|
|
258551
|
-
if (!ID_RE5.test(a8.id)) continue;
|
|
258552
|
-
try {
|
|
258553
|
-
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
258554
|
-
const prompt = profile.systemPrompt ?? "";
|
|
258555
|
-
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
258556
|
-
rows.push({
|
|
258557
|
-
key: a8.id,
|
|
258558
|
-
agentId: a8.id,
|
|
258559
|
-
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
258560
|
-
systemPrompt: prompt,
|
|
258561
|
-
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
258562
|
-
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
258563
|
-
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
258564
|
-
...effort ? { effort } : {},
|
|
258565
|
-
...launch.model ? { launchModel: launch.model } : {},
|
|
258566
|
-
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
258567
|
-
});
|
|
258568
|
-
} catch (err2) {
|
|
258569
|
-
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
258570
|
-
}
|
|
258571
|
-
}
|
|
258572
|
-
return rows;
|
|
258573
|
-
}
|
|
258574
|
-
function hashOf8(row) {
|
|
258575
|
-
let h8 = hashes6.get(row);
|
|
258576
|
-
if (h8 === void 0) {
|
|
258577
|
-
h8 = sha12(JSON.stringify(row));
|
|
258578
|
-
hashes6.set(row, h8);
|
|
258579
|
-
}
|
|
258580
|
-
return h8;
|
|
258581
|
-
}
|
|
258582
|
-
function isRow7(v3) {
|
|
258583
|
-
const r8 = v3;
|
|
258584
|
-
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
258585
|
-
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
258586
|
-
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE5.test(r8.key) || typeof r8.name !== "string") return false;
|
|
258587
|
-
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
258588
|
-
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
258589
|
-
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
258590
|
-
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;
|
|
258591
|
-
return true;
|
|
258592
|
-
}
|
|
258593
|
-
function admit2(r8) {
|
|
258594
|
-
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
258595
|
-
}
|
|
258596
|
-
async function readPersonaCopy(agentId) {
|
|
258597
|
-
const rows = await copy3.read();
|
|
258598
|
-
return rows?.[agentId] ?? null;
|
|
258599
|
-
}
|
|
258600
|
-
function _resetPersonasCopyForTesting() {
|
|
258601
|
-
copy3.reset();
|
|
258602
|
-
}
|
|
258603
|
-
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE5, TOOL_RE, hashes6, PERSONAS_KIND, ROW_KEYS, copy3, personasFollower;
|
|
258604
|
-
var init_personas = __esm({
|
|
258605
|
-
"src/core/replication/kinds/personas.ts"() {
|
|
258606
|
-
"use strict";
|
|
258607
|
-
init_logging();
|
|
258608
|
-
init_config_allowlist();
|
|
258609
|
-
init_kind();
|
|
258610
|
-
init_file_copy();
|
|
258611
|
-
PERSONAS_SCHEMA_VERSION = 1;
|
|
258612
|
-
PERSONAS_REMOVAL_FLOOR = 0;
|
|
258613
|
-
MAX_PROMPT_BYTES = 120 * 1024;
|
|
258614
|
-
ID_RE5 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
258615
|
-
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
258616
|
-
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
258617
|
-
PERSONAS_KIND = {
|
|
258618
|
-
kind: "personas",
|
|
258619
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
258620
|
-
key: (r8) => r8.key,
|
|
258621
|
-
hash: hashOf8,
|
|
258622
|
-
ordered: false,
|
|
258623
|
-
digest: false,
|
|
258624
|
-
choice: "personas",
|
|
258625
|
-
rows: leaderRows2,
|
|
258626
|
-
watch: (soon) => {
|
|
258627
|
-
let stop2 = null;
|
|
258628
|
-
let stopped2 = false;
|
|
258629
|
-
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
258630
|
-
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
258631
|
-
});
|
|
258632
|
-
return () => {
|
|
258633
|
-
stopped2 = true;
|
|
258634
|
-
stop2?.();
|
|
258635
|
-
};
|
|
258636
|
-
}
|
|
258637
|
-
};
|
|
258638
|
-
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
258639
|
-
copy3 = createFileCopy({
|
|
258640
|
-
kind: "personas",
|
|
258641
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
258642
|
-
label: "personas copy",
|
|
258643
|
-
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
258644
|
-
isRow: isRow7,
|
|
258645
|
-
key: (r8) => r8.key,
|
|
258646
|
-
admit: admit2
|
|
258647
|
-
});
|
|
258648
|
-
personasFollower = copy3.follower;
|
|
258649
|
-
}
|
|
258650
|
-
});
|
|
258651
|
-
|
|
258652
258736
|
// src/core/replication/kinds/index.ts
|
|
258653
258737
|
var kinds_exports = {};
|
|
258654
258738
|
__export(kinds_exports, {
|
|
258739
|
+
copyKeepersOnly: () => copyKeepersOnly,
|
|
258655
258740
|
copyKinds: () => copyKinds,
|
|
258656
|
-
hostReplicaOnly: () => hostReplicaOnly,
|
|
258657
258741
|
registerCopyFollowerKinds: () => registerCopyFollowerKinds,
|
|
258658
258742
|
startCopyKinds: () => startCopyKinds
|
|
258659
258743
|
});
|
|
@@ -258671,14 +258755,14 @@ function copyKinds() {
|
|
|
258671
258755
|
PERSONAS_KIND
|
|
258672
258756
|
];
|
|
258673
258757
|
}
|
|
258674
|
-
function
|
|
258758
|
+
function copyKeepersOnly(h8) {
|
|
258675
258759
|
return {
|
|
258676
258760
|
kind: h8.kind,
|
|
258677
|
-
// followerStep checks the version before the step: never `schema_newer`
|
|
258761
|
+
// followerStep checks the version before the step: never `schema_newer` where the kind is not kept.
|
|
258678
258762
|
get schemaVersion() {
|
|
258679
|
-
return keepsCopies() ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
258763
|
+
return keepsCopies(h8.kind) ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
258680
258764
|
},
|
|
258681
|
-
step: (op2, body7) => keepsCopies() ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
258765
|
+
step: (op2, body7) => keepsCopies(h8.kind) ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
258682
258766
|
};
|
|
258683
258767
|
}
|
|
258684
258768
|
function registerCopyFollowerKinds() {
|
|
@@ -258693,7 +258777,7 @@ function registerCopyFollowerKinds() {
|
|
|
258693
258777
|
prefsFollower(),
|
|
258694
258778
|
configFollower(),
|
|
258695
258779
|
personasFollower()
|
|
258696
|
-
].map((h8) => registerFollowerKind(
|
|
258780
|
+
].map((h8) => registerFollowerKind(copyKeepersOnly(h8)));
|
|
258697
258781
|
return () => {
|
|
258698
258782
|
for (const u3 of off) u3();
|
|
258699
258783
|
};
|
|
@@ -291071,10 +291155,13 @@ async function cleanupLaneClaudeMd(homeDir2 = WALNUT_HOME) {
|
|
|
291071
291155
|
}
|
|
291072
291156
|
}
|
|
291073
291157
|
async function buildLaneProfile(config, agentId, opts2) {
|
|
291074
|
-
const
|
|
291075
|
-
const
|
|
291158
|
+
const persona = opts2?.persona;
|
|
291159
|
+
const skillsIndex = persona ? "" : await buildSessionSkillsPrompt().catch(() => "");
|
|
291160
|
+
const memoryContext = persona ? "" : await buildLaneMemoryContext().catch(() => "");
|
|
291076
291161
|
let profile;
|
|
291077
|
-
if (
|
|
291162
|
+
if (persona) {
|
|
291163
|
+
profile = mergeProfiles({ systemPrompt: persona.systemPrompt, systemPromptMode: persona.systemPromptMode }, walnutMcpProfile());
|
|
291164
|
+
} else if (agentId === "general") {
|
|
291078
291165
|
profile = personalAiProfile(config.user?.name ?? "the user", skillsIndex, memoryContext);
|
|
291079
291166
|
} else {
|
|
291080
291167
|
const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports));
|
|
@@ -291084,7 +291171,8 @@ async function buildLaneProfile(config, agentId, opts2) {
|
|
|
291084
291171
|
const contextBlock = await loadContextSources2(agentDef, {}).catch(() => "");
|
|
291085
291172
|
profile = consoleAgentProfile(agentDef, skillsIndex, contextBlock);
|
|
291086
291173
|
}
|
|
291087
|
-
const
|
|
291174
|
+
const personaEffort = persona?.effort && LANE_EFFORTS.has(persona.effort) ? persona.effort : void 0;
|
|
291175
|
+
const effort = personaEffort ?? config.agent?.session_effort ?? "medium";
|
|
291088
291176
|
if (!opts2?.conversationId) return { profile, effort };
|
|
291089
291177
|
const base = profile.systemPrompt ?? "";
|
|
291090
291178
|
const headroom = MAX_LANE_PROMPT_BYTES - Buffer.byteLength(base, "utf-8") - LANE_SEED_RESERVE_BYTES;
|
|
@@ -291354,7 +291442,7 @@ async function resolveLane(lane, agentId, conversationId, firstMessage, engine)
|
|
|
291354
291442
|
});
|
|
291355
291443
|
return { sessionId, created: true, engine: "claude" };
|
|
291356
291444
|
}
|
|
291357
|
-
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;
|
|
291445
|
+
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;
|
|
291358
291446
|
var init_personal_ai_lane = __esm({
|
|
291359
291447
|
"src/core/sessions/personal-ai-lane.ts"() {
|
|
291360
291448
|
"use strict";
|
|
@@ -291369,6 +291457,7 @@ var init_personal_ai_lane = __esm({
|
|
|
291369
291457
|
init_default_engine();
|
|
291370
291458
|
init_ask_profile_prefix();
|
|
291371
291459
|
init_logging();
|
|
291460
|
+
LANE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
291372
291461
|
inFlight20 = /* @__PURE__ */ new Map();
|
|
291373
291462
|
LANE_MEMORY_HEADER = "## Standing memory (injected by Walnut)";
|
|
291374
291463
|
MANAGED_LANE_CONTEXT_MARKERS = [
|
|
@@ -319294,9 +319383,13 @@ var init_task_replica_store = __esm({
|
|
|
319294
319383
|
// src/core/replication/kinds/gate.ts
|
|
319295
319384
|
var gate_exports = {};
|
|
319296
319385
|
__export(gate_exports, {
|
|
319386
|
+
COMPANION_COPY_KINDS: () => COMPANION_COPY_KINDS,
|
|
319387
|
+
COPY_AS_OF_HEADER: () => COPY_AS_OF_HEADER,
|
|
319297
319388
|
KIND_NOT_COPIED: () => KIND_NOT_COPIED,
|
|
319389
|
+
copyKindAsOf: () => copyKindAsOf,
|
|
319298
319390
|
copyKindHeld: () => copyKindHeld,
|
|
319299
319391
|
copyKindOff: () => copyKindOff,
|
|
319392
|
+
copyPath: () => copyPath,
|
|
319300
319393
|
copyRefusal: () => copyRefusal,
|
|
319301
319394
|
copyStateFile: () => copyStateFile,
|
|
319302
319395
|
keepsCopies: () => keepsCopies,
|
|
@@ -319304,8 +319397,16 @@ __export(gate_exports, {
|
|
|
319304
319397
|
});
|
|
319305
319398
|
import fsp152 from "fs/promises";
|
|
319306
319399
|
import path295 from "path";
|
|
319307
|
-
function keepsCopies() {
|
|
319308
|
-
|
|
319400
|
+
function keepsCopies(kind) {
|
|
319401
|
+
if (isHostReplicaProgram()) return true;
|
|
319402
|
+
if (followerKind() !== "companion") return false;
|
|
319403
|
+
return kind === void 0 || COMPANION_COPY_KINDS.has(kind);
|
|
319404
|
+
}
|
|
319405
|
+
function copyPath(live6) {
|
|
319406
|
+
if (followerKind() !== "companion") return live6;
|
|
319407
|
+
const rel = path295.relative(WALNUT_HOME, live6);
|
|
319408
|
+
if (!rel || rel.startsWith("..") || path295.isAbsolute(rel)) throw new Error(`copyPath: ${live6} is not under the data dir`);
|
|
319409
|
+
return path295.join(WALNUT_HOME, "cache", "replica", "home", rel);
|
|
319309
319410
|
}
|
|
319310
319411
|
async function copyRefusal() {
|
|
319311
319412
|
if (!keepsCopies()) return { status: 404, error: "unknown_kind" };
|
|
@@ -319326,20 +319427,26 @@ async function copyKindOff(kind) {
|
|
|
319326
319427
|
}
|
|
319327
319428
|
}
|
|
319328
319429
|
async function copyKindHeld(kind) {
|
|
319430
|
+
return await copyKindAsOf(kind) !== null;
|
|
319431
|
+
}
|
|
319432
|
+
async function copyKindAsOf(kind) {
|
|
319329
319433
|
try {
|
|
319330
319434
|
const raw = JSON.parse(await fsp152.readFile(copyStateFile(kind), "utf8"));
|
|
319331
|
-
|
|
319435
|
+
if (!(raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object")) return null;
|
|
319436
|
+
return Number(raw.asOf) || 0;
|
|
319332
319437
|
} catch {
|
|
319333
|
-
return
|
|
319438
|
+
return null;
|
|
319334
319439
|
}
|
|
319335
319440
|
}
|
|
319336
|
-
var KIND_NOT_COPIED;
|
|
319441
|
+
var COMPANION_COPY_KINDS, COPY_AS_OF_HEADER, KIND_NOT_COPIED;
|
|
319337
319442
|
var init_gate = __esm({
|
|
319338
319443
|
"src/core/replication/kinds/gate.ts"() {
|
|
319339
319444
|
"use strict";
|
|
319340
319445
|
init_constants();
|
|
319341
319446
|
init_server_role();
|
|
319342
319447
|
init_kind_follower();
|
|
319448
|
+
COMPANION_COPY_KINDS = /* @__PURE__ */ new Set(["requests", "routines", "prefs", "personas"]);
|
|
319449
|
+
COPY_AS_OF_HEADER = "x-walnut-copy-as-of";
|
|
319343
319450
|
KIND_NOT_COPIED = "kind_not_copied";
|
|
319344
319451
|
}
|
|
319345
319452
|
});
|