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