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