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;
|
|
@@ -164277,8 +164302,8 @@ import path134 from "path";
|
|
|
164277
164302
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
164278
164303
|
function getVersion() {
|
|
164279
164304
|
if (cachedVersion) return cachedVersion;
|
|
164280
|
-
if ("0.6.
|
|
164281
|
-
cachedVersion = "0.6.
|
|
164305
|
+
if ("0.6.17") {
|
|
164306
|
+
cachedVersion = "0.6.17";
|
|
164282
164307
|
versionKnown = true;
|
|
164283
164308
|
return cachedVersion;
|
|
164284
164309
|
}
|
|
@@ -188644,6 +188669,132 @@ var init_agent_turn_queue = __esm({
|
|
|
188644
188669
|
}
|
|
188645
188670
|
});
|
|
188646
188671
|
|
|
188672
|
+
// src/core/replication/kinds/personas.ts
|
|
188673
|
+
var personas_exports = {};
|
|
188674
|
+
__export(personas_exports, {
|
|
188675
|
+
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
188676
|
+
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
188677
|
+
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
188678
|
+
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
188679
|
+
personasFollower: () => personasFollower,
|
|
188680
|
+
readPersonaCopy: () => readPersonaCopy
|
|
188681
|
+
});
|
|
188682
|
+
function tools(v3) {
|
|
188683
|
+
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
188684
|
+
}
|
|
188685
|
+
async function leaderRows() {
|
|
188686
|
+
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
188687
|
+
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
188688
|
+
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
188689
|
+
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
188690
|
+
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
188691
|
+
]);
|
|
188692
|
+
const config = await getConfig2();
|
|
188693
|
+
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
188694
|
+
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
188695
|
+
const rows = [];
|
|
188696
|
+
for (const a8 of agents) {
|
|
188697
|
+
if (!ID_RE2.test(a8.id)) continue;
|
|
188698
|
+
try {
|
|
188699
|
+
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
188700
|
+
const prompt = profile.systemPrompt ?? "";
|
|
188701
|
+
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
188702
|
+
rows.push({
|
|
188703
|
+
key: a8.id,
|
|
188704
|
+
agentId: a8.id,
|
|
188705
|
+
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
188706
|
+
systemPrompt: prompt,
|
|
188707
|
+
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
188708
|
+
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
188709
|
+
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
188710
|
+
...effort ? { effort } : {},
|
|
188711
|
+
...launch.model ? { launchModel: launch.model } : {},
|
|
188712
|
+
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
188713
|
+
});
|
|
188714
|
+
} catch (err2) {
|
|
188715
|
+
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
188716
|
+
}
|
|
188717
|
+
}
|
|
188718
|
+
return rows;
|
|
188719
|
+
}
|
|
188720
|
+
function hashOf4(row) {
|
|
188721
|
+
let h8 = hashes3.get(row);
|
|
188722
|
+
if (h8 === void 0) {
|
|
188723
|
+
h8 = sha12(JSON.stringify(row));
|
|
188724
|
+
hashes3.set(row, h8);
|
|
188725
|
+
}
|
|
188726
|
+
return h8;
|
|
188727
|
+
}
|
|
188728
|
+
function isRow3(v3) {
|
|
188729
|
+
const r8 = v3;
|
|
188730
|
+
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
188731
|
+
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
188732
|
+
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE2.test(r8.key) || typeof r8.name !== "string") return false;
|
|
188733
|
+
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
188734
|
+
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
188735
|
+
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
188736
|
+
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;
|
|
188737
|
+
return true;
|
|
188738
|
+
}
|
|
188739
|
+
function admit(r8) {
|
|
188740
|
+
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
188741
|
+
}
|
|
188742
|
+
async function readPersonaCopy(agentId) {
|
|
188743
|
+
const rows = await copy2.read();
|
|
188744
|
+
return rows?.[agentId] ?? null;
|
|
188745
|
+
}
|
|
188746
|
+
function _resetPersonasCopyForTesting() {
|
|
188747
|
+
copy2.reset();
|
|
188748
|
+
}
|
|
188749
|
+
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE2, TOOL_RE, hashes3, PERSONAS_KIND, ROW_KEYS, copy2, personasFollower;
|
|
188750
|
+
var init_personas = __esm({
|
|
188751
|
+
"src/core/replication/kinds/personas.ts"() {
|
|
188752
|
+
"use strict";
|
|
188753
|
+
init_logging();
|
|
188754
|
+
init_config_allowlist();
|
|
188755
|
+
init_kind();
|
|
188756
|
+
init_file_copy();
|
|
188757
|
+
PERSONAS_SCHEMA_VERSION = 1;
|
|
188758
|
+
PERSONAS_REMOVAL_FLOOR = 0;
|
|
188759
|
+
MAX_PROMPT_BYTES = 120 * 1024;
|
|
188760
|
+
ID_RE2 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
188761
|
+
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
188762
|
+
hashes3 = /* @__PURE__ */ new WeakMap();
|
|
188763
|
+
PERSONAS_KIND = {
|
|
188764
|
+
kind: "personas",
|
|
188765
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
188766
|
+
key: (r8) => r8.key,
|
|
188767
|
+
hash: hashOf4,
|
|
188768
|
+
ordered: false,
|
|
188769
|
+
digest: false,
|
|
188770
|
+
choice: "personas",
|
|
188771
|
+
rows: leaderRows,
|
|
188772
|
+
watch: (soon) => {
|
|
188773
|
+
let stop2 = null;
|
|
188774
|
+
let stopped2 = false;
|
|
188775
|
+
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
188776
|
+
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
188777
|
+
});
|
|
188778
|
+
return () => {
|
|
188779
|
+
stopped2 = true;
|
|
188780
|
+
stop2?.();
|
|
188781
|
+
};
|
|
188782
|
+
}
|
|
188783
|
+
};
|
|
188784
|
+
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
188785
|
+
copy2 = createFileCopy({
|
|
188786
|
+
kind: "personas",
|
|
188787
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
188788
|
+
label: "personas copy",
|
|
188789
|
+
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
188790
|
+
isRow: isRow3,
|
|
188791
|
+
key: (r8) => r8.key,
|
|
188792
|
+
admit
|
|
188793
|
+
});
|
|
188794
|
+
personasFollower = copy2.follower;
|
|
188795
|
+
}
|
|
188796
|
+
});
|
|
188797
|
+
|
|
188647
188798
|
// src/core/sessions/cloud-chat-lane.ts
|
|
188648
188799
|
var cloud_chat_lane_exports = {};
|
|
188649
188800
|
__export(cloud_chat_lane_exports, {
|
|
@@ -188782,7 +188933,9 @@ async function resolveCloudChatLane(lane, agentId, conversationId, cwd, firstMes
|
|
|
188782
188933
|
CATCH_UP_BANNER_CLOSE: CATCH_UP_BANNER_CLOSE2,
|
|
188783
188934
|
buildConversationSeed: buildConversationSeed2
|
|
188784
188935
|
} = await Promise.resolve().then(() => (init_chat_history(), chat_history_exports));
|
|
188785
|
-
const {
|
|
188936
|
+
const { readPersonaCopy: readPersonaCopy2 } = await Promise.resolve().then(() => (init_personas(), personas_exports));
|
|
188937
|
+
const persona = await readPersonaCopy2(agentId).catch(() => null);
|
|
188938
|
+
const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId, ...persona ? { persona } : {} });
|
|
188786
188939
|
const profile = toCloudChatProfile(base, CONVERSATION_SEED_HEADER2);
|
|
188787
188940
|
const sessionId = crypto49.randomUUID();
|
|
188788
188941
|
const seedInProfile = !!seed && (seed.text !== "" || seed.stats.turnsTotal === 0);
|
|
@@ -195751,9 +195904,9 @@ function sanitizeHealthSync(body7, now = Date.now()) {
|
|
|
195751
195904
|
const tz = isValidTz(b8.tz) ? b8.tz : "";
|
|
195752
195905
|
const spec = metricSpec(type);
|
|
195753
195906
|
const generic = isGenericType(type);
|
|
195754
|
-
const storeId = typeof b8.storeId === "string" &&
|
|
195907
|
+
const storeId = typeof b8.storeId === "string" && ID_RE3.test(b8.storeId) ? b8.storeId : void 0;
|
|
195755
195908
|
const dev = b8.device && typeof b8.device === "object" ? b8.device : {};
|
|
195756
|
-
const installId = typeof dev.installId === "string" &&
|
|
195909
|
+
const installId = typeof dev.installId === "string" && ID_RE3.test(dev.installId) ? dev.installId : void 0;
|
|
195757
195910
|
const device = { installId, model: str10(dev.model, 64), os: str10(dev.os, 64) };
|
|
195758
195911
|
const hasDevice = Object.values(device).some((v3) => v3 !== void 0);
|
|
195759
195912
|
const deleted = [...new Set(deletedIn.filter((u3) => typeof u3 === "string" && UUID_RE3.test(u3)))];
|
|
@@ -195821,14 +195974,14 @@ function relayPayload(batch) {
|
|
|
195821
195974
|
samples: batch.samples.map(({ tz, ...rest }) => tz === batch.tz ? rest : { ...rest, tz })
|
|
195822
195975
|
};
|
|
195823
195976
|
}
|
|
195824
|
-
var UUID_RE3,
|
|
195977
|
+
var UUID_RE3, ID_RE3, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
|
|
195825
195978
|
var init_sanitize = __esm({
|
|
195826
195979
|
"src/core/health/sanitize.ts"() {
|
|
195827
195980
|
"use strict";
|
|
195828
195981
|
init_catalog();
|
|
195829
195982
|
init_day_key();
|
|
195830
195983
|
UUID_RE3 = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
|
|
195831
|
-
|
|
195984
|
+
ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
|
|
195832
195985
|
MIN_INSTANT = Date.UTC(2010, 0, 1);
|
|
195833
195986
|
FUTURE_SLACK_MS2 = 36 * 36e5;
|
|
195834
195987
|
MAX_SPAN_MS = 2 * 864e5;
|
|
@@ -213432,7 +213585,7 @@ function prefAdmissible(p6) {
|
|
|
213432
213585
|
function strings(v3) {
|
|
213433
213586
|
return Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string") : [];
|
|
213434
213587
|
}
|
|
213435
|
-
async function
|
|
213588
|
+
async function leaderRows2() {
|
|
213436
213589
|
const raw = await readJsonFile(UI_PREFS_FILE, {}, { readErrors: "throw" });
|
|
213437
213590
|
const rows = [];
|
|
213438
213591
|
for (const [k8, v3] of Object.entries(raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {})) {
|
|
@@ -213444,15 +213597,15 @@ async function leaderRows() {
|
|
|
213444
213597
|
rows.push({ key: "favorites", favorites: { projects: strings(fav?.projects), notes: strings(fav?.notes) } });
|
|
213445
213598
|
return rows;
|
|
213446
213599
|
}
|
|
213447
|
-
function
|
|
213448
|
-
let h8 =
|
|
213600
|
+
function hashOf5(row) {
|
|
213601
|
+
let h8 = hashes4.get(row);
|
|
213449
213602
|
if (h8 === void 0) {
|
|
213450
213603
|
h8 = sha12(JSON.stringify(row));
|
|
213451
|
-
|
|
213604
|
+
hashes4.set(row, h8);
|
|
213452
213605
|
}
|
|
213453
213606
|
return h8;
|
|
213454
213607
|
}
|
|
213455
|
-
function
|
|
213608
|
+
function isRow4(v3) {
|
|
213456
213609
|
const r8 = v3;
|
|
213457
213610
|
if (!r8 || typeof r8 !== "object" || typeof r8.key !== "string") return false;
|
|
213458
213611
|
if (r8.key === "favorites") {
|
|
@@ -213462,27 +213615,27 @@ function isRow3(v3) {
|
|
|
213462
213615
|
const p6 = prefOf(r8.pref);
|
|
213463
213616
|
return Object.keys(r8).length === 2 && r8.key.startsWith(UI) && copyableUiPrefKey(r8.key.slice(UI.length)) && !!p6 && typeof r8.pref === "object";
|
|
213464
213617
|
}
|
|
213465
|
-
function
|
|
213618
|
+
function admit2(r8) {
|
|
213466
213619
|
if ("favorites" in r8) return [...r8.favorites.projects, ...r8.favorites.notes].every((s4) => typeof s4 === "string" && secretShapedValue(s4) === null);
|
|
213467
213620
|
return prefAdmissible(r8.pref);
|
|
213468
213621
|
}
|
|
213469
213622
|
async function readUiPrefsCopy() {
|
|
213470
|
-
const rows = await
|
|
213623
|
+
const rows = await copy3.read();
|
|
213471
213624
|
if (!rows) return null;
|
|
213472
213625
|
const out = {};
|
|
213473
213626
|
for (const r8 of Object.values(rows)) if ("pref" in r8) out[r8.key.slice(UI.length)] = r8.pref;
|
|
213474
213627
|
return out;
|
|
213475
213628
|
}
|
|
213476
213629
|
async function readFavoritesCopy() {
|
|
213477
|
-
const rows = await
|
|
213630
|
+
const rows = await copy3.read();
|
|
213478
213631
|
if (!rows) return null;
|
|
213479
213632
|
const f8 = rows.favorites;
|
|
213480
213633
|
return f8 && "favorites" in f8 ? f8.favorites : { projects: [], notes: [] };
|
|
213481
213634
|
}
|
|
213482
213635
|
function _resetPrefsCopyForTesting() {
|
|
213483
|
-
|
|
213636
|
+
copy3.reset();
|
|
213484
213637
|
}
|
|
213485
|
-
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2,
|
|
213638
|
+
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes4, PREFS_KIND, copy3, prefsFollower;
|
|
213486
213639
|
var init_prefs = __esm({
|
|
213487
213640
|
"src/core/replication/kinds/prefs.ts"() {
|
|
213488
213641
|
"use strict";
|
|
@@ -213496,16 +213649,16 @@ var init_prefs = __esm({
|
|
|
213496
213649
|
PREFS_REMOVAL_FLOOR = 0;
|
|
213497
213650
|
UI = "ui:";
|
|
213498
213651
|
MAX_VALUE_LEN2 = 8 * 1024;
|
|
213499
|
-
|
|
213652
|
+
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
213500
213653
|
PREFS_KIND = {
|
|
213501
213654
|
kind: "prefs",
|
|
213502
213655
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
213503
213656
|
key: (r8) => r8.key,
|
|
213504
|
-
hash:
|
|
213657
|
+
hash: hashOf5,
|
|
213505
213658
|
ordered: false,
|
|
213506
213659
|
digest: false,
|
|
213507
213660
|
choice: "prefs",
|
|
213508
|
-
rows:
|
|
213661
|
+
rows: leaderRows2,
|
|
213509
213662
|
watch: (soon) => {
|
|
213510
213663
|
const stops = [];
|
|
213511
213664
|
let stopped2 = false;
|
|
@@ -213518,16 +213671,16 @@ var init_prefs = __esm({
|
|
|
213518
213671
|
};
|
|
213519
213672
|
}
|
|
213520
213673
|
};
|
|
213521
|
-
|
|
213674
|
+
copy3 = createFileCopy({
|
|
213522
213675
|
kind: "prefs",
|
|
213523
213676
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
213524
213677
|
label: "prefs copy",
|
|
213525
213678
|
removalFloor: PREFS_REMOVAL_FLOOR,
|
|
213526
|
-
isRow:
|
|
213679
|
+
isRow: isRow4,
|
|
213527
213680
|
key: (r8) => r8.key,
|
|
213528
|
-
admit
|
|
213681
|
+
admit: admit2
|
|
213529
213682
|
});
|
|
213530
|
-
prefsFollower =
|
|
213683
|
+
prefsFollower = copy3.follower;
|
|
213531
213684
|
}
|
|
213532
213685
|
});
|
|
213533
213686
|
|
|
@@ -214119,7 +214272,7 @@ async function adoptDeviceRecord(input, opts2 = {}) {
|
|
|
214119
214272
|
const existing = devices.find((d8) => d8.tokenHash === tokenHash);
|
|
214120
214273
|
if (existing) return { result: { name: existing.name, adopted: false } };
|
|
214121
214274
|
const finalName = freeName(devices, name);
|
|
214122
|
-
const wanted = typeof input.id === "string" &&
|
|
214275
|
+
const wanted = typeof input.id === "string" && ID_RE4.test(input.id) ? input.id : void 0;
|
|
214123
214276
|
const idFree = wanted !== void 0 && !devices.some((d8) => d8.id === wanted || d8.ownerId === wanted);
|
|
214124
214277
|
const record2 = {
|
|
214125
214278
|
name: finalName,
|
|
@@ -214154,7 +214307,7 @@ async function revokeAdopted(tokenHash) {
|
|
|
214154
214307
|
if (out.revoked) log.web.info("device-adoption: twin pairing revoked", { name: record2.name, adoptedFrom: record2.adoptedFrom ?? null });
|
|
214155
214308
|
return out.revoked ? { name: record2.name, refused: false, push: out.push } : { name: null, refused: false, push: null };
|
|
214156
214309
|
}
|
|
214157
|
-
var AdoptionError, HASH_RE2,
|
|
214310
|
+
var AdoptionError, HASH_RE2, ID_RE4, INFO_FIELD_MAX2, NAME_MAX2;
|
|
214158
214311
|
var init_device_adoption = __esm({
|
|
214159
214312
|
"src/core/device-adoption.ts"() {
|
|
214160
214313
|
"use strict";
|
|
@@ -214172,7 +214325,7 @@ var init_device_adoption = __esm({
|
|
|
214172
214325
|
}
|
|
214173
214326
|
};
|
|
214174
214327
|
HASH_RE2 = /^[0-9a-f]{64}$/;
|
|
214175
|
-
|
|
214328
|
+
ID_RE4 = /^d[0-9a-f]{16}$/;
|
|
214176
214329
|
INFO_FIELD_MAX2 = 120;
|
|
214177
214330
|
NAME_MAX2 = 64;
|
|
214178
214331
|
}
|
|
@@ -243544,7 +243697,7 @@ async function saveRecordingAudio(audioBase64, format2) {
|
|
|
243544
243697
|
return { id, audioPath };
|
|
243545
243698
|
}
|
|
243546
243699
|
async function writeRecordingResult(id, meta) {
|
|
243547
|
-
if (!
|
|
243700
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
243548
243701
|
await mkdir7(dir3(), { recursive: true });
|
|
243549
243702
|
const stamped = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...meta };
|
|
243550
243703
|
await writeFile6(join16(dir3(), `${id}.json`), JSON.stringify(stamped, null, 2));
|
|
@@ -243553,7 +243706,7 @@ async function writeRecordingResult(id, meta) {
|
|
|
243553
243706
|
return stamped.timestamp;
|
|
243554
243707
|
}
|
|
243555
243708
|
async function writeRecordingSecondary(id, secondary, expectTimestamp) {
|
|
243556
|
-
if (!
|
|
243709
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
243557
243710
|
const path297 = join16(dir3(), `${id}.json`);
|
|
243558
243711
|
let existing;
|
|
243559
243712
|
try {
|
|
@@ -243575,7 +243728,7 @@ async function listRecordings(limit = 20) {
|
|
|
243575
243728
|
const out = [];
|
|
243576
243729
|
for (const jf of jsonFiles) {
|
|
243577
243730
|
const id = jf.slice(0, -5);
|
|
243578
|
-
if (!
|
|
243731
|
+
if (!ID_RE5.test(id)) continue;
|
|
243579
243732
|
try {
|
|
243580
243733
|
const raw = JSON.parse(await readFile8(join16(dir3(), jf), "utf-8"));
|
|
243581
243734
|
out.push({
|
|
@@ -243595,7 +243748,7 @@ async function listRecordings(limit = 20) {
|
|
|
243595
243748
|
return out;
|
|
243596
243749
|
}
|
|
243597
243750
|
async function readRecordingAudio(id) {
|
|
243598
|
-
if (!
|
|
243751
|
+
if (!ID_RE5.test(id)) return null;
|
|
243599
243752
|
let files;
|
|
243600
243753
|
try {
|
|
243601
243754
|
files = await readdir3(dir3());
|
|
@@ -243623,13 +243776,13 @@ async function pruneOldRecordings() {
|
|
|
243623
243776
|
}
|
|
243624
243777
|
}
|
|
243625
243778
|
}
|
|
243626
|
-
var MAX_RECORDINGS,
|
|
243779
|
+
var MAX_RECORDINGS, ID_RE5, AUDIO_EXTS;
|
|
243627
243780
|
var init_recordings = __esm({
|
|
243628
243781
|
"src/core/stt/recordings.ts"() {
|
|
243629
243782
|
"use strict";
|
|
243630
243783
|
init_constants();
|
|
243631
243784
|
MAX_RECORDINGS = 100;
|
|
243632
|
-
|
|
243785
|
+
ID_RE5 = /^[0-9A-Za-z-]+$/;
|
|
243633
243786
|
AUDIO_EXTS = ["webm", "mp4", "ogg", "wav", "mp3", "m4a", "flac"];
|
|
243634
243787
|
}
|
|
243635
243788
|
});
|
|
@@ -250277,6 +250430,147 @@ var init_task_v1 = __esm({
|
|
|
250277
250430
|
}
|
|
250278
250431
|
});
|
|
250279
250432
|
|
|
250433
|
+
// src/core/replication/kinds/requests.ts
|
|
250434
|
+
var requests_exports = {};
|
|
250435
|
+
__export(requests_exports, {
|
|
250436
|
+
REQUESTS_KIND: () => REQUESTS_KIND,
|
|
250437
|
+
REQUESTS_REMOVAL_FLOOR: () => REQUESTS_REMOVAL_FLOOR,
|
|
250438
|
+
REQUESTS_SCHEMA_VERSION: () => REQUESTS_SCHEMA_VERSION,
|
|
250439
|
+
_resetRequestsCopyForTesting: () => _resetRequestsCopyForTesting,
|
|
250440
|
+
forwardRequest: () => forwardRequest,
|
|
250441
|
+
readRequestCopy: () => readRequestCopy,
|
|
250442
|
+
requestsFollower: () => requestsFollower
|
|
250443
|
+
});
|
|
250444
|
+
import fsp124 from "fs/promises";
|
|
250445
|
+
import path233 from "path";
|
|
250446
|
+
function forwardRequest(local, incoming) {
|
|
250447
|
+
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
250448
|
+
return incoming;
|
|
250449
|
+
}
|
|
250450
|
+
function hashOf6(row) {
|
|
250451
|
+
let h8 = hashes5.get(row);
|
|
250452
|
+
if (h8 === void 0) {
|
|
250453
|
+
h8 = sha12(JSON.stringify(row));
|
|
250454
|
+
hashes5.set(row, h8);
|
|
250455
|
+
}
|
|
250456
|
+
return h8;
|
|
250457
|
+
}
|
|
250458
|
+
async function load6() {
|
|
250459
|
+
if (state11) return state11;
|
|
250460
|
+
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
250461
|
+
try {
|
|
250462
|
+
const raw = JSON.parse(await fsp124.readFile(STATE_FILE(), "utf8"));
|
|
250463
|
+
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 };
|
|
250464
|
+
} catch {
|
|
250465
|
+
}
|
|
250466
|
+
state11 = s4;
|
|
250467
|
+
return s4;
|
|
250468
|
+
}
|
|
250469
|
+
async function save() {
|
|
250470
|
+
if (state11) await writeCopyFile(STATE_FILE(), { v: 1, asOf: state11.asOf, at: state11.at, hashes: state11.hashes });
|
|
250471
|
+
}
|
|
250472
|
+
async function readStore8() {
|
|
250473
|
+
try {
|
|
250474
|
+
const raw = JSON.parse(await fsp124.readFile(STORE_FILE(), "utf8"));
|
|
250475
|
+
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
250476
|
+
} catch {
|
|
250477
|
+
return [];
|
|
250478
|
+
}
|
|
250479
|
+
}
|
|
250480
|
+
function isRow5(v3) {
|
|
250481
|
+
const r8 = v3;
|
|
250482
|
+
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
250483
|
+
}
|
|
250484
|
+
function requestsFollower() {
|
|
250485
|
+
follower3 ??= createRowSetFollower({
|
|
250486
|
+
kind: "requests",
|
|
250487
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
250488
|
+
label: "requests copy",
|
|
250489
|
+
log: log.session,
|
|
250490
|
+
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
250491
|
+
ordered: false,
|
|
250492
|
+
serial: (fn) => serial4(fn),
|
|
250493
|
+
refuse: copyRefusal,
|
|
250494
|
+
load: load6,
|
|
250495
|
+
save,
|
|
250496
|
+
isRow: isRow5,
|
|
250497
|
+
key: (r8) => r8.id,
|
|
250498
|
+
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
250499
|
+
apply: async ({ rows, removeIds }) => {
|
|
250500
|
+
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
250501
|
+
for (const id of removeIds ?? []) byId.delete(id);
|
|
250502
|
+
for (const r8 of rows ?? []) {
|
|
250503
|
+
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
250504
|
+
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 });
|
|
250505
|
+
byId.set(r8.id, kept);
|
|
250506
|
+
}
|
|
250507
|
+
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
250508
|
+
return { skipped: [] };
|
|
250509
|
+
},
|
|
250510
|
+
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
250511
|
+
changed: () => {
|
|
250512
|
+
},
|
|
250513
|
+
purge: async () => {
|
|
250514
|
+
const removed = (await readStore8()).length;
|
|
250515
|
+
await fsp124.rm(STORE_FILE(), { force: true });
|
|
250516
|
+
await markCopyOff("requests");
|
|
250517
|
+
state11 = null;
|
|
250518
|
+
return { removed };
|
|
250519
|
+
}
|
|
250520
|
+
});
|
|
250521
|
+
return follower3;
|
|
250522
|
+
}
|
|
250523
|
+
async function readRequestCopy(id) {
|
|
250524
|
+
if (!await copyKindHeld("requests")) return null;
|
|
250525
|
+
return (await readStore8()).find((r8) => r8.id === id) ?? null;
|
|
250526
|
+
}
|
|
250527
|
+
function _resetRequestsCopyForTesting() {
|
|
250528
|
+
state11 = null;
|
|
250529
|
+
follower3 = null;
|
|
250530
|
+
serial4 = serialChain();
|
|
250531
|
+
}
|
|
250532
|
+
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes5, REQUESTS_KIND, STATE_FILE, STORE_FILE, state11, serial4, follower3;
|
|
250533
|
+
var init_requests = __esm({
|
|
250534
|
+
"src/core/replication/kinds/requests.ts"() {
|
|
250535
|
+
"use strict";
|
|
250536
|
+
init_constants();
|
|
250537
|
+
init_logging();
|
|
250538
|
+
init_kind();
|
|
250539
|
+
init_kind_follower();
|
|
250540
|
+
init_gate();
|
|
250541
|
+
REQUESTS_SCHEMA_VERSION = 1;
|
|
250542
|
+
REQUESTS_REMOVAL_FLOOR = 50;
|
|
250543
|
+
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
250544
|
+
hashes5 = /* @__PURE__ */ new WeakMap();
|
|
250545
|
+
REQUESTS_KIND = {
|
|
250546
|
+
kind: "requests",
|
|
250547
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
250548
|
+
key: (r8) => r8.id,
|
|
250549
|
+
hash: hashOf6,
|
|
250550
|
+
ordered: false,
|
|
250551
|
+
digest: false,
|
|
250552
|
+
choice: "requests",
|
|
250553
|
+
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
250554
|
+
watch: (soon) => {
|
|
250555
|
+
let stop2 = null;
|
|
250556
|
+
let stopped2 = false;
|
|
250557
|
+
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
250558
|
+
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
250559
|
+
});
|
|
250560
|
+
return () => {
|
|
250561
|
+
stopped2 = true;
|
|
250562
|
+
stop2?.();
|
|
250563
|
+
};
|
|
250564
|
+
}
|
|
250565
|
+
};
|
|
250566
|
+
STATE_FILE = () => path233.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
250567
|
+
STORE_FILE = () => copyPath(path233.join(WALNUT_HOME, "session-requests.json"));
|
|
250568
|
+
state11 = null;
|
|
250569
|
+
serial4 = serialChain();
|
|
250570
|
+
follower3 = null;
|
|
250571
|
+
}
|
|
250572
|
+
});
|
|
250573
|
+
|
|
250280
250574
|
// src/web/routes/messages-v1.ts
|
|
250281
250575
|
import { Router as Router82 } from "express";
|
|
250282
250576
|
function header(req, name) {
|
|
@@ -250337,7 +250631,15 @@ var init_messages_v1 = __esm({
|
|
|
250337
250631
|
return;
|
|
250338
250632
|
}
|
|
250339
250633
|
const { getSessionRequest: getSessionRequest2 } = await Promise.resolve().then(() => (init_session_requests(), session_requests_exports));
|
|
250340
|
-
|
|
250634
|
+
let request3 = await getSessionRequest2(id);
|
|
250635
|
+
if (!request3) {
|
|
250636
|
+
const [{ readRequestCopy: readRequestCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
250637
|
+
Promise.resolve().then(() => (init_requests(), requests_exports)),
|
|
250638
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
250639
|
+
]);
|
|
250640
|
+
request3 = await readRequestCopy2(id) ?? void 0;
|
|
250641
|
+
if (request3) res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("requests") ?? 0));
|
|
250642
|
+
}
|
|
250341
250643
|
if (!request3) {
|
|
250342
250644
|
sendV1Error(res, 404, "not_found", `No such request: ${id}`);
|
|
250343
250645
|
return;
|
|
@@ -252012,6 +252314,17 @@ var init_search_memory_v1 = __esm({
|
|
|
252012
252314
|
});
|
|
252013
252315
|
searchMemoryV1Router.get("/favorites", async (_req, res, next) => {
|
|
252014
252316
|
try {
|
|
252317
|
+
const [{ readFavoritesCopy: readFavoritesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
252318
|
+
Promise.resolve().then(() => (init_prefs(), prefs_exports)),
|
|
252319
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
252320
|
+
]);
|
|
252321
|
+
const asOf2 = await copyKindAsOf2("prefs");
|
|
252322
|
+
const fav = asOf2 === null ? null : await readFavoritesCopy2();
|
|
252323
|
+
if (fav) {
|
|
252324
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(asOf2));
|
|
252325
|
+
res.json({ projects: fav.projects ?? [], notes: fav.notes ?? [] });
|
|
252326
|
+
return;
|
|
252327
|
+
}
|
|
252015
252328
|
const { readFavorites: readFavorites2 } = await Promise.resolve().then(() => (init_favorites(), favorites_exports));
|
|
252016
252329
|
res.json(await readFavorites2());
|
|
252017
252330
|
} catch (err2) {
|
|
@@ -253044,9 +253357,9 @@ var init_stt_v1 = __esm({
|
|
|
253044
253357
|
|
|
253045
253358
|
// src/web/routes/pastes.ts
|
|
253046
253359
|
import { Router as Router89 } from "express";
|
|
253047
|
-
import
|
|
253360
|
+
import path234 from "path";
|
|
253048
253361
|
import { createHash as createHash38 } from "crypto";
|
|
253049
|
-
import
|
|
253362
|
+
import fsp125 from "fs/promises";
|
|
253050
253363
|
var pastesRouter, MAX_PASTE_CHARS;
|
|
253051
253364
|
var init_pastes = __esm({
|
|
253052
253365
|
"src/web/routes/pastes.ts"() {
|
|
@@ -253066,11 +253379,11 @@ var init_pastes = __esm({
|
|
|
253066
253379
|
res.status(413).json({ error: `Paste too large (max ${MAX_PASTE_CHARS} chars)` });
|
|
253067
253380
|
return;
|
|
253068
253381
|
}
|
|
253069
|
-
await
|
|
253382
|
+
await fsp125.mkdir(PASTES_DIR, { recursive: true });
|
|
253070
253383
|
const hash3 = createHash38("sha256").update(text5).digest("hex").slice(0, 12);
|
|
253071
253384
|
const filename = `${Date.now()}-${hash3}.txt`;
|
|
253072
|
-
const filePath =
|
|
253073
|
-
await
|
|
253385
|
+
const filePath = path234.join(PASTES_DIR, filename);
|
|
253386
|
+
await fsp125.writeFile(filePath, text5, "utf8");
|
|
253074
253387
|
log.web.info("paste spilled to disk", { filePath, chars: text5.length });
|
|
253075
253388
|
res.json({ path: filePath, filename, chars: text5.length });
|
|
253076
253389
|
} catch (err2) {
|
|
@@ -253086,8 +253399,8 @@ __export(file_content_replica_copy_exports, {
|
|
|
253086
253399
|
primaryDataDirRelPath: () => primaryDataDirRelPath,
|
|
253087
253400
|
resolveReplicaCopy: () => resolveReplicaCopy
|
|
253088
253401
|
});
|
|
253089
|
-
import
|
|
253090
|
-
import
|
|
253402
|
+
import path235 from "path";
|
|
253403
|
+
import fsp126 from "fs/promises";
|
|
253091
253404
|
function dataDirIndex(parts, tilde) {
|
|
253092
253405
|
if (tilde) return parts[1] === DATA_DIR_NAME ? 1 : -1;
|
|
253093
253406
|
if ((parts[0] === "Users" || parts[0] === "home") && parts[2] === DATA_DIR_NAME) return 2;
|
|
@@ -253117,12 +253430,12 @@ async function resolveReplicaCopy(requestPath) {
|
|
|
253117
253430
|
const rel = primaryDataDirRelPath(requestPath);
|
|
253118
253431
|
if (rel === null || deniedName(rel)) return null;
|
|
253119
253432
|
try {
|
|
253120
|
-
const root6 = await
|
|
253121
|
-
const real = await
|
|
253122
|
-
if (!real.startsWith(root6 +
|
|
253123
|
-
const realRel =
|
|
253124
|
-
if (isSecretPath(
|
|
253125
|
-
const st2 = await
|
|
253433
|
+
const root6 = await fsp126.realpath(WALNUT_HOME);
|
|
253434
|
+
const real = await fsp126.realpath(path235.join(WALNUT_HOME, rel));
|
|
253435
|
+
if (!real.startsWith(root6 + path235.sep)) return null;
|
|
253436
|
+
const realRel = path235.relative(root6, real).split(path235.sep).join("/");
|
|
253437
|
+
if (isSecretPath(path235.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
|
|
253438
|
+
const st2 = await fsp126.stat(real);
|
|
253126
253439
|
if (!st2.isFile()) return null;
|
|
253127
253440
|
if (!await isTracked(root6, realRel)) return null;
|
|
253128
253441
|
return { localPath: real, size: st2.size };
|
|
@@ -253162,11 +253475,11 @@ var init_file_content_replica_copy = __esm({
|
|
|
253162
253475
|
// src/web/routes/media-v1.ts
|
|
253163
253476
|
import { Router as Router90 } from "express";
|
|
253164
253477
|
import crypto67 from "crypto";
|
|
253165
|
-
import
|
|
253166
|
-
import
|
|
253478
|
+
import path236 from "path";
|
|
253479
|
+
import fsp127 from "fs/promises";
|
|
253167
253480
|
function cachePathFor(host, filePath) {
|
|
253168
253481
|
const hash3 = crypto67.createHash("sha256").update(filePath).digest("hex").slice(0, 16);
|
|
253169
|
-
return
|
|
253482
|
+
return path236.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path236.basename(filePath)}`);
|
|
253170
253483
|
}
|
|
253171
253484
|
async function hostForSession(sessionId) {
|
|
253172
253485
|
if (CLOUD_MODE) {
|
|
@@ -253231,11 +253544,11 @@ var init_media_v1 = __esm({
|
|
|
253231
253544
|
try {
|
|
253232
253545
|
const filePath = req.query.path;
|
|
253233
253546
|
const session2 = typeof req.query.session === "string" && SID_RE6.test(req.query.session) ? req.query.session : void 0;
|
|
253234
|
-
if (!filePath || typeof filePath !== "string" || !
|
|
253547
|
+
if (!filePath || typeof filePath !== "string" || !path236.isAbsolute(filePath) || filePath.includes("..")) {
|
|
253235
253548
|
res.status(400).json({ error: { code: "bad_request", message: "path must be an absolute file path" } });
|
|
253236
253549
|
return;
|
|
253237
253550
|
}
|
|
253238
|
-
const ext2 =
|
|
253551
|
+
const ext2 = path236.extname(filePath).slice(1).toLowerCase();
|
|
253239
253552
|
const mime = EXT_TO_MIME3[ext2];
|
|
253240
253553
|
if (!mime) {
|
|
253241
253554
|
res.status(400).json({ error: { code: "bad_request", message: "file type not allowed" } });
|
|
@@ -253243,8 +253556,8 @@ var init_media_v1 = __esm({
|
|
|
253243
253556
|
}
|
|
253244
253557
|
let buffer2 = null;
|
|
253245
253558
|
try {
|
|
253246
|
-
const st2 = await
|
|
253247
|
-
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
253559
|
+
const st2 = await fsp127.stat(filePath);
|
|
253560
|
+
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(filePath);
|
|
253248
253561
|
} catch {
|
|
253249
253562
|
}
|
|
253250
253563
|
let waitedOnPending = false;
|
|
@@ -253265,8 +253578,8 @@ var init_media_v1 = __esm({
|
|
|
253265
253578
|
if (buffer2) {
|
|
253266
253579
|
try {
|
|
253267
253580
|
const cachePath3 = cachePathFor(host, filePath);
|
|
253268
|
-
await
|
|
253269
|
-
await
|
|
253581
|
+
await fsp127.mkdir(path236.dirname(cachePath3), { recursive: true });
|
|
253582
|
+
await fsp127.writeFile(cachePath3, buffer2);
|
|
253270
253583
|
} catch {
|
|
253271
253584
|
}
|
|
253272
253585
|
break;
|
|
@@ -253276,9 +253589,9 @@ var init_media_v1 = __esm({
|
|
|
253276
253589
|
for (const host of hosts2) {
|
|
253277
253590
|
try {
|
|
253278
253591
|
const cached8 = cachePathFor(host, filePath);
|
|
253279
|
-
const st2 = await
|
|
253592
|
+
const st2 = await fsp127.stat(cached8);
|
|
253280
253593
|
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) {
|
|
253281
|
-
buffer2 = await
|
|
253594
|
+
buffer2 = await fsp127.readFile(cached8);
|
|
253282
253595
|
break;
|
|
253283
253596
|
}
|
|
253284
253597
|
} catch {
|
|
@@ -253288,7 +253601,7 @@ var init_media_v1 = __esm({
|
|
|
253288
253601
|
if (!buffer2 && hosts2.length > 0 && hosts2.every((h8) => h8 === "__local__") && !(await Promise.resolve().then(() => (init_bridge_registry(), bridge_registry_exports))).bridgeForHost("__local__").connected) {
|
|
253289
253602
|
const { resolveReplicaCopy: resolveReplicaCopy2 } = await Promise.resolve().then(() => (init_file_content_replica_copy(), file_content_replica_copy_exports));
|
|
253290
253603
|
const copy5 = await resolveReplicaCopy2(filePath);
|
|
253291
|
-
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
253604
|
+
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(copy5.localPath);
|
|
253292
253605
|
}
|
|
253293
253606
|
}
|
|
253294
253607
|
if (!buffer2) {
|
|
@@ -253313,6 +253626,19 @@ var init_media_v1 = __esm({
|
|
|
253313
253626
|
|
|
253314
253627
|
// src/web/routes/routines-v1.ts
|
|
253315
253628
|
import { Router as Router91 } from "express";
|
|
253629
|
+
async function answeredFromCopy(res, includeDisabled, answer5) {
|
|
253630
|
+
const [{ companionRoutinesCopy: companionRoutinesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
253631
|
+
Promise.resolve().then(() => (init_routines_follower(), routines_follower_exports)),
|
|
253632
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
253633
|
+
]);
|
|
253634
|
+
const jobs2 = await companionRoutinesCopy2({ includeDisabled });
|
|
253635
|
+
if (!jobs2) return false;
|
|
253636
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("routines") ?? 0));
|
|
253637
|
+
const body7 = answer5(jobs2);
|
|
253638
|
+
if (body7 === null) sendV1Error(res, 404, "not_found", "No such routine in the copy of your Mac's routines");
|
|
253639
|
+
else res.json(body7);
|
|
253640
|
+
return true;
|
|
253641
|
+
}
|
|
253316
253642
|
function validRid(req, res) {
|
|
253317
253643
|
const id = String(req.params.id ?? "");
|
|
253318
253644
|
if (!RID_RE.test(id)) {
|
|
@@ -253359,6 +253685,7 @@ var init_routines_v1 = __esm({
|
|
|
253359
253685
|
try {
|
|
253360
253686
|
const includeDisabled = req.query.includeDisabled === "true";
|
|
253361
253687
|
if (CLOUD_MODE) {
|
|
253688
|
+
if (await answeredFromCopy(res, includeDisabled, (jobs2) => ({ jobs: jobs2 }))) return;
|
|
253362
253689
|
await relayControlAction(res, "server.routines", SERVER_RELAY_SID14, { includeDisabled }, 200);
|
|
253363
253690
|
return;
|
|
253364
253691
|
}
|
|
@@ -253383,6 +253710,7 @@ var init_routines_v1 = __esm({
|
|
|
253383
253710
|
routinesV1Router.get("/routines/status", async (_req, res, next) => {
|
|
253384
253711
|
try {
|
|
253385
253712
|
if (CLOUD_MODE) {
|
|
253713
|
+
if (await answeredFromCopy(res, true, (jobs2) => ({ enabled: false, storePath: "", jobs: jobs2.length, nextWakeAtMs: null }))) return;
|
|
253386
253714
|
await relayControlAction(res, "server.routines.status", SERVER_RELAY_SID14, void 0, 200);
|
|
253387
253715
|
return;
|
|
253388
253716
|
}
|
|
@@ -253454,6 +253782,10 @@ var init_routines_v1 = __esm({
|
|
|
253454
253782
|
const id = validRid(req, res);
|
|
253455
253783
|
if (!id) return;
|
|
253456
253784
|
if (CLOUD_MODE) {
|
|
253785
|
+
if (await answeredFromCopy(res, true, (jobs2) => {
|
|
253786
|
+
const job2 = jobs2.find((j8) => j8.id === id);
|
|
253787
|
+
return job2 ? { job: job2 } : null;
|
|
253788
|
+
})) return;
|
|
253457
253789
|
await relayControlAction(res, "server.routines.get", SERVER_RELAY_SID14, { id }, 200);
|
|
253458
253790
|
return;
|
|
253459
253791
|
}
|
|
@@ -254648,8 +254980,8 @@ __export(file_content_bridge_exports, {
|
|
|
254648
254980
|
resolveBridgeHost: () => resolveBridgeHost,
|
|
254649
254981
|
serveCloudFileContent: () => serveCloudFileContent
|
|
254650
254982
|
});
|
|
254651
|
-
import
|
|
254652
|
-
import
|
|
254983
|
+
import path237 from "path";
|
|
254984
|
+
import fsp128 from "fs/promises";
|
|
254653
254985
|
function resolveBridgeHost(host) {
|
|
254654
254986
|
return typeof host === "string" && host.length > 0 ? host : PRIMARY_BRIDGE_ALIAS4;
|
|
254655
254987
|
}
|
|
@@ -254720,7 +255052,7 @@ function precheckPath(res, rawPath) {
|
|
|
254720
255052
|
sendV1Error(res, 400, "bad_request", "Invalid path");
|
|
254721
255053
|
return null;
|
|
254722
255054
|
}
|
|
254723
|
-
if (rawPath !== "~" && !rawPath.startsWith("~/") && !
|
|
255055
|
+
if (rawPath !== "~" && !rawPath.startsWith("~/") && !path237.isAbsolute(rawPath)) {
|
|
254724
255056
|
sendV1Error(res, 400, "bad_request", "Path must be absolute");
|
|
254725
255057
|
return null;
|
|
254726
255058
|
}
|
|
@@ -254764,7 +255096,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
254764
255096
|
const hostAlias2 = resolveBridgeHost(req.query.host);
|
|
254765
255097
|
const raw = req.query.raw === "1" || req.query.raw === "true";
|
|
254766
255098
|
const download = req.query.download === "1" || req.query.download === "true";
|
|
254767
|
-
const ext2 =
|
|
255099
|
+
const ext2 = path237.extname(filePath).slice(1).toLowerCase();
|
|
254768
255100
|
const {
|
|
254769
255101
|
assertPathAllowed: assertPathAllowed2,
|
|
254770
255102
|
isSecretPath: isSecretPath2,
|
|
@@ -254774,7 +255106,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
254774
255106
|
FileContentError: FileContentError2
|
|
254775
255107
|
} = await Promise.resolve().then(() => (init_file_content(), file_content_exports));
|
|
254776
255108
|
const explicitHost = typeof req.query.host === "string" && req.query.host.length > 0;
|
|
254777
|
-
const locallyPresent = await
|
|
255109
|
+
const locallyPresent = await fsp128.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
|
|
254778
255110
|
if (!explicitHost && locallyPresent && cloudLocalReadAllowed2(filePath) && !isSecretPath2(filePath)) {
|
|
254779
255111
|
try {
|
|
254780
255112
|
if (raw) {
|
|
@@ -254872,10 +255204,10 @@ async function serveReplicaCopy(req, res, requestPath, copy5, opts2) {
|
|
|
254872
255204
|
return;
|
|
254873
255205
|
}
|
|
254874
255206
|
if (copy5.size <= MAX_BRIDGE_FILE_BYTES) {
|
|
254875
|
-
res.json(jsonPayloadFromBuffer(await
|
|
255207
|
+
res.json(jsonPayloadFromBuffer(await fsp128.readFile(copy5.localPath), opts2.ext, false));
|
|
254876
255208
|
return;
|
|
254877
255209
|
}
|
|
254878
|
-
const fh = await
|
|
255210
|
+
const fh = await fsp128.open(copy5.localPath, "r");
|
|
254879
255211
|
try {
|
|
254880
255212
|
const head2 = Buffer.alloc(MAX_TEXT_PAYLOAD);
|
|
254881
255213
|
const { bytesRead } = await fh.read(head2, 0, head2.length, 0);
|
|
@@ -255949,17 +256281,17 @@ __export(checklist_io_exports, {
|
|
|
255949
256281
|
readHeartbeatChecklist: () => readHeartbeatChecklist,
|
|
255950
256282
|
writeHeartbeatChecklist: () => writeHeartbeatChecklist
|
|
255951
256283
|
});
|
|
255952
|
-
import
|
|
256284
|
+
import fsp129 from "fs/promises";
|
|
255953
256285
|
async function readHeartbeatChecklist() {
|
|
255954
256286
|
try {
|
|
255955
|
-
return await
|
|
256287
|
+
return await fsp129.readFile(HEARTBEAT_FILE, "utf-8");
|
|
255956
256288
|
} catch (err2) {
|
|
255957
256289
|
if (err2.code === "ENOENT") return "";
|
|
255958
256290
|
throw err2;
|
|
255959
256291
|
}
|
|
255960
256292
|
}
|
|
255961
256293
|
async function writeHeartbeatChecklist(content) {
|
|
255962
|
-
await
|
|
256294
|
+
await fsp129.writeFile(HEARTBEAT_FILE, content, "utf-8");
|
|
255963
256295
|
}
|
|
255964
256296
|
var init_checklist_io = __esm({
|
|
255965
256297
|
"src/heartbeat/checklist-io.ts"() {
|
|
@@ -258099,11 +258431,11 @@ __export(ephemeral_guard_exports, {
|
|
|
258099
258431
|
});
|
|
258100
258432
|
import fs127 from "fs";
|
|
258101
258433
|
import os60 from "os";
|
|
258102
|
-
import
|
|
258434
|
+
import path238 from "path";
|
|
258103
258435
|
function productionWalnutHomes() {
|
|
258104
258436
|
const homes = /* @__PURE__ */ new Set();
|
|
258105
258437
|
const add3 = (home) => {
|
|
258106
|
-
if (home) homes.add(
|
|
258438
|
+
if (home) homes.add(path238.join(home, ".open-walnut"));
|
|
258107
258439
|
};
|
|
258108
258440
|
add3(os60.homedir());
|
|
258109
258441
|
try {
|
|
@@ -258113,7 +258445,7 @@ function productionWalnutHomes() {
|
|
|
258113
258445
|
return [...homes];
|
|
258114
258446
|
}
|
|
258115
258447
|
function canonical2(dir4) {
|
|
258116
|
-
const resolved =
|
|
258448
|
+
const resolved = path238.resolve(dir4);
|
|
258117
258449
|
try {
|
|
258118
258450
|
return fs127.realpathSync(resolved);
|
|
258119
258451
|
} catch {
|
|
@@ -258149,28 +258481,28 @@ __export(boot_guard_exports, {
|
|
|
258149
258481
|
});
|
|
258150
258482
|
import fs128 from "fs";
|
|
258151
258483
|
import os61 from "os";
|
|
258152
|
-
import
|
|
258484
|
+
import path239 from "path";
|
|
258153
258485
|
function canonical3(dir4) {
|
|
258154
|
-
let head2 =
|
|
258486
|
+
let head2 = path239.resolve(dir4);
|
|
258155
258487
|
const rest = [];
|
|
258156
258488
|
for (; ; ) {
|
|
258157
258489
|
try {
|
|
258158
|
-
return
|
|
258490
|
+
return path239.join(fs128.realpathSync(head2), ...rest);
|
|
258159
258491
|
} catch {
|
|
258160
258492
|
}
|
|
258161
|
-
const up =
|
|
258162
|
-
if (up === head2) return
|
|
258163
|
-
rest.unshift(
|
|
258493
|
+
const up = path239.dirname(head2);
|
|
258494
|
+
if (up === head2) return path239.resolve(dir4);
|
|
258495
|
+
rest.unshift(path239.basename(head2));
|
|
258164
258496
|
head2 = up;
|
|
258165
258497
|
}
|
|
258166
258498
|
}
|
|
258167
258499
|
function spellings(dir4) {
|
|
258168
|
-
const resolved =
|
|
258500
|
+
const resolved = path239.resolve(dir4);
|
|
258169
258501
|
return [.../* @__PURE__ */ new Set([resolved, canonical3(resolved), `/private${resolved}`])];
|
|
258170
258502
|
}
|
|
258171
258503
|
function within5(child2, parent) {
|
|
258172
|
-
const rel =
|
|
258173
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
258504
|
+
const rel = path239.relative(parent, child2);
|
|
258505
|
+
return rel === "" || !rel.startsWith("..") && !path239.isAbsolute(rel);
|
|
258174
258506
|
}
|
|
258175
258507
|
function overlaps(a8, b8) {
|
|
258176
258508
|
return spellings(a8).some((x3) => spellings(b8).some((y3) => within5(x3, y3) || within5(y3, x3)));
|
|
@@ -258181,7 +258513,7 @@ function holdsOrIs(outer, inner2) {
|
|
|
258181
258513
|
function accountHomes(env3) {
|
|
258182
258514
|
const homes = /* @__PURE__ */ new Set();
|
|
258183
258515
|
const add3 = (h8) => {
|
|
258184
|
-
if (h8 && h8.trim()) homes.add(
|
|
258516
|
+
if (h8 && h8.trim()) homes.add(path239.resolve(h8.trim()));
|
|
258185
258517
|
};
|
|
258186
258518
|
add3(env3.HOME);
|
|
258187
258519
|
add3(os61.homedir());
|
|
@@ -258239,7 +258571,7 @@ function assertReplicaBootSafe(input) {
|
|
|
258239
258571
|
if (why2) throw new Error(`Host replica refused to start: ${why2}.`);
|
|
258240
258572
|
}
|
|
258241
258573
|
function claimReplicaDir(dir4) {
|
|
258242
|
-
const marker =
|
|
258574
|
+
const marker = path239.join(dir4, REPLICA_DIR_MARKER);
|
|
258243
258575
|
try {
|
|
258244
258576
|
return fs128.lstatSync(marker).isFile();
|
|
258245
258577
|
} catch {
|
|
@@ -258264,7 +258596,7 @@ function claimReplicaDir(dir4) {
|
|
|
258264
258596
|
function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
258265
258597
|
const marked = dirs2.filter((d8) => {
|
|
258266
258598
|
try {
|
|
258267
|
-
return fs128.lstatSync(
|
|
258599
|
+
return fs128.lstatSync(path239.join(d8, REPLICA_DIR_MARKER)).isFile();
|
|
258268
258600
|
} catch {
|
|
258269
258601
|
return false;
|
|
258270
258602
|
}
|
|
@@ -258294,7 +258626,7 @@ function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
|
258294
258626
|
} catch {
|
|
258295
258627
|
return;
|
|
258296
258628
|
}
|
|
258297
|
-
for (const n6 of names2) visit(
|
|
258629
|
+
for (const n6 of names2) visit(path239.join(p6, n6));
|
|
258298
258630
|
} else if (st2.isFile() && (st2.mode & 63) !== 0) {
|
|
258299
258631
|
try {
|
|
258300
258632
|
fs128.chmodSync(p6, st2.mode & 448 | 384);
|
|
@@ -258481,29 +258813,29 @@ __export(search_replica_store_exports, {
|
|
|
258481
258813
|
searchReplicaSync: () => searchReplicaSync,
|
|
258482
258814
|
startSearchReplicaStore: () => startSearchReplicaStore
|
|
258483
258815
|
});
|
|
258484
|
-
import
|
|
258816
|
+
import fsp130 from "fs/promises";
|
|
258485
258817
|
import os62 from "os";
|
|
258486
|
-
import
|
|
258818
|
+
import path240 from "path";
|
|
258487
258819
|
async function wiring() {
|
|
258488
258820
|
return Promise.resolve().then(() => (init_wiring(), wiring_exports));
|
|
258489
258821
|
}
|
|
258490
258822
|
async function loadState() {
|
|
258491
|
-
if (
|
|
258823
|
+
if (state12) return state12;
|
|
258492
258824
|
let s4 = { v: 1, mode: null, syncedAt: null };
|
|
258493
258825
|
try {
|
|
258494
|
-
const raw = JSON.parse(await
|
|
258826
|
+
const raw = JSON.parse(await fsp130.readFile(STATE_FILE2(), "utf8"));
|
|
258495
258827
|
if (raw && raw.v === 1) {
|
|
258496
258828
|
s4 = { v: 1, mode: raw.mode ? companionSearchMode(raw.mode) : null, syncedAt: typeof raw.syncedAt === "number" ? raw.syncedAt : null };
|
|
258497
258829
|
}
|
|
258498
258830
|
} catch {
|
|
258499
258831
|
}
|
|
258500
|
-
|
|
258832
|
+
state12 = s4;
|
|
258501
258833
|
return s4;
|
|
258502
258834
|
}
|
|
258503
258835
|
async function saveState() {
|
|
258504
|
-
if (
|
|
258836
|
+
if (state12) await writeJsonFile(STATE_FILE2(), state12);
|
|
258505
258837
|
}
|
|
258506
|
-
function
|
|
258838
|
+
function serial5(fn) {
|
|
258507
258839
|
const run12 = chain4.then(fn, fn);
|
|
258508
258840
|
chain4 = run12.catch(() => {
|
|
258509
258841
|
});
|
|
@@ -258567,8 +258899,8 @@ async function closeIndex() {
|
|
|
258567
258899
|
allDirty2 = true;
|
|
258568
258900
|
}
|
|
258569
258901
|
function publishReady() {
|
|
258570
|
-
const ready2 = enabled && mapBuilt && map3.size > 0 &&
|
|
258571
|
-
setCompanionSearchReady(ready2, ready2 ?
|
|
258902
|
+
const ready2 = enabled && mapBuilt && map3.size > 0 && state12?.syncedAt != null;
|
|
258903
|
+
setCompanionSearchReady(ready2, ready2 ? state12.syncedAt : null);
|
|
258572
258904
|
}
|
|
258573
258905
|
async function markInSync() {
|
|
258574
258906
|
const s4 = await loadState();
|
|
@@ -258595,7 +258927,7 @@ async function warm(why2) {
|
|
|
258595
258927
|
}
|
|
258596
258928
|
}
|
|
258597
258929
|
function searchReplicaStatus(body7) {
|
|
258598
|
-
return
|
|
258930
|
+
return serial5(async () => {
|
|
258599
258931
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
258600
258932
|
const s4 = await loadState();
|
|
258601
258933
|
const mode = companionSearchMode(body7.mode);
|
|
@@ -258643,7 +258975,7 @@ function searchReplicaStatus(body7) {
|
|
|
258643
258975
|
});
|
|
258644
258976
|
}
|
|
258645
258977
|
function searchReplicaSync(body7) {
|
|
258646
|
-
return
|
|
258978
|
+
return serial5(async () => {
|
|
258647
258979
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
258648
258980
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
258649
258981
|
if (!Array.isArray(body7.entries)) return { ok: false, status: 400, error: "bad_entries" };
|
|
@@ -258688,7 +259020,7 @@ async function forgetSearchMemo() {
|
|
|
258688
259020
|
}
|
|
258689
259021
|
}
|
|
258690
259022
|
function searchReplicaPut(body7) {
|
|
258691
|
-
return
|
|
259023
|
+
return serial5(async () => {
|
|
258692
259024
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
258693
259025
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
258694
259026
|
if (!Array.isArray(body7.docs)) return { ok: false, status: 400, error: "bad_docs" };
|
|
@@ -258754,7 +259086,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
258754
259086
|
if (!s4.mode || stopped2) return;
|
|
258755
259087
|
const decision = companionSearchDecision(s4.mode, deps3.totalMb());
|
|
258756
259088
|
if (!decision.enabled) return;
|
|
258757
|
-
await
|
|
259089
|
+
await serial5(async () => {
|
|
258758
259090
|
enabled = true;
|
|
258759
259091
|
reason2 = decision.reason;
|
|
258760
259092
|
await refreshMap2(await openIndex());
|
|
@@ -258787,12 +259119,12 @@ function startSearchReplicaStore(options = {}) {
|
|
|
258787
259119
|
}));
|
|
258788
259120
|
}).catch((err2) => log.memory.warn("search replica: local writes not wired", { error: err2 instanceof Error ? err2.message : String(err2) }));
|
|
258789
259121
|
unsubs.push(onLeaderPresence((answers4) => {
|
|
258790
|
-
if (stopped2 || answers4 || !enabled ||
|
|
259122
|
+
if (stopped2 || answers4 || !enabled || state12?.syncedAt == null) return;
|
|
258791
259123
|
void warm("leader away");
|
|
258792
259124
|
}));
|
|
258793
259125
|
const tick = setInterval(() => {
|
|
258794
259126
|
void (async () => {
|
|
258795
|
-
if (stopped2 || !enabled ||
|
|
259127
|
+
if (stopped2 || !enabled || state12?.syncedAt == null) return;
|
|
258796
259128
|
if (Date.now() - lastWarmAt < WARM_EVERY_MS) return;
|
|
258797
259129
|
if (!await deps3.macAway()) return;
|
|
258798
259130
|
await warm("mac away");
|
|
@@ -258811,7 +259143,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
258811
259143
|
};
|
|
258812
259144
|
}
|
|
258813
259145
|
function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
258814
|
-
|
|
259146
|
+
state12 = null;
|
|
258815
259147
|
enabled = false;
|
|
258816
259148
|
reason2 = "off";
|
|
258817
259149
|
map3.clear();
|
|
@@ -258826,7 +259158,7 @@ function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
|
258826
259158
|
deps3 = { totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)), macAway: defaultMacAway, ...overrides };
|
|
258827
259159
|
setCompanionSearchReady(false, null);
|
|
258828
259160
|
}
|
|
258829
|
-
var
|
|
259161
|
+
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;
|
|
258830
259162
|
var init_search_replica_store = __esm({
|
|
258831
259163
|
"src/core/replication/search-replica-store.ts"() {
|
|
258832
259164
|
"use strict";
|
|
@@ -258838,7 +259170,7 @@ var init_search_replica_store = __esm({
|
|
|
258838
259170
|
init_replica_refs();
|
|
258839
259171
|
init_search_digest();
|
|
258840
259172
|
init_search_replica_wire();
|
|
258841
|
-
|
|
259173
|
+
STATE_FILE2 = () => path240.join(WALNUT_HOME, "cache", "search-replica.json");
|
|
258842
259174
|
MASS_REMOVE_FLOOR = 200;
|
|
258843
259175
|
SCAN_SLICE2 = 500;
|
|
258844
259176
|
WARM_EVERY_MS = 4 * 6e4;
|
|
@@ -258848,7 +259180,7 @@ var init_search_replica_store = __esm({
|
|
|
258848
259180
|
totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)),
|
|
258849
259181
|
macAway: defaultMacAway
|
|
258850
259182
|
};
|
|
258851
|
-
|
|
259183
|
+
state12 = null;
|
|
258852
259184
|
enabled = false;
|
|
258853
259185
|
reason2 = "off";
|
|
258854
259186
|
map3 = new DigestMap();
|
|
@@ -258864,10 +259196,10 @@ var init_search_replica_store = __esm({
|
|
|
258864
259196
|
});
|
|
258865
259197
|
|
|
258866
259198
|
// src/core/replication/kinds/boards.ts
|
|
258867
|
-
import
|
|
258868
|
-
import
|
|
259199
|
+
import fsp131 from "fs/promises";
|
|
259200
|
+
import path241 from "path";
|
|
258869
259201
|
async function leaderBoards(dir4 = boardsDir2()) {
|
|
258870
|
-
const names2 = await
|
|
259202
|
+
const names2 = await fsp131.readdir(dir4).catch(() => []);
|
|
258871
259203
|
const out = [];
|
|
258872
259204
|
const unreadable = [];
|
|
258873
259205
|
const seen2 = /* @__PURE__ */ new Set();
|
|
@@ -258876,9 +259208,9 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
258876
259208
|
const id = name.slice(0, -".json".length);
|
|
258877
259209
|
if (!TASK_ID_RE3.test(id)) continue;
|
|
258878
259210
|
seen2.add(id);
|
|
258879
|
-
const file =
|
|
259211
|
+
const file = path241.join(dir4, name);
|
|
258880
259212
|
try {
|
|
258881
|
-
const st2 = await
|
|
259213
|
+
const st2 = await fsp131.stat(file);
|
|
258882
259214
|
if (!st2.isFile()) continue;
|
|
258883
259215
|
if (st2.size > BOARD_COPY_MAX_BYTES) {
|
|
258884
259216
|
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 });
|
|
@@ -258887,14 +259219,14 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
258887
259219
|
}
|
|
258888
259220
|
let c8 = cache16.get(id);
|
|
258889
259221
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
258890
|
-
const row = JSON.parse(await
|
|
258891
|
-
if (!
|
|
259222
|
+
const row = JSON.parse(await fsp131.readFile(file, "utf8"));
|
|
259223
|
+
if (!isRow6(row) || row.task_id !== id) {
|
|
258892
259224
|
unreadable.push(id);
|
|
258893
259225
|
continue;
|
|
258894
259226
|
}
|
|
258895
259227
|
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, row, hash: sha12(JSON.stringify(row)) };
|
|
258896
259228
|
cache16.set(id, c8);
|
|
258897
|
-
|
|
259229
|
+
hashOf7.set(row, c8.hash);
|
|
258898
259230
|
}
|
|
258899
259231
|
out.push(c8.row);
|
|
258900
259232
|
} catch (err2) {
|
|
@@ -258909,56 +259241,56 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
258909
259241
|
if (fresh.length > 0) log.session.warn("boards copy: a board could not be read, the host keeps its copy of it", { taskIds: fresh });
|
|
258910
259242
|
return out;
|
|
258911
259243
|
}
|
|
258912
|
-
function
|
|
259244
|
+
function isRow6(v3) {
|
|
258913
259245
|
const b8 = v3;
|
|
258914
259246
|
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";
|
|
258915
259247
|
}
|
|
258916
|
-
async function
|
|
258917
|
-
if (
|
|
259248
|
+
async function load7() {
|
|
259249
|
+
if (state13) return state13;
|
|
258918
259250
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
258919
259251
|
try {
|
|
258920
|
-
const raw = JSON.parse(await
|
|
259252
|
+
const raw = JSON.parse(await fsp131.readFile(STATE_FILE3(), "utf8"));
|
|
258921
259253
|
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 };
|
|
258922
259254
|
} catch {
|
|
258923
259255
|
}
|
|
258924
|
-
|
|
259256
|
+
state13 = s4;
|
|
258925
259257
|
return s4;
|
|
258926
259258
|
}
|
|
258927
|
-
async function
|
|
258928
|
-
if (
|
|
259259
|
+
async function save2() {
|
|
259260
|
+
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
258929
259261
|
}
|
|
258930
259262
|
async function localIds() {
|
|
258931
|
-
const names2 = await
|
|
259263
|
+
const names2 = await fsp131.readdir(boardsDir2()).catch(() => []);
|
|
258932
259264
|
return names2.filter((n6) => n6.endsWith(".json")).map((n6) => n6.slice(0, -".json".length)).filter((id) => TASK_ID_RE3.test(id));
|
|
258933
259265
|
}
|
|
258934
259266
|
function changed3() {
|
|
258935
259267
|
}
|
|
258936
259268
|
function boardsFollower() {
|
|
258937
|
-
|
|
259269
|
+
follower4 ??= createRowSetFollower({
|
|
258938
259270
|
kind: "boards",
|
|
258939
259271
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
258940
259272
|
label: "boards copy",
|
|
258941
259273
|
log: log.session,
|
|
258942
259274
|
removalFloor: BOARDS_REMOVAL_FLOOR,
|
|
258943
259275
|
ordered: false,
|
|
258944
|
-
serial: (fn) =>
|
|
259276
|
+
serial: (fn) => serial6(fn),
|
|
258945
259277
|
refuse: copyRefusal,
|
|
258946
|
-
load:
|
|
258947
|
-
save,
|
|
258948
|
-
isRow:
|
|
259278
|
+
load: load7,
|
|
259279
|
+
save: save2,
|
|
259280
|
+
isRow: isRow6,
|
|
258949
259281
|
key: (b8) => b8.task_id,
|
|
258950
259282
|
localKeys: localIds,
|
|
258951
259283
|
apply: async ({ rows, removeIds }) => {
|
|
258952
259284
|
const skipped = [];
|
|
258953
259285
|
for (const id of removeIds ?? []) {
|
|
258954
|
-
if (TASK_ID_RE3.test(id)) await
|
|
259286
|
+
if (TASK_ID_RE3.test(id)) await fsp131.rm(path241.join(boardsDir2(), `${id}.json`), { force: true });
|
|
258955
259287
|
}
|
|
258956
259288
|
for (const b8 of rows ?? []) {
|
|
258957
259289
|
if (Buffer.byteLength(JSON.stringify(b8)) > BOARD_COPY_MAX_BYTES) {
|
|
258958
259290
|
skipped.push(b8.task_id);
|
|
258959
259291
|
continue;
|
|
258960
259292
|
}
|
|
258961
|
-
await writeCopyFile(
|
|
259293
|
+
await writeCopyFile(path241.join(boardsDir2(), `${b8.task_id}.json`), b8);
|
|
258962
259294
|
}
|
|
258963
259295
|
return { skipped };
|
|
258964
259296
|
},
|
|
@@ -258966,15 +259298,15 @@ function boardsFollower() {
|
|
|
258966
259298
|
changed: changed3,
|
|
258967
259299
|
purge: async () => {
|
|
258968
259300
|
const ids2 = await localIds();
|
|
258969
|
-
for (const id of ids2) await
|
|
259301
|
+
for (const id of ids2) await fsp131.rm(path241.join(boardsDir2(), `${id}.json`), { force: true });
|
|
258970
259302
|
await markCopyOff("boards");
|
|
258971
|
-
|
|
259303
|
+
state13 = null;
|
|
258972
259304
|
return { removed: ids2.length };
|
|
258973
259305
|
}
|
|
258974
259306
|
});
|
|
258975
|
-
return
|
|
259307
|
+
return follower4;
|
|
258976
259308
|
}
|
|
258977
|
-
var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16,
|
|
259309
|
+
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;
|
|
258978
259310
|
var init_boards2 = __esm({
|
|
258979
259311
|
"src/core/replication/kinds/boards.ts"() {
|
|
258980
259312
|
"use strict";
|
|
@@ -258987,9 +259319,9 @@ var init_boards2 = __esm({
|
|
|
258987
259319
|
BOARDS_REMOVAL_FLOOR = 20;
|
|
258988
259320
|
BOARD_COPY_MAX_BYTES = 2 * 1024 * 1024;
|
|
258989
259321
|
TASK_ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
258990
|
-
boardsDir2 = () =>
|
|
259322
|
+
boardsDir2 = () => path241.join(WALNUT_HOME, "boards");
|
|
258991
259323
|
cache16 = /* @__PURE__ */ new Map();
|
|
258992
|
-
|
|
259324
|
+
hashOf7 = /* @__PURE__ */ new WeakMap();
|
|
258993
259325
|
warnedTooBig = /* @__PURE__ */ new Set();
|
|
258994
259326
|
unreadableOf2 = /* @__PURE__ */ new WeakMap();
|
|
258995
259327
|
warnedUnreadable = /* @__PURE__ */ new Set();
|
|
@@ -258997,7 +259329,7 @@ var init_boards2 = __esm({
|
|
|
258997
259329
|
kind: "boards",
|
|
258998
259330
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
258999
259331
|
key: (b8) => b8.task_id,
|
|
259000
|
-
hash: (b8) =>
|
|
259332
|
+
hash: (b8) => hashOf7.get(b8) ?? sha12(JSON.stringify(b8)),
|
|
259001
259333
|
ordered: false,
|
|
259002
259334
|
digest: false,
|
|
259003
259335
|
choice: "boards",
|
|
@@ -259017,16 +259349,16 @@ var init_boards2 = __esm({
|
|
|
259017
259349
|
};
|
|
259018
259350
|
}
|
|
259019
259351
|
};
|
|
259020
|
-
|
|
259021
|
-
|
|
259022
|
-
|
|
259023
|
-
|
|
259352
|
+
STATE_FILE3 = () => path241.join(WALNUT_HOME, "cache", "replica", "boards.json");
|
|
259353
|
+
state13 = null;
|
|
259354
|
+
serial6 = serialChain();
|
|
259355
|
+
follower4 = null;
|
|
259024
259356
|
}
|
|
259025
259357
|
});
|
|
259026
259358
|
|
|
259027
259359
|
// src/core/replication/kinds/inbox.ts
|
|
259028
|
-
import
|
|
259029
|
-
import
|
|
259360
|
+
import fsp132 from "fs/promises";
|
|
259361
|
+
import path242 from "path";
|
|
259030
259362
|
function watchLetters(soon) {
|
|
259031
259363
|
let stop2 = null;
|
|
259032
259364
|
let stopped2 = false;
|
|
@@ -259039,18 +259371,18 @@ function watchLetters(soon) {
|
|
|
259039
259371
|
};
|
|
259040
259372
|
}
|
|
259041
259373
|
async function leaderBodies(dir4 = bodiesDir()) {
|
|
259042
|
-
const names2 = (await
|
|
259374
|
+
const names2 = (await fsp132.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
|
|
259043
259375
|
const out = [];
|
|
259044
259376
|
const unreadable = [];
|
|
259045
259377
|
const seen2 = new Set(names2);
|
|
259046
259378
|
for (const name of names2) {
|
|
259047
|
-
const file =
|
|
259379
|
+
const file = path242.join(dir4, name);
|
|
259048
259380
|
try {
|
|
259049
|
-
const st2 = await
|
|
259381
|
+
const st2 = await fsp132.stat(file);
|
|
259050
259382
|
if (!st2.isFile() || st2.size > INBOX_BODY_COPY_MAX_BYTES) continue;
|
|
259051
259383
|
let c8 = bodyCache.get(name);
|
|
259052
259384
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
259053
|
-
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await
|
|
259385
|
+
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp132.readFile(file, "utf8")) };
|
|
259054
259386
|
bodyCache.set(name, c8);
|
|
259055
259387
|
}
|
|
259056
259388
|
const row = { name };
|
|
@@ -259069,21 +259401,21 @@ async function loadBody(b8) {
|
|
|
259069
259401
|
const file = bodyFiles.get(b8);
|
|
259070
259402
|
if (!file) return typeof b8.body === "string" ? b8 : void 0;
|
|
259071
259403
|
try {
|
|
259072
|
-
const body7 = await
|
|
259404
|
+
const body7 = await fsp132.readFile(file, "utf8");
|
|
259073
259405
|
return Buffer.byteLength(body7) > INBOX_BODY_COPY_MAX_BYTES ? void 0 : { name: b8.name, body: body7 };
|
|
259074
259406
|
} catch {
|
|
259075
259407
|
return void 0;
|
|
259076
259408
|
}
|
|
259077
259409
|
}
|
|
259078
259410
|
function stateIo(name) {
|
|
259079
|
-
const file = () =>
|
|
259411
|
+
const file = () => path242.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
|
|
259080
259412
|
let state17 = null;
|
|
259081
259413
|
return {
|
|
259082
259414
|
load: async () => {
|
|
259083
259415
|
if (state17) return state17;
|
|
259084
259416
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
259085
259417
|
try {
|
|
259086
|
-
const raw = JSON.parse(await
|
|
259418
|
+
const raw = JSON.parse(await fsp132.readFile(file(), "utf8"));
|
|
259087
259419
|
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") {
|
|
259088
259420
|
s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: Array.isArray(raw.order) ? raw.order.map(String) : [], hashes: raw.hashes };
|
|
259089
259421
|
}
|
|
@@ -259102,7 +259434,7 @@ function stateIo(name) {
|
|
|
259102
259434
|
}
|
|
259103
259435
|
async function readIndex3() {
|
|
259104
259436
|
try {
|
|
259105
|
-
const raw = JSON.parse(await
|
|
259437
|
+
const raw = JSON.parse(await fsp132.readFile(indexFile3(), "utf8"));
|
|
259106
259438
|
return Array.isArray(raw?.letters) ? raw.letters.filter(isLetter) : [];
|
|
259107
259439
|
} catch {
|
|
259108
259440
|
return [];
|
|
@@ -259125,7 +259457,7 @@ function inboxFollower() {
|
|
|
259125
259457
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
259126
259458
|
ordered: true,
|
|
259127
259459
|
digest: true,
|
|
259128
|
-
serial: (fn) =>
|
|
259460
|
+
serial: (fn) => serial7(fn),
|
|
259129
259461
|
refuse: refuse14,
|
|
259130
259462
|
load: () => indexIo.load(),
|
|
259131
259463
|
save: () => indexIo.save(),
|
|
@@ -259155,7 +259487,7 @@ function inboxFollower() {
|
|
|
259155
259487
|
},
|
|
259156
259488
|
purge: async () => {
|
|
259157
259489
|
const removed = (await readIndex3()).length;
|
|
259158
|
-
await
|
|
259490
|
+
await fsp132.rm(indexFile3(), { force: true });
|
|
259159
259491
|
await markCopyOff("inbox");
|
|
259160
259492
|
indexIo.reset();
|
|
259161
259493
|
return { removed };
|
|
@@ -259171,23 +259503,23 @@ function inboxBodiesFollower() {
|
|
|
259171
259503
|
log: log.notif,
|
|
259172
259504
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
259173
259505
|
ordered: false,
|
|
259174
|
-
serial: (fn) =>
|
|
259506
|
+
serial: (fn) => serial7(fn),
|
|
259175
259507
|
refuse: refuse14,
|
|
259176
259508
|
load: () => bodiesIo.load(),
|
|
259177
259509
|
save: () => bodiesIo.save(),
|
|
259178
259510
|
isRow: isBody,
|
|
259179
259511
|
key: (b8) => b8.name,
|
|
259180
259512
|
hash: (b8) => sha12(b8.body),
|
|
259181
|
-
localKeys: async () => (await
|
|
259513
|
+
localKeys: async () => (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
|
|
259182
259514
|
apply: async ({ rows, removeIds }) => {
|
|
259183
|
-
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await
|
|
259515
|
+
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp132.rm(path242.join(bodiesDir(), name), { force: true });
|
|
259184
259516
|
const skipped = [];
|
|
259185
259517
|
for (const b8 of rows ?? []) {
|
|
259186
259518
|
if (Buffer.byteLength(b8.body) > INBOX_BODY_COPY_MAX_BYTES) {
|
|
259187
259519
|
skipped.push(b8.name);
|
|
259188
259520
|
continue;
|
|
259189
259521
|
}
|
|
259190
|
-
await writeCopyText(
|
|
259522
|
+
await writeCopyText(path242.join(bodiesDir(), b8.name), b8.body);
|
|
259191
259523
|
}
|
|
259192
259524
|
return { skipped };
|
|
259193
259525
|
},
|
|
@@ -259195,8 +259527,8 @@ function inboxBodiesFollower() {
|
|
|
259195
259527
|
changed: () => {
|
|
259196
259528
|
},
|
|
259197
259529
|
purge: async () => {
|
|
259198
|
-
const names2 = (await
|
|
259199
|
-
for (const name of names2) await
|
|
259530
|
+
const names2 = (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
|
|
259531
|
+
for (const name of names2) await fsp132.rm(path242.join(bodiesDir(), name), { force: true });
|
|
259200
259532
|
await markCopyOff("inbox-bodies");
|
|
259201
259533
|
bodiesIo.reset();
|
|
259202
259534
|
return { removed: names2.length };
|
|
@@ -259204,7 +259536,7 @@ function inboxBodiesFollower() {
|
|
|
259204
259536
|
});
|
|
259205
259537
|
return bodiesF;
|
|
259206
259538
|
}
|
|
259207
|
-
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,
|
|
259539
|
+
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;
|
|
259208
259540
|
var init_inbox = __esm({
|
|
259209
259541
|
"src/core/replication/kinds/inbox.ts"() {
|
|
259210
259542
|
"use strict";
|
|
@@ -259217,9 +259549,9 @@ var init_inbox = __esm({
|
|
|
259217
259549
|
INBOX_SCHEMA_VERSION = 1;
|
|
259218
259550
|
INBOX_REMOVAL_FLOOR = 50;
|
|
259219
259551
|
INBOX_BODY_COPY_MAX_BYTES = 4 * 1024 * 1024;
|
|
259220
|
-
inboxDir = () =>
|
|
259221
|
-
indexFile3 = () =>
|
|
259222
|
-
bodiesDir = () =>
|
|
259552
|
+
inboxDir = () => path242.join(WALNUT_HOME, "human-inbox");
|
|
259553
|
+
indexFile3 = () => path242.join(inboxDir(), "index.json");
|
|
259554
|
+
bodiesDir = () => path242.join(inboxDir(), "bodies");
|
|
259223
259555
|
letterHashes = /* @__PURE__ */ new WeakMap();
|
|
259224
259556
|
INBOX_KIND = {
|
|
259225
259557
|
kind: "inbox",
|
|
@@ -259261,134 +259593,12 @@ var init_inbox = __esm({
|
|
|
259261
259593
|
refuse14 = copyRefusal;
|
|
259262
259594
|
indexIo = stateIo("inbox");
|
|
259263
259595
|
bodiesIo = stateIo("inbox-bodies");
|
|
259264
|
-
|
|
259596
|
+
serial7 = serialChain();
|
|
259265
259597
|
inboxF = null;
|
|
259266
259598
|
bodiesF = null;
|
|
259267
259599
|
}
|
|
259268
259600
|
});
|
|
259269
259601
|
|
|
259270
|
-
// src/core/replication/kinds/requests.ts
|
|
259271
|
-
import fsp132 from "fs/promises";
|
|
259272
|
-
import path242 from "path";
|
|
259273
|
-
function forwardRequest(local, incoming) {
|
|
259274
|
-
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
259275
|
-
return incoming;
|
|
259276
|
-
}
|
|
259277
|
-
function hashOf6(row) {
|
|
259278
|
-
let h8 = hashes4.get(row);
|
|
259279
|
-
if (h8 === void 0) {
|
|
259280
|
-
h8 = sha12(JSON.stringify(row));
|
|
259281
|
-
hashes4.set(row, h8);
|
|
259282
|
-
}
|
|
259283
|
-
return h8;
|
|
259284
|
-
}
|
|
259285
|
-
async function load7() {
|
|
259286
|
-
if (state13) return state13;
|
|
259287
|
-
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
259288
|
-
try {
|
|
259289
|
-
const raw = JSON.parse(await fsp132.readFile(STATE_FILE3(), "utf8"));
|
|
259290
|
-
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 };
|
|
259291
|
-
} catch {
|
|
259292
|
-
}
|
|
259293
|
-
state13 = s4;
|
|
259294
|
-
return s4;
|
|
259295
|
-
}
|
|
259296
|
-
async function save2() {
|
|
259297
|
-
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
259298
|
-
}
|
|
259299
|
-
async function readStore8() {
|
|
259300
|
-
try {
|
|
259301
|
-
const raw = JSON.parse(await fsp132.readFile(STORE_FILE(), "utf8"));
|
|
259302
|
-
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
259303
|
-
} catch {
|
|
259304
|
-
return [];
|
|
259305
|
-
}
|
|
259306
|
-
}
|
|
259307
|
-
function isRow5(v3) {
|
|
259308
|
-
const r8 = v3;
|
|
259309
|
-
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
259310
|
-
}
|
|
259311
|
-
function requestsFollower() {
|
|
259312
|
-
follower4 ??= createRowSetFollower({
|
|
259313
|
-
kind: "requests",
|
|
259314
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
259315
|
-
label: "requests copy",
|
|
259316
|
-
log: log.session,
|
|
259317
|
-
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
259318
|
-
ordered: false,
|
|
259319
|
-
serial: (fn) => serial7(fn),
|
|
259320
|
-
refuse: copyRefusal,
|
|
259321
|
-
load: load7,
|
|
259322
|
-
save: save2,
|
|
259323
|
-
isRow: isRow5,
|
|
259324
|
-
key: (r8) => r8.id,
|
|
259325
|
-
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
259326
|
-
apply: async ({ rows, removeIds }) => {
|
|
259327
|
-
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
259328
|
-
for (const id of removeIds ?? []) byId.delete(id);
|
|
259329
|
-
for (const r8 of rows ?? []) {
|
|
259330
|
-
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
259331
|
-
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 });
|
|
259332
|
-
byId.set(r8.id, kept);
|
|
259333
|
-
}
|
|
259334
|
-
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
259335
|
-
return { skipped: [] };
|
|
259336
|
-
},
|
|
259337
|
-
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
259338
|
-
changed: () => {
|
|
259339
|
-
},
|
|
259340
|
-
purge: async () => {
|
|
259341
|
-
const removed = (await readStore8()).length;
|
|
259342
|
-
await fsp132.rm(STORE_FILE(), { force: true });
|
|
259343
|
-
await markCopyOff("requests");
|
|
259344
|
-
state13 = null;
|
|
259345
|
-
return { removed };
|
|
259346
|
-
}
|
|
259347
|
-
});
|
|
259348
|
-
return follower4;
|
|
259349
|
-
}
|
|
259350
|
-
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes4, REQUESTS_KIND, STATE_FILE3, STORE_FILE, state13, serial7, follower4;
|
|
259351
|
-
var init_requests = __esm({
|
|
259352
|
-
"src/core/replication/kinds/requests.ts"() {
|
|
259353
|
-
"use strict";
|
|
259354
|
-
init_constants();
|
|
259355
|
-
init_logging();
|
|
259356
|
-
init_kind();
|
|
259357
|
-
init_kind_follower();
|
|
259358
|
-
init_gate();
|
|
259359
|
-
REQUESTS_SCHEMA_VERSION = 1;
|
|
259360
|
-
REQUESTS_REMOVAL_FLOOR = 50;
|
|
259361
|
-
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
259362
|
-
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
259363
|
-
REQUESTS_KIND = {
|
|
259364
|
-
kind: "requests",
|
|
259365
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
259366
|
-
key: (r8) => r8.id,
|
|
259367
|
-
hash: hashOf6,
|
|
259368
|
-
ordered: false,
|
|
259369
|
-
digest: false,
|
|
259370
|
-
choice: "requests",
|
|
259371
|
-
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
259372
|
-
watch: (soon) => {
|
|
259373
|
-
let stop2 = null;
|
|
259374
|
-
let stopped2 = false;
|
|
259375
|
-
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
259376
|
-
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
259377
|
-
});
|
|
259378
|
-
return () => {
|
|
259379
|
-
stopped2 = true;
|
|
259380
|
-
stop2?.();
|
|
259381
|
-
};
|
|
259382
|
-
}
|
|
259383
|
-
};
|
|
259384
|
-
STATE_FILE3 = () => path242.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
259385
|
-
STORE_FILE = () => path242.join(WALNUT_HOME, "session-requests.json");
|
|
259386
|
-
state13 = null;
|
|
259387
|
-
serial7 = serialChain();
|
|
259388
|
-
follower4 = null;
|
|
259389
|
-
}
|
|
259390
|
-
});
|
|
259391
|
-
|
|
259392
259602
|
// src/core/replication/kinds/sessions.ts
|
|
259393
259603
|
import fsp133 from "fs/promises";
|
|
259394
259604
|
import path243 from "path";
|
|
@@ -259419,11 +259629,11 @@ function projectedOf(row) {
|
|
|
259419
259629
|
}
|
|
259420
259630
|
return p6;
|
|
259421
259631
|
}
|
|
259422
|
-
function
|
|
259423
|
-
let h8 =
|
|
259632
|
+
function hashOf8(row) {
|
|
259633
|
+
let h8 = hashes6.get(row);
|
|
259424
259634
|
if (h8 === void 0) {
|
|
259425
259635
|
h8 = sessionCopyHash(row);
|
|
259426
|
-
|
|
259636
|
+
hashes6.set(row, h8);
|
|
259427
259637
|
}
|
|
259428
259638
|
return h8;
|
|
259429
259639
|
}
|
|
@@ -259443,7 +259653,7 @@ async function load8() {
|
|
|
259443
259653
|
async function save3() {
|
|
259444
259654
|
if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
|
|
259445
259655
|
}
|
|
259446
|
-
function
|
|
259656
|
+
function isRow7(v3) {
|
|
259447
259657
|
const r8 = v3;
|
|
259448
259658
|
return !!r8 && typeof r8 === "object" && !Array.isArray(r8) && typeof r8.claudeSessionId === "string" && r8.claudeSessionId.length > 0 && r8.claudeSessionId.length <= 200;
|
|
259449
259659
|
}
|
|
@@ -259463,7 +259673,7 @@ function sessionsFollower() {
|
|
|
259463
259673
|
refuse: copyRefusal,
|
|
259464
259674
|
load: load8,
|
|
259465
259675
|
save: save3,
|
|
259466
|
-
isRow:
|
|
259676
|
+
isRow: isRow7,
|
|
259467
259677
|
key: (r8) => r8.claudeSessionId,
|
|
259468
259678
|
hash: sessionCopyHash,
|
|
259469
259679
|
localKeys: async () => (await Promise.resolve().then(() => (init_session_db(), session_db_exports))).sessionIdsInStore(),
|
|
@@ -259485,7 +259695,7 @@ function sessionsFollower() {
|
|
|
259485
259695
|
});
|
|
259486
259696
|
return follower5;
|
|
259487
259697
|
}
|
|
259488
|
-
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected,
|
|
259698
|
+
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;
|
|
259489
259699
|
var init_sessions2 = __esm({
|
|
259490
259700
|
"src/core/replication/kinds/sessions.ts"() {
|
|
259491
259701
|
"use strict";
|
|
@@ -259522,12 +259732,12 @@ var init_sessions2 = __esm({
|
|
|
259522
259732
|
VOLATILE_SESSION_FIELDS = ["lastActiveAt", "activity", "contextTokens"];
|
|
259523
259733
|
VOLATILE_SET = new Set(VOLATILE_SESSION_FIELDS);
|
|
259524
259734
|
projected = /* @__PURE__ */ new WeakMap();
|
|
259525
|
-
|
|
259735
|
+
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
259526
259736
|
SESSIONS_KIND = {
|
|
259527
259737
|
kind: "sessions",
|
|
259528
259738
|
schemaVersion: SESSIONS_SCHEMA_VERSION,
|
|
259529
259739
|
key: (s4) => s4.claudeSessionId,
|
|
259530
|
-
hash:
|
|
259740
|
+
hash: hashOf8,
|
|
259531
259741
|
ordered: false,
|
|
259532
259742
|
digest: true,
|
|
259533
259743
|
choice: "sessions",
|
|
@@ -259559,137 +259769,11 @@ var init_sessions2 = __esm({
|
|
|
259559
259769
|
}
|
|
259560
259770
|
});
|
|
259561
259771
|
|
|
259562
|
-
// src/core/replication/kinds/personas.ts
|
|
259563
|
-
var personas_exports = {};
|
|
259564
|
-
__export(personas_exports, {
|
|
259565
|
-
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
259566
|
-
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
259567
|
-
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
259568
|
-
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
259569
|
-
personasFollower: () => personasFollower,
|
|
259570
|
-
readPersonaCopy: () => readPersonaCopy
|
|
259571
|
-
});
|
|
259572
|
-
function tools(v3) {
|
|
259573
|
-
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
259574
|
-
}
|
|
259575
|
-
async function leaderRows2() {
|
|
259576
|
-
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
259577
|
-
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
259578
|
-
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
259579
|
-
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
259580
|
-
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
259581
|
-
]);
|
|
259582
|
-
const config = await getConfig2();
|
|
259583
|
-
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
259584
|
-
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
259585
|
-
const rows = [];
|
|
259586
|
-
for (const a8 of agents) {
|
|
259587
|
-
if (!ID_RE5.test(a8.id)) continue;
|
|
259588
|
-
try {
|
|
259589
|
-
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
259590
|
-
const prompt = profile.systemPrompt ?? "";
|
|
259591
|
-
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
259592
|
-
rows.push({
|
|
259593
|
-
key: a8.id,
|
|
259594
|
-
agentId: a8.id,
|
|
259595
|
-
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
259596
|
-
systemPrompt: prompt,
|
|
259597
|
-
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
259598
|
-
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
259599
|
-
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
259600
|
-
...effort ? { effort } : {},
|
|
259601
|
-
...launch.model ? { launchModel: launch.model } : {},
|
|
259602
|
-
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
259603
|
-
});
|
|
259604
|
-
} catch (err2) {
|
|
259605
|
-
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
259606
|
-
}
|
|
259607
|
-
}
|
|
259608
|
-
return rows;
|
|
259609
|
-
}
|
|
259610
|
-
function hashOf8(row) {
|
|
259611
|
-
let h8 = hashes6.get(row);
|
|
259612
|
-
if (h8 === void 0) {
|
|
259613
|
-
h8 = sha12(JSON.stringify(row));
|
|
259614
|
-
hashes6.set(row, h8);
|
|
259615
|
-
}
|
|
259616
|
-
return h8;
|
|
259617
|
-
}
|
|
259618
|
-
function isRow7(v3) {
|
|
259619
|
-
const r8 = v3;
|
|
259620
|
-
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
259621
|
-
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
259622
|
-
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE5.test(r8.key) || typeof r8.name !== "string") return false;
|
|
259623
|
-
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
259624
|
-
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
259625
|
-
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
259626
|
-
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;
|
|
259627
|
-
return true;
|
|
259628
|
-
}
|
|
259629
|
-
function admit2(r8) {
|
|
259630
|
-
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
259631
|
-
}
|
|
259632
|
-
async function readPersonaCopy(agentId) {
|
|
259633
|
-
const rows = await copy3.read();
|
|
259634
|
-
return rows?.[agentId] ?? null;
|
|
259635
|
-
}
|
|
259636
|
-
function _resetPersonasCopyForTesting() {
|
|
259637
|
-
copy3.reset();
|
|
259638
|
-
}
|
|
259639
|
-
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE5, TOOL_RE, hashes6, PERSONAS_KIND, ROW_KEYS, copy3, personasFollower;
|
|
259640
|
-
var init_personas = __esm({
|
|
259641
|
-
"src/core/replication/kinds/personas.ts"() {
|
|
259642
|
-
"use strict";
|
|
259643
|
-
init_logging();
|
|
259644
|
-
init_config_allowlist();
|
|
259645
|
-
init_kind();
|
|
259646
|
-
init_file_copy();
|
|
259647
|
-
PERSONAS_SCHEMA_VERSION = 1;
|
|
259648
|
-
PERSONAS_REMOVAL_FLOOR = 0;
|
|
259649
|
-
MAX_PROMPT_BYTES = 120 * 1024;
|
|
259650
|
-
ID_RE5 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
259651
|
-
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
259652
|
-
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
259653
|
-
PERSONAS_KIND = {
|
|
259654
|
-
kind: "personas",
|
|
259655
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
259656
|
-
key: (r8) => r8.key,
|
|
259657
|
-
hash: hashOf8,
|
|
259658
|
-
ordered: false,
|
|
259659
|
-
digest: false,
|
|
259660
|
-
choice: "personas",
|
|
259661
|
-
rows: leaderRows2,
|
|
259662
|
-
watch: (soon) => {
|
|
259663
|
-
let stop2 = null;
|
|
259664
|
-
let stopped2 = false;
|
|
259665
|
-
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
259666
|
-
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
259667
|
-
});
|
|
259668
|
-
return () => {
|
|
259669
|
-
stopped2 = true;
|
|
259670
|
-
stop2?.();
|
|
259671
|
-
};
|
|
259672
|
-
}
|
|
259673
|
-
};
|
|
259674
|
-
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
259675
|
-
copy3 = createFileCopy({
|
|
259676
|
-
kind: "personas",
|
|
259677
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
259678
|
-
label: "personas copy",
|
|
259679
|
-
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
259680
|
-
isRow: isRow7,
|
|
259681
|
-
key: (r8) => r8.key,
|
|
259682
|
-
admit: admit2
|
|
259683
|
-
});
|
|
259684
|
-
personasFollower = copy3.follower;
|
|
259685
|
-
}
|
|
259686
|
-
});
|
|
259687
|
-
|
|
259688
259772
|
// src/core/replication/kinds/index.ts
|
|
259689
259773
|
var kinds_exports = {};
|
|
259690
259774
|
__export(kinds_exports, {
|
|
259775
|
+
copyKeepersOnly: () => copyKeepersOnly,
|
|
259691
259776
|
copyKinds: () => copyKinds,
|
|
259692
|
-
hostReplicaOnly: () => hostReplicaOnly,
|
|
259693
259777
|
registerCopyFollowerKinds: () => registerCopyFollowerKinds,
|
|
259694
259778
|
startCopyKinds: () => startCopyKinds
|
|
259695
259779
|
});
|
|
@@ -259707,14 +259791,14 @@ function copyKinds() {
|
|
|
259707
259791
|
PERSONAS_KIND
|
|
259708
259792
|
];
|
|
259709
259793
|
}
|
|
259710
|
-
function
|
|
259794
|
+
function copyKeepersOnly(h8) {
|
|
259711
259795
|
return {
|
|
259712
259796
|
kind: h8.kind,
|
|
259713
|
-
// followerStep checks the version before the step: never `schema_newer`
|
|
259797
|
+
// followerStep checks the version before the step: never `schema_newer` where the kind is not kept.
|
|
259714
259798
|
get schemaVersion() {
|
|
259715
|
-
return keepsCopies() ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
259799
|
+
return keepsCopies(h8.kind) ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
259716
259800
|
},
|
|
259717
|
-
step: (op2, body7) => keepsCopies() ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
259801
|
+
step: (op2, body7) => keepsCopies(h8.kind) ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
259718
259802
|
};
|
|
259719
259803
|
}
|
|
259720
259804
|
function registerCopyFollowerKinds() {
|
|
@@ -259729,7 +259813,7 @@ function registerCopyFollowerKinds() {
|
|
|
259729
259813
|
prefsFollower(),
|
|
259730
259814
|
configFollower(),
|
|
259731
259815
|
personasFollower()
|
|
259732
|
-
].map((h8) => registerFollowerKind(
|
|
259816
|
+
].map((h8) => registerFollowerKind(copyKeepersOnly(h8)));
|
|
259733
259817
|
return () => {
|
|
259734
259818
|
for (const u3 of off) u3();
|
|
259735
259819
|
};
|
|
@@ -292107,10 +292191,13 @@ async function cleanupLaneClaudeMd(homeDir2 = WALNUT_HOME) {
|
|
|
292107
292191
|
}
|
|
292108
292192
|
}
|
|
292109
292193
|
async function buildLaneProfile(config, agentId, opts2) {
|
|
292110
|
-
const
|
|
292111
|
-
const
|
|
292194
|
+
const persona = opts2?.persona;
|
|
292195
|
+
const skillsIndex = persona ? "" : await buildSessionSkillsPrompt().catch(() => "");
|
|
292196
|
+
const memoryContext = persona ? "" : await buildLaneMemoryContext().catch(() => "");
|
|
292112
292197
|
let profile;
|
|
292113
|
-
if (
|
|
292198
|
+
if (persona) {
|
|
292199
|
+
profile = mergeProfiles({ systemPrompt: persona.systemPrompt, systemPromptMode: persona.systemPromptMode }, walnutMcpProfile());
|
|
292200
|
+
} else if (agentId === "general") {
|
|
292114
292201
|
profile = personalAiProfile(config.user?.name ?? "the user", skillsIndex, memoryContext);
|
|
292115
292202
|
} else {
|
|
292116
292203
|
const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports));
|
|
@@ -292120,7 +292207,8 @@ async function buildLaneProfile(config, agentId, opts2) {
|
|
|
292120
292207
|
const contextBlock = await loadContextSources2(agentDef, {}).catch(() => "");
|
|
292121
292208
|
profile = consoleAgentProfile(agentDef, skillsIndex, contextBlock);
|
|
292122
292209
|
}
|
|
292123
|
-
const
|
|
292210
|
+
const personaEffort = persona?.effort && LANE_EFFORTS.has(persona.effort) ? persona.effort : void 0;
|
|
292211
|
+
const effort = personaEffort ?? config.agent?.session_effort ?? "medium";
|
|
292124
292212
|
if (!opts2?.conversationId) return { profile, effort };
|
|
292125
292213
|
const base = profile.systemPrompt ?? "";
|
|
292126
292214
|
const headroom = MAX_LANE_PROMPT_BYTES - Buffer.byteLength(base, "utf-8") - LANE_SEED_RESERVE_BYTES;
|
|
@@ -292390,7 +292478,7 @@ async function resolveLane(lane, agentId, conversationId, firstMessage, engine)
|
|
|
292390
292478
|
});
|
|
292391
292479
|
return { sessionId, created: true, engine: "claude" };
|
|
292392
292480
|
}
|
|
292393
|
-
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;
|
|
292481
|
+
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;
|
|
292394
292482
|
var init_personal_ai_lane = __esm({
|
|
292395
292483
|
"src/core/sessions/personal-ai-lane.ts"() {
|
|
292396
292484
|
"use strict";
|
|
@@ -292405,6 +292493,7 @@ var init_personal_ai_lane = __esm({
|
|
|
292405
292493
|
init_default_engine();
|
|
292406
292494
|
init_ask_profile_prefix();
|
|
292407
292495
|
init_logging();
|
|
292496
|
+
LANE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
292408
292497
|
inFlight20 = /* @__PURE__ */ new Map();
|
|
292409
292498
|
LANE_MEMORY_HEADER = "## Standing memory (injected by Walnut)";
|
|
292410
292499
|
MANAGED_LANE_CONTEXT_MARKERS = [
|
|
@@ -320172,9 +320261,13 @@ var init_task_replica_store = __esm({
|
|
|
320172
320261
|
// src/core/replication/kinds/gate.ts
|
|
320173
320262
|
var gate_exports = {};
|
|
320174
320263
|
__export(gate_exports, {
|
|
320264
|
+
COMPANION_COPY_KINDS: () => COMPANION_COPY_KINDS,
|
|
320265
|
+
COPY_AS_OF_HEADER: () => COPY_AS_OF_HEADER,
|
|
320175
320266
|
KIND_NOT_COPIED: () => KIND_NOT_COPIED,
|
|
320267
|
+
copyKindAsOf: () => copyKindAsOf,
|
|
320176
320268
|
copyKindHeld: () => copyKindHeld,
|
|
320177
320269
|
copyKindOff: () => copyKindOff,
|
|
320270
|
+
copyPath: () => copyPath,
|
|
320178
320271
|
copyRefusal: () => copyRefusal,
|
|
320179
320272
|
copyStateFile: () => copyStateFile,
|
|
320180
320273
|
keepsCopies: () => keepsCopies,
|
|
@@ -320182,8 +320275,16 @@ __export(gate_exports, {
|
|
|
320182
320275
|
});
|
|
320183
320276
|
import fsp152 from "fs/promises";
|
|
320184
320277
|
import path295 from "path";
|
|
320185
|
-
function keepsCopies() {
|
|
320186
|
-
|
|
320278
|
+
function keepsCopies(kind) {
|
|
320279
|
+
if (isHostReplicaProgram()) return true;
|
|
320280
|
+
if (followerKind() !== "companion") return false;
|
|
320281
|
+
return kind === void 0 || COMPANION_COPY_KINDS.has(kind);
|
|
320282
|
+
}
|
|
320283
|
+
function copyPath(live6) {
|
|
320284
|
+
if (followerKind() !== "companion") return live6;
|
|
320285
|
+
const rel = path295.relative(WALNUT_HOME, live6);
|
|
320286
|
+
if (!rel || rel.startsWith("..") || path295.isAbsolute(rel)) throw new Error(`copyPath: ${live6} is not under the data dir`);
|
|
320287
|
+
return path295.join(WALNUT_HOME, "cache", "replica", "home", rel);
|
|
320187
320288
|
}
|
|
320188
320289
|
async function copyRefusal() {
|
|
320189
320290
|
if (!keepsCopies()) return { status: 404, error: "unknown_kind" };
|
|
@@ -320204,20 +320305,26 @@ async function copyKindOff(kind) {
|
|
|
320204
320305
|
}
|
|
320205
320306
|
}
|
|
320206
320307
|
async function copyKindHeld(kind) {
|
|
320308
|
+
return await copyKindAsOf(kind) !== null;
|
|
320309
|
+
}
|
|
320310
|
+
async function copyKindAsOf(kind) {
|
|
320207
320311
|
try {
|
|
320208
320312
|
const raw = JSON.parse(await fsp152.readFile(copyStateFile(kind), "utf8"));
|
|
320209
|
-
|
|
320313
|
+
if (!(raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object")) return null;
|
|
320314
|
+
return Number(raw.asOf) || 0;
|
|
320210
320315
|
} catch {
|
|
320211
|
-
return
|
|
320316
|
+
return null;
|
|
320212
320317
|
}
|
|
320213
320318
|
}
|
|
320214
|
-
var KIND_NOT_COPIED;
|
|
320319
|
+
var COMPANION_COPY_KINDS, COPY_AS_OF_HEADER, KIND_NOT_COPIED;
|
|
320215
320320
|
var init_gate = __esm({
|
|
320216
320321
|
"src/core/replication/kinds/gate.ts"() {
|
|
320217
320322
|
"use strict";
|
|
320218
320323
|
init_constants();
|
|
320219
320324
|
init_server_role();
|
|
320220
320325
|
init_kind_follower();
|
|
320326
|
+
COMPANION_COPY_KINDS = /* @__PURE__ */ new Set(["requests", "routines", "prefs", "personas"]);
|
|
320327
|
+
COPY_AS_OF_HEADER = "x-walnut-copy-as-of";
|
|
320221
320328
|
KIND_NOT_COPIED = "kind_not_copied";
|
|
320222
320329
|
}
|
|
320223
320330
|
});
|