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