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
|
@@ -6451,6 +6451,7 @@ function createOfflineHostCore(deps4) {
|
|
|
6451
6451
|
const MAX_ARGS_BYTES = 256 * 1024;
|
|
6452
6452
|
const WRITE_BUDGET = 30;
|
|
6453
6453
|
const WRITE_WINDOW_MS = 6e4;
|
|
6454
|
+
const LOCK_RETRY_MS = [100, 300, 900];
|
|
6454
6455
|
const DEFAULT_REPLY_SECS = 3600;
|
|
6455
6456
|
const IMPLICIT_REPLY_SECS = 6 * 3600;
|
|
6456
6457
|
const DRAIN_BATCH = 200;
|
|
@@ -6597,7 +6598,7 @@ function createOfflineHostCore(deps4) {
|
|
|
6597
6598
|
...opts2.admit ? { admit: opts2.admit } : {}
|
|
6598
6599
|
});
|
|
6599
6600
|
if (!r8.ok) {
|
|
6600
|
-
if (r8.code === "journal_unwritable") deps4.log("error", "offline host: journal write refused", { home, kind, code: r8.code, why: r8.why, error: r8.message });
|
|
6601
|
+
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 });
|
|
6601
6602
|
return r8;
|
|
6602
6603
|
}
|
|
6603
6604
|
if (!r8.duplicate) {
|
|
@@ -6612,6 +6613,19 @@ function createOfflineHostCore(deps4) {
|
|
|
6612
6613
|
if (r8.ok) return null;
|
|
6613
6614
|
return fail6(r8.code, r8.message, { ...r8.retryAfterMs !== void 0 ? { retryAfterMs: r8.retryAfterMs } : {}, ...r8.why ? { detail: { why: r8.why } } : {} });
|
|
6614
6615
|
}
|
|
6616
|
+
const lockRefused = (r8) => !r8.ok && r8.error.code === "journal_unwritable" && r8.error.detail?.why === "locked";
|
|
6617
|
+
async function whenUnlocked(home, op2, run12) {
|
|
6618
|
+
const t0 = Date.now();
|
|
6619
|
+
let r8 = run12();
|
|
6620
|
+
for (const ms2 of LOCK_RETRY_MS) {
|
|
6621
|
+
if (!lockRefused(r8)) return r8;
|
|
6622
|
+
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 });
|
|
6623
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms2));
|
|
6624
|
+
r8 = run12();
|
|
6625
|
+
}
|
|
6626
|
+
if (lockRefused(r8)) deps4.log("error", "offline host: the journal stayed locked; write refused", { home, op: op2, waitedMs: Date.now() - t0 });
|
|
6627
|
+
return r8;
|
|
6628
|
+
}
|
|
6615
6629
|
function configure(slice) {
|
|
6616
6630
|
if (!slice || slice.v !== 1 || typeof slice.home !== "string" || !slice.home) throw new Error("host.slice: bad slice");
|
|
6617
6631
|
const prev = slices.get(slice.home);
|
|
@@ -7345,10 +7359,8 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
7345
7359
|
if (no) return no;
|
|
7346
7360
|
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 });
|
|
7347
7361
|
} else {
|
|
7348
|
-
const denied = admitWrite(callerSid5) ?? roomFor(home);
|
|
7349
|
-
if (denied) return denied;
|
|
7350
7362
|
const base = slices.get(home)?.tasks.find((t3) => t3.id === task.id)?.updated_at;
|
|
7351
|
-
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }));
|
|
7363
|
+
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }, false, { admit: () => admitWrite(callerSid5) ?? roomFor(home) }));
|
|
7352
7364
|
if (no) return no;
|
|
7353
7365
|
deps4.log("info", "offline host: write queued", { home, op: name, taskId: task.id, callerSid: callerSid5 });
|
|
7354
7366
|
}
|
|
@@ -7790,7 +7802,7 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
7790
7802
|
const fromCopy = deps4.replica ? deps4.replica.answer(home, name, args, offlineNote(home)) : null;
|
|
7791
7803
|
if (fromCopy) return fromCopy;
|
|
7792
7804
|
if (deps4.boards && deps4.boards.BOARD_OPS.indexOf(name) !== -1) return opBoard(home, callerSid5, name, args);
|
|
7793
|
-
if (QUEUED_OPS.includes(name)) return opQueued(home, callerSid5, name, args);
|
|
7805
|
+
if (QUEUED_OPS.includes(name)) return whenUnlocked(home, name, () => opQueued(home, callerSid5, name, args));
|
|
7794
7806
|
return needsServer(name ? `"${name}"` : "That call");
|
|
7795
7807
|
}
|
|
7796
7808
|
}
|
|
@@ -8303,6 +8315,10 @@ ${mid}` : "";
|
|
|
8303
8315
|
handle: handle4,
|
|
8304
8316
|
handleLocal,
|
|
8305
8317
|
handleFollower,
|
|
8318
|
+
/** handleFollower, waiting out another process's journal lock (whenUnlocked): the twins' follower.op. */
|
|
8319
|
+
handleFollowerWaiting: (home, req) => whenUnlocked(home, String(req.op ?? ""), () => handleFollower(home, req)),
|
|
8320
|
+
/** noteSession, waiting out another process's journal lock (whenUnlocked): the twins' host ask. */
|
|
8321
|
+
noteSessionWaiting: (home, rec3, opId, by) => whenUnlocked(home, "session", () => noteSession(home, rec3, opId, by)),
|
|
8306
8322
|
pendingFor,
|
|
8307
8323
|
journalStats,
|
|
8308
8324
|
onResult,
|
|
@@ -23497,7 +23513,7 @@ function dispatchCommand(ws, id, cmd) {
|
|
|
23497
23513
|
case 'follower.sessions': return cmdFollowerSessions(ws, id);
|
|
23498
23514
|
case 'follower.send': return daemonCommands.run(function () { return cmdFollowerSend(ws, id, cmd); });
|
|
23499
23515
|
case 'follower.permission': return daemonCommands.run(function () { return cmdFollowerPermission(ws, id, cmd); });
|
|
23500
|
-
case 'follower.op': return cmdFollowerOp(ws, id, cmd);
|
|
23516
|
+
case 'follower.op': return daemonCommands.run(function () { return cmdFollowerOp(ws, id, cmd); });
|
|
23501
23517
|
case 'follower.pending': return cmdFollowerPending(ws, id, cmd);
|
|
23502
23518
|
// A new ask while the Mac is away ('replica-start-v1', WP12). Twin of daemon-standalone.ts.
|
|
23503
23519
|
case 'follower.start': return daemonCommands.run(function () { return cmdFollowerStart(ws, id, cmd); });
|
|
@@ -24911,14 +24927,15 @@ async function cmdFollowerPermission(ws, id, cmd) {
|
|
|
24911
24927
|
// The replica's write while the Mac is away (replica-ops-v1, journal v2). Its own gate:
|
|
24912
24928
|
// the follower's own Walnut, the quiet window unless the Mac is still taking the
|
|
24913
24929
|
// journal, and the daemon dir's owner. Twin of daemon-standalone.ts cmdFollowerOp.
|
|
24914
|
-
function cmdFollowerOp(ws, id, cmd) {
|
|
24930
|
+
async function cmdFollowerOp(ws, id, cmd) {
|
|
24915
24931
|
var home = followerHomeOf(ws);
|
|
24916
24932
|
if (!home) return sendError(ws, id, 'follower.op: send follower.hello first');
|
|
24917
24933
|
if (!followerMayWrite(home)) return sendError(ws, id, 'follower.op: your Mac answers again; write through it', { errorKind: 'leader_answers' });
|
|
24918
24934
|
if (!ownsDaemonDir()) {
|
|
24919
24935
|
return sendError(ws, id, 'follower.op: this daemon no longer owns its directory', { errorKind: 'journal_unwritable', detail: { why: 'not_owner' } });
|
|
24920
24936
|
}
|
|
24921
|
-
|
|
24937
|
+
// Waits out another process's journal lock (about 1.3 s) before it answers.
|
|
24938
|
+
var r = await offlineHost.handleFollowerWaiting(home, { op: cmd.op, args: cmd.args, actor: cmd.actor, opId: cmd.opId, base: cmd.base });
|
|
24922
24939
|
if (r.ok) return sendOk(ws, id, r.result);
|
|
24923
24940
|
sendError(ws, id, 'follower.op: ' + r.error.message, Object.assign({ errorKind: r.error.code },
|
|
24924
24941
|
r.error.detail !== undefined ? { detail: r.error.detail } : {}, r.error.retryAfterMs !== undefined ? { retryAfterMs: r.error.retryAfterMs } : {}));
|
|
@@ -25068,7 +25085,7 @@ async function startHostAsk(home, p, cmd) {
|
|
|
25068
25085
|
throw err;
|
|
25069
25086
|
}
|
|
25070
25087
|
if (DIE_AFTER_ASK_SPAWN) process.kill(process.pid, 'SIGKILL');
|
|
25071
|
-
var saved = offlineHost.
|
|
25088
|
+
var saved = await offlineHost.noteSessionWaiting(home, p.record, opId, cmd.actor);
|
|
25072
25089
|
hostStart.releasePending(home, p.sid);
|
|
25073
25090
|
if (!saved.ok) {
|
|
25074
25091
|
// Nothing would tell the Mac about this CLI: it must not run unseen. Not stamped as an
|
|
@@ -142922,8 +142939,9 @@ async function buildCopyManifest(kind) {
|
|
|
142922
142939
|
}
|
|
142923
142940
|
return manifest;
|
|
142924
142941
|
}
|
|
142925
|
-
function keepsCopiesTarget(t3) {
|
|
142926
|
-
|
|
142942
|
+
function keepsCopiesTarget(t3, kind) {
|
|
142943
|
+
if (t3.kind === "host") return t3.program?.() === "replica";
|
|
142944
|
+
return t3.kind === "companion" && (kind === void 0 || COMPANION_COPY_KINDS.has(kind));
|
|
142927
142945
|
}
|
|
142928
142946
|
function manifestDigest(manifest, ordered = false) {
|
|
142929
142947
|
let d8 = manifestDigests.get(manifest);
|
|
@@ -143037,7 +143055,7 @@ async function choiceOf(target2) {
|
|
|
143037
143055
|
}
|
|
143038
143056
|
async function syncCopyKinds(kinds, deps4 = {}) {
|
|
143039
143057
|
const now = deps4.now ?? Date.now;
|
|
143040
|
-
const all = (deps4.targets ?? await defaultTargets())().filter(keepsCopiesTarget);
|
|
143058
|
+
const all = (deps4.targets ?? await defaultTargets())().filter((t3) => kinds.some((k8) => keepsCopiesTarget(t3, k8.kind)));
|
|
143041
143059
|
const ready2 = [];
|
|
143042
143060
|
for (const target2 of all) if (await target2.available()) ready2.push({ target: target2, choice: await choiceOf(target2) });
|
|
143043
143061
|
const results = [];
|
|
@@ -143045,7 +143063,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
143045
143063
|
const asOf2 = now();
|
|
143046
143064
|
const manifests = /* @__PURE__ */ new Map();
|
|
143047
143065
|
for (const kind of kinds) {
|
|
143048
|
-
if (!ready2.some((r8) => r8.choice[kind.choice])) continue;
|
|
143066
|
+
if (!ready2.some((r8) => r8.choice[kind.choice] && keepsCopiesTarget(r8.target, kind.kind))) continue;
|
|
143049
143067
|
try {
|
|
143050
143068
|
manifests.set(kind.kind, await buildCopyManifest(kind));
|
|
143051
143069
|
} catch (err2) {
|
|
@@ -143054,6 +143072,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
143054
143072
|
}
|
|
143055
143073
|
for (const { target: target2, choice } of ready2) {
|
|
143056
143074
|
for (const kind of kinds) {
|
|
143075
|
+
if (!keepsCopiesTarget(target2, kind.kind)) continue;
|
|
143057
143076
|
const manifest = manifests.get(kind.kind);
|
|
143058
143077
|
const st2 = kindState(target2, kind.kind);
|
|
143059
143078
|
if (!choice[kind.choice]) {
|
|
@@ -143099,7 +143118,7 @@ async function purgeKind(kind, target2, st2) {
|
|
|
143099
143118
|
async function confirmCopyKindRemoval(targetId, kind, opts2 = {}) {
|
|
143100
143119
|
const { replicaTargets: replicaTargets2 } = await Promise.resolve().then(() => (init_replica_targets(), replica_targets_exports));
|
|
143101
143120
|
const target2 = replicaTargets2().find((t3) => t3.id === targetId);
|
|
143102
|
-
if (!target2 || target2
|
|
143121
|
+
if (!target2 || !keepsCopiesTarget(target2, kind) || !peekKindState(targetId, kind)) return false;
|
|
143103
143122
|
if (!confirmKindRemoval(target2, kind, opts2)) return false;
|
|
143104
143123
|
log.session.warn("copies: the user confirmed a removal of most rows", { target: targetId, kind, entries: peekKindState(targetId, kind)?.confirmFor?.entries });
|
|
143105
143124
|
copySoon(kind);
|
|
@@ -143214,6 +143233,7 @@ var init_copy_kind = __esm({
|
|
|
143214
143233
|
init_kind_leader();
|
|
143215
143234
|
init_search_digest();
|
|
143216
143235
|
init_replica_status();
|
|
143236
|
+
init_gate();
|
|
143217
143237
|
COPY_DEBOUNCE_MS = 3e3;
|
|
143218
143238
|
COPY_SWEEP_MS = 5 * 6e4;
|
|
143219
143239
|
COPY_FIRST_ROUND_MS = 15e3;
|
|
@@ -148907,6 +148927,7 @@ var init_routines = __esm({
|
|
|
148907
148927
|
var routines_follower_exports = {};
|
|
148908
148928
|
__export(routines_follower_exports, {
|
|
148909
148929
|
_resetRoutinesCopyForTesting: () => _resetRoutinesCopyForTesting,
|
|
148930
|
+
companionRoutinesCopy: () => companionRoutinesCopy,
|
|
148910
148931
|
readRoutinesCopy: () => readRoutinesCopy,
|
|
148911
148932
|
routinesFollower: () => routinesFollower
|
|
148912
148933
|
});
|
|
@@ -149002,6 +149023,10 @@ async function readRoutinesCopy(opts2 = {}) {
|
|
|
149002
149023
|
const shown = opts2.includeDisabled ? all : all.filter((j8) => j8.enabled);
|
|
149003
149024
|
return shown.sort((a8, b8) => (a8.state.nextRunAtMs ?? 0) - (b8.state.nextRunAtMs ?? 0));
|
|
149004
149025
|
}
|
|
149026
|
+
async function companionRoutinesCopy(opts2 = {}) {
|
|
149027
|
+
if (!await copyKindHeld("routines")) return null;
|
|
149028
|
+
return await readRoutinesCopy(opts2) ?? [];
|
|
149029
|
+
}
|
|
149005
149030
|
function _resetRoutinesCopyForTesting() {
|
|
149006
149031
|
io2 = copyStateIo("routines");
|
|
149007
149032
|
serial3 = serialChain();
|
|
@@ -149017,8 +149042,8 @@ var init_routines_follower = __esm({
|
|
|
149017
149042
|
init_gate();
|
|
149018
149043
|
init_state_io();
|
|
149019
149044
|
init_routines();
|
|
149020
|
-
jobsFile = () => CRON_FILE;
|
|
149021
|
-
statesFile = () => path117.join(path117.dirname(CRON_FILE), "cron-state.json");
|
|
149045
|
+
jobsFile = () => copyPath(CRON_FILE);
|
|
149046
|
+
statesFile = () => copyPath(path117.join(path117.dirname(CRON_FILE), "cron-state.json"));
|
|
149022
149047
|
io2 = copyStateIo("routines");
|
|
149023
149048
|
serial3 = serialChain();
|
|
149024
149049
|
follower2 = null;
|
|
@@ -164583,8 +164608,8 @@ import path135 from "path";
|
|
|
164583
164608
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
164584
164609
|
function getVersion() {
|
|
164585
164610
|
if (cachedVersion) return cachedVersion;
|
|
164586
|
-
if ("0.6.
|
|
164587
|
-
cachedVersion = "0.6.
|
|
164611
|
+
if ("0.6.17") {
|
|
164612
|
+
cachedVersion = "0.6.17";
|
|
164588
164613
|
versionKnown = true;
|
|
164589
164614
|
return cachedVersion;
|
|
164590
164615
|
}
|
|
@@ -188816,6 +188841,132 @@ var init_agent_turn_queue = __esm({
|
|
|
188816
188841
|
}
|
|
188817
188842
|
});
|
|
188818
188843
|
|
|
188844
|
+
// src/core/replication/kinds/personas.ts
|
|
188845
|
+
var personas_exports = {};
|
|
188846
|
+
__export(personas_exports, {
|
|
188847
|
+
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
188848
|
+
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
188849
|
+
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
188850
|
+
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
188851
|
+
personasFollower: () => personasFollower,
|
|
188852
|
+
readPersonaCopy: () => readPersonaCopy
|
|
188853
|
+
});
|
|
188854
|
+
function tools(v3) {
|
|
188855
|
+
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
188856
|
+
}
|
|
188857
|
+
async function leaderRows() {
|
|
188858
|
+
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
188859
|
+
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
188860
|
+
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
188861
|
+
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
188862
|
+
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
188863
|
+
]);
|
|
188864
|
+
const config = await getConfig2();
|
|
188865
|
+
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
188866
|
+
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
188867
|
+
const rows = [];
|
|
188868
|
+
for (const a8 of agents) {
|
|
188869
|
+
if (!ID_RE2.test(a8.id)) continue;
|
|
188870
|
+
try {
|
|
188871
|
+
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
188872
|
+
const prompt = profile.systemPrompt ?? "";
|
|
188873
|
+
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
188874
|
+
rows.push({
|
|
188875
|
+
key: a8.id,
|
|
188876
|
+
agentId: a8.id,
|
|
188877
|
+
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
188878
|
+
systemPrompt: prompt,
|
|
188879
|
+
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
188880
|
+
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
188881
|
+
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
188882
|
+
...effort ? { effort } : {},
|
|
188883
|
+
...launch.model ? { launchModel: launch.model } : {},
|
|
188884
|
+
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
188885
|
+
});
|
|
188886
|
+
} catch (err2) {
|
|
188887
|
+
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
188888
|
+
}
|
|
188889
|
+
}
|
|
188890
|
+
return rows;
|
|
188891
|
+
}
|
|
188892
|
+
function hashOf4(row) {
|
|
188893
|
+
let h8 = hashes3.get(row);
|
|
188894
|
+
if (h8 === void 0) {
|
|
188895
|
+
h8 = sha12(JSON.stringify(row));
|
|
188896
|
+
hashes3.set(row, h8);
|
|
188897
|
+
}
|
|
188898
|
+
return h8;
|
|
188899
|
+
}
|
|
188900
|
+
function isRow3(v3) {
|
|
188901
|
+
const r8 = v3;
|
|
188902
|
+
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
188903
|
+
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
188904
|
+
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE2.test(r8.key) || typeof r8.name !== "string") return false;
|
|
188905
|
+
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
188906
|
+
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
188907
|
+
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
188908
|
+
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;
|
|
188909
|
+
return true;
|
|
188910
|
+
}
|
|
188911
|
+
function admit(r8) {
|
|
188912
|
+
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
188913
|
+
}
|
|
188914
|
+
async function readPersonaCopy(agentId) {
|
|
188915
|
+
const rows = await copy2.read();
|
|
188916
|
+
return rows?.[agentId] ?? null;
|
|
188917
|
+
}
|
|
188918
|
+
function _resetPersonasCopyForTesting() {
|
|
188919
|
+
copy2.reset();
|
|
188920
|
+
}
|
|
188921
|
+
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE2, TOOL_RE, hashes3, PERSONAS_KIND, ROW_KEYS, copy2, personasFollower;
|
|
188922
|
+
var init_personas = __esm({
|
|
188923
|
+
"src/core/replication/kinds/personas.ts"() {
|
|
188924
|
+
"use strict";
|
|
188925
|
+
init_logging();
|
|
188926
|
+
init_config_allowlist();
|
|
188927
|
+
init_kind();
|
|
188928
|
+
init_file_copy();
|
|
188929
|
+
PERSONAS_SCHEMA_VERSION = 1;
|
|
188930
|
+
PERSONAS_REMOVAL_FLOOR = 0;
|
|
188931
|
+
MAX_PROMPT_BYTES = 120 * 1024;
|
|
188932
|
+
ID_RE2 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
188933
|
+
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
188934
|
+
hashes3 = /* @__PURE__ */ new WeakMap();
|
|
188935
|
+
PERSONAS_KIND = {
|
|
188936
|
+
kind: "personas",
|
|
188937
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
188938
|
+
key: (r8) => r8.key,
|
|
188939
|
+
hash: hashOf4,
|
|
188940
|
+
ordered: false,
|
|
188941
|
+
digest: false,
|
|
188942
|
+
choice: "personas",
|
|
188943
|
+
rows: leaderRows,
|
|
188944
|
+
watch: (soon) => {
|
|
188945
|
+
let stop2 = null;
|
|
188946
|
+
let stopped2 = false;
|
|
188947
|
+
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
188948
|
+
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
188949
|
+
});
|
|
188950
|
+
return () => {
|
|
188951
|
+
stopped2 = true;
|
|
188952
|
+
stop2?.();
|
|
188953
|
+
};
|
|
188954
|
+
}
|
|
188955
|
+
};
|
|
188956
|
+
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
188957
|
+
copy2 = createFileCopy({
|
|
188958
|
+
kind: "personas",
|
|
188959
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
188960
|
+
label: "personas copy",
|
|
188961
|
+
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
188962
|
+
isRow: isRow3,
|
|
188963
|
+
key: (r8) => r8.key,
|
|
188964
|
+
admit
|
|
188965
|
+
});
|
|
188966
|
+
personasFollower = copy2.follower;
|
|
188967
|
+
}
|
|
188968
|
+
});
|
|
188969
|
+
|
|
188819
188970
|
// src/core/sessions/cloud-chat-lane.ts
|
|
188820
188971
|
var cloud_chat_lane_exports = {};
|
|
188821
188972
|
__export(cloud_chat_lane_exports, {
|
|
@@ -188954,7 +189105,9 @@ async function resolveCloudChatLane(lane, agentId, conversationId, cwd, firstMes
|
|
|
188954
189105
|
CATCH_UP_BANNER_CLOSE: CATCH_UP_BANNER_CLOSE2,
|
|
188955
189106
|
buildConversationSeed: buildConversationSeed2
|
|
188956
189107
|
} = await Promise.resolve().then(() => (init_chat_history(), chat_history_exports));
|
|
188957
|
-
const {
|
|
189108
|
+
const { readPersonaCopy: readPersonaCopy2 } = await Promise.resolve().then(() => (init_personas(), personas_exports));
|
|
189109
|
+
const persona = await readPersonaCopy2(agentId).catch(() => null);
|
|
189110
|
+
const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId, ...persona ? { persona } : {} });
|
|
188958
189111
|
const profile = toCloudChatProfile(base, CONVERSATION_SEED_HEADER2);
|
|
188959
189112
|
const sessionId = crypto49.randomUUID();
|
|
188960
189113
|
const seedInProfile = !!seed && (seed.text !== "" || seed.stats.turnsTotal === 0);
|
|
@@ -195923,9 +196076,9 @@ function sanitizeHealthSync(body7, now = Date.now()) {
|
|
|
195923
196076
|
const tz = isValidTz(b8.tz) ? b8.tz : "";
|
|
195924
196077
|
const spec = metricSpec(type);
|
|
195925
196078
|
const generic = isGenericType(type);
|
|
195926
|
-
const storeId = typeof b8.storeId === "string" &&
|
|
196079
|
+
const storeId = typeof b8.storeId === "string" && ID_RE3.test(b8.storeId) ? b8.storeId : void 0;
|
|
195927
196080
|
const dev = b8.device && typeof b8.device === "object" ? b8.device : {};
|
|
195928
|
-
const installId = typeof dev.installId === "string" &&
|
|
196081
|
+
const installId = typeof dev.installId === "string" && ID_RE3.test(dev.installId) ? dev.installId : void 0;
|
|
195929
196082
|
const device = { installId, model: str10(dev.model, 64), os: str10(dev.os, 64) };
|
|
195930
196083
|
const hasDevice = Object.values(device).some((v3) => v3 !== void 0);
|
|
195931
196084
|
const deleted = [...new Set(deletedIn.filter((u3) => typeof u3 === "string" && UUID_RE3.test(u3)))];
|
|
@@ -195993,14 +196146,14 @@ function relayPayload(batch) {
|
|
|
195993
196146
|
samples: batch.samples.map(({ tz, ...rest }) => tz === batch.tz ? rest : { ...rest, tz })
|
|
195994
196147
|
};
|
|
195995
196148
|
}
|
|
195996
|
-
var UUID_RE3,
|
|
196149
|
+
var UUID_RE3, ID_RE3, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
|
|
195997
196150
|
var init_sanitize = __esm({
|
|
195998
196151
|
"src/core/health/sanitize.ts"() {
|
|
195999
196152
|
"use strict";
|
|
196000
196153
|
init_catalog();
|
|
196001
196154
|
init_day_key();
|
|
196002
196155
|
UUID_RE3 = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
|
|
196003
|
-
|
|
196156
|
+
ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
|
|
196004
196157
|
MIN_INSTANT = Date.UTC(2010, 0, 1);
|
|
196005
196158
|
FUTURE_SLACK_MS2 = 36 * 36e5;
|
|
196006
196159
|
MAX_SPAN_MS = 2 * 864e5;
|
|
@@ -213604,7 +213757,7 @@ function prefAdmissible(p6) {
|
|
|
213604
213757
|
function strings(v3) {
|
|
213605
213758
|
return Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string") : [];
|
|
213606
213759
|
}
|
|
213607
|
-
async function
|
|
213760
|
+
async function leaderRows2() {
|
|
213608
213761
|
const raw = await readJsonFile(UI_PREFS_FILE, {}, { readErrors: "throw" });
|
|
213609
213762
|
const rows = [];
|
|
213610
213763
|
for (const [k8, v3] of Object.entries(raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {})) {
|
|
@@ -213616,15 +213769,15 @@ async function leaderRows() {
|
|
|
213616
213769
|
rows.push({ key: "favorites", favorites: { projects: strings(fav?.projects), notes: strings(fav?.notes) } });
|
|
213617
213770
|
return rows;
|
|
213618
213771
|
}
|
|
213619
|
-
function
|
|
213620
|
-
let h8 =
|
|
213772
|
+
function hashOf5(row) {
|
|
213773
|
+
let h8 = hashes4.get(row);
|
|
213621
213774
|
if (h8 === void 0) {
|
|
213622
213775
|
h8 = sha12(JSON.stringify(row));
|
|
213623
|
-
|
|
213776
|
+
hashes4.set(row, h8);
|
|
213624
213777
|
}
|
|
213625
213778
|
return h8;
|
|
213626
213779
|
}
|
|
213627
|
-
function
|
|
213780
|
+
function isRow4(v3) {
|
|
213628
213781
|
const r8 = v3;
|
|
213629
213782
|
if (!r8 || typeof r8 !== "object" || typeof r8.key !== "string") return false;
|
|
213630
213783
|
if (r8.key === "favorites") {
|
|
@@ -213634,27 +213787,27 @@ function isRow3(v3) {
|
|
|
213634
213787
|
const p6 = prefOf(r8.pref);
|
|
213635
213788
|
return Object.keys(r8).length === 2 && r8.key.startsWith(UI) && copyableUiPrefKey(r8.key.slice(UI.length)) && !!p6 && typeof r8.pref === "object";
|
|
213636
213789
|
}
|
|
213637
|
-
function
|
|
213790
|
+
function admit2(r8) {
|
|
213638
213791
|
if ("favorites" in r8) return [...r8.favorites.projects, ...r8.favorites.notes].every((s4) => typeof s4 === "string" && secretShapedValue(s4) === null);
|
|
213639
213792
|
return prefAdmissible(r8.pref);
|
|
213640
213793
|
}
|
|
213641
213794
|
async function readUiPrefsCopy() {
|
|
213642
|
-
const rows = await
|
|
213795
|
+
const rows = await copy3.read();
|
|
213643
213796
|
if (!rows) return null;
|
|
213644
213797
|
const out = {};
|
|
213645
213798
|
for (const r8 of Object.values(rows)) if ("pref" in r8) out[r8.key.slice(UI.length)] = r8.pref;
|
|
213646
213799
|
return out;
|
|
213647
213800
|
}
|
|
213648
213801
|
async function readFavoritesCopy() {
|
|
213649
|
-
const rows = await
|
|
213802
|
+
const rows = await copy3.read();
|
|
213650
213803
|
if (!rows) return null;
|
|
213651
213804
|
const f8 = rows.favorites;
|
|
213652
213805
|
return f8 && "favorites" in f8 ? f8.favorites : { projects: [], notes: [] };
|
|
213653
213806
|
}
|
|
213654
213807
|
function _resetPrefsCopyForTesting() {
|
|
213655
|
-
|
|
213808
|
+
copy3.reset();
|
|
213656
213809
|
}
|
|
213657
|
-
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2,
|
|
213810
|
+
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes4, PREFS_KIND, copy3, prefsFollower;
|
|
213658
213811
|
var init_prefs = __esm({
|
|
213659
213812
|
"src/core/replication/kinds/prefs.ts"() {
|
|
213660
213813
|
"use strict";
|
|
@@ -213668,16 +213821,16 @@ var init_prefs = __esm({
|
|
|
213668
213821
|
PREFS_REMOVAL_FLOOR = 0;
|
|
213669
213822
|
UI = "ui:";
|
|
213670
213823
|
MAX_VALUE_LEN2 = 8 * 1024;
|
|
213671
|
-
|
|
213824
|
+
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
213672
213825
|
PREFS_KIND = {
|
|
213673
213826
|
kind: "prefs",
|
|
213674
213827
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
213675
213828
|
key: (r8) => r8.key,
|
|
213676
|
-
hash:
|
|
213829
|
+
hash: hashOf5,
|
|
213677
213830
|
ordered: false,
|
|
213678
213831
|
digest: false,
|
|
213679
213832
|
choice: "prefs",
|
|
213680
|
-
rows:
|
|
213833
|
+
rows: leaderRows2,
|
|
213681
213834
|
watch: (soon) => {
|
|
213682
213835
|
const stops = [];
|
|
213683
213836
|
let stopped2 = false;
|
|
@@ -213690,16 +213843,16 @@ var init_prefs = __esm({
|
|
|
213690
213843
|
};
|
|
213691
213844
|
}
|
|
213692
213845
|
};
|
|
213693
|
-
|
|
213846
|
+
copy3 = createFileCopy({
|
|
213694
213847
|
kind: "prefs",
|
|
213695
213848
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
213696
213849
|
label: "prefs copy",
|
|
213697
213850
|
removalFloor: PREFS_REMOVAL_FLOOR,
|
|
213698
|
-
isRow:
|
|
213851
|
+
isRow: isRow4,
|
|
213699
213852
|
key: (r8) => r8.key,
|
|
213700
|
-
admit
|
|
213853
|
+
admit: admit2
|
|
213701
213854
|
});
|
|
213702
|
-
prefsFollower =
|
|
213855
|
+
prefsFollower = copy3.follower;
|
|
213703
213856
|
}
|
|
213704
213857
|
});
|
|
213705
213858
|
|
|
@@ -214291,7 +214444,7 @@ async function adoptDeviceRecord(input, opts2 = {}) {
|
|
|
214291
214444
|
const existing = devices.find((d8) => d8.tokenHash === tokenHash);
|
|
214292
214445
|
if (existing) return { result: { name: existing.name, adopted: false } };
|
|
214293
214446
|
const finalName = freeName(devices, name);
|
|
214294
|
-
const wanted = typeof input.id === "string" &&
|
|
214447
|
+
const wanted = typeof input.id === "string" && ID_RE4.test(input.id) ? input.id : void 0;
|
|
214295
214448
|
const idFree = wanted !== void 0 && !devices.some((d8) => d8.id === wanted || d8.ownerId === wanted);
|
|
214296
214449
|
const record2 = {
|
|
214297
214450
|
name: finalName,
|
|
@@ -214326,7 +214479,7 @@ async function revokeAdopted(tokenHash) {
|
|
|
214326
214479
|
if (out.revoked) log.web.info("device-adoption: twin pairing revoked", { name: record2.name, adoptedFrom: record2.adoptedFrom ?? null });
|
|
214327
214480
|
return out.revoked ? { name: record2.name, refused: false, push: out.push } : { name: null, refused: false, push: null };
|
|
214328
214481
|
}
|
|
214329
|
-
var AdoptionError, HASH_RE2,
|
|
214482
|
+
var AdoptionError, HASH_RE2, ID_RE4, INFO_FIELD_MAX2, NAME_MAX2;
|
|
214330
214483
|
var init_device_adoption = __esm({
|
|
214331
214484
|
"src/core/device-adoption.ts"() {
|
|
214332
214485
|
"use strict";
|
|
@@ -214344,7 +214497,7 @@ var init_device_adoption = __esm({
|
|
|
214344
214497
|
}
|
|
214345
214498
|
};
|
|
214346
214499
|
HASH_RE2 = /^[0-9a-f]{64}$/;
|
|
214347
|
-
|
|
214500
|
+
ID_RE4 = /^d[0-9a-f]{16}$/;
|
|
214348
214501
|
INFO_FIELD_MAX2 = 120;
|
|
214349
214502
|
NAME_MAX2 = 64;
|
|
214350
214503
|
}
|
|
@@ -243731,7 +243884,7 @@ async function saveRecordingAudio(audioBase64, format2) {
|
|
|
243731
243884
|
return { id, audioPath };
|
|
243732
243885
|
}
|
|
243733
243886
|
async function writeRecordingResult(id, meta) {
|
|
243734
|
-
if (!
|
|
243887
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
243735
243888
|
await mkdir7(dir3(), { recursive: true });
|
|
243736
243889
|
const stamped = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...meta };
|
|
243737
243890
|
await writeFile6(join16(dir3(), `${id}.json`), JSON.stringify(stamped, null, 2));
|
|
@@ -243740,7 +243893,7 @@ async function writeRecordingResult(id, meta) {
|
|
|
243740
243893
|
return stamped.timestamp;
|
|
243741
243894
|
}
|
|
243742
243895
|
async function writeRecordingSecondary(id, secondary, expectTimestamp) {
|
|
243743
|
-
if (!
|
|
243896
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
243744
243897
|
const path297 = join16(dir3(), `${id}.json`);
|
|
243745
243898
|
let existing;
|
|
243746
243899
|
try {
|
|
@@ -243762,7 +243915,7 @@ async function listRecordings(limit = 20) {
|
|
|
243762
243915
|
const out = [];
|
|
243763
243916
|
for (const jf of jsonFiles) {
|
|
243764
243917
|
const id = jf.slice(0, -5);
|
|
243765
|
-
if (!
|
|
243918
|
+
if (!ID_RE5.test(id)) continue;
|
|
243766
243919
|
try {
|
|
243767
243920
|
const raw = JSON.parse(await readFile8(join16(dir3(), jf), "utf-8"));
|
|
243768
243921
|
out.push({
|
|
@@ -243782,7 +243935,7 @@ async function listRecordings(limit = 20) {
|
|
|
243782
243935
|
return out;
|
|
243783
243936
|
}
|
|
243784
243937
|
async function readRecordingAudio(id) {
|
|
243785
|
-
if (!
|
|
243938
|
+
if (!ID_RE5.test(id)) return null;
|
|
243786
243939
|
let files;
|
|
243787
243940
|
try {
|
|
243788
243941
|
files = await readdir3(dir3());
|
|
@@ -243810,13 +243963,13 @@ async function pruneOldRecordings() {
|
|
|
243810
243963
|
}
|
|
243811
243964
|
}
|
|
243812
243965
|
}
|
|
243813
|
-
var MAX_RECORDINGS,
|
|
243966
|
+
var MAX_RECORDINGS, ID_RE5, AUDIO_EXTS;
|
|
243814
243967
|
var init_recordings = __esm({
|
|
243815
243968
|
"src/core/stt/recordings.ts"() {
|
|
243816
243969
|
"use strict";
|
|
243817
243970
|
init_constants();
|
|
243818
243971
|
MAX_RECORDINGS = 100;
|
|
243819
|
-
|
|
243972
|
+
ID_RE5 = /^[0-9A-Za-z-]+$/;
|
|
243820
243973
|
AUDIO_EXTS = ["webm", "mp4", "ogg", "wav", "mp3", "m4a", "flac"];
|
|
243821
243974
|
}
|
|
243822
243975
|
});
|
|
@@ -250464,6 +250617,147 @@ var init_task_v1 = __esm({
|
|
|
250464
250617
|
}
|
|
250465
250618
|
});
|
|
250466
250619
|
|
|
250620
|
+
// src/core/replication/kinds/requests.ts
|
|
250621
|
+
var requests_exports = {};
|
|
250622
|
+
__export(requests_exports, {
|
|
250623
|
+
REQUESTS_KIND: () => REQUESTS_KIND,
|
|
250624
|
+
REQUESTS_REMOVAL_FLOOR: () => REQUESTS_REMOVAL_FLOOR,
|
|
250625
|
+
REQUESTS_SCHEMA_VERSION: () => REQUESTS_SCHEMA_VERSION,
|
|
250626
|
+
_resetRequestsCopyForTesting: () => _resetRequestsCopyForTesting,
|
|
250627
|
+
forwardRequest: () => forwardRequest,
|
|
250628
|
+
readRequestCopy: () => readRequestCopy,
|
|
250629
|
+
requestsFollower: () => requestsFollower
|
|
250630
|
+
});
|
|
250631
|
+
import fsp124 from "fs/promises";
|
|
250632
|
+
import path234 from "path";
|
|
250633
|
+
function forwardRequest(local, incoming) {
|
|
250634
|
+
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
250635
|
+
return incoming;
|
|
250636
|
+
}
|
|
250637
|
+
function hashOf6(row) {
|
|
250638
|
+
let h8 = hashes5.get(row);
|
|
250639
|
+
if (h8 === void 0) {
|
|
250640
|
+
h8 = sha12(JSON.stringify(row));
|
|
250641
|
+
hashes5.set(row, h8);
|
|
250642
|
+
}
|
|
250643
|
+
return h8;
|
|
250644
|
+
}
|
|
250645
|
+
async function load6() {
|
|
250646
|
+
if (state11) return state11;
|
|
250647
|
+
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
250648
|
+
try {
|
|
250649
|
+
const raw = JSON.parse(await fsp124.readFile(STATE_FILE(), "utf8"));
|
|
250650
|
+
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 };
|
|
250651
|
+
} catch {
|
|
250652
|
+
}
|
|
250653
|
+
state11 = s4;
|
|
250654
|
+
return s4;
|
|
250655
|
+
}
|
|
250656
|
+
async function save() {
|
|
250657
|
+
if (state11) await writeCopyFile(STATE_FILE(), { v: 1, asOf: state11.asOf, at: state11.at, hashes: state11.hashes });
|
|
250658
|
+
}
|
|
250659
|
+
async function readStore8() {
|
|
250660
|
+
try {
|
|
250661
|
+
const raw = JSON.parse(await fsp124.readFile(STORE_FILE(), "utf8"));
|
|
250662
|
+
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
250663
|
+
} catch {
|
|
250664
|
+
return [];
|
|
250665
|
+
}
|
|
250666
|
+
}
|
|
250667
|
+
function isRow5(v3) {
|
|
250668
|
+
const r8 = v3;
|
|
250669
|
+
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
250670
|
+
}
|
|
250671
|
+
function requestsFollower() {
|
|
250672
|
+
follower3 ??= createRowSetFollower({
|
|
250673
|
+
kind: "requests",
|
|
250674
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
250675
|
+
label: "requests copy",
|
|
250676
|
+
log: log.session,
|
|
250677
|
+
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
250678
|
+
ordered: false,
|
|
250679
|
+
serial: (fn) => serial4(fn),
|
|
250680
|
+
refuse: copyRefusal,
|
|
250681
|
+
load: load6,
|
|
250682
|
+
save,
|
|
250683
|
+
isRow: isRow5,
|
|
250684
|
+
key: (r8) => r8.id,
|
|
250685
|
+
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
250686
|
+
apply: async ({ rows, removeIds }) => {
|
|
250687
|
+
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
250688
|
+
for (const id of removeIds ?? []) byId.delete(id);
|
|
250689
|
+
for (const r8 of rows ?? []) {
|
|
250690
|
+
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
250691
|
+
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 });
|
|
250692
|
+
byId.set(r8.id, kept);
|
|
250693
|
+
}
|
|
250694
|
+
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
250695
|
+
return { skipped: [] };
|
|
250696
|
+
},
|
|
250697
|
+
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
250698
|
+
changed: () => {
|
|
250699
|
+
},
|
|
250700
|
+
purge: async () => {
|
|
250701
|
+
const removed = (await readStore8()).length;
|
|
250702
|
+
await fsp124.rm(STORE_FILE(), { force: true });
|
|
250703
|
+
await markCopyOff("requests");
|
|
250704
|
+
state11 = null;
|
|
250705
|
+
return { removed };
|
|
250706
|
+
}
|
|
250707
|
+
});
|
|
250708
|
+
return follower3;
|
|
250709
|
+
}
|
|
250710
|
+
async function readRequestCopy(id) {
|
|
250711
|
+
if (!await copyKindHeld("requests")) return null;
|
|
250712
|
+
return (await readStore8()).find((r8) => r8.id === id) ?? null;
|
|
250713
|
+
}
|
|
250714
|
+
function _resetRequestsCopyForTesting() {
|
|
250715
|
+
state11 = null;
|
|
250716
|
+
follower3 = null;
|
|
250717
|
+
serial4 = serialChain();
|
|
250718
|
+
}
|
|
250719
|
+
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes5, REQUESTS_KIND, STATE_FILE, STORE_FILE, state11, serial4, follower3;
|
|
250720
|
+
var init_requests = __esm({
|
|
250721
|
+
"src/core/replication/kinds/requests.ts"() {
|
|
250722
|
+
"use strict";
|
|
250723
|
+
init_constants();
|
|
250724
|
+
init_logging();
|
|
250725
|
+
init_kind();
|
|
250726
|
+
init_kind_follower();
|
|
250727
|
+
init_gate();
|
|
250728
|
+
REQUESTS_SCHEMA_VERSION = 1;
|
|
250729
|
+
REQUESTS_REMOVAL_FLOOR = 50;
|
|
250730
|
+
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
250731
|
+
hashes5 = /* @__PURE__ */ new WeakMap();
|
|
250732
|
+
REQUESTS_KIND = {
|
|
250733
|
+
kind: "requests",
|
|
250734
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
250735
|
+
key: (r8) => r8.id,
|
|
250736
|
+
hash: hashOf6,
|
|
250737
|
+
ordered: false,
|
|
250738
|
+
digest: false,
|
|
250739
|
+
choice: "requests",
|
|
250740
|
+
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
250741
|
+
watch: (soon) => {
|
|
250742
|
+
let stop2 = null;
|
|
250743
|
+
let stopped2 = false;
|
|
250744
|
+
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
250745
|
+
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
250746
|
+
});
|
|
250747
|
+
return () => {
|
|
250748
|
+
stopped2 = true;
|
|
250749
|
+
stop2?.();
|
|
250750
|
+
};
|
|
250751
|
+
}
|
|
250752
|
+
};
|
|
250753
|
+
STATE_FILE = () => path234.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
250754
|
+
STORE_FILE = () => copyPath(path234.join(WALNUT_HOME, "session-requests.json"));
|
|
250755
|
+
state11 = null;
|
|
250756
|
+
serial4 = serialChain();
|
|
250757
|
+
follower3 = null;
|
|
250758
|
+
}
|
|
250759
|
+
});
|
|
250760
|
+
|
|
250467
250761
|
// src/web/routes/messages-v1.ts
|
|
250468
250762
|
import { Router as Router82 } from "express";
|
|
250469
250763
|
function header(req, name) {
|
|
@@ -250524,7 +250818,15 @@ var init_messages_v1 = __esm({
|
|
|
250524
250818
|
return;
|
|
250525
250819
|
}
|
|
250526
250820
|
const { getSessionRequest: getSessionRequest2 } = await Promise.resolve().then(() => (init_session_requests(), session_requests_exports));
|
|
250527
|
-
|
|
250821
|
+
let request3 = await getSessionRequest2(id);
|
|
250822
|
+
if (!request3) {
|
|
250823
|
+
const [{ readRequestCopy: readRequestCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
250824
|
+
Promise.resolve().then(() => (init_requests(), requests_exports)),
|
|
250825
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
250826
|
+
]);
|
|
250827
|
+
request3 = await readRequestCopy2(id) ?? void 0;
|
|
250828
|
+
if (request3) res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("requests") ?? 0));
|
|
250829
|
+
}
|
|
250528
250830
|
if (!request3) {
|
|
250529
250831
|
sendV1Error(res, 404, "not_found", `No such request: ${id}`);
|
|
250530
250832
|
return;
|
|
@@ -252199,6 +252501,17 @@ var init_search_memory_v1 = __esm({
|
|
|
252199
252501
|
});
|
|
252200
252502
|
searchMemoryV1Router.get("/favorites", async (_req, res, next) => {
|
|
252201
252503
|
try {
|
|
252504
|
+
const [{ readFavoritesCopy: readFavoritesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
252505
|
+
Promise.resolve().then(() => (init_prefs(), prefs_exports)),
|
|
252506
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
252507
|
+
]);
|
|
252508
|
+
const asOf2 = await copyKindAsOf2("prefs");
|
|
252509
|
+
const fav = asOf2 === null ? null : await readFavoritesCopy2();
|
|
252510
|
+
if (fav) {
|
|
252511
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(asOf2));
|
|
252512
|
+
res.json({ projects: fav.projects ?? [], notes: fav.notes ?? [] });
|
|
252513
|
+
return;
|
|
252514
|
+
}
|
|
252202
252515
|
const { readFavorites: readFavorites2 } = await Promise.resolve().then(() => (init_favorites(), favorites_exports));
|
|
252203
252516
|
res.json(await readFavorites2());
|
|
252204
252517
|
} catch (err2) {
|
|
@@ -253231,9 +253544,9 @@ var init_stt_v1 = __esm({
|
|
|
253231
253544
|
|
|
253232
253545
|
// src/web/routes/pastes.ts
|
|
253233
253546
|
import { Router as Router89 } from "express";
|
|
253234
|
-
import
|
|
253547
|
+
import path235 from "path";
|
|
253235
253548
|
import { createHash as createHash37 } from "crypto";
|
|
253236
|
-
import
|
|
253549
|
+
import fsp125 from "fs/promises";
|
|
253237
253550
|
var pastesRouter, MAX_PASTE_CHARS;
|
|
253238
253551
|
var init_pastes = __esm({
|
|
253239
253552
|
"src/web/routes/pastes.ts"() {
|
|
@@ -253253,11 +253566,11 @@ var init_pastes = __esm({
|
|
|
253253
253566
|
res.status(413).json({ error: `Paste too large (max ${MAX_PASTE_CHARS} chars)` });
|
|
253254
253567
|
return;
|
|
253255
253568
|
}
|
|
253256
|
-
await
|
|
253569
|
+
await fsp125.mkdir(PASTES_DIR, { recursive: true });
|
|
253257
253570
|
const hash3 = createHash37("sha256").update(text5).digest("hex").slice(0, 12);
|
|
253258
253571
|
const filename = `${Date.now()}-${hash3}.txt`;
|
|
253259
|
-
const filePath =
|
|
253260
|
-
await
|
|
253572
|
+
const filePath = path235.join(PASTES_DIR, filename);
|
|
253573
|
+
await fsp125.writeFile(filePath, text5, "utf8");
|
|
253261
253574
|
log.web.info("paste spilled to disk", { filePath, chars: text5.length });
|
|
253262
253575
|
res.json({ path: filePath, filename, chars: text5.length });
|
|
253263
253576
|
} catch (err2) {
|
|
@@ -253273,8 +253586,8 @@ __export(file_content_replica_copy_exports, {
|
|
|
253273
253586
|
primaryDataDirRelPath: () => primaryDataDirRelPath,
|
|
253274
253587
|
resolveReplicaCopy: () => resolveReplicaCopy
|
|
253275
253588
|
});
|
|
253276
|
-
import
|
|
253277
|
-
import
|
|
253589
|
+
import path236 from "path";
|
|
253590
|
+
import fsp126 from "fs/promises";
|
|
253278
253591
|
function dataDirIndex(parts, tilde) {
|
|
253279
253592
|
if (tilde) return parts[1] === DATA_DIR_NAME ? 1 : -1;
|
|
253280
253593
|
if ((parts[0] === "Users" || parts[0] === "home") && parts[2] === DATA_DIR_NAME) return 2;
|
|
@@ -253304,12 +253617,12 @@ async function resolveReplicaCopy(requestPath) {
|
|
|
253304
253617
|
const rel = primaryDataDirRelPath(requestPath);
|
|
253305
253618
|
if (rel === null || deniedName(rel)) return null;
|
|
253306
253619
|
try {
|
|
253307
|
-
const root6 = await
|
|
253308
|
-
const real = await
|
|
253309
|
-
if (!real.startsWith(root6 +
|
|
253310
|
-
const realRel =
|
|
253311
|
-
if (isSecretPath(
|
|
253312
|
-
const st2 = await
|
|
253620
|
+
const root6 = await fsp126.realpath(WALNUT_HOME);
|
|
253621
|
+
const real = await fsp126.realpath(path236.join(WALNUT_HOME, rel));
|
|
253622
|
+
if (!real.startsWith(root6 + path236.sep)) return null;
|
|
253623
|
+
const realRel = path236.relative(root6, real).split(path236.sep).join("/");
|
|
253624
|
+
if (isSecretPath(path236.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
|
|
253625
|
+
const st2 = await fsp126.stat(real);
|
|
253313
253626
|
if (!st2.isFile()) return null;
|
|
253314
253627
|
if (!await isTracked(root6, realRel)) return null;
|
|
253315
253628
|
return { localPath: real, size: st2.size };
|
|
@@ -253349,11 +253662,11 @@ var init_file_content_replica_copy = __esm({
|
|
|
253349
253662
|
// src/web/routes/media-v1.ts
|
|
253350
253663
|
import { Router as Router90 } from "express";
|
|
253351
253664
|
import crypto67 from "crypto";
|
|
253352
|
-
import
|
|
253353
|
-
import
|
|
253665
|
+
import path237 from "path";
|
|
253666
|
+
import fsp127 from "fs/promises";
|
|
253354
253667
|
function cachePathFor(host, filePath) {
|
|
253355
253668
|
const hash3 = crypto67.createHash("sha256").update(filePath).digest("hex").slice(0, 16);
|
|
253356
|
-
return
|
|
253669
|
+
return path237.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path237.basename(filePath)}`);
|
|
253357
253670
|
}
|
|
253358
253671
|
async function hostForSession(sessionId) {
|
|
253359
253672
|
if (CLOUD_MODE) {
|
|
@@ -253418,11 +253731,11 @@ var init_media_v1 = __esm({
|
|
|
253418
253731
|
try {
|
|
253419
253732
|
const filePath = req.query.path;
|
|
253420
253733
|
const session2 = typeof req.query.session === "string" && SID_RE6.test(req.query.session) ? req.query.session : void 0;
|
|
253421
|
-
if (!filePath || typeof filePath !== "string" || !
|
|
253734
|
+
if (!filePath || typeof filePath !== "string" || !path237.isAbsolute(filePath) || filePath.includes("..")) {
|
|
253422
253735
|
res.status(400).json({ error: { code: "bad_request", message: "path must be an absolute file path" } });
|
|
253423
253736
|
return;
|
|
253424
253737
|
}
|
|
253425
|
-
const ext2 =
|
|
253738
|
+
const ext2 = path237.extname(filePath).slice(1).toLowerCase();
|
|
253426
253739
|
const mime = EXT_TO_MIME3[ext2];
|
|
253427
253740
|
if (!mime) {
|
|
253428
253741
|
res.status(400).json({ error: { code: "bad_request", message: "file type not allowed" } });
|
|
@@ -253430,8 +253743,8 @@ var init_media_v1 = __esm({
|
|
|
253430
253743
|
}
|
|
253431
253744
|
let buffer2 = null;
|
|
253432
253745
|
try {
|
|
253433
|
-
const st2 = await
|
|
253434
|
-
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
253746
|
+
const st2 = await fsp127.stat(filePath);
|
|
253747
|
+
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(filePath);
|
|
253435
253748
|
} catch {
|
|
253436
253749
|
}
|
|
253437
253750
|
let waitedOnPending = false;
|
|
@@ -253452,8 +253765,8 @@ var init_media_v1 = __esm({
|
|
|
253452
253765
|
if (buffer2) {
|
|
253453
253766
|
try {
|
|
253454
253767
|
const cachePath3 = cachePathFor(host, filePath);
|
|
253455
|
-
await
|
|
253456
|
-
await
|
|
253768
|
+
await fsp127.mkdir(path237.dirname(cachePath3), { recursive: true });
|
|
253769
|
+
await fsp127.writeFile(cachePath3, buffer2);
|
|
253457
253770
|
} catch {
|
|
253458
253771
|
}
|
|
253459
253772
|
break;
|
|
@@ -253463,9 +253776,9 @@ var init_media_v1 = __esm({
|
|
|
253463
253776
|
for (const host of hosts2) {
|
|
253464
253777
|
try {
|
|
253465
253778
|
const cached8 = cachePathFor(host, filePath);
|
|
253466
|
-
const st2 = await
|
|
253779
|
+
const st2 = await fsp127.stat(cached8);
|
|
253467
253780
|
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) {
|
|
253468
|
-
buffer2 = await
|
|
253781
|
+
buffer2 = await fsp127.readFile(cached8);
|
|
253469
253782
|
break;
|
|
253470
253783
|
}
|
|
253471
253784
|
} catch {
|
|
@@ -253475,7 +253788,7 @@ var init_media_v1 = __esm({
|
|
|
253475
253788
|
if (!buffer2 && hosts2.length > 0 && hosts2.every((h8) => h8 === "__local__") && !(await Promise.resolve().then(() => (init_bridge_registry(), bridge_registry_exports))).bridgeForHost("__local__").connected) {
|
|
253476
253789
|
const { resolveReplicaCopy: resolveReplicaCopy2 } = await Promise.resolve().then(() => (init_file_content_replica_copy(), file_content_replica_copy_exports));
|
|
253477
253790
|
const copy5 = await resolveReplicaCopy2(filePath);
|
|
253478
|
-
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
253791
|
+
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp127.readFile(copy5.localPath);
|
|
253479
253792
|
}
|
|
253480
253793
|
}
|
|
253481
253794
|
if (!buffer2) {
|
|
@@ -253500,6 +253813,19 @@ var init_media_v1 = __esm({
|
|
|
253500
253813
|
|
|
253501
253814
|
// src/web/routes/routines-v1.ts
|
|
253502
253815
|
import { Router as Router91 } from "express";
|
|
253816
|
+
async function answeredFromCopy(res, includeDisabled, answer5) {
|
|
253817
|
+
const [{ companionRoutinesCopy: companionRoutinesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
253818
|
+
Promise.resolve().then(() => (init_routines_follower(), routines_follower_exports)),
|
|
253819
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
253820
|
+
]);
|
|
253821
|
+
const jobs2 = await companionRoutinesCopy2({ includeDisabled });
|
|
253822
|
+
if (!jobs2) return false;
|
|
253823
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("routines") ?? 0));
|
|
253824
|
+
const body7 = answer5(jobs2);
|
|
253825
|
+
if (body7 === null) sendV1Error(res, 404, "not_found", "No such routine in the copy of your Mac's routines");
|
|
253826
|
+
else res.json(body7);
|
|
253827
|
+
return true;
|
|
253828
|
+
}
|
|
253503
253829
|
function validRid(req, res) {
|
|
253504
253830
|
const id = String(req.params.id ?? "");
|
|
253505
253831
|
if (!RID_RE.test(id)) {
|
|
@@ -253546,6 +253872,7 @@ var init_routines_v1 = __esm({
|
|
|
253546
253872
|
try {
|
|
253547
253873
|
const includeDisabled = req.query.includeDisabled === "true";
|
|
253548
253874
|
if (CLOUD_MODE) {
|
|
253875
|
+
if (await answeredFromCopy(res, includeDisabled, (jobs2) => ({ jobs: jobs2 }))) return;
|
|
253549
253876
|
await relayControlAction(res, "server.routines", SERVER_RELAY_SID14, { includeDisabled }, 200);
|
|
253550
253877
|
return;
|
|
253551
253878
|
}
|
|
@@ -253570,6 +253897,7 @@ var init_routines_v1 = __esm({
|
|
|
253570
253897
|
routinesV1Router.get("/routines/status", async (_req, res, next) => {
|
|
253571
253898
|
try {
|
|
253572
253899
|
if (CLOUD_MODE) {
|
|
253900
|
+
if (await answeredFromCopy(res, true, (jobs2) => ({ enabled: false, storePath: "", jobs: jobs2.length, nextWakeAtMs: null }))) return;
|
|
253573
253901
|
await relayControlAction(res, "server.routines.status", SERVER_RELAY_SID14, void 0, 200);
|
|
253574
253902
|
return;
|
|
253575
253903
|
}
|
|
@@ -253641,6 +253969,10 @@ var init_routines_v1 = __esm({
|
|
|
253641
253969
|
const id = validRid(req, res);
|
|
253642
253970
|
if (!id) return;
|
|
253643
253971
|
if (CLOUD_MODE) {
|
|
253972
|
+
if (await answeredFromCopy(res, true, (jobs2) => {
|
|
253973
|
+
const job2 = jobs2.find((j8) => j8.id === id);
|
|
253974
|
+
return job2 ? { job: job2 } : null;
|
|
253975
|
+
})) return;
|
|
253644
253976
|
await relayControlAction(res, "server.routines.get", SERVER_RELAY_SID14, { id }, 200);
|
|
253645
253977
|
return;
|
|
253646
253978
|
}
|
|
@@ -254835,8 +255167,8 @@ __export(file_content_bridge_exports, {
|
|
|
254835
255167
|
resolveBridgeHost: () => resolveBridgeHost,
|
|
254836
255168
|
serveCloudFileContent: () => serveCloudFileContent
|
|
254837
255169
|
});
|
|
254838
|
-
import
|
|
254839
|
-
import
|
|
255170
|
+
import path238 from "path";
|
|
255171
|
+
import fsp128 from "fs/promises";
|
|
254840
255172
|
function resolveBridgeHost(host) {
|
|
254841
255173
|
return typeof host === "string" && host.length > 0 ? host : PRIMARY_BRIDGE_ALIAS4;
|
|
254842
255174
|
}
|
|
@@ -254907,7 +255239,7 @@ function precheckPath(res, rawPath) {
|
|
|
254907
255239
|
sendV1Error(res, 400, "bad_request", "Invalid path");
|
|
254908
255240
|
return null;
|
|
254909
255241
|
}
|
|
254910
|
-
if (rawPath !== "~" && !rawPath.startsWith("~/") && !
|
|
255242
|
+
if (rawPath !== "~" && !rawPath.startsWith("~/") && !path238.isAbsolute(rawPath)) {
|
|
254911
255243
|
sendV1Error(res, 400, "bad_request", "Path must be absolute");
|
|
254912
255244
|
return null;
|
|
254913
255245
|
}
|
|
@@ -254951,7 +255283,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
254951
255283
|
const hostAlias2 = resolveBridgeHost(req.query.host);
|
|
254952
255284
|
const raw = req.query.raw === "1" || req.query.raw === "true";
|
|
254953
255285
|
const download = req.query.download === "1" || req.query.download === "true";
|
|
254954
|
-
const ext2 =
|
|
255286
|
+
const ext2 = path238.extname(filePath).slice(1).toLowerCase();
|
|
254955
255287
|
const {
|
|
254956
255288
|
assertPathAllowed: assertPathAllowed2,
|
|
254957
255289
|
isSecretPath: isSecretPath2,
|
|
@@ -254961,7 +255293,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
254961
255293
|
FileContentError: FileContentError2
|
|
254962
255294
|
} = await Promise.resolve().then(() => (init_file_content(), file_content_exports));
|
|
254963
255295
|
const explicitHost = typeof req.query.host === "string" && req.query.host.length > 0;
|
|
254964
|
-
const locallyPresent = await
|
|
255296
|
+
const locallyPresent = await fsp128.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
|
|
254965
255297
|
if (!explicitHost && locallyPresent && cloudLocalReadAllowed2(filePath) && !isSecretPath2(filePath)) {
|
|
254966
255298
|
try {
|
|
254967
255299
|
if (raw) {
|
|
@@ -255059,10 +255391,10 @@ async function serveReplicaCopy(req, res, requestPath, copy5, opts2) {
|
|
|
255059
255391
|
return;
|
|
255060
255392
|
}
|
|
255061
255393
|
if (copy5.size <= MAX_BRIDGE_FILE_BYTES) {
|
|
255062
|
-
res.json(jsonPayloadFromBuffer(await
|
|
255394
|
+
res.json(jsonPayloadFromBuffer(await fsp128.readFile(copy5.localPath), opts2.ext, false));
|
|
255063
255395
|
return;
|
|
255064
255396
|
}
|
|
255065
|
-
const fh = await
|
|
255397
|
+
const fh = await fsp128.open(copy5.localPath, "r");
|
|
255066
255398
|
try {
|
|
255067
255399
|
const head2 = Buffer.alloc(MAX_TEXT_PAYLOAD);
|
|
255068
255400
|
const { bytesRead } = await fh.read(head2, 0, head2.length, 0);
|
|
@@ -256136,17 +256468,17 @@ __export(checklist_io_exports, {
|
|
|
256136
256468
|
readHeartbeatChecklist: () => readHeartbeatChecklist,
|
|
256137
256469
|
writeHeartbeatChecklist: () => writeHeartbeatChecklist
|
|
256138
256470
|
});
|
|
256139
|
-
import
|
|
256471
|
+
import fsp129 from "fs/promises";
|
|
256140
256472
|
async function readHeartbeatChecklist() {
|
|
256141
256473
|
try {
|
|
256142
|
-
return await
|
|
256474
|
+
return await fsp129.readFile(HEARTBEAT_FILE, "utf-8");
|
|
256143
256475
|
} catch (err2) {
|
|
256144
256476
|
if (err2.code === "ENOENT") return "";
|
|
256145
256477
|
throw err2;
|
|
256146
256478
|
}
|
|
256147
256479
|
}
|
|
256148
256480
|
async function writeHeartbeatChecklist(content) {
|
|
256149
|
-
await
|
|
256481
|
+
await fsp129.writeFile(HEARTBEAT_FILE, content, "utf-8");
|
|
256150
256482
|
}
|
|
256151
256483
|
var init_checklist_io = __esm({
|
|
256152
256484
|
"src/heartbeat/checklist-io.ts"() {
|
|
@@ -258286,11 +258618,11 @@ __export(ephemeral_guard_exports, {
|
|
|
258286
258618
|
});
|
|
258287
258619
|
import fs127 from "fs";
|
|
258288
258620
|
import os60 from "os";
|
|
258289
|
-
import
|
|
258621
|
+
import path239 from "path";
|
|
258290
258622
|
function productionWalnutHomes() {
|
|
258291
258623
|
const homes = /* @__PURE__ */ new Set();
|
|
258292
258624
|
const add3 = (home) => {
|
|
258293
|
-
if (home) homes.add(
|
|
258625
|
+
if (home) homes.add(path239.join(home, ".open-walnut"));
|
|
258294
258626
|
};
|
|
258295
258627
|
add3(os60.homedir());
|
|
258296
258628
|
try {
|
|
@@ -258300,7 +258632,7 @@ function productionWalnutHomes() {
|
|
|
258300
258632
|
return [...homes];
|
|
258301
258633
|
}
|
|
258302
258634
|
function canonical2(dir4) {
|
|
258303
|
-
const resolved =
|
|
258635
|
+
const resolved = path239.resolve(dir4);
|
|
258304
258636
|
try {
|
|
258305
258637
|
return fs127.realpathSync(resolved);
|
|
258306
258638
|
} catch {
|
|
@@ -258336,28 +258668,28 @@ __export(boot_guard_exports, {
|
|
|
258336
258668
|
});
|
|
258337
258669
|
import fs128 from "fs";
|
|
258338
258670
|
import os61 from "os";
|
|
258339
|
-
import
|
|
258671
|
+
import path240 from "path";
|
|
258340
258672
|
function canonical3(dir4) {
|
|
258341
|
-
let head2 =
|
|
258673
|
+
let head2 = path240.resolve(dir4);
|
|
258342
258674
|
const rest = [];
|
|
258343
258675
|
for (; ; ) {
|
|
258344
258676
|
try {
|
|
258345
|
-
return
|
|
258677
|
+
return path240.join(fs128.realpathSync(head2), ...rest);
|
|
258346
258678
|
} catch {
|
|
258347
258679
|
}
|
|
258348
|
-
const up =
|
|
258349
|
-
if (up === head2) return
|
|
258350
|
-
rest.unshift(
|
|
258680
|
+
const up = path240.dirname(head2);
|
|
258681
|
+
if (up === head2) return path240.resolve(dir4);
|
|
258682
|
+
rest.unshift(path240.basename(head2));
|
|
258351
258683
|
head2 = up;
|
|
258352
258684
|
}
|
|
258353
258685
|
}
|
|
258354
258686
|
function spellings(dir4) {
|
|
258355
|
-
const resolved =
|
|
258687
|
+
const resolved = path240.resolve(dir4);
|
|
258356
258688
|
return [.../* @__PURE__ */ new Set([resolved, canonical3(resolved), `/private${resolved}`])];
|
|
258357
258689
|
}
|
|
258358
258690
|
function within5(child2, parent) {
|
|
258359
|
-
const rel =
|
|
258360
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
258691
|
+
const rel = path240.relative(parent, child2);
|
|
258692
|
+
return rel === "" || !rel.startsWith("..") && !path240.isAbsolute(rel);
|
|
258361
258693
|
}
|
|
258362
258694
|
function overlaps(a8, b8) {
|
|
258363
258695
|
return spellings(a8).some((x3) => spellings(b8).some((y3) => within5(x3, y3) || within5(y3, x3)));
|
|
@@ -258368,7 +258700,7 @@ function holdsOrIs(outer, inner2) {
|
|
|
258368
258700
|
function accountHomes(env3) {
|
|
258369
258701
|
const homes = /* @__PURE__ */ new Set();
|
|
258370
258702
|
const add3 = (h8) => {
|
|
258371
|
-
if (h8 && h8.trim()) homes.add(
|
|
258703
|
+
if (h8 && h8.trim()) homes.add(path240.resolve(h8.trim()));
|
|
258372
258704
|
};
|
|
258373
258705
|
add3(env3.HOME);
|
|
258374
258706
|
add3(os61.homedir());
|
|
@@ -258426,7 +258758,7 @@ function assertReplicaBootSafe(input) {
|
|
|
258426
258758
|
if (why2) throw new Error(`Host replica refused to start: ${why2}.`);
|
|
258427
258759
|
}
|
|
258428
258760
|
function claimReplicaDir(dir4) {
|
|
258429
|
-
const marker =
|
|
258761
|
+
const marker = path240.join(dir4, REPLICA_DIR_MARKER);
|
|
258430
258762
|
try {
|
|
258431
258763
|
return fs128.lstatSync(marker).isFile();
|
|
258432
258764
|
} catch {
|
|
@@ -258451,7 +258783,7 @@ function claimReplicaDir(dir4) {
|
|
|
258451
258783
|
function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
258452
258784
|
const marked = dirs2.filter((d8) => {
|
|
258453
258785
|
try {
|
|
258454
|
-
return fs128.lstatSync(
|
|
258786
|
+
return fs128.lstatSync(path240.join(d8, REPLICA_DIR_MARKER)).isFile();
|
|
258455
258787
|
} catch {
|
|
258456
258788
|
return false;
|
|
258457
258789
|
}
|
|
@@ -258481,7 +258813,7 @@ function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
|
258481
258813
|
} catch {
|
|
258482
258814
|
return;
|
|
258483
258815
|
}
|
|
258484
|
-
for (const n6 of names2) visit(
|
|
258816
|
+
for (const n6 of names2) visit(path240.join(p6, n6));
|
|
258485
258817
|
} else if (st2.isFile() && (st2.mode & 63) !== 0) {
|
|
258486
258818
|
try {
|
|
258487
258819
|
fs128.chmodSync(p6, st2.mode & 448 | 384);
|
|
@@ -258668,29 +259000,29 @@ __export(search_replica_store_exports, {
|
|
|
258668
259000
|
searchReplicaSync: () => searchReplicaSync,
|
|
258669
259001
|
startSearchReplicaStore: () => startSearchReplicaStore
|
|
258670
259002
|
});
|
|
258671
|
-
import
|
|
259003
|
+
import fsp130 from "fs/promises";
|
|
258672
259004
|
import os62 from "os";
|
|
258673
|
-
import
|
|
259005
|
+
import path241 from "path";
|
|
258674
259006
|
async function wiring() {
|
|
258675
259007
|
return Promise.resolve().then(() => (init_wiring(), wiring_exports));
|
|
258676
259008
|
}
|
|
258677
259009
|
async function loadState() {
|
|
258678
|
-
if (
|
|
259010
|
+
if (state12) return state12;
|
|
258679
259011
|
let s4 = { v: 1, mode: null, syncedAt: null };
|
|
258680
259012
|
try {
|
|
258681
|
-
const raw = JSON.parse(await
|
|
259013
|
+
const raw = JSON.parse(await fsp130.readFile(STATE_FILE2(), "utf8"));
|
|
258682
259014
|
if (raw && raw.v === 1) {
|
|
258683
259015
|
s4 = { v: 1, mode: raw.mode ? companionSearchMode(raw.mode) : null, syncedAt: typeof raw.syncedAt === "number" ? raw.syncedAt : null };
|
|
258684
259016
|
}
|
|
258685
259017
|
} catch {
|
|
258686
259018
|
}
|
|
258687
|
-
|
|
259019
|
+
state12 = s4;
|
|
258688
259020
|
return s4;
|
|
258689
259021
|
}
|
|
258690
259022
|
async function saveState() {
|
|
258691
|
-
if (
|
|
259023
|
+
if (state12) await writeJsonFile(STATE_FILE2(), state12);
|
|
258692
259024
|
}
|
|
258693
|
-
function
|
|
259025
|
+
function serial5(fn) {
|
|
258694
259026
|
const run12 = chain4.then(fn, fn);
|
|
258695
259027
|
chain4 = run12.catch(() => {
|
|
258696
259028
|
});
|
|
@@ -258754,8 +259086,8 @@ async function closeIndex() {
|
|
|
258754
259086
|
allDirty2 = true;
|
|
258755
259087
|
}
|
|
258756
259088
|
function publishReady() {
|
|
258757
|
-
const ready2 = enabled && mapBuilt && map3.size > 0 &&
|
|
258758
|
-
setCompanionSearchReady(ready2, ready2 ?
|
|
259089
|
+
const ready2 = enabled && mapBuilt && map3.size > 0 && state12?.syncedAt != null;
|
|
259090
|
+
setCompanionSearchReady(ready2, ready2 ? state12.syncedAt : null);
|
|
258759
259091
|
}
|
|
258760
259092
|
async function markInSync() {
|
|
258761
259093
|
const s4 = await loadState();
|
|
@@ -258782,7 +259114,7 @@ async function warm(why2) {
|
|
|
258782
259114
|
}
|
|
258783
259115
|
}
|
|
258784
259116
|
function searchReplicaStatus(body7) {
|
|
258785
|
-
return
|
|
259117
|
+
return serial5(async () => {
|
|
258786
259118
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
258787
259119
|
const s4 = await loadState();
|
|
258788
259120
|
const mode = companionSearchMode(body7.mode);
|
|
@@ -258830,7 +259162,7 @@ function searchReplicaStatus(body7) {
|
|
|
258830
259162
|
});
|
|
258831
259163
|
}
|
|
258832
259164
|
function searchReplicaSync(body7) {
|
|
258833
|
-
return
|
|
259165
|
+
return serial5(async () => {
|
|
258834
259166
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
258835
259167
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
258836
259168
|
if (!Array.isArray(body7.entries)) return { ok: false, status: 400, error: "bad_entries" };
|
|
@@ -258875,7 +259207,7 @@ async function forgetSearchMemo() {
|
|
|
258875
259207
|
}
|
|
258876
259208
|
}
|
|
258877
259209
|
function searchReplicaPut(body7) {
|
|
258878
|
-
return
|
|
259210
|
+
return serial5(async () => {
|
|
258879
259211
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
258880
259212
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
258881
259213
|
if (!Array.isArray(body7.docs)) return { ok: false, status: 400, error: "bad_docs" };
|
|
@@ -258941,7 +259273,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
258941
259273
|
if (!s4.mode || stopped2) return;
|
|
258942
259274
|
const decision = companionSearchDecision(s4.mode, deps3.totalMb());
|
|
258943
259275
|
if (!decision.enabled) return;
|
|
258944
|
-
await
|
|
259276
|
+
await serial5(async () => {
|
|
258945
259277
|
enabled = true;
|
|
258946
259278
|
reason2 = decision.reason;
|
|
258947
259279
|
await refreshMap2(await openIndex());
|
|
@@ -258974,12 +259306,12 @@ function startSearchReplicaStore(options = {}) {
|
|
|
258974
259306
|
}));
|
|
258975
259307
|
}).catch((err2) => log.memory.warn("search replica: local writes not wired", { error: err2 instanceof Error ? err2.message : String(err2) }));
|
|
258976
259308
|
unsubs.push(onLeaderPresence((answers4) => {
|
|
258977
|
-
if (stopped2 || answers4 || !enabled ||
|
|
259309
|
+
if (stopped2 || answers4 || !enabled || state12?.syncedAt == null) return;
|
|
258978
259310
|
void warm("leader away");
|
|
258979
259311
|
}));
|
|
258980
259312
|
const tick = setInterval(() => {
|
|
258981
259313
|
void (async () => {
|
|
258982
|
-
if (stopped2 || !enabled ||
|
|
259314
|
+
if (stopped2 || !enabled || state12?.syncedAt == null) return;
|
|
258983
259315
|
if (Date.now() - lastWarmAt < WARM_EVERY_MS) return;
|
|
258984
259316
|
if (!await deps3.macAway()) return;
|
|
258985
259317
|
await warm("mac away");
|
|
@@ -258998,7 +259330,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
258998
259330
|
};
|
|
258999
259331
|
}
|
|
259000
259332
|
function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
259001
|
-
|
|
259333
|
+
state12 = null;
|
|
259002
259334
|
enabled = false;
|
|
259003
259335
|
reason2 = "off";
|
|
259004
259336
|
map3.clear();
|
|
@@ -259013,7 +259345,7 @@ function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
|
259013
259345
|
deps3 = { totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)), macAway: defaultMacAway, ...overrides };
|
|
259014
259346
|
setCompanionSearchReady(false, null);
|
|
259015
259347
|
}
|
|
259016
|
-
var
|
|
259348
|
+
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;
|
|
259017
259349
|
var init_search_replica_store = __esm({
|
|
259018
259350
|
"src/core/replication/search-replica-store.ts"() {
|
|
259019
259351
|
"use strict";
|
|
@@ -259025,7 +259357,7 @@ var init_search_replica_store = __esm({
|
|
|
259025
259357
|
init_replica_refs();
|
|
259026
259358
|
init_search_digest();
|
|
259027
259359
|
init_search_replica_wire();
|
|
259028
|
-
|
|
259360
|
+
STATE_FILE2 = () => path241.join(WALNUT_HOME, "cache", "search-replica.json");
|
|
259029
259361
|
MASS_REMOVE_FLOOR = 200;
|
|
259030
259362
|
SCAN_SLICE2 = 500;
|
|
259031
259363
|
WARM_EVERY_MS = 4 * 6e4;
|
|
@@ -259035,7 +259367,7 @@ var init_search_replica_store = __esm({
|
|
|
259035
259367
|
totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)),
|
|
259036
259368
|
macAway: defaultMacAway
|
|
259037
259369
|
};
|
|
259038
|
-
|
|
259370
|
+
state12 = null;
|
|
259039
259371
|
enabled = false;
|
|
259040
259372
|
reason2 = "off";
|
|
259041
259373
|
map3 = new DigestMap();
|
|
@@ -259051,10 +259383,10 @@ var init_search_replica_store = __esm({
|
|
|
259051
259383
|
});
|
|
259052
259384
|
|
|
259053
259385
|
// src/core/replication/kinds/boards.ts
|
|
259054
|
-
import
|
|
259055
|
-
import
|
|
259386
|
+
import fsp131 from "fs/promises";
|
|
259387
|
+
import path242 from "path";
|
|
259056
259388
|
async function leaderBoards(dir4 = boardsDir2()) {
|
|
259057
|
-
const names2 = await
|
|
259389
|
+
const names2 = await fsp131.readdir(dir4).catch(() => []);
|
|
259058
259390
|
const out = [];
|
|
259059
259391
|
const unreadable = [];
|
|
259060
259392
|
const seen2 = /* @__PURE__ */ new Set();
|
|
@@ -259063,9 +259395,9 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
259063
259395
|
const id = name.slice(0, -".json".length);
|
|
259064
259396
|
if (!TASK_ID_RE3.test(id)) continue;
|
|
259065
259397
|
seen2.add(id);
|
|
259066
|
-
const file =
|
|
259398
|
+
const file = path242.join(dir4, name);
|
|
259067
259399
|
try {
|
|
259068
|
-
const st2 = await
|
|
259400
|
+
const st2 = await fsp131.stat(file);
|
|
259069
259401
|
if (!st2.isFile()) continue;
|
|
259070
259402
|
if (st2.size > BOARD_COPY_MAX_BYTES) {
|
|
259071
259403
|
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 });
|
|
@@ -259074,14 +259406,14 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
259074
259406
|
}
|
|
259075
259407
|
let c8 = cache16.get(id);
|
|
259076
259408
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
259077
|
-
const row = JSON.parse(await
|
|
259078
|
-
if (!
|
|
259409
|
+
const row = JSON.parse(await fsp131.readFile(file, "utf8"));
|
|
259410
|
+
if (!isRow6(row) || row.task_id !== id) {
|
|
259079
259411
|
unreadable.push(id);
|
|
259080
259412
|
continue;
|
|
259081
259413
|
}
|
|
259082
259414
|
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, row, hash: sha12(JSON.stringify(row)) };
|
|
259083
259415
|
cache16.set(id, c8);
|
|
259084
|
-
|
|
259416
|
+
hashOf7.set(row, c8.hash);
|
|
259085
259417
|
}
|
|
259086
259418
|
out.push(c8.row);
|
|
259087
259419
|
} catch (err2) {
|
|
@@ -259096,56 +259428,56 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
259096
259428
|
if (fresh.length > 0) log.session.warn("boards copy: a board could not be read, the host keeps its copy of it", { taskIds: fresh });
|
|
259097
259429
|
return out;
|
|
259098
259430
|
}
|
|
259099
|
-
function
|
|
259431
|
+
function isRow6(v3) {
|
|
259100
259432
|
const b8 = v3;
|
|
259101
259433
|
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";
|
|
259102
259434
|
}
|
|
259103
|
-
async function
|
|
259104
|
-
if (
|
|
259435
|
+
async function load7() {
|
|
259436
|
+
if (state13) return state13;
|
|
259105
259437
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
259106
259438
|
try {
|
|
259107
|
-
const raw = JSON.parse(await
|
|
259439
|
+
const raw = JSON.parse(await fsp131.readFile(STATE_FILE3(), "utf8"));
|
|
259108
259440
|
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 };
|
|
259109
259441
|
} catch {
|
|
259110
259442
|
}
|
|
259111
|
-
|
|
259443
|
+
state13 = s4;
|
|
259112
259444
|
return s4;
|
|
259113
259445
|
}
|
|
259114
|
-
async function
|
|
259115
|
-
if (
|
|
259446
|
+
async function save2() {
|
|
259447
|
+
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
259116
259448
|
}
|
|
259117
259449
|
async function localIds() {
|
|
259118
|
-
const names2 = await
|
|
259450
|
+
const names2 = await fsp131.readdir(boardsDir2()).catch(() => []);
|
|
259119
259451
|
return names2.filter((n6) => n6.endsWith(".json")).map((n6) => n6.slice(0, -".json".length)).filter((id) => TASK_ID_RE3.test(id));
|
|
259120
259452
|
}
|
|
259121
259453
|
function changed3() {
|
|
259122
259454
|
}
|
|
259123
259455
|
function boardsFollower() {
|
|
259124
|
-
|
|
259456
|
+
follower4 ??= createRowSetFollower({
|
|
259125
259457
|
kind: "boards",
|
|
259126
259458
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
259127
259459
|
label: "boards copy",
|
|
259128
259460
|
log: log.session,
|
|
259129
259461
|
removalFloor: BOARDS_REMOVAL_FLOOR,
|
|
259130
259462
|
ordered: false,
|
|
259131
|
-
serial: (fn) =>
|
|
259463
|
+
serial: (fn) => serial6(fn),
|
|
259132
259464
|
refuse: copyRefusal,
|
|
259133
|
-
load:
|
|
259134
|
-
save,
|
|
259135
|
-
isRow:
|
|
259465
|
+
load: load7,
|
|
259466
|
+
save: save2,
|
|
259467
|
+
isRow: isRow6,
|
|
259136
259468
|
key: (b8) => b8.task_id,
|
|
259137
259469
|
localKeys: localIds,
|
|
259138
259470
|
apply: async ({ rows, removeIds }) => {
|
|
259139
259471
|
const skipped = [];
|
|
259140
259472
|
for (const id of removeIds ?? []) {
|
|
259141
|
-
if (TASK_ID_RE3.test(id)) await
|
|
259473
|
+
if (TASK_ID_RE3.test(id)) await fsp131.rm(path242.join(boardsDir2(), `${id}.json`), { force: true });
|
|
259142
259474
|
}
|
|
259143
259475
|
for (const b8 of rows ?? []) {
|
|
259144
259476
|
if (Buffer.byteLength(JSON.stringify(b8)) > BOARD_COPY_MAX_BYTES) {
|
|
259145
259477
|
skipped.push(b8.task_id);
|
|
259146
259478
|
continue;
|
|
259147
259479
|
}
|
|
259148
|
-
await writeCopyFile(
|
|
259480
|
+
await writeCopyFile(path242.join(boardsDir2(), `${b8.task_id}.json`), b8);
|
|
259149
259481
|
}
|
|
259150
259482
|
return { skipped };
|
|
259151
259483
|
},
|
|
@@ -259153,15 +259485,15 @@ function boardsFollower() {
|
|
|
259153
259485
|
changed: changed3,
|
|
259154
259486
|
purge: async () => {
|
|
259155
259487
|
const ids2 = await localIds();
|
|
259156
|
-
for (const id of ids2) await
|
|
259488
|
+
for (const id of ids2) await fsp131.rm(path242.join(boardsDir2(), `${id}.json`), { force: true });
|
|
259157
259489
|
await markCopyOff("boards");
|
|
259158
|
-
|
|
259490
|
+
state13 = null;
|
|
259159
259491
|
return { removed: ids2.length };
|
|
259160
259492
|
}
|
|
259161
259493
|
});
|
|
259162
|
-
return
|
|
259494
|
+
return follower4;
|
|
259163
259495
|
}
|
|
259164
|
-
var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16,
|
|
259496
|
+
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;
|
|
259165
259497
|
var init_boards2 = __esm({
|
|
259166
259498
|
"src/core/replication/kinds/boards.ts"() {
|
|
259167
259499
|
"use strict";
|
|
@@ -259174,9 +259506,9 @@ var init_boards2 = __esm({
|
|
|
259174
259506
|
BOARDS_REMOVAL_FLOOR = 20;
|
|
259175
259507
|
BOARD_COPY_MAX_BYTES = 2 * 1024 * 1024;
|
|
259176
259508
|
TASK_ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
259177
|
-
boardsDir2 = () =>
|
|
259509
|
+
boardsDir2 = () => path242.join(WALNUT_HOME, "boards");
|
|
259178
259510
|
cache16 = /* @__PURE__ */ new Map();
|
|
259179
|
-
|
|
259511
|
+
hashOf7 = /* @__PURE__ */ new WeakMap();
|
|
259180
259512
|
warnedTooBig = /* @__PURE__ */ new Set();
|
|
259181
259513
|
unreadableOf2 = /* @__PURE__ */ new WeakMap();
|
|
259182
259514
|
warnedUnreadable = /* @__PURE__ */ new Set();
|
|
@@ -259184,7 +259516,7 @@ var init_boards2 = __esm({
|
|
|
259184
259516
|
kind: "boards",
|
|
259185
259517
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
259186
259518
|
key: (b8) => b8.task_id,
|
|
259187
|
-
hash: (b8) =>
|
|
259519
|
+
hash: (b8) => hashOf7.get(b8) ?? sha12(JSON.stringify(b8)),
|
|
259188
259520
|
ordered: false,
|
|
259189
259521
|
digest: false,
|
|
259190
259522
|
choice: "boards",
|
|
@@ -259204,16 +259536,16 @@ var init_boards2 = __esm({
|
|
|
259204
259536
|
};
|
|
259205
259537
|
}
|
|
259206
259538
|
};
|
|
259207
|
-
|
|
259208
|
-
|
|
259209
|
-
|
|
259210
|
-
|
|
259539
|
+
STATE_FILE3 = () => path242.join(WALNUT_HOME, "cache", "replica", "boards.json");
|
|
259540
|
+
state13 = null;
|
|
259541
|
+
serial6 = serialChain();
|
|
259542
|
+
follower4 = null;
|
|
259211
259543
|
}
|
|
259212
259544
|
});
|
|
259213
259545
|
|
|
259214
259546
|
// src/core/replication/kinds/inbox.ts
|
|
259215
|
-
import
|
|
259216
|
-
import
|
|
259547
|
+
import fsp132 from "fs/promises";
|
|
259548
|
+
import path243 from "path";
|
|
259217
259549
|
function watchLetters(soon) {
|
|
259218
259550
|
let stop2 = null;
|
|
259219
259551
|
let stopped2 = false;
|
|
@@ -259226,18 +259558,18 @@ function watchLetters(soon) {
|
|
|
259226
259558
|
};
|
|
259227
259559
|
}
|
|
259228
259560
|
async function leaderBodies(dir4 = bodiesDir()) {
|
|
259229
|
-
const names2 = (await
|
|
259561
|
+
const names2 = (await fsp132.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
|
|
259230
259562
|
const out = [];
|
|
259231
259563
|
const unreadable = [];
|
|
259232
259564
|
const seen2 = new Set(names2);
|
|
259233
259565
|
for (const name of names2) {
|
|
259234
|
-
const file =
|
|
259566
|
+
const file = path243.join(dir4, name);
|
|
259235
259567
|
try {
|
|
259236
|
-
const st2 = await
|
|
259568
|
+
const st2 = await fsp132.stat(file);
|
|
259237
259569
|
if (!st2.isFile() || st2.size > INBOX_BODY_COPY_MAX_BYTES) continue;
|
|
259238
259570
|
let c8 = bodyCache.get(name);
|
|
259239
259571
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
259240
|
-
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await
|
|
259572
|
+
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp132.readFile(file, "utf8")) };
|
|
259241
259573
|
bodyCache.set(name, c8);
|
|
259242
259574
|
}
|
|
259243
259575
|
const row = { name };
|
|
@@ -259256,21 +259588,21 @@ async function loadBody(b8) {
|
|
|
259256
259588
|
const file = bodyFiles.get(b8);
|
|
259257
259589
|
if (!file) return typeof b8.body === "string" ? b8 : void 0;
|
|
259258
259590
|
try {
|
|
259259
|
-
const body7 = await
|
|
259591
|
+
const body7 = await fsp132.readFile(file, "utf8");
|
|
259260
259592
|
return Buffer.byteLength(body7) > INBOX_BODY_COPY_MAX_BYTES ? void 0 : { name: b8.name, body: body7 };
|
|
259261
259593
|
} catch {
|
|
259262
259594
|
return void 0;
|
|
259263
259595
|
}
|
|
259264
259596
|
}
|
|
259265
259597
|
function stateIo(name) {
|
|
259266
|
-
const file = () =>
|
|
259598
|
+
const file = () => path243.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
|
|
259267
259599
|
let state17 = null;
|
|
259268
259600
|
return {
|
|
259269
259601
|
load: async () => {
|
|
259270
259602
|
if (state17) return state17;
|
|
259271
259603
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
259272
259604
|
try {
|
|
259273
|
-
const raw = JSON.parse(await
|
|
259605
|
+
const raw = JSON.parse(await fsp132.readFile(file(), "utf8"));
|
|
259274
259606
|
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") {
|
|
259275
259607
|
s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: Array.isArray(raw.order) ? raw.order.map(String) : [], hashes: raw.hashes };
|
|
259276
259608
|
}
|
|
@@ -259289,7 +259621,7 @@ function stateIo(name) {
|
|
|
259289
259621
|
}
|
|
259290
259622
|
async function readIndex3() {
|
|
259291
259623
|
try {
|
|
259292
|
-
const raw = JSON.parse(await
|
|
259624
|
+
const raw = JSON.parse(await fsp132.readFile(indexFile3(), "utf8"));
|
|
259293
259625
|
return Array.isArray(raw?.letters) ? raw.letters.filter(isLetter) : [];
|
|
259294
259626
|
} catch {
|
|
259295
259627
|
return [];
|
|
@@ -259312,7 +259644,7 @@ function inboxFollower() {
|
|
|
259312
259644
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
259313
259645
|
ordered: true,
|
|
259314
259646
|
digest: true,
|
|
259315
|
-
serial: (fn) =>
|
|
259647
|
+
serial: (fn) => serial7(fn),
|
|
259316
259648
|
refuse: refuse14,
|
|
259317
259649
|
load: () => indexIo.load(),
|
|
259318
259650
|
save: () => indexIo.save(),
|
|
@@ -259342,7 +259674,7 @@ function inboxFollower() {
|
|
|
259342
259674
|
},
|
|
259343
259675
|
purge: async () => {
|
|
259344
259676
|
const removed = (await readIndex3()).length;
|
|
259345
|
-
await
|
|
259677
|
+
await fsp132.rm(indexFile3(), { force: true });
|
|
259346
259678
|
await markCopyOff("inbox");
|
|
259347
259679
|
indexIo.reset();
|
|
259348
259680
|
return { removed };
|
|
@@ -259358,23 +259690,23 @@ function inboxBodiesFollower() {
|
|
|
259358
259690
|
log: log.notif,
|
|
259359
259691
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
259360
259692
|
ordered: false,
|
|
259361
|
-
serial: (fn) =>
|
|
259693
|
+
serial: (fn) => serial7(fn),
|
|
259362
259694
|
refuse: refuse14,
|
|
259363
259695
|
load: () => bodiesIo.load(),
|
|
259364
259696
|
save: () => bodiesIo.save(),
|
|
259365
259697
|
isRow: isBody,
|
|
259366
259698
|
key: (b8) => b8.name,
|
|
259367
259699
|
hash: (b8) => sha12(b8.body),
|
|
259368
|
-
localKeys: async () => (await
|
|
259700
|
+
localKeys: async () => (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
|
|
259369
259701
|
apply: async ({ rows, removeIds }) => {
|
|
259370
|
-
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await
|
|
259702
|
+
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp132.rm(path243.join(bodiesDir(), name), { force: true });
|
|
259371
259703
|
const skipped = [];
|
|
259372
259704
|
for (const b8 of rows ?? []) {
|
|
259373
259705
|
if (Buffer.byteLength(b8.body) > INBOX_BODY_COPY_MAX_BYTES) {
|
|
259374
259706
|
skipped.push(b8.name);
|
|
259375
259707
|
continue;
|
|
259376
259708
|
}
|
|
259377
|
-
await writeCopyText(
|
|
259709
|
+
await writeCopyText(path243.join(bodiesDir(), b8.name), b8.body);
|
|
259378
259710
|
}
|
|
259379
259711
|
return { skipped };
|
|
259380
259712
|
},
|
|
@@ -259382,8 +259714,8 @@ function inboxBodiesFollower() {
|
|
|
259382
259714
|
changed: () => {
|
|
259383
259715
|
},
|
|
259384
259716
|
purge: async () => {
|
|
259385
|
-
const names2 = (await
|
|
259386
|
-
for (const name of names2) await
|
|
259717
|
+
const names2 = (await fsp132.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
|
|
259718
|
+
for (const name of names2) await fsp132.rm(path243.join(bodiesDir(), name), { force: true });
|
|
259387
259719
|
await markCopyOff("inbox-bodies");
|
|
259388
259720
|
bodiesIo.reset();
|
|
259389
259721
|
return { removed: names2.length };
|
|
@@ -259391,7 +259723,7 @@ function inboxBodiesFollower() {
|
|
|
259391
259723
|
});
|
|
259392
259724
|
return bodiesF;
|
|
259393
259725
|
}
|
|
259394
|
-
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,
|
|
259726
|
+
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;
|
|
259395
259727
|
var init_inbox = __esm({
|
|
259396
259728
|
"src/core/replication/kinds/inbox.ts"() {
|
|
259397
259729
|
"use strict";
|
|
@@ -259404,9 +259736,9 @@ var init_inbox = __esm({
|
|
|
259404
259736
|
INBOX_SCHEMA_VERSION = 1;
|
|
259405
259737
|
INBOX_REMOVAL_FLOOR = 50;
|
|
259406
259738
|
INBOX_BODY_COPY_MAX_BYTES = 4 * 1024 * 1024;
|
|
259407
|
-
inboxDir = () =>
|
|
259408
|
-
indexFile3 = () =>
|
|
259409
|
-
bodiesDir = () =>
|
|
259739
|
+
inboxDir = () => path243.join(WALNUT_HOME, "human-inbox");
|
|
259740
|
+
indexFile3 = () => path243.join(inboxDir(), "index.json");
|
|
259741
|
+
bodiesDir = () => path243.join(inboxDir(), "bodies");
|
|
259410
259742
|
letterHashes = /* @__PURE__ */ new WeakMap();
|
|
259411
259743
|
INBOX_KIND = {
|
|
259412
259744
|
kind: "inbox",
|
|
@@ -259448,134 +259780,12 @@ var init_inbox = __esm({
|
|
|
259448
259780
|
refuse14 = copyRefusal;
|
|
259449
259781
|
indexIo = stateIo("inbox");
|
|
259450
259782
|
bodiesIo = stateIo("inbox-bodies");
|
|
259451
|
-
|
|
259783
|
+
serial7 = serialChain();
|
|
259452
259784
|
inboxF = null;
|
|
259453
259785
|
bodiesF = null;
|
|
259454
259786
|
}
|
|
259455
259787
|
});
|
|
259456
259788
|
|
|
259457
|
-
// src/core/replication/kinds/requests.ts
|
|
259458
|
-
import fsp132 from "fs/promises";
|
|
259459
|
-
import path243 from "path";
|
|
259460
|
-
function forwardRequest(local, incoming) {
|
|
259461
|
-
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
259462
|
-
return incoming;
|
|
259463
|
-
}
|
|
259464
|
-
function hashOf6(row) {
|
|
259465
|
-
let h8 = hashes4.get(row);
|
|
259466
|
-
if (h8 === void 0) {
|
|
259467
|
-
h8 = sha12(JSON.stringify(row));
|
|
259468
|
-
hashes4.set(row, h8);
|
|
259469
|
-
}
|
|
259470
|
-
return h8;
|
|
259471
|
-
}
|
|
259472
|
-
async function load7() {
|
|
259473
|
-
if (state13) return state13;
|
|
259474
|
-
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
259475
|
-
try {
|
|
259476
|
-
const raw = JSON.parse(await fsp132.readFile(STATE_FILE3(), "utf8"));
|
|
259477
|
-
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 };
|
|
259478
|
-
} catch {
|
|
259479
|
-
}
|
|
259480
|
-
state13 = s4;
|
|
259481
|
-
return s4;
|
|
259482
|
-
}
|
|
259483
|
-
async function save2() {
|
|
259484
|
-
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
259485
|
-
}
|
|
259486
|
-
async function readStore8() {
|
|
259487
|
-
try {
|
|
259488
|
-
const raw = JSON.parse(await fsp132.readFile(STORE_FILE(), "utf8"));
|
|
259489
|
-
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
259490
|
-
} catch {
|
|
259491
|
-
return [];
|
|
259492
|
-
}
|
|
259493
|
-
}
|
|
259494
|
-
function isRow5(v3) {
|
|
259495
|
-
const r8 = v3;
|
|
259496
|
-
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
259497
|
-
}
|
|
259498
|
-
function requestsFollower() {
|
|
259499
|
-
follower4 ??= createRowSetFollower({
|
|
259500
|
-
kind: "requests",
|
|
259501
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
259502
|
-
label: "requests copy",
|
|
259503
|
-
log: log.session,
|
|
259504
|
-
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
259505
|
-
ordered: false,
|
|
259506
|
-
serial: (fn) => serial7(fn),
|
|
259507
|
-
refuse: copyRefusal,
|
|
259508
|
-
load: load7,
|
|
259509
|
-
save: save2,
|
|
259510
|
-
isRow: isRow5,
|
|
259511
|
-
key: (r8) => r8.id,
|
|
259512
|
-
localKeys: async () => (await readStore8()).map((r8) => r8.id),
|
|
259513
|
-
apply: async ({ rows, removeIds }) => {
|
|
259514
|
-
const byId = new Map((await readStore8()).map((r8) => [r8.id, r8]));
|
|
259515
|
-
for (const id of removeIds ?? []) byId.delete(id);
|
|
259516
|
-
for (const r8 of rows ?? []) {
|
|
259517
|
-
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
259518
|
-
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 });
|
|
259519
|
-
byId.set(r8.id, kept);
|
|
259520
|
-
}
|
|
259521
|
-
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
259522
|
-
return { skipped: [] };
|
|
259523
|
-
},
|
|
259524
|
-
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
259525
|
-
changed: () => {
|
|
259526
|
-
},
|
|
259527
|
-
purge: async () => {
|
|
259528
|
-
const removed = (await readStore8()).length;
|
|
259529
|
-
await fsp132.rm(STORE_FILE(), { force: true });
|
|
259530
|
-
await markCopyOff("requests");
|
|
259531
|
-
state13 = null;
|
|
259532
|
-
return { removed };
|
|
259533
|
-
}
|
|
259534
|
-
});
|
|
259535
|
-
return follower4;
|
|
259536
|
-
}
|
|
259537
|
-
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes4, REQUESTS_KIND, STATE_FILE3, STORE_FILE, state13, serial7, follower4;
|
|
259538
|
-
var init_requests = __esm({
|
|
259539
|
-
"src/core/replication/kinds/requests.ts"() {
|
|
259540
|
-
"use strict";
|
|
259541
|
-
init_constants();
|
|
259542
|
-
init_logging();
|
|
259543
|
-
init_kind();
|
|
259544
|
-
init_kind_follower();
|
|
259545
|
-
init_gate();
|
|
259546
|
-
REQUESTS_SCHEMA_VERSION = 1;
|
|
259547
|
-
REQUESTS_REMOVAL_FLOOR = 50;
|
|
259548
|
-
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
259549
|
-
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
259550
|
-
REQUESTS_KIND = {
|
|
259551
|
-
kind: "requests",
|
|
259552
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
259553
|
-
key: (r8) => r8.id,
|
|
259554
|
-
hash: hashOf6,
|
|
259555
|
-
ordered: false,
|
|
259556
|
-
digest: false,
|
|
259557
|
-
choice: "requests",
|
|
259558
|
-
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
259559
|
-
watch: (soon) => {
|
|
259560
|
-
let stop2 = null;
|
|
259561
|
-
let stopped2 = false;
|
|
259562
|
-
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
259563
|
-
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
259564
|
-
});
|
|
259565
|
-
return () => {
|
|
259566
|
-
stopped2 = true;
|
|
259567
|
-
stop2?.();
|
|
259568
|
-
};
|
|
259569
|
-
}
|
|
259570
|
-
};
|
|
259571
|
-
STATE_FILE3 = () => path243.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
259572
|
-
STORE_FILE = () => path243.join(WALNUT_HOME, "session-requests.json");
|
|
259573
|
-
state13 = null;
|
|
259574
|
-
serial7 = serialChain();
|
|
259575
|
-
follower4 = null;
|
|
259576
|
-
}
|
|
259577
|
-
});
|
|
259578
|
-
|
|
259579
259789
|
// src/core/replication/kinds/sessions.ts
|
|
259580
259790
|
import fsp133 from "fs/promises";
|
|
259581
259791
|
import path244 from "path";
|
|
@@ -259606,11 +259816,11 @@ function projectedOf(row) {
|
|
|
259606
259816
|
}
|
|
259607
259817
|
return p6;
|
|
259608
259818
|
}
|
|
259609
|
-
function
|
|
259610
|
-
let h8 =
|
|
259819
|
+
function hashOf8(row) {
|
|
259820
|
+
let h8 = hashes6.get(row);
|
|
259611
259821
|
if (h8 === void 0) {
|
|
259612
259822
|
h8 = sessionCopyHash(row);
|
|
259613
|
-
|
|
259823
|
+
hashes6.set(row, h8);
|
|
259614
259824
|
}
|
|
259615
259825
|
return h8;
|
|
259616
259826
|
}
|
|
@@ -259630,7 +259840,7 @@ async function load8() {
|
|
|
259630
259840
|
async function save3() {
|
|
259631
259841
|
if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
|
|
259632
259842
|
}
|
|
259633
|
-
function
|
|
259843
|
+
function isRow7(v3) {
|
|
259634
259844
|
const r8 = v3;
|
|
259635
259845
|
return !!r8 && typeof r8 === "object" && !Array.isArray(r8) && typeof r8.claudeSessionId === "string" && r8.claudeSessionId.length > 0 && r8.claudeSessionId.length <= 200;
|
|
259636
259846
|
}
|
|
@@ -259650,7 +259860,7 @@ function sessionsFollower() {
|
|
|
259650
259860
|
refuse: copyRefusal,
|
|
259651
259861
|
load: load8,
|
|
259652
259862
|
save: save3,
|
|
259653
|
-
isRow:
|
|
259863
|
+
isRow: isRow7,
|
|
259654
259864
|
key: (r8) => r8.claudeSessionId,
|
|
259655
259865
|
hash: sessionCopyHash,
|
|
259656
259866
|
localKeys: async () => (await Promise.resolve().then(() => (init_session_db(), session_db_exports))).sessionIdsInStore(),
|
|
@@ -259672,7 +259882,7 @@ function sessionsFollower() {
|
|
|
259672
259882
|
});
|
|
259673
259883
|
return follower5;
|
|
259674
259884
|
}
|
|
259675
|
-
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected,
|
|
259885
|
+
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;
|
|
259676
259886
|
var init_sessions2 = __esm({
|
|
259677
259887
|
"src/core/replication/kinds/sessions.ts"() {
|
|
259678
259888
|
"use strict";
|
|
@@ -259709,12 +259919,12 @@ var init_sessions2 = __esm({
|
|
|
259709
259919
|
VOLATILE_SESSION_FIELDS = ["lastActiveAt", "activity", "contextTokens"];
|
|
259710
259920
|
VOLATILE_SET = new Set(VOLATILE_SESSION_FIELDS);
|
|
259711
259921
|
projected = /* @__PURE__ */ new WeakMap();
|
|
259712
|
-
|
|
259922
|
+
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
259713
259923
|
SESSIONS_KIND = {
|
|
259714
259924
|
kind: "sessions",
|
|
259715
259925
|
schemaVersion: SESSIONS_SCHEMA_VERSION,
|
|
259716
259926
|
key: (s4) => s4.claudeSessionId,
|
|
259717
|
-
hash:
|
|
259927
|
+
hash: hashOf8,
|
|
259718
259928
|
ordered: false,
|
|
259719
259929
|
digest: true,
|
|
259720
259930
|
choice: "sessions",
|
|
@@ -259746,137 +259956,11 @@ var init_sessions2 = __esm({
|
|
|
259746
259956
|
}
|
|
259747
259957
|
});
|
|
259748
259958
|
|
|
259749
|
-
// src/core/replication/kinds/personas.ts
|
|
259750
|
-
var personas_exports = {};
|
|
259751
|
-
__export(personas_exports, {
|
|
259752
|
-
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
259753
|
-
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
259754
|
-
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
259755
|
-
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
259756
|
-
personasFollower: () => personasFollower,
|
|
259757
|
-
readPersonaCopy: () => readPersonaCopy
|
|
259758
|
-
});
|
|
259759
|
-
function tools(v3) {
|
|
259760
|
-
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
259761
|
-
}
|
|
259762
|
-
async function leaderRows2() {
|
|
259763
|
-
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
259764
|
-
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
259765
|
-
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
259766
|
-
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
259767
|
-
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
259768
|
-
]);
|
|
259769
|
-
const config = await getConfig2();
|
|
259770
|
-
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
259771
|
-
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
259772
|
-
const rows = [];
|
|
259773
|
-
for (const a8 of agents) {
|
|
259774
|
-
if (!ID_RE5.test(a8.id)) continue;
|
|
259775
|
-
try {
|
|
259776
|
-
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
259777
|
-
const prompt = profile.systemPrompt ?? "";
|
|
259778
|
-
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
259779
|
-
rows.push({
|
|
259780
|
-
key: a8.id,
|
|
259781
|
-
agentId: a8.id,
|
|
259782
|
-
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
259783
|
-
systemPrompt: prompt,
|
|
259784
|
-
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
259785
|
-
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
259786
|
-
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
259787
|
-
...effort ? { effort } : {},
|
|
259788
|
-
...launch.model ? { launchModel: launch.model } : {},
|
|
259789
|
-
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
259790
|
-
});
|
|
259791
|
-
} catch (err2) {
|
|
259792
|
-
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
259793
|
-
}
|
|
259794
|
-
}
|
|
259795
|
-
return rows;
|
|
259796
|
-
}
|
|
259797
|
-
function hashOf8(row) {
|
|
259798
|
-
let h8 = hashes6.get(row);
|
|
259799
|
-
if (h8 === void 0) {
|
|
259800
|
-
h8 = sha12(JSON.stringify(row));
|
|
259801
|
-
hashes6.set(row, h8);
|
|
259802
|
-
}
|
|
259803
|
-
return h8;
|
|
259804
|
-
}
|
|
259805
|
-
function isRow7(v3) {
|
|
259806
|
-
const r8 = v3;
|
|
259807
|
-
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
259808
|
-
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
259809
|
-
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE5.test(r8.key) || typeof r8.name !== "string") return false;
|
|
259810
|
-
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
259811
|
-
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
259812
|
-
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
259813
|
-
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;
|
|
259814
|
-
return true;
|
|
259815
|
-
}
|
|
259816
|
-
function admit2(r8) {
|
|
259817
|
-
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
259818
|
-
}
|
|
259819
|
-
async function readPersonaCopy(agentId) {
|
|
259820
|
-
const rows = await copy3.read();
|
|
259821
|
-
return rows?.[agentId] ?? null;
|
|
259822
|
-
}
|
|
259823
|
-
function _resetPersonasCopyForTesting() {
|
|
259824
|
-
copy3.reset();
|
|
259825
|
-
}
|
|
259826
|
-
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE5, TOOL_RE, hashes6, PERSONAS_KIND, ROW_KEYS, copy3, personasFollower;
|
|
259827
|
-
var init_personas = __esm({
|
|
259828
|
-
"src/core/replication/kinds/personas.ts"() {
|
|
259829
|
-
"use strict";
|
|
259830
|
-
init_logging();
|
|
259831
|
-
init_config_allowlist();
|
|
259832
|
-
init_kind();
|
|
259833
|
-
init_file_copy();
|
|
259834
|
-
PERSONAS_SCHEMA_VERSION = 1;
|
|
259835
|
-
PERSONAS_REMOVAL_FLOOR = 0;
|
|
259836
|
-
MAX_PROMPT_BYTES = 120 * 1024;
|
|
259837
|
-
ID_RE5 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
259838
|
-
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
259839
|
-
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
259840
|
-
PERSONAS_KIND = {
|
|
259841
|
-
kind: "personas",
|
|
259842
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
259843
|
-
key: (r8) => r8.key,
|
|
259844
|
-
hash: hashOf8,
|
|
259845
|
-
ordered: false,
|
|
259846
|
-
digest: false,
|
|
259847
|
-
choice: "personas",
|
|
259848
|
-
rows: leaderRows2,
|
|
259849
|
-
watch: (soon) => {
|
|
259850
|
-
let stop2 = null;
|
|
259851
|
-
let stopped2 = false;
|
|
259852
|
-
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
259853
|
-
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
259854
|
-
});
|
|
259855
|
-
return () => {
|
|
259856
|
-
stopped2 = true;
|
|
259857
|
-
stop2?.();
|
|
259858
|
-
};
|
|
259859
|
-
}
|
|
259860
|
-
};
|
|
259861
|
-
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
259862
|
-
copy3 = createFileCopy({
|
|
259863
|
-
kind: "personas",
|
|
259864
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
259865
|
-
label: "personas copy",
|
|
259866
|
-
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
259867
|
-
isRow: isRow7,
|
|
259868
|
-
key: (r8) => r8.key,
|
|
259869
|
-
admit: admit2
|
|
259870
|
-
});
|
|
259871
|
-
personasFollower = copy3.follower;
|
|
259872
|
-
}
|
|
259873
|
-
});
|
|
259874
|
-
|
|
259875
259959
|
// src/core/replication/kinds/index.ts
|
|
259876
259960
|
var kinds_exports = {};
|
|
259877
259961
|
__export(kinds_exports, {
|
|
259962
|
+
copyKeepersOnly: () => copyKeepersOnly,
|
|
259878
259963
|
copyKinds: () => copyKinds,
|
|
259879
|
-
hostReplicaOnly: () => hostReplicaOnly,
|
|
259880
259964
|
registerCopyFollowerKinds: () => registerCopyFollowerKinds,
|
|
259881
259965
|
startCopyKinds: () => startCopyKinds
|
|
259882
259966
|
});
|
|
@@ -259894,14 +259978,14 @@ function copyKinds() {
|
|
|
259894
259978
|
PERSONAS_KIND
|
|
259895
259979
|
];
|
|
259896
259980
|
}
|
|
259897
|
-
function
|
|
259981
|
+
function copyKeepersOnly(h8) {
|
|
259898
259982
|
return {
|
|
259899
259983
|
kind: h8.kind,
|
|
259900
|
-
// followerStep checks the version before the step: never `schema_newer`
|
|
259984
|
+
// followerStep checks the version before the step: never `schema_newer` where the kind is not kept.
|
|
259901
259985
|
get schemaVersion() {
|
|
259902
|
-
return keepsCopies() ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
259986
|
+
return keepsCopies(h8.kind) ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
259903
259987
|
},
|
|
259904
|
-
step: (op2, body7) => keepsCopies() ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
259988
|
+
step: (op2, body7) => keepsCopies(h8.kind) ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
259905
259989
|
};
|
|
259906
259990
|
}
|
|
259907
259991
|
function registerCopyFollowerKinds() {
|
|
@@ -259916,7 +260000,7 @@ function registerCopyFollowerKinds() {
|
|
|
259916
260000
|
prefsFollower(),
|
|
259917
260001
|
configFollower(),
|
|
259918
260002
|
personasFollower()
|
|
259919
|
-
].map((h8) => registerFollowerKind(
|
|
260003
|
+
].map((h8) => registerFollowerKind(copyKeepersOnly(h8)));
|
|
259920
260004
|
return () => {
|
|
259921
260005
|
for (const u3 of off) u3();
|
|
259922
260006
|
};
|
|
@@ -292294,10 +292378,13 @@ async function cleanupLaneClaudeMd(homeDir2 = WALNUT_HOME) {
|
|
|
292294
292378
|
}
|
|
292295
292379
|
}
|
|
292296
292380
|
async function buildLaneProfile(config, agentId, opts2) {
|
|
292297
|
-
const
|
|
292298
|
-
const
|
|
292381
|
+
const persona = opts2?.persona;
|
|
292382
|
+
const skillsIndex = persona ? "" : await buildSessionSkillsPrompt().catch(() => "");
|
|
292383
|
+
const memoryContext = persona ? "" : await buildLaneMemoryContext().catch(() => "");
|
|
292299
292384
|
let profile;
|
|
292300
|
-
if (
|
|
292385
|
+
if (persona) {
|
|
292386
|
+
profile = mergeProfiles({ systemPrompt: persona.systemPrompt, systemPromptMode: persona.systemPromptMode }, walnutMcpProfile());
|
|
292387
|
+
} else if (agentId === "general") {
|
|
292301
292388
|
profile = personalAiProfile(config.user?.name ?? "the user", skillsIndex, memoryContext);
|
|
292302
292389
|
} else {
|
|
292303
292390
|
const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports));
|
|
@@ -292307,7 +292394,8 @@ async function buildLaneProfile(config, agentId, opts2) {
|
|
|
292307
292394
|
const contextBlock = await loadContextSources2(agentDef, {}).catch(() => "");
|
|
292308
292395
|
profile = consoleAgentProfile(agentDef, skillsIndex, contextBlock);
|
|
292309
292396
|
}
|
|
292310
|
-
const
|
|
292397
|
+
const personaEffort = persona?.effort && LANE_EFFORTS.has(persona.effort) ? persona.effort : void 0;
|
|
292398
|
+
const effort = personaEffort ?? config.agent?.session_effort ?? "medium";
|
|
292311
292399
|
if (!opts2?.conversationId) return { profile, effort };
|
|
292312
292400
|
const base = profile.systemPrompt ?? "";
|
|
292313
292401
|
const headroom = MAX_LANE_PROMPT_BYTES - Buffer.byteLength(base, "utf-8") - LANE_SEED_RESERVE_BYTES;
|
|
@@ -292577,7 +292665,7 @@ async function resolveLane(lane, agentId, conversationId, firstMessage, engine)
|
|
|
292577
292665
|
});
|
|
292578
292666
|
return { sessionId, created: true, engine: "claude" };
|
|
292579
292667
|
}
|
|
292580
|
-
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;
|
|
292668
|
+
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;
|
|
292581
292669
|
var init_personal_ai_lane = __esm({
|
|
292582
292670
|
"src/core/sessions/personal-ai-lane.ts"() {
|
|
292583
292671
|
"use strict";
|
|
@@ -292592,6 +292680,7 @@ var init_personal_ai_lane = __esm({
|
|
|
292592
292680
|
init_default_engine();
|
|
292593
292681
|
init_ask_profile_prefix();
|
|
292594
292682
|
init_logging();
|
|
292683
|
+
LANE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
292595
292684
|
inFlight20 = /* @__PURE__ */ new Map();
|
|
292596
292685
|
LANE_MEMORY_HEADER = "## Standing memory (injected by Walnut)";
|
|
292597
292686
|
MANAGED_LANE_CONTEXT_MARKERS = [
|
|
@@ -320359,9 +320448,13 @@ var init_task_replica_store = __esm({
|
|
|
320359
320448
|
// src/core/replication/kinds/gate.ts
|
|
320360
320449
|
var gate_exports = {};
|
|
320361
320450
|
__export(gate_exports, {
|
|
320451
|
+
COMPANION_COPY_KINDS: () => COMPANION_COPY_KINDS,
|
|
320452
|
+
COPY_AS_OF_HEADER: () => COPY_AS_OF_HEADER,
|
|
320362
320453
|
KIND_NOT_COPIED: () => KIND_NOT_COPIED,
|
|
320454
|
+
copyKindAsOf: () => copyKindAsOf,
|
|
320363
320455
|
copyKindHeld: () => copyKindHeld,
|
|
320364
320456
|
copyKindOff: () => copyKindOff,
|
|
320457
|
+
copyPath: () => copyPath,
|
|
320365
320458
|
copyRefusal: () => copyRefusal,
|
|
320366
320459
|
copyStateFile: () => copyStateFile,
|
|
320367
320460
|
keepsCopies: () => keepsCopies,
|
|
@@ -320369,8 +320462,16 @@ __export(gate_exports, {
|
|
|
320369
320462
|
});
|
|
320370
320463
|
import fsp152 from "fs/promises";
|
|
320371
320464
|
import path296 from "path";
|
|
320372
|
-
function keepsCopies() {
|
|
320373
|
-
|
|
320465
|
+
function keepsCopies(kind) {
|
|
320466
|
+
if (isHostReplicaProgram()) return true;
|
|
320467
|
+
if (followerKind() !== "companion") return false;
|
|
320468
|
+
return kind === void 0 || COMPANION_COPY_KINDS.has(kind);
|
|
320469
|
+
}
|
|
320470
|
+
function copyPath(live6) {
|
|
320471
|
+
if (followerKind() !== "companion") return live6;
|
|
320472
|
+
const rel = path296.relative(WALNUT_HOME, live6);
|
|
320473
|
+
if (!rel || rel.startsWith("..") || path296.isAbsolute(rel)) throw new Error(`copyPath: ${live6} is not under the data dir`);
|
|
320474
|
+
return path296.join(WALNUT_HOME, "cache", "replica", "home", rel);
|
|
320374
320475
|
}
|
|
320375
320476
|
async function copyRefusal() {
|
|
320376
320477
|
if (!keepsCopies()) return { status: 404, error: "unknown_kind" };
|
|
@@ -320391,20 +320492,26 @@ async function copyKindOff(kind) {
|
|
|
320391
320492
|
}
|
|
320392
320493
|
}
|
|
320393
320494
|
async function copyKindHeld(kind) {
|
|
320495
|
+
return await copyKindAsOf(kind) !== null;
|
|
320496
|
+
}
|
|
320497
|
+
async function copyKindAsOf(kind) {
|
|
320394
320498
|
try {
|
|
320395
320499
|
const raw = JSON.parse(await fsp152.readFile(copyStateFile(kind), "utf8"));
|
|
320396
|
-
|
|
320500
|
+
if (!(raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object")) return null;
|
|
320501
|
+
return Number(raw.asOf) || 0;
|
|
320397
320502
|
} catch {
|
|
320398
|
-
return
|
|
320503
|
+
return null;
|
|
320399
320504
|
}
|
|
320400
320505
|
}
|
|
320401
|
-
var KIND_NOT_COPIED;
|
|
320506
|
+
var COMPANION_COPY_KINDS, COPY_AS_OF_HEADER, KIND_NOT_COPIED;
|
|
320402
320507
|
var init_gate = __esm({
|
|
320403
320508
|
"src/core/replication/kinds/gate.ts"() {
|
|
320404
320509
|
"use strict";
|
|
320405
320510
|
init_constants();
|
|
320406
320511
|
init_server_role();
|
|
320407
320512
|
init_kind_follower();
|
|
320513
|
+
COMPANION_COPY_KINDS = /* @__PURE__ */ new Set(["requests", "routines", "prefs", "personas"]);
|
|
320514
|
+
COPY_AS_OF_HEADER = "x-walnut-copy-as-of";
|
|
320408
320515
|
KIND_NOT_COPIED = "kind_not_copied";
|
|
320409
320516
|
}
|
|
320410
320517
|
});
|