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.
@@ -11691,6 +11691,7 @@ function createOfflineHostCore(deps4) {
11691
11691
  const MAX_ARGS_BYTES = 256 * 1024;
11692
11692
  const WRITE_BUDGET = 30;
11693
11693
  const WRITE_WINDOW_MS = 6e4;
11694
+ const LOCK_RETRY_MS = [100, 300, 900];
11694
11695
  const DEFAULT_REPLY_SECS = 3600;
11695
11696
  const IMPLICIT_REPLY_SECS = 6 * 3600;
11696
11697
  const DRAIN_BATCH = 200;
@@ -11837,7 +11838,7 @@ function createOfflineHostCore(deps4) {
11837
11838
  ...opts2.admit ? { admit: opts2.admit } : {}
11838
11839
  });
11839
11840
  if (!r8.ok) {
11840
- if (r8.code === "journal_unwritable") deps4.log("error", "offline host: journal write refused", { home, kind, code: r8.code, why: r8.why, error: r8.message });
11841
+ 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 });
11841
11842
  return r8;
11842
11843
  }
11843
11844
  if (!r8.duplicate) {
@@ -11852,6 +11853,19 @@ function createOfflineHostCore(deps4) {
11852
11853
  if (r8.ok) return null;
11853
11854
  return fail6(r8.code, r8.message, { ...r8.retryAfterMs !== void 0 ? { retryAfterMs: r8.retryAfterMs } : {}, ...r8.why ? { detail: { why: r8.why } } : {} });
11854
11855
  }
11856
+ const lockRefused = (r8) => !r8.ok && r8.error.code === "journal_unwritable" && r8.error.detail?.why === "locked";
11857
+ async function whenUnlocked(home, op2, run12) {
11858
+ const t0 = Date.now();
11859
+ let r8 = run12();
11860
+ for (const ms2 of LOCK_RETRY_MS) {
11861
+ if (!lockRefused(r8)) return r8;
11862
+ 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 });
11863
+ await new Promise((resolve2) => setTimeout(resolve2, ms2));
11864
+ r8 = run12();
11865
+ }
11866
+ if (lockRefused(r8)) deps4.log("error", "offline host: the journal stayed locked; write refused", { home, op: op2, waitedMs: Date.now() - t0 });
11867
+ return r8;
11868
+ }
11855
11869
  function configure(slice) {
11856
11870
  if (!slice || slice.v !== 1 || typeof slice.home !== "string" || !slice.home) throw new Error("host.slice: bad slice");
11857
11871
  const prev = slices.get(slice.home);
@@ -12585,10 +12599,8 @@ ${kit10.buildReplyTrailer(row)}`;
12585
12599
  if (no) return no;
12586
12600
  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 });
12587
12601
  } else {
12588
- const denied = admitWrite(callerSid5) ?? roomFor(home);
12589
- if (denied) return denied;
12590
12602
  const base = slices.get(home)?.tasks.find((t3) => t3.id === task.id)?.updated_at;
12591
- const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }));
12603
+ const no = refusal2(append(home, { kind: "op", op: name, args: { ...args, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }, false, { admit: () => admitWrite(callerSid5) ?? roomFor(home) }));
12592
12604
  if (no) return no;
12593
12605
  deps4.log("info", "offline host: write queued", { home, op: name, taskId: task.id, callerSid: callerSid5 });
12594
12606
  }
@@ -13030,7 +13042,7 @@ ${kit10.buildReplyTrailer(row)}`;
13030
13042
  const fromCopy = deps4.replica ? deps4.replica.answer(home, name, args, offlineNote(home)) : null;
13031
13043
  if (fromCopy) return fromCopy;
13032
13044
  if (deps4.boards && deps4.boards.BOARD_OPS.indexOf(name) !== -1) return opBoard(home, callerSid5, name, args);
13033
- if (QUEUED_OPS.includes(name)) return opQueued(home, callerSid5, name, args);
13045
+ if (QUEUED_OPS.includes(name)) return whenUnlocked(home, name, () => opQueued(home, callerSid5, name, args));
13034
13046
  return needsServer(name ? `"${name}"` : "That call");
13035
13047
  }
13036
13048
  }
@@ -13543,6 +13555,10 @@ ${mid}` : "";
13543
13555
  handle: handle4,
13544
13556
  handleLocal,
13545
13557
  handleFollower,
13558
+ /** handleFollower, waiting out another process's journal lock (whenUnlocked): the twins' follower.op. */
13559
+ handleFollowerWaiting: (home, req) => whenUnlocked(home, String(req.op ?? ""), () => handleFollower(home, req)),
13560
+ /** noteSession, waiting out another process's journal lock (whenUnlocked): the twins' host ask. */
13561
+ noteSessionWaiting: (home, rec3, opId, by) => whenUnlocked(home, "session", () => noteSession(home, rec3, opId, by)),
13546
13562
  pendingFor,
13547
13563
  journalStats,
13548
13564
  onResult,
@@ -28499,7 +28515,7 @@ function dispatchCommand(ws, id, cmd) {
28499
28515
  case 'follower.sessions': return cmdFollowerSessions(ws, id);
28500
28516
  case 'follower.send': return daemonCommands.run(function () { return cmdFollowerSend(ws, id, cmd); });
28501
28517
  case 'follower.permission': return daemonCommands.run(function () { return cmdFollowerPermission(ws, id, cmd); });
28502
- case 'follower.op': return cmdFollowerOp(ws, id, cmd);
28518
+ case 'follower.op': return daemonCommands.run(function () { return cmdFollowerOp(ws, id, cmd); });
28503
28519
  case 'follower.pending': return cmdFollowerPending(ws, id, cmd);
28504
28520
  // A new ask while the Mac is away ('replica-start-v1', WP12). Twin of daemon-standalone.ts.
28505
28521
  case 'follower.start': return daemonCommands.run(function () { return cmdFollowerStart(ws, id, cmd); });
@@ -29913,14 +29929,15 @@ async function cmdFollowerPermission(ws, id, cmd) {
29913
29929
  // The replica's write while the Mac is away (replica-ops-v1, journal v2). Its own gate:
29914
29930
  // the follower's own Walnut, the quiet window unless the Mac is still taking the
29915
29931
  // journal, and the daemon dir's owner. Twin of daemon-standalone.ts cmdFollowerOp.
29916
- function cmdFollowerOp(ws, id, cmd) {
29932
+ async function cmdFollowerOp(ws, id, cmd) {
29917
29933
  var home = followerHomeOf(ws);
29918
29934
  if (!home) return sendError(ws, id, 'follower.op: send follower.hello first');
29919
29935
  if (!followerMayWrite(home)) return sendError(ws, id, 'follower.op: your Mac answers again; write through it', { errorKind: 'leader_answers' });
29920
29936
  if (!ownsDaemonDir()) {
29921
29937
  return sendError(ws, id, 'follower.op: this daemon no longer owns its directory', { errorKind: 'journal_unwritable', detail: { why: 'not_owner' } });
29922
29938
  }
29923
- var r = offlineHost.handleFollower(home, { op: cmd.op, args: cmd.args, actor: cmd.actor, opId: cmd.opId, base: cmd.base });
29939
+ // Waits out another process's journal lock (about 1.3 s) before it answers.
29940
+ var r = await offlineHost.handleFollowerWaiting(home, { op: cmd.op, args: cmd.args, actor: cmd.actor, opId: cmd.opId, base: cmd.base });
29924
29941
  if (r.ok) return sendOk(ws, id, r.result);
29925
29942
  sendError(ws, id, 'follower.op: ' + r.error.message, Object.assign({ errorKind: r.error.code },
29926
29943
  r.error.detail !== undefined ? { detail: r.error.detail } : {}, r.error.retryAfterMs !== undefined ? { retryAfterMs: r.error.retryAfterMs } : {}));
@@ -30070,7 +30087,7 @@ async function startHostAsk(home, p, cmd) {
30070
30087
  throw err;
30071
30088
  }
30072
30089
  if (DIE_AFTER_ASK_SPAWN) process.kill(process.pid, 'SIGKILL');
30073
- var saved = offlineHost.noteSession(home, p.record, opId, cmd.actor);
30090
+ var saved = await offlineHost.noteSessionWaiting(home, p.record, opId, cmd.actor);
30074
30091
  hostStart.releasePending(home, p.sid);
30075
30092
  if (!saved.ok) {
30076
30093
  // Nothing would tell the Mac about this CLI: it must not run unseen. Not stamped as an
@@ -138297,8 +138314,9 @@ async function buildCopyManifest(kind) {
138297
138314
  }
138298
138315
  return manifest;
138299
138316
  }
138300
- function keepsCopiesTarget(t3) {
138301
- return t3.kind === "host" && t3.program?.() === "replica";
138317
+ function keepsCopiesTarget(t3, kind) {
138318
+ if (t3.kind === "host") return t3.program?.() === "replica";
138319
+ return t3.kind === "companion" && (kind === void 0 || COMPANION_COPY_KINDS.has(kind));
138302
138320
  }
138303
138321
  function manifestDigest(manifest, ordered = false) {
138304
138322
  let d8 = manifestDigests.get(manifest);
@@ -138412,7 +138430,7 @@ async function choiceOf(target2) {
138412
138430
  }
138413
138431
  async function syncCopyKinds(kinds, deps4 = {}) {
138414
138432
  const now = deps4.now ?? Date.now;
138415
- const all = (deps4.targets ?? await defaultTargets())().filter(keepsCopiesTarget);
138433
+ const all = (deps4.targets ?? await defaultTargets())().filter((t3) => kinds.some((k8) => keepsCopiesTarget(t3, k8.kind)));
138416
138434
  const ready2 = [];
138417
138435
  for (const target2 of all) if (await target2.available()) ready2.push({ target: target2, choice: await choiceOf(target2) });
138418
138436
  const results = [];
@@ -138420,7 +138438,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
138420
138438
  const asOf2 = now();
138421
138439
  const manifests = /* @__PURE__ */ new Map();
138422
138440
  for (const kind of kinds) {
138423
- if (!ready2.some((r8) => r8.choice[kind.choice])) continue;
138441
+ if (!ready2.some((r8) => r8.choice[kind.choice] && keepsCopiesTarget(r8.target, kind.kind))) continue;
138424
138442
  try {
138425
138443
  manifests.set(kind.kind, await buildCopyManifest(kind));
138426
138444
  } catch (err2) {
@@ -138429,6 +138447,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
138429
138447
  }
138430
138448
  for (const { target: target2, choice } of ready2) {
138431
138449
  for (const kind of kinds) {
138450
+ if (!keepsCopiesTarget(target2, kind.kind)) continue;
138432
138451
  const manifest = manifests.get(kind.kind);
138433
138452
  const st2 = kindState(target2, kind.kind);
138434
138453
  if (!choice[kind.choice]) {
@@ -138474,7 +138493,7 @@ async function purgeKind(kind, target2, st2) {
138474
138493
  async function confirmCopyKindRemoval(targetId, kind, opts2 = {}) {
138475
138494
  const { replicaTargets: replicaTargets2 } = await Promise.resolve().then(() => (init_replica_targets(), replica_targets_exports));
138476
138495
  const target2 = replicaTargets2().find((t3) => t3.id === targetId);
138477
- if (!target2 || target2.kind !== "host" || !peekKindState(targetId, kind)) return false;
138496
+ if (!target2 || !keepsCopiesTarget(target2, kind) || !peekKindState(targetId, kind)) return false;
138478
138497
  if (!confirmKindRemoval(target2, kind, opts2)) return false;
138479
138498
  log.session.warn("copies: the user confirmed a removal of most rows", { target: targetId, kind, entries: peekKindState(targetId, kind)?.confirmFor?.entries });
138480
138499
  copySoon(kind);
@@ -138589,6 +138608,7 @@ var init_copy_kind = __esm({
138589
138608
  init_kind_leader();
138590
138609
  init_search_digest();
138591
138610
  init_replica_status();
138611
+ init_gate();
138592
138612
  COPY_DEBOUNCE_MS = 3e3;
138593
138613
  COPY_SWEEP_MS = 5 * 6e4;
138594
138614
  COPY_FIRST_ROUND_MS = 15e3;
@@ -144407,6 +144427,7 @@ var init_routines = __esm({
144407
144427
  var routines_follower_exports = {};
144408
144428
  __export(routines_follower_exports, {
144409
144429
  _resetRoutinesCopyForTesting: () => _resetRoutinesCopyForTesting,
144430
+ companionRoutinesCopy: () => companionRoutinesCopy,
144410
144431
  readRoutinesCopy: () => readRoutinesCopy,
144411
144432
  routinesFollower: () => routinesFollower
144412
144433
  });
@@ -144502,6 +144523,10 @@ async function readRoutinesCopy(opts2 = {}) {
144502
144523
  const shown = opts2.includeDisabled ? all : all.filter((j8) => j8.enabled);
144503
144524
  return shown.sort((a8, b8) => (a8.state.nextRunAtMs ?? 0) - (b8.state.nextRunAtMs ?? 0));
144504
144525
  }
144526
+ async function companionRoutinesCopy(opts2 = {}) {
144527
+ if (!await copyKindHeld("routines")) return null;
144528
+ return await readRoutinesCopy(opts2) ?? [];
144529
+ }
144505
144530
  function _resetRoutinesCopyForTesting() {
144506
144531
  io2 = copyStateIo("routines");
144507
144532
  serial3 = serialChain();
@@ -144517,8 +144542,8 @@ var init_routines_follower = __esm({
144517
144542
  init_gate();
144518
144543
  init_state_io();
144519
144544
  init_routines();
144520
- jobsFile = () => CRON_FILE;
144521
- statesFile = () => path112.join(path112.dirname(CRON_FILE), "cron-state.json");
144545
+ jobsFile = () => copyPath(CRON_FILE);
144546
+ statesFile = () => copyPath(path112.join(path112.dirname(CRON_FILE), "cron-state.json"));
144522
144547
  io2 = copyStateIo("routines");
144523
144548
  serial3 = serialChain();
144524
144549
  follower2 = null;
@@ -161110,8 +161135,8 @@ import path130 from "path";
161110
161135
  import { fileURLToPath as fileURLToPath9 } from "url";
161111
161136
  function getVersion() {
161112
161137
  if (cachedVersion) return cachedVersion;
161113
- if ("0.6.16") {
161114
- cachedVersion = "0.6.16";
161138
+ if ("0.6.17") {
161139
+ cachedVersion = "0.6.17";
161115
161140
  versionKnown = true;
161116
161141
  return cachedVersion;
161117
161142
  }
@@ -185571,6 +185596,132 @@ var init_cloud_owned_session = __esm({
185571
185596
  }
185572
185597
  });
185573
185598
 
185599
+ // src/core/replication/kinds/personas.ts
185600
+ var personas_exports = {};
185601
+ __export(personas_exports, {
185602
+ PERSONAS_KIND: () => PERSONAS_KIND,
185603
+ PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
185604
+ PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
185605
+ _resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
185606
+ personasFollower: () => personasFollower,
185607
+ readPersonaCopy: () => readPersonaCopy
185608
+ });
185609
+ function tools(v3) {
185610
+ return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
185611
+ }
185612
+ async function leaderRows() {
185613
+ const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
185614
+ Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
185615
+ Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
185616
+ Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
185617
+ Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
185618
+ ]);
185619
+ const config = await getConfig2();
185620
+ const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
185621
+ const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
185622
+ const rows = [];
185623
+ for (const a8 of agents) {
185624
+ if (!ID_RE.test(a8.id)) continue;
185625
+ try {
185626
+ const { profile, effort } = await buildLaneProfile2(config, a8.id);
185627
+ const prompt = profile.systemPrompt ?? "";
185628
+ if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
185629
+ rows.push({
185630
+ key: a8.id,
185631
+ agentId: a8.id,
185632
+ name: String(a8.name ?? a8.id).slice(0, 120),
185633
+ systemPrompt: prompt,
185634
+ systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
185635
+ ...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
185636
+ ...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
185637
+ ...effort ? { effort } : {},
185638
+ ...launch.model ? { launchModel: launch.model } : {},
185639
+ ...launch.effort ? { launchEffort: launch.effort } : {}
185640
+ });
185641
+ } catch (err2) {
185642
+ log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
185643
+ }
185644
+ }
185645
+ return rows;
185646
+ }
185647
+ function hashOf4(row) {
185648
+ let h8 = hashes3.get(row);
185649
+ if (h8 === void 0) {
185650
+ h8 = sha12(JSON.stringify(row));
185651
+ hashes3.set(row, h8);
185652
+ }
185653
+ return h8;
185654
+ }
185655
+ function isRow3(v3) {
185656
+ const r8 = v3;
185657
+ if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
185658
+ if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
185659
+ if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE.test(r8.key) || typeof r8.name !== "string") return false;
185660
+ if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
185661
+ if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
185662
+ for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
185663
+ 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;
185664
+ return true;
185665
+ }
185666
+ function admit(r8) {
185667
+ return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
185668
+ }
185669
+ async function readPersonaCopy(agentId) {
185670
+ const rows = await copy.read();
185671
+ return rows?.[agentId] ?? null;
185672
+ }
185673
+ function _resetPersonasCopyForTesting() {
185674
+ copy.reset();
185675
+ }
185676
+ var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE, TOOL_RE, hashes3, PERSONAS_KIND, ROW_KEYS, copy, personasFollower;
185677
+ var init_personas = __esm({
185678
+ "src/core/replication/kinds/personas.ts"() {
185679
+ "use strict";
185680
+ init_logging();
185681
+ init_config_allowlist();
185682
+ init_kind();
185683
+ init_file_copy();
185684
+ PERSONAS_SCHEMA_VERSION = 1;
185685
+ PERSONAS_REMOVAL_FLOOR = 0;
185686
+ MAX_PROMPT_BYTES = 120 * 1024;
185687
+ ID_RE = /^[A-Za-z0-9_-]{1,80}$/;
185688
+ TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
185689
+ hashes3 = /* @__PURE__ */ new WeakMap();
185690
+ PERSONAS_KIND = {
185691
+ kind: "personas",
185692
+ schemaVersion: PERSONAS_SCHEMA_VERSION,
185693
+ key: (r8) => r8.key,
185694
+ hash: hashOf4,
185695
+ ordered: false,
185696
+ digest: false,
185697
+ choice: "personas",
185698
+ rows: leaderRows,
185699
+ watch: (soon) => {
185700
+ let stop2 = null;
185701
+ let stopped2 = false;
185702
+ void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
185703
+ if (!stopped2) stop2 = cm.onConfigWritten(soon);
185704
+ });
185705
+ return () => {
185706
+ stopped2 = true;
185707
+ stop2?.();
185708
+ };
185709
+ }
185710
+ };
185711
+ ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
185712
+ copy = createFileCopy({
185713
+ kind: "personas",
185714
+ schemaVersion: PERSONAS_SCHEMA_VERSION,
185715
+ label: "personas copy",
185716
+ removalFloor: PERSONAS_REMOVAL_FLOOR,
185717
+ isRow: isRow3,
185718
+ key: (r8) => r8.key,
185719
+ admit
185720
+ });
185721
+ personasFollower = copy.follower;
185722
+ }
185723
+ });
185724
+
185574
185725
  // src/core/sessions/cloud-chat-lane.ts
185575
185726
  var cloud_chat_lane_exports = {};
185576
185727
  __export(cloud_chat_lane_exports, {
@@ -185709,7 +185860,9 @@ async function resolveCloudChatLane(lane, agentId, conversationId, cwd, firstMes
185709
185860
  CATCH_UP_BANNER_CLOSE: CATCH_UP_BANNER_CLOSE2,
185710
185861
  buildConversationSeed: buildConversationSeed2
185711
185862
  } = await Promise.resolve().then(() => (init_chat_history(), chat_history_exports));
185712
- const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId });
185863
+ const { readPersonaCopy: readPersonaCopy2 } = await Promise.resolve().then(() => (init_personas(), personas_exports));
185864
+ const persona = await readPersonaCopy2(agentId).catch(() => null);
185865
+ const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId, ...persona ? { persona } : {} });
185713
185866
  const profile = toCloudChatProfile(base, CONVERSATION_SEED_HEADER2);
185714
185867
  const sessionId = crypto46.randomUUID();
185715
185868
  const seedInProfile = !!seed && (seed.text !== "" || seed.stats.turnsTotal === 0);
@@ -192678,9 +192831,9 @@ function sanitizeHealthSync(body7, now = Date.now()) {
192678
192831
  const tz = isValidTz(b8.tz) ? b8.tz : "";
192679
192832
  const spec = metricSpec(type);
192680
192833
  const generic = isGenericType(type);
192681
- const storeId = typeof b8.storeId === "string" && ID_RE.test(b8.storeId) ? b8.storeId : void 0;
192834
+ const storeId = typeof b8.storeId === "string" && ID_RE2.test(b8.storeId) ? b8.storeId : void 0;
192682
192835
  const dev = b8.device && typeof b8.device === "object" ? b8.device : {};
192683
- const installId = typeof dev.installId === "string" && ID_RE.test(dev.installId) ? dev.installId : void 0;
192836
+ const installId = typeof dev.installId === "string" && ID_RE2.test(dev.installId) ? dev.installId : void 0;
192684
192837
  const device = { installId, model: str10(dev.model, 64), os: str10(dev.os, 64) };
192685
192838
  const hasDevice = Object.values(device).some((v3) => v3 !== void 0);
192686
192839
  const deleted = [...new Set(deletedIn.filter((u3) => typeof u3 === "string" && UUID_RE3.test(u3)))];
@@ -192748,14 +192901,14 @@ function relayPayload(batch) {
192748
192901
  samples: batch.samples.map(({ tz, ...rest }) => tz === batch.tz ? rest : { ...rest, tz })
192749
192902
  };
192750
192903
  }
192751
- var UUID_RE3, ID_RE, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
192904
+ var UUID_RE3, ID_RE2, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
192752
192905
  var init_sanitize = __esm({
192753
192906
  "src/core/health/sanitize.ts"() {
192754
192907
  "use strict";
192755
192908
  init_catalog();
192756
192909
  init_day_key();
192757
192910
  UUID_RE3 = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
192758
- ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
192911
+ ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
192759
192912
  MIN_INSTANT = Date.UTC(2010, 0, 1);
192760
192913
  FUTURE_SLACK_MS2 = 36 * 36e5;
192761
192914
  MAX_SPAN_MS = 2 * 864e5;
@@ -205327,7 +205480,7 @@ async function saveRecordingAudio(audioBase64, format2) {
205327
205480
  return { id, audioPath };
205328
205481
  }
205329
205482
  async function writeRecordingResult(id, meta) {
205330
- if (!ID_RE2.test(id)) throw new Error(`Invalid recording id: ${id}`);
205483
+ if (!ID_RE3.test(id)) throw new Error(`Invalid recording id: ${id}`);
205331
205484
  await mkdir7(dir(), { recursive: true });
205332
205485
  const stamped = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...meta };
205333
205486
  await writeFile6(join17(dir(), `${id}.json`), JSON.stringify(stamped, null, 2));
@@ -205336,7 +205489,7 @@ async function writeRecordingResult(id, meta) {
205336
205489
  return stamped.timestamp;
205337
205490
  }
205338
205491
  async function writeRecordingSecondary(id, secondary, expectTimestamp) {
205339
- if (!ID_RE2.test(id)) throw new Error(`Invalid recording id: ${id}`);
205492
+ if (!ID_RE3.test(id)) throw new Error(`Invalid recording id: ${id}`);
205340
205493
  const path297 = join17(dir(), `${id}.json`);
205341
205494
  let existing;
205342
205495
  try {
@@ -205358,7 +205511,7 @@ async function listRecordings(limit = 20) {
205358
205511
  const out = [];
205359
205512
  for (const jf of jsonFiles) {
205360
205513
  const id = jf.slice(0, -5);
205361
- if (!ID_RE2.test(id)) continue;
205514
+ if (!ID_RE3.test(id)) continue;
205362
205515
  try {
205363
205516
  const raw = JSON.parse(await readFile8(join17(dir(), jf), "utf-8"));
205364
205517
  out.push({
@@ -205378,7 +205531,7 @@ async function listRecordings(limit = 20) {
205378
205531
  return out;
205379
205532
  }
205380
205533
  async function readRecordingAudio(id) {
205381
- if (!ID_RE2.test(id)) return null;
205534
+ if (!ID_RE3.test(id)) return null;
205382
205535
  let files;
205383
205536
  try {
205384
205537
  files = await readdir4(dir());
@@ -205406,13 +205559,13 @@ async function pruneOldRecordings() {
205406
205559
  }
205407
205560
  }
205408
205561
  }
205409
- var MAX_RECORDINGS, ID_RE2, AUDIO_EXTS;
205562
+ var MAX_RECORDINGS, ID_RE3, AUDIO_EXTS;
205410
205563
  var init_recordings = __esm({
205411
205564
  "src/core/stt/recordings.ts"() {
205412
205565
  "use strict";
205413
205566
  init_constants();
205414
205567
  MAX_RECORDINGS = 100;
205415
- ID_RE2 = /^[0-9A-Za-z-]+$/;
205568
+ ID_RE3 = /^[0-9A-Za-z-]+$/;
205416
205569
  AUDIO_EXTS = ["webm", "mp4", "ogg", "wav", "mp3", "m4a", "flac"];
205417
205570
  }
205418
205571
  });
@@ -208124,7 +208277,7 @@ async function adoptDeviceRecord(input, opts2 = {}) {
208124
208277
  const existing = devices.find((d8) => d8.tokenHash === tokenHash);
208125
208278
  if (existing) return { result: { name: existing.name, adopted: false } };
208126
208279
  const finalName = freeName(devices, name);
208127
- const wanted = typeof input.id === "string" && ID_RE3.test(input.id) ? input.id : void 0;
208280
+ const wanted = typeof input.id === "string" && ID_RE4.test(input.id) ? input.id : void 0;
208128
208281
  const idFree = wanted !== void 0 && !devices.some((d8) => d8.id === wanted || d8.ownerId === wanted);
208129
208282
  const record2 = {
208130
208283
  name: finalName,
@@ -208159,7 +208312,7 @@ async function revokeAdopted(tokenHash) {
208159
208312
  if (out.revoked) log.web.info("device-adoption: twin pairing revoked", { name: record2.name, adoptedFrom: record2.adoptedFrom ?? null });
208160
208313
  return out.revoked ? { name: record2.name, refused: false, push: out.push } : { name: null, refused: false, push: null };
208161
208314
  }
208162
- var AdoptionError, HASH_RE, ID_RE3, INFO_FIELD_MAX2, NAME_MAX;
208315
+ var AdoptionError, HASH_RE, ID_RE4, INFO_FIELD_MAX2, NAME_MAX;
208163
208316
  var init_device_adoption = __esm({
208164
208317
  "src/core/device-adoption.ts"() {
208165
208318
  "use strict";
@@ -208177,7 +208330,7 @@ var init_device_adoption = __esm({
208177
208330
  }
208178
208331
  };
208179
208332
  HASH_RE = /^[0-9a-f]{64}$/;
208180
- ID_RE3 = /^d[0-9a-f]{16}$/;
208333
+ ID_RE4 = /^d[0-9a-f]{16}$/;
208181
208334
  INFO_FIELD_MAX2 = 120;
208182
208335
  NAME_MAX = 64;
208183
208336
  }
@@ -214780,10 +214933,13 @@ async function cleanupLaneClaudeMd(homeDir2 = WALNUT_HOME) {
214780
214933
  }
214781
214934
  }
214782
214935
  async function buildLaneProfile(config, agentId, opts2) {
214783
- const skillsIndex = await buildSessionSkillsPrompt().catch(() => "");
214784
- const memoryContext = await buildLaneMemoryContext().catch(() => "");
214936
+ const persona = opts2?.persona;
214937
+ const skillsIndex = persona ? "" : await buildSessionSkillsPrompt().catch(() => "");
214938
+ const memoryContext = persona ? "" : await buildLaneMemoryContext().catch(() => "");
214785
214939
  let profile;
214786
- if (agentId === "general") {
214940
+ if (persona) {
214941
+ profile = mergeProfiles({ systemPrompt: persona.systemPrompt, systemPromptMode: persona.systemPromptMode }, walnutMcpProfile());
214942
+ } else if (agentId === "general") {
214787
214943
  profile = personalAiProfile(config.user?.name ?? "the user", skillsIndex, memoryContext);
214788
214944
  } else {
214789
214945
  const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports));
@@ -214793,7 +214949,8 @@ async function buildLaneProfile(config, agentId, opts2) {
214793
214949
  const contextBlock = await loadContextSources2(agentDef, {}).catch(() => "");
214794
214950
  profile = consoleAgentProfile(agentDef, skillsIndex, contextBlock);
214795
214951
  }
214796
- const effort = config.agent?.session_effort ?? "medium";
214952
+ const personaEffort = persona?.effort && LANE_EFFORTS.has(persona.effort) ? persona.effort : void 0;
214953
+ const effort = personaEffort ?? config.agent?.session_effort ?? "medium";
214797
214954
  if (!opts2?.conversationId) return { profile, effort };
214798
214955
  const base = profile.systemPrompt ?? "";
214799
214956
  const headroom = MAX_LANE_PROMPT_BYTES - Buffer.byteLength(base, "utf-8") - LANE_SEED_RESERVE_BYTES;
@@ -215063,7 +215220,7 @@ async function resolveLane(lane, agentId, conversationId, firstMessage, engine)
215063
215220
  });
215064
215221
  return { sessionId, created: true, engine: "claude" };
215065
215222
  }
215066
- var inFlight13, 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;
215223
+ var LANE_EFFORTS, inFlight13, 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;
215067
215224
  var init_personal_ai_lane = __esm({
215068
215225
  "src/core/sessions/personal-ai-lane.ts"() {
215069
215226
  "use strict";
@@ -215078,6 +215235,7 @@ var init_personal_ai_lane = __esm({
215078
215235
  init_default_engine();
215079
215236
  init_ask_profile_prefix();
215080
215237
  init_logging();
215238
+ LANE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
215081
215239
  inFlight13 = /* @__PURE__ */ new Map();
215082
215240
  LANE_MEMORY_HEADER = "## Standing memory (injected by Walnut)";
215083
215241
  MANAGED_LANE_CONTEXT_MARKERS = [
@@ -251129,7 +251287,7 @@ function changed3() {
251129
251287
  }).catch(() => {
251130
251288
  });
251131
251289
  }
251132
- function isRow3(v3) {
251290
+ function isRow4(v3) {
251133
251291
  const t3 = v3;
251134
251292
  return !!t3 && typeof t3 === "object" && typeof t3.id === "string" && !!t3.id && typeof t3.title === "string";
251135
251293
  }
@@ -251201,7 +251359,7 @@ function makeTasksFollower() {
251201
251359
  refuse: refuse10,
251202
251360
  load: load3,
251203
251361
  save,
251204
- isRow: isRow3,
251362
+ isRow: isRow4,
251205
251363
  key: (t3) => t3.id,
251206
251364
  localKeys: async () => (await (await Promise.resolve().then(() => (init_task_manager(), task_manager_exports))).taskStoreForReplica()).tasks.map((t3) => t3.id),
251207
251365
  apply: applyToStore,
@@ -251341,9 +251499,13 @@ var init_task_replica_store = __esm({
251341
251499
  // src/core/replication/kinds/gate.ts
251342
251500
  var gate_exports = {};
251343
251501
  __export(gate_exports, {
251502
+ COMPANION_COPY_KINDS: () => COMPANION_COPY_KINDS,
251503
+ COPY_AS_OF_HEADER: () => COPY_AS_OF_HEADER,
251344
251504
  KIND_NOT_COPIED: () => KIND_NOT_COPIED,
251505
+ copyKindAsOf: () => copyKindAsOf,
251345
251506
  copyKindHeld: () => copyKindHeld,
251346
251507
  copyKindOff: () => copyKindOff,
251508
+ copyPath: () => copyPath,
251347
251509
  copyRefusal: () => copyRefusal,
251348
251510
  copyStateFile: () => copyStateFile,
251349
251511
  keepsCopies: () => keepsCopies,
@@ -251351,8 +251513,16 @@ __export(gate_exports, {
251351
251513
  });
251352
251514
  import fsp107 from "fs/promises";
251353
251515
  import path202 from "path";
251354
- function keepsCopies() {
251355
- return isHostReplicaProgram();
251516
+ function keepsCopies(kind) {
251517
+ if (isHostReplicaProgram()) return true;
251518
+ if (followerKind() !== "companion") return false;
251519
+ return kind === void 0 || COMPANION_COPY_KINDS.has(kind);
251520
+ }
251521
+ function copyPath(live6) {
251522
+ if (followerKind() !== "companion") return live6;
251523
+ const rel = path202.relative(WALNUT_HOME, live6);
251524
+ if (!rel || rel.startsWith("..") || path202.isAbsolute(rel)) throw new Error(`copyPath: ${live6} is not under the data dir`);
251525
+ return path202.join(WALNUT_HOME, "cache", "replica", "home", rel);
251356
251526
  }
251357
251527
  async function copyRefusal() {
251358
251528
  if (!keepsCopies()) return { status: 404, error: "unknown_kind" };
@@ -251373,20 +251543,26 @@ async function copyKindOff(kind) {
251373
251543
  }
251374
251544
  }
251375
251545
  async function copyKindHeld(kind) {
251546
+ return await copyKindAsOf(kind) !== null;
251547
+ }
251548
+ async function copyKindAsOf(kind) {
251376
251549
  try {
251377
251550
  const raw = JSON.parse(await fsp107.readFile(copyStateFile(kind), "utf8"));
251378
- return raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object";
251551
+ if (!(raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object")) return null;
251552
+ return Number(raw.asOf) || 0;
251379
251553
  } catch {
251380
- return false;
251554
+ return null;
251381
251555
  }
251382
251556
  }
251383
- var KIND_NOT_COPIED;
251557
+ var COMPANION_COPY_KINDS, COPY_AS_OF_HEADER, KIND_NOT_COPIED;
251384
251558
  var init_gate = __esm({
251385
251559
  "src/core/replication/kinds/gate.ts"() {
251386
251560
  "use strict";
251387
251561
  init_constants();
251388
251562
  init_server_role();
251389
251563
  init_kind_follower();
251564
+ COMPANION_COPY_KINDS = /* @__PURE__ */ new Set(["requests", "routines", "prefs", "personas"]);
251565
+ COPY_AS_OF_HEADER = "x-walnut-copy-as-of";
251390
251566
  KIND_NOT_COPIED = "kind_not_copied";
251391
251567
  }
251392
251568
  });
@@ -251505,7 +251681,7 @@ async function readLeaderConfig() {
251505
251681
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("config.yaml is not a mapping");
251506
251682
  return parsed;
251507
251683
  }
251508
- async function leaderRows() {
251684
+ async function leaderRows2() {
251509
251685
  const { rows, refused: refused2, unknown } = configCopyRows(await readLeaderConfig());
251510
251686
  const note = JSON.stringify({ refused: refused2.map((r8) => [r8.key, r8.findings.map((f8) => `${f8.path}:${f8.reason}`)]), unknown });
251511
251687
  if ((refused2.length > 0 || unknown.length > 0) && note !== lastWarned2) {
@@ -251517,30 +251693,30 @@ async function leaderRows() {
251517
251693
  }
251518
251694
  return rows;
251519
251695
  }
251520
- function hashOf4(row) {
251521
- let h8 = hashes3.get(row);
251696
+ function hashOf5(row) {
251697
+ let h8 = hashes4.get(row);
251522
251698
  if (h8 === void 0) {
251523
251699
  h8 = sha12(JSON.stringify(row));
251524
- hashes3.set(row, h8);
251700
+ hashes4.set(row, h8);
251525
251701
  }
251526
251702
  return h8;
251527
251703
  }
251528
- function isRow4(v3) {
251704
+ function isRow5(v3) {
251529
251705
  const r8 = v3;
251530
251706
  return !!r8 && typeof r8 === "object" && typeof r8.key === "string" && !!r8.key && "value" in r8 && Object.keys(r8).length === 2;
251531
251707
  }
251532
251708
  async function readConfigCopy() {
251533
- const rows = await copy.read();
251709
+ const rows = await copy2.read();
251534
251710
  if (!rows) return null;
251535
251711
  const out = {};
251536
251712
  for (const r8 of Object.values(rows)) if (configRowAdmissible(r8)) out[r8.key] = r8.value;
251537
251713
  return out;
251538
251714
  }
251539
251715
  function _resetConfigCopyForTesting() {
251540
- copy.reset();
251716
+ copy2.reset();
251541
251717
  lastWarned2 = "";
251542
251718
  }
251543
- var CONFIG_SCHEMA_VERSION, CONFIG_REMOVAL_FLOOR, lastWarned2, hashes3, CONFIG_KIND, copy, configFollower;
251719
+ var CONFIG_SCHEMA_VERSION, CONFIG_REMOVAL_FLOOR, lastWarned2, hashes4, CONFIG_KIND, copy2, configFollower;
251544
251720
  var init_config12 = __esm({
251545
251721
  "src/core/replication/kinds/config.ts"() {
251546
251722
  "use strict";
@@ -251552,16 +251728,16 @@ var init_config12 = __esm({
251552
251728
  CONFIG_SCHEMA_VERSION = 1;
251553
251729
  CONFIG_REMOVAL_FLOOR = 0;
251554
251730
  lastWarned2 = "";
251555
- hashes3 = /* @__PURE__ */ new WeakMap();
251731
+ hashes4 = /* @__PURE__ */ new WeakMap();
251556
251732
  CONFIG_KIND = {
251557
251733
  kind: "config",
251558
251734
  schemaVersion: CONFIG_SCHEMA_VERSION,
251559
251735
  key: (r8) => r8.key,
251560
- hash: hashOf4,
251736
+ hash: hashOf5,
251561
251737
  ordered: false,
251562
251738
  digest: false,
251563
251739
  choice: "config",
251564
- rows: leaderRows,
251740
+ rows: leaderRows2,
251565
251741
  watch: (soon) => {
251566
251742
  let stop2 = null;
251567
251743
  let stopped2 = false;
@@ -251574,16 +251750,16 @@ var init_config12 = __esm({
251574
251750
  };
251575
251751
  }
251576
251752
  };
251577
- copy = createFileCopy({
251753
+ copy2 = createFileCopy({
251578
251754
  kind: "config",
251579
251755
  schemaVersion: CONFIG_SCHEMA_VERSION,
251580
251756
  label: "config copy",
251581
251757
  removalFloor: CONFIG_REMOVAL_FLOOR,
251582
- isRow: isRow4,
251758
+ isRow: isRow5,
251583
251759
  key: (r8) => r8.key,
251584
251760
  admit: configRowAdmissible
251585
251761
  });
251586
- configFollower = copy.follower;
251762
+ configFollower = copy2.follower;
251587
251763
  }
251588
251764
  });
251589
251765
 
@@ -251779,7 +251955,7 @@ function prefAdmissible(p6) {
251779
251955
  function strings(v3) {
251780
251956
  return Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string") : [];
251781
251957
  }
251782
- async function leaderRows2() {
251958
+ async function leaderRows3() {
251783
251959
  const raw = await readJsonFile(UI_PREFS_FILE, {}, { readErrors: "throw" });
251784
251960
  const rows = [];
251785
251961
  for (const [k8, v3] of Object.entries(raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {})) {
@@ -251791,15 +251967,15 @@ async function leaderRows2() {
251791
251967
  rows.push({ key: "favorites", favorites: { projects: strings(fav?.projects), notes: strings(fav?.notes) } });
251792
251968
  return rows;
251793
251969
  }
251794
- function hashOf5(row) {
251795
- let h8 = hashes4.get(row);
251970
+ function hashOf6(row) {
251971
+ let h8 = hashes5.get(row);
251796
251972
  if (h8 === void 0) {
251797
251973
  h8 = sha12(JSON.stringify(row));
251798
- hashes4.set(row, h8);
251974
+ hashes5.set(row, h8);
251799
251975
  }
251800
251976
  return h8;
251801
251977
  }
251802
- function isRow5(v3) {
251978
+ function isRow6(v3) {
251803
251979
  const r8 = v3;
251804
251980
  if (!r8 || typeof r8 !== "object" || typeof r8.key !== "string") return false;
251805
251981
  if (r8.key === "favorites") {
@@ -251809,27 +251985,27 @@ function isRow5(v3) {
251809
251985
  const p6 = prefOf(r8.pref);
251810
251986
  return Object.keys(r8).length === 2 && r8.key.startsWith(UI) && copyableUiPrefKey(r8.key.slice(UI.length)) && !!p6 && typeof r8.pref === "object";
251811
251987
  }
251812
- function admit(r8) {
251988
+ function admit2(r8) {
251813
251989
  if ("favorites" in r8) return [...r8.favorites.projects, ...r8.favorites.notes].every((s4) => typeof s4 === "string" && secretShapedValue(s4) === null);
251814
251990
  return prefAdmissible(r8.pref);
251815
251991
  }
251816
251992
  async function readUiPrefsCopy() {
251817
- const rows = await copy2.read();
251993
+ const rows = await copy3.read();
251818
251994
  if (!rows) return null;
251819
251995
  const out = {};
251820
251996
  for (const r8 of Object.values(rows)) if ("pref" in r8) out[r8.key.slice(UI.length)] = r8.pref;
251821
251997
  return out;
251822
251998
  }
251823
251999
  async function readFavoritesCopy() {
251824
- const rows = await copy2.read();
252000
+ const rows = await copy3.read();
251825
252001
  if (!rows) return null;
251826
252002
  const f8 = rows.favorites;
251827
252003
  return f8 && "favorites" in f8 ? f8.favorites : { projects: [], notes: [] };
251828
252004
  }
251829
252005
  function _resetPrefsCopyForTesting() {
251830
- copy2.reset();
252006
+ copy3.reset();
251831
252007
  }
251832
- var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes4, PREFS_KIND, copy2, prefsFollower;
252008
+ var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes5, PREFS_KIND, copy3, prefsFollower;
251833
252009
  var init_prefs = __esm({
251834
252010
  "src/core/replication/kinds/prefs.ts"() {
251835
252011
  "use strict";
@@ -251843,16 +252019,16 @@ var init_prefs = __esm({
251843
252019
  PREFS_REMOVAL_FLOOR = 0;
251844
252020
  UI = "ui:";
251845
252021
  MAX_VALUE_LEN2 = 8 * 1024;
251846
- hashes4 = /* @__PURE__ */ new WeakMap();
252022
+ hashes5 = /* @__PURE__ */ new WeakMap();
251847
252023
  PREFS_KIND = {
251848
252024
  kind: "prefs",
251849
252025
  schemaVersion: PREFS_SCHEMA_VERSION,
251850
252026
  key: (r8) => r8.key,
251851
- hash: hashOf5,
252027
+ hash: hashOf6,
251852
252028
  ordered: false,
251853
252029
  digest: false,
251854
252030
  choice: "prefs",
251855
- rows: leaderRows2,
252031
+ rows: leaderRows3,
251856
252032
  watch: (soon) => {
251857
252033
  const stops = [];
251858
252034
  let stopped2 = false;
@@ -251865,16 +252041,16 @@ var init_prefs = __esm({
251865
252041
  };
251866
252042
  }
251867
252043
  };
251868
- copy2 = createFileCopy({
252044
+ copy3 = createFileCopy({
251869
252045
  kind: "prefs",
251870
252046
  schemaVersion: PREFS_SCHEMA_VERSION,
251871
252047
  label: "prefs copy",
251872
252048
  removalFloor: PREFS_REMOVAL_FLOOR,
251873
- isRow: isRow5,
252049
+ isRow: isRow6,
251874
252050
  key: (r8) => r8.key,
251875
- admit
252051
+ admit: admit2
251876
252052
  });
251877
- prefsFollower = copy2.follower;
252053
+ prefsFollower = copy3.follower;
251878
252054
  }
251879
252055
  });
251880
252056
 
@@ -255022,7 +255198,7 @@ import crypto64 from "crypto";
255022
255198
  import fs111 from "fs";
255023
255199
  import path205 from "path";
255024
255200
  function isDeviceCopyId(id) {
255025
- return typeof id === "string" && ID_RE4.test(id);
255201
+ return typeof id === "string" && ID_RE5.test(id);
255026
255202
  }
255027
255203
  function sha256Hex2(text5) {
255028
255204
  return crypto64.createHash("sha256").update(text5, "utf-8").digest("hex");
@@ -255112,14 +255288,14 @@ function createDeviceCopy(file) {
255112
255288
  }
255113
255289
  };
255114
255290
  }
255115
- var HASH_RE2, NAME_MAX2, MAX_DEVICES, ID_RE4;
255291
+ var HASH_RE2, NAME_MAX2, MAX_DEVICES, ID_RE5;
255116
255292
  var init_device_copy = __esm({
255117
255293
  "src/host-server/device-copy.ts"() {
255118
255294
  "use strict";
255119
255295
  HASH_RE2 = /^[0-9a-f]{64}$/;
255120
255296
  NAME_MAX2 = 64;
255121
255297
  MAX_DEVICES = 500;
255122
- ID_RE4 = /^[A-Za-z0-9._:-]{1,80}$/;
255298
+ ID_RE5 = /^[A-Za-z0-9._:-]{1,80}$/;
255123
255299
  }
255124
255300
  });
255125
255301
 
@@ -255140,11 +255316,11 @@ function replicaDeviceCopyFile(home = WALNUT_HOME) {
255140
255316
  return path206.join(home, "replica", "devices.json");
255141
255317
  }
255142
255318
  function replicaDeviceCopy() {
255143
- copy3 ??= createDeviceCopy(replicaDeviceCopyFile());
255144
- return copy3;
255319
+ copy4 ??= createDeviceCopy(replicaDeviceCopyFile());
255320
+ return copy4;
255145
255321
  }
255146
255322
  function _resetReplicaAuthForTesting() {
255147
- copy3 = null;
255323
+ copy4 = null;
255148
255324
  }
255149
255325
  function verifyReplicaToken(token) {
255150
255326
  const name = replicaDeviceCopy().verify(token);
@@ -255187,14 +255363,14 @@ async function replicaAuthMiddleware(req, res, next) {
255187
255363
  req.deviceName = cred.name;
255188
255364
  next();
255189
255365
  }
255190
- var copy3, PUBLIC_GET_PATHS, REPLICA_FAILURE_KEY;
255366
+ var copy4, PUBLIC_GET_PATHS, REPLICA_FAILURE_KEY;
255191
255367
  var init_auth11 = __esm({
255192
255368
  "src/replica/auth.ts"() {
255193
255369
  "use strict";
255194
255370
  init_constants();
255195
255371
  init_device_copy();
255196
255372
  init_logging();
255197
- copy3 = null;
255373
+ copy4 = null;
255198
255374
  PUBLIC_GET_PATHS = /* @__PURE__ */ new Set(["/v1/instance"]);
255199
255375
  REPLICA_FAILURE_KEY = "host-replica";
255200
255376
  }
@@ -290793,6 +290969,147 @@ var init_task_v1 = __esm({
290793
290969
  }
290794
290970
  });
290795
290971
 
290972
+ // src/core/replication/kinds/requests.ts
290973
+ var requests_exports = {};
290974
+ __export(requests_exports, {
290975
+ REQUESTS_KIND: () => REQUESTS_KIND,
290976
+ REQUESTS_REMOVAL_FLOOR: () => REQUESTS_REMOVAL_FLOOR,
290977
+ REQUESTS_SCHEMA_VERSION: () => REQUESTS_SCHEMA_VERSION,
290978
+ _resetRequestsCopyForTesting: () => _resetRequestsCopyForTesting,
290979
+ forwardRequest: () => forwardRequest,
290980
+ readRequestCopy: () => readRequestCopy,
290981
+ requestsFollower: () => requestsFollower
290982
+ });
290983
+ import fsp136 from "fs/promises";
290984
+ import path259 from "path";
290985
+ function forwardRequest(local, incoming) {
290986
+ if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
290987
+ return incoming;
290988
+ }
290989
+ function hashOf7(row) {
290990
+ let h8 = hashes6.get(row);
290991
+ if (h8 === void 0) {
290992
+ h8 = sha12(JSON.stringify(row));
290993
+ hashes6.set(row, h8);
290994
+ }
290995
+ return h8;
290996
+ }
290997
+ async function load7() {
290998
+ if (state12) return state12;
290999
+ let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
291000
+ try {
291001
+ const raw = JSON.parse(await fsp136.readFile(STATE_FILE2(), "utf8"));
291002
+ 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 };
291003
+ } catch {
291004
+ }
291005
+ state12 = s4;
291006
+ return s4;
291007
+ }
291008
+ async function save2() {
291009
+ if (state12) await writeCopyFile(STATE_FILE2(), { v: 1, asOf: state12.asOf, at: state12.at, hashes: state12.hashes });
291010
+ }
291011
+ async function readStore10() {
291012
+ try {
291013
+ const raw = JSON.parse(await fsp136.readFile(STORE_FILE(), "utf8"));
291014
+ return Array.isArray(raw?.requests) ? raw.requests.filter(isRow7) : [];
291015
+ } catch {
291016
+ return [];
291017
+ }
291018
+ }
291019
+ function isRow7(v3) {
291020
+ const r8 = v3;
291021
+ return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
291022
+ }
291023
+ function requestsFollower() {
291024
+ follower3 ??= createRowSetFollower({
291025
+ kind: "requests",
291026
+ schemaVersion: REQUESTS_SCHEMA_VERSION,
291027
+ label: "requests copy",
291028
+ log: log.session,
291029
+ removalFloor: REQUESTS_REMOVAL_FLOOR,
291030
+ ordered: false,
291031
+ serial: (fn) => serial5(fn),
291032
+ refuse: copyRefusal,
291033
+ load: load7,
291034
+ save: save2,
291035
+ isRow: isRow7,
291036
+ key: (r8) => r8.id,
291037
+ localKeys: async () => (await readStore10()).map((r8) => r8.id),
291038
+ apply: async ({ rows, removeIds }) => {
291039
+ const byId = new Map((await readStore10()).map((r8) => [r8.id, r8]));
291040
+ for (const id of removeIds ?? []) byId.delete(id);
291041
+ for (const r8 of rows ?? []) {
291042
+ const kept = forwardRequest(byId.get(r8.id), r8);
291043
+ 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 });
291044
+ byId.set(r8.id, kept);
291045
+ }
291046
+ await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
291047
+ return { skipped: [] };
291048
+ },
291049
+ held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
291050
+ changed: () => {
291051
+ },
291052
+ purge: async () => {
291053
+ const removed = (await readStore10()).length;
291054
+ await fsp136.rm(STORE_FILE(), { force: true });
291055
+ await markCopyOff("requests");
291056
+ state12 = null;
291057
+ return { removed };
291058
+ }
291059
+ });
291060
+ return follower3;
291061
+ }
291062
+ async function readRequestCopy(id) {
291063
+ if (!await copyKindHeld("requests")) return null;
291064
+ return (await readStore10()).find((r8) => r8.id === id) ?? null;
291065
+ }
291066
+ function _resetRequestsCopyForTesting() {
291067
+ state12 = null;
291068
+ follower3 = null;
291069
+ serial5 = serialChain();
291070
+ }
291071
+ var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes6, REQUESTS_KIND, STATE_FILE2, STORE_FILE, state12, serial5, follower3;
291072
+ var init_requests = __esm({
291073
+ "src/core/replication/kinds/requests.ts"() {
291074
+ "use strict";
291075
+ init_constants();
291076
+ init_logging();
291077
+ init_kind();
291078
+ init_kind_follower();
291079
+ init_gate();
291080
+ REQUESTS_SCHEMA_VERSION = 1;
291081
+ REQUESTS_REMOVAL_FLOOR = 50;
291082
+ FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
291083
+ hashes6 = /* @__PURE__ */ new WeakMap();
291084
+ REQUESTS_KIND = {
291085
+ kind: "requests",
291086
+ schemaVersion: REQUESTS_SCHEMA_VERSION,
291087
+ key: (r8) => r8.id,
291088
+ hash: hashOf7,
291089
+ ordered: false,
291090
+ digest: false,
291091
+ choice: "requests",
291092
+ rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
291093
+ watch: (soon) => {
291094
+ let stop2 = null;
291095
+ let stopped2 = false;
291096
+ void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
291097
+ if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
291098
+ });
291099
+ return () => {
291100
+ stopped2 = true;
291101
+ stop2?.();
291102
+ };
291103
+ }
291104
+ };
291105
+ STATE_FILE2 = () => path259.join(WALNUT_HOME, "cache", "replica", "requests.json");
291106
+ STORE_FILE = () => copyPath(path259.join(WALNUT_HOME, "session-requests.json"));
291107
+ state12 = null;
291108
+ serial5 = serialChain();
291109
+ follower3 = null;
291110
+ }
291111
+ });
291112
+
290796
291113
  // src/web/routes/messages-v1.ts
290797
291114
  import { Router as Router86 } from "express";
290798
291115
  function header(req, name) {
@@ -290853,7 +291170,15 @@ var init_messages_v1 = __esm({
290853
291170
  return;
290854
291171
  }
290855
291172
  const { getSessionRequest: getSessionRequest2 } = await Promise.resolve().then(() => (init_session_requests(), session_requests_exports));
290856
- const request3 = await getSessionRequest2(id);
291173
+ let request3 = await getSessionRequest2(id);
291174
+ if (!request3) {
291175
+ const [{ readRequestCopy: readRequestCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
291176
+ Promise.resolve().then(() => (init_requests(), requests_exports)),
291177
+ Promise.resolve().then(() => (init_gate(), gate_exports))
291178
+ ]);
291179
+ request3 = await readRequestCopy2(id) ?? void 0;
291180
+ if (request3) res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("requests") ?? 0));
291181
+ }
290857
291182
  if (!request3) {
290858
291183
  sendV1Error(res, 404, "not_found", `No such request: ${id}`);
290859
291184
  return;
@@ -292097,6 +292422,17 @@ var init_search_memory_v1 = __esm({
292097
292422
  });
292098
292423
  searchMemoryV1Router.get("/favorites", async (_req, res, next) => {
292099
292424
  try {
292425
+ const [{ readFavoritesCopy: readFavoritesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
292426
+ Promise.resolve().then(() => (init_prefs(), prefs_exports)),
292427
+ Promise.resolve().then(() => (init_gate(), gate_exports))
292428
+ ]);
292429
+ const asOf2 = await copyKindAsOf2("prefs");
292430
+ const fav = asOf2 === null ? null : await readFavoritesCopy2();
292431
+ if (fav) {
292432
+ res.setHeader(COPY_AS_OF_HEADER2, String(asOf2));
292433
+ res.json({ projects: fav.projects ?? [], notes: fav.notes ?? [] });
292434
+ return;
292435
+ }
292100
292436
  const { readFavorites: readFavorites2 } = await Promise.resolve().then(() => (init_favorites(), favorites_exports));
292101
292437
  res.json(await readFavorites2());
292102
292438
  } catch (err2) {
@@ -292259,9 +292595,9 @@ var init_leader = __esm({
292259
292595
 
292260
292596
  // src/web/routes/pastes.ts
292261
292597
  import { Router as Router91 } from "express";
292262
- import path259 from "path";
292598
+ import path260 from "path";
292263
292599
  import { createHash as createHash41 } from "crypto";
292264
- import fsp136 from "fs/promises";
292600
+ import fsp137 from "fs/promises";
292265
292601
  var pastesRouter, MAX_PASTE_CHARS;
292266
292602
  var init_pastes = __esm({
292267
292603
  "src/web/routes/pastes.ts"() {
@@ -292281,11 +292617,11 @@ var init_pastes = __esm({
292281
292617
  res.status(413).json({ error: `Paste too large (max ${MAX_PASTE_CHARS} chars)` });
292282
292618
  return;
292283
292619
  }
292284
- await fsp136.mkdir(PASTES_DIR, { recursive: true });
292620
+ await fsp137.mkdir(PASTES_DIR, { recursive: true });
292285
292621
  const hash3 = createHash41("sha256").update(text5).digest("hex").slice(0, 12);
292286
292622
  const filename = `${Date.now()}-${hash3}.txt`;
292287
- const filePath = path259.join(PASTES_DIR, filename);
292288
- await fsp136.writeFile(filePath, text5, "utf8");
292623
+ const filePath = path260.join(PASTES_DIR, filename);
292624
+ await fsp137.writeFile(filePath, text5, "utf8");
292289
292625
  log.web.info("paste spilled to disk", { filePath, chars: text5.length });
292290
292626
  res.json({ path: filePath, filename, chars: text5.length });
292291
292627
  } catch (err2) {
@@ -292301,8 +292637,8 @@ __export(file_content_replica_copy_exports, {
292301
292637
  primaryDataDirRelPath: () => primaryDataDirRelPath,
292302
292638
  resolveReplicaCopy: () => resolveReplicaCopy
292303
292639
  });
292304
- import path260 from "path";
292305
- import fsp137 from "fs/promises";
292640
+ import path261 from "path";
292641
+ import fsp138 from "fs/promises";
292306
292642
  function dataDirIndex(parts, tilde) {
292307
292643
  if (tilde) return parts[1] === DATA_DIR_NAME ? 1 : -1;
292308
292644
  if ((parts[0] === "Users" || parts[0] === "home") && parts[2] === DATA_DIR_NAME) return 2;
@@ -292332,12 +292668,12 @@ async function resolveReplicaCopy(requestPath) {
292332
292668
  const rel = primaryDataDirRelPath(requestPath);
292333
292669
  if (rel === null || deniedName(rel)) return null;
292334
292670
  try {
292335
- const root6 = await fsp137.realpath(WALNUT_HOME);
292336
- const real = await fsp137.realpath(path260.join(WALNUT_HOME, rel));
292337
- if (!real.startsWith(root6 + path260.sep)) return null;
292338
- const realRel = path260.relative(root6, real).split(path260.sep).join("/");
292339
- if (isSecretPath(path260.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
292340
- const st2 = await fsp137.stat(real);
292671
+ const root6 = await fsp138.realpath(WALNUT_HOME);
292672
+ const real = await fsp138.realpath(path261.join(WALNUT_HOME, rel));
292673
+ if (!real.startsWith(root6 + path261.sep)) return null;
292674
+ const realRel = path261.relative(root6, real).split(path261.sep).join("/");
292675
+ if (isSecretPath(path261.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
292676
+ const st2 = await fsp138.stat(real);
292341
292677
  if (!st2.isFile()) return null;
292342
292678
  if (!await isTracked(root6, realRel)) return null;
292343
292679
  return { localPath: real, size: st2.size };
@@ -292377,11 +292713,11 @@ var init_file_content_replica_copy = __esm({
292377
292713
  // src/web/routes/media-v1.ts
292378
292714
  import { Router as Router92 } from "express";
292379
292715
  import crypto75 from "crypto";
292380
- import path261 from "path";
292381
- import fsp138 from "fs/promises";
292716
+ import path262 from "path";
292717
+ import fsp139 from "fs/promises";
292382
292718
  function cachePathFor(host, filePath) {
292383
292719
  const hash3 = crypto75.createHash("sha256").update(filePath).digest("hex").slice(0, 16);
292384
- return path261.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path261.basename(filePath)}`);
292720
+ return path262.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path262.basename(filePath)}`);
292385
292721
  }
292386
292722
  async function hostForSession(sessionId) {
292387
292723
  if (CLOUD_MODE) {
@@ -292446,11 +292782,11 @@ var init_media_v1 = __esm({
292446
292782
  try {
292447
292783
  const filePath = req.query.path;
292448
292784
  const session2 = typeof req.query.session === "string" && SID_RE6.test(req.query.session) ? req.query.session : void 0;
292449
- if (!filePath || typeof filePath !== "string" || !path261.isAbsolute(filePath) || filePath.includes("..")) {
292785
+ if (!filePath || typeof filePath !== "string" || !path262.isAbsolute(filePath) || filePath.includes("..")) {
292450
292786
  res.status(400).json({ error: { code: "bad_request", message: "path must be an absolute file path" } });
292451
292787
  return;
292452
292788
  }
292453
- const ext2 = path261.extname(filePath).slice(1).toLowerCase();
292789
+ const ext2 = path262.extname(filePath).slice(1).toLowerCase();
292454
292790
  const mime = EXT_TO_MIME3[ext2];
292455
292791
  if (!mime) {
292456
292792
  res.status(400).json({ error: { code: "bad_request", message: "file type not allowed" } });
@@ -292458,8 +292794,8 @@ var init_media_v1 = __esm({
292458
292794
  }
292459
292795
  let buffer2 = null;
292460
292796
  try {
292461
- const st2 = await fsp138.stat(filePath);
292462
- if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp138.readFile(filePath);
292797
+ const st2 = await fsp139.stat(filePath);
292798
+ if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp139.readFile(filePath);
292463
292799
  } catch {
292464
292800
  }
292465
292801
  let waitedOnPending = false;
@@ -292480,8 +292816,8 @@ var init_media_v1 = __esm({
292480
292816
  if (buffer2) {
292481
292817
  try {
292482
292818
  const cachePath3 = cachePathFor(host, filePath);
292483
- await fsp138.mkdir(path261.dirname(cachePath3), { recursive: true });
292484
- await fsp138.writeFile(cachePath3, buffer2);
292819
+ await fsp139.mkdir(path262.dirname(cachePath3), { recursive: true });
292820
+ await fsp139.writeFile(cachePath3, buffer2);
292485
292821
  } catch {
292486
292822
  }
292487
292823
  break;
@@ -292491,9 +292827,9 @@ var init_media_v1 = __esm({
292491
292827
  for (const host of hosts2) {
292492
292828
  try {
292493
292829
  const cached8 = cachePathFor(host, filePath);
292494
- const st2 = await fsp138.stat(cached8);
292830
+ const st2 = await fsp139.stat(cached8);
292495
292831
  if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) {
292496
- buffer2 = await fsp138.readFile(cached8);
292832
+ buffer2 = await fsp139.readFile(cached8);
292497
292833
  break;
292498
292834
  }
292499
292835
  } catch {
@@ -292503,7 +292839,7 @@ var init_media_v1 = __esm({
292503
292839
  if (!buffer2 && hosts2.length > 0 && hosts2.every((h8) => h8 === "__local__") && !(await Promise.resolve().then(() => (init_bridge_registry(), bridge_registry_exports))).bridgeForHost("__local__").connected) {
292504
292840
  const { resolveReplicaCopy: resolveReplicaCopy2 } = await Promise.resolve().then(() => (init_file_content_replica_copy(), file_content_replica_copy_exports));
292505
292841
  const copy5 = await resolveReplicaCopy2(filePath);
292506
- if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp138.readFile(copy5.localPath);
292842
+ if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp139.readFile(copy5.localPath);
292507
292843
  }
292508
292844
  }
292509
292845
  if (!buffer2) {
@@ -292528,6 +292864,19 @@ var init_media_v1 = __esm({
292528
292864
 
292529
292865
  // src/web/routes/routines-v1.ts
292530
292866
  import { Router as Router93 } from "express";
292867
+ async function answeredFromCopy(res, includeDisabled, answer5) {
292868
+ const [{ companionRoutinesCopy: companionRoutinesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
292869
+ Promise.resolve().then(() => (init_routines_follower(), routines_follower_exports)),
292870
+ Promise.resolve().then(() => (init_gate(), gate_exports))
292871
+ ]);
292872
+ const jobs2 = await companionRoutinesCopy2({ includeDisabled });
292873
+ if (!jobs2) return false;
292874
+ res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("routines") ?? 0));
292875
+ const body7 = answer5(jobs2);
292876
+ if (body7 === null) sendV1Error(res, 404, "not_found", "No such routine in the copy of your Mac's routines");
292877
+ else res.json(body7);
292878
+ return true;
292879
+ }
292531
292880
  function validRid(req, res) {
292532
292881
  const id = String(req.params.id ?? "");
292533
292882
  if (!RID_RE.test(id)) {
@@ -292574,6 +292923,7 @@ var init_routines_v1 = __esm({
292574
292923
  try {
292575
292924
  const includeDisabled = req.query.includeDisabled === "true";
292576
292925
  if (CLOUD_MODE) {
292926
+ if (await answeredFromCopy(res, includeDisabled, (jobs2) => ({ jobs: jobs2 }))) return;
292577
292927
  await relayControlAction(res, "server.routines", SERVER_RELAY_SID16, { includeDisabled }, 200);
292578
292928
  return;
292579
292929
  }
@@ -292598,6 +292948,7 @@ var init_routines_v1 = __esm({
292598
292948
  routinesV1Router.get("/routines/status", async (_req, res, next) => {
292599
292949
  try {
292600
292950
  if (CLOUD_MODE) {
292951
+ if (await answeredFromCopy(res, true, (jobs2) => ({ enabled: false, storePath: "", jobs: jobs2.length, nextWakeAtMs: null }))) return;
292601
292952
  await relayControlAction(res, "server.routines.status", SERVER_RELAY_SID16, void 0, 200);
292602
292953
  return;
292603
292954
  }
@@ -292669,6 +293020,10 @@ var init_routines_v1 = __esm({
292669
293020
  const id = validRid(req, res);
292670
293021
  if (!id) return;
292671
293022
  if (CLOUD_MODE) {
293023
+ if (await answeredFromCopy(res, true, (jobs2) => {
293024
+ const job2 = jobs2.find((j8) => j8.id === id);
293025
+ return job2 ? { job: job2 } : null;
293026
+ })) return;
292672
293027
  await relayControlAction(res, "server.routines.get", SERVER_RELAY_SID16, { id }, 200);
292673
293028
  return;
292674
293029
  }
@@ -293863,8 +294218,8 @@ __export(file_content_bridge_exports, {
293863
294218
  resolveBridgeHost: () => resolveBridgeHost,
293864
294219
  serveCloudFileContent: () => serveCloudFileContent
293865
294220
  });
293866
- import path262 from "path";
293867
- import fsp139 from "fs/promises";
294221
+ import path263 from "path";
294222
+ import fsp140 from "fs/promises";
293868
294223
  function resolveBridgeHost(host) {
293869
294224
  return typeof host === "string" && host.length > 0 ? host : PRIMARY_BRIDGE_ALIAS5;
293870
294225
  }
@@ -293935,7 +294290,7 @@ function precheckPath(res, rawPath) {
293935
294290
  sendV1Error(res, 400, "bad_request", "Invalid path");
293936
294291
  return null;
293937
294292
  }
293938
- if (rawPath !== "~" && !rawPath.startsWith("~/") && !path262.isAbsolute(rawPath)) {
294293
+ if (rawPath !== "~" && !rawPath.startsWith("~/") && !path263.isAbsolute(rawPath)) {
293939
294294
  sendV1Error(res, 400, "bad_request", "Path must be absolute");
293940
294295
  return null;
293941
294296
  }
@@ -293979,7 +294334,7 @@ async function serveCloudFileContent(req, res) {
293979
294334
  const hostAlias2 = resolveBridgeHost(req.query.host);
293980
294335
  const raw = req.query.raw === "1" || req.query.raw === "true";
293981
294336
  const download = req.query.download === "1" || req.query.download === "true";
293982
- const ext2 = path262.extname(filePath).slice(1).toLowerCase();
294337
+ const ext2 = path263.extname(filePath).slice(1).toLowerCase();
293983
294338
  const {
293984
294339
  assertPathAllowed: assertPathAllowed2,
293985
294340
  isSecretPath: isSecretPath2,
@@ -293989,7 +294344,7 @@ async function serveCloudFileContent(req, res) {
293989
294344
  FileContentError: FileContentError2
293990
294345
  } = await Promise.resolve().then(() => (init_file_content(), file_content_exports));
293991
294346
  const explicitHost = typeof req.query.host === "string" && req.query.host.length > 0;
293992
- const locallyPresent = await fsp139.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
294347
+ const locallyPresent = await fsp140.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
293993
294348
  if (!explicitHost && locallyPresent && cloudLocalReadAllowed2(filePath) && !isSecretPath2(filePath)) {
293994
294349
  try {
293995
294350
  if (raw) {
@@ -294087,10 +294442,10 @@ async function serveReplicaCopy(req, res, requestPath, copy5, opts2) {
294087
294442
  return;
294088
294443
  }
294089
294444
  if (copy5.size <= MAX_BRIDGE_FILE_BYTES) {
294090
- res.json(jsonPayloadFromBuffer(await fsp139.readFile(copy5.localPath), opts2.ext, false));
294445
+ res.json(jsonPayloadFromBuffer(await fsp140.readFile(copy5.localPath), opts2.ext, false));
294091
294446
  return;
294092
294447
  }
294093
- const fh = await fsp139.open(copy5.localPath, "r");
294448
+ const fh = await fsp140.open(copy5.localPath, "r");
294094
294449
  try {
294095
294450
  const head2 = Buffer.alloc(MAX_TEXT_PAYLOAD);
294096
294451
  const { bytesRead } = await fh.read(head2, 0, head2.length, 0);
@@ -295164,17 +295519,17 @@ __export(checklist_io_exports, {
295164
295519
  readHeartbeatChecklist: () => readHeartbeatChecklist,
295165
295520
  writeHeartbeatChecklist: () => writeHeartbeatChecklist
295166
295521
  });
295167
- import fsp140 from "fs/promises";
295522
+ import fsp141 from "fs/promises";
295168
295523
  async function readHeartbeatChecklist() {
295169
295524
  try {
295170
- return await fsp140.readFile(HEARTBEAT_FILE, "utf-8");
295525
+ return await fsp141.readFile(HEARTBEAT_FILE, "utf-8");
295171
295526
  } catch (err2) {
295172
295527
  if (err2.code === "ENOENT") return "";
295173
295528
  throw err2;
295174
295529
  }
295175
295530
  }
295176
295531
  async function writeHeartbeatChecklist(content) {
295177
- await fsp140.writeFile(HEARTBEAT_FILE, content, "utf-8");
295532
+ await fsp141.writeFile(HEARTBEAT_FILE, content, "utf-8");
295178
295533
  }
295179
295534
  var init_checklist_io = __esm({
295180
295535
  "src/heartbeat/checklist-io.ts"() {
@@ -296958,28 +297313,28 @@ __export(boot_guard_exports, {
296958
297313
  });
296959
297314
  import fs142 from "fs";
296960
297315
  import os63 from "os";
296961
- import path263 from "path";
297316
+ import path264 from "path";
296962
297317
  function canonical3(dir4) {
296963
- let head2 = path263.resolve(dir4);
297318
+ let head2 = path264.resolve(dir4);
296964
297319
  const rest = [];
296965
297320
  for (; ; ) {
296966
297321
  try {
296967
- return path263.join(fs142.realpathSync(head2), ...rest);
297322
+ return path264.join(fs142.realpathSync(head2), ...rest);
296968
297323
  } catch {
296969
297324
  }
296970
- const up = path263.dirname(head2);
296971
- if (up === head2) return path263.resolve(dir4);
296972
- rest.unshift(path263.basename(head2));
297325
+ const up = path264.dirname(head2);
297326
+ if (up === head2) return path264.resolve(dir4);
297327
+ rest.unshift(path264.basename(head2));
296973
297328
  head2 = up;
296974
297329
  }
296975
297330
  }
296976
297331
  function spellings(dir4) {
296977
- const resolved = path263.resolve(dir4);
297332
+ const resolved = path264.resolve(dir4);
296978
297333
  return [.../* @__PURE__ */ new Set([resolved, canonical3(resolved), `/private${resolved}`])];
296979
297334
  }
296980
297335
  function within5(child2, parent) {
296981
- const rel = path263.relative(parent, child2);
296982
- return rel === "" || !rel.startsWith("..") && !path263.isAbsolute(rel);
297336
+ const rel = path264.relative(parent, child2);
297337
+ return rel === "" || !rel.startsWith("..") && !path264.isAbsolute(rel);
296983
297338
  }
296984
297339
  function overlaps(a8, b8) {
296985
297340
  return spellings(a8).some((x3) => spellings(b8).some((y3) => within5(x3, y3) || within5(y3, x3)));
@@ -296990,7 +297345,7 @@ function holdsOrIs(outer, inner2) {
296990
297345
  function accountHomes(env3) {
296991
297346
  const homes = /* @__PURE__ */ new Set();
296992
297347
  const add3 = (h8) => {
296993
- if (h8 && h8.trim()) homes.add(path263.resolve(h8.trim()));
297348
+ if (h8 && h8.trim()) homes.add(path264.resolve(h8.trim()));
296994
297349
  };
296995
297350
  add3(env3.HOME);
296996
297351
  add3(os63.homedir());
@@ -297048,7 +297403,7 @@ function assertReplicaBootSafe(input) {
297048
297403
  if (why2) throw new Error(`Host replica refused to start: ${why2}.`);
297049
297404
  }
297050
297405
  function claimReplicaDir(dir4) {
297051
- const marker = path263.join(dir4, REPLICA_DIR_MARKER);
297406
+ const marker = path264.join(dir4, REPLICA_DIR_MARKER);
297052
297407
  try {
297053
297408
  return fs142.lstatSync(marker).isFile();
297054
297409
  } catch {
@@ -297073,7 +297428,7 @@ function claimReplicaDir(dir4) {
297073
297428
  function tightenReplicaModes(dirs2, limit = 2e4) {
297074
297429
  const marked = dirs2.filter((d8) => {
297075
297430
  try {
297076
- return fs142.lstatSync(path263.join(d8, REPLICA_DIR_MARKER)).isFile();
297431
+ return fs142.lstatSync(path264.join(d8, REPLICA_DIR_MARKER)).isFile();
297077
297432
  } catch {
297078
297433
  return false;
297079
297434
  }
@@ -297103,7 +297458,7 @@ function tightenReplicaModes(dirs2, limit = 2e4) {
297103
297458
  } catch {
297104
297459
  return;
297105
297460
  }
297106
- for (const n6 of names2) visit(path263.join(p6, n6));
297461
+ for (const n6 of names2) visit(path264.join(p6, n6));
297107
297462
  } else if (st2.isFile() && (st2.mode & 63) !== 0) {
297108
297463
  try {
297109
297464
  fs142.chmodSync(p6, st2.mode & 448 | 384);
@@ -297290,29 +297645,29 @@ __export(search_replica_store_exports, {
297290
297645
  searchReplicaSync: () => searchReplicaSync,
297291
297646
  startSearchReplicaStore: () => startSearchReplicaStore
297292
297647
  });
297293
- import fsp141 from "fs/promises";
297648
+ import fsp142 from "fs/promises";
297294
297649
  import os64 from "os";
297295
- import path264 from "path";
297650
+ import path265 from "path";
297296
297651
  async function wiring() {
297297
297652
  return Promise.resolve().then(() => (init_wiring(), wiring_exports));
297298
297653
  }
297299
297654
  async function loadState() {
297300
- if (state12) return state12;
297655
+ if (state13) return state13;
297301
297656
  let s4 = { v: 1, mode: null, syncedAt: null };
297302
297657
  try {
297303
- const raw = JSON.parse(await fsp141.readFile(STATE_FILE2(), "utf8"));
297658
+ const raw = JSON.parse(await fsp142.readFile(STATE_FILE3(), "utf8"));
297304
297659
  if (raw && raw.v === 1) {
297305
297660
  s4 = { v: 1, mode: raw.mode ? companionSearchMode(raw.mode) : null, syncedAt: typeof raw.syncedAt === "number" ? raw.syncedAt : null };
297306
297661
  }
297307
297662
  } catch {
297308
297663
  }
297309
- state12 = s4;
297664
+ state13 = s4;
297310
297665
  return s4;
297311
297666
  }
297312
297667
  async function saveState() {
297313
- if (state12) await writeJsonFile(STATE_FILE2(), state12);
297668
+ if (state13) await writeJsonFile(STATE_FILE3(), state13);
297314
297669
  }
297315
- function serial5(fn) {
297670
+ function serial6(fn) {
297316
297671
  const run12 = chain4.then(fn, fn);
297317
297672
  chain4 = run12.catch(() => {
297318
297673
  });
@@ -297376,8 +297731,8 @@ async function closeIndex() {
297376
297731
  allDirty2 = true;
297377
297732
  }
297378
297733
  function publishReady() {
297379
- const ready2 = enabled && mapBuilt && map3.size > 0 && state12?.syncedAt != null;
297380
- setCompanionSearchReady(ready2, ready2 ? state12.syncedAt : null);
297734
+ const ready2 = enabled && mapBuilt && map3.size > 0 && state13?.syncedAt != null;
297735
+ setCompanionSearchReady(ready2, ready2 ? state13.syncedAt : null);
297381
297736
  }
297382
297737
  async function markInSync() {
297383
297738
  const s4 = await loadState();
@@ -297404,7 +297759,7 @@ async function warm(why2) {
297404
297759
  }
297405
297760
  }
297406
297761
  function searchReplicaStatus(body7) {
297407
- return serial5(async () => {
297762
+ return serial6(async () => {
297408
297763
  if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
297409
297764
  const s4 = await loadState();
297410
297765
  const mode = companionSearchMode(body7.mode);
@@ -297452,7 +297807,7 @@ function searchReplicaStatus(body7) {
297452
297807
  });
297453
297808
  }
297454
297809
  function searchReplicaSync(body7) {
297455
- return serial5(async () => {
297810
+ return serial6(async () => {
297456
297811
  if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
297457
297812
  if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
297458
297813
  if (!Array.isArray(body7.entries)) return { ok: false, status: 400, error: "bad_entries" };
@@ -297497,7 +297852,7 @@ async function forgetSearchMemo() {
297497
297852
  }
297498
297853
  }
297499
297854
  function searchReplicaPut(body7) {
297500
- return serial5(async () => {
297855
+ return serial6(async () => {
297501
297856
  if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
297502
297857
  if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
297503
297858
  if (!Array.isArray(body7.docs)) return { ok: false, status: 400, error: "bad_docs" };
@@ -297563,7 +297918,7 @@ function startSearchReplicaStore(options = {}) {
297563
297918
  if (!s4.mode || stopped2) return;
297564
297919
  const decision = companionSearchDecision(s4.mode, deps3.totalMb());
297565
297920
  if (!decision.enabled) return;
297566
- await serial5(async () => {
297921
+ await serial6(async () => {
297567
297922
  enabled = true;
297568
297923
  reason2 = decision.reason;
297569
297924
  await refreshMap2(await openIndex());
@@ -297596,12 +297951,12 @@ function startSearchReplicaStore(options = {}) {
297596
297951
  }));
297597
297952
  }).catch((err2) => log.memory.warn("search replica: local writes not wired", { error: err2 instanceof Error ? err2.message : String(err2) }));
297598
297953
  unsubs.push(onLeaderPresence((answers4) => {
297599
- if (stopped2 || answers4 || !enabled || state12?.syncedAt == null) return;
297954
+ if (stopped2 || answers4 || !enabled || state13?.syncedAt == null) return;
297600
297955
  void warm("leader away");
297601
297956
  }));
297602
297957
  const tick = setInterval(() => {
297603
297958
  void (async () => {
297604
- if (stopped2 || !enabled || state12?.syncedAt == null) return;
297959
+ if (stopped2 || !enabled || state13?.syncedAt == null) return;
297605
297960
  if (Date.now() - lastWarmAt < WARM_EVERY_MS) return;
297606
297961
  if (!await deps3.macAway()) return;
297607
297962
  await warm("mac away");
@@ -297620,7 +297975,7 @@ function startSearchReplicaStore(options = {}) {
297620
297975
  };
297621
297976
  }
297622
297977
  function _resetSearchReplicaStoreForTesting(overrides = {}) {
297623
- state12 = null;
297978
+ state13 = null;
297624
297979
  enabled = false;
297625
297980
  reason2 = "off";
297626
297981
  map3.clear();
@@ -297635,7 +297990,7 @@ function _resetSearchReplicaStoreForTesting(overrides = {}) {
297635
297990
  deps3 = { totalMb: () => Math.round(os64.totalmem() / (1024 * 1024)), macAway: defaultMacAway, ...overrides };
297636
297991
  setCompanionSearchReady(false, null);
297637
297992
  }
297638
- var STATE_FILE2, MASS_REMOVE_FLOOR2, SCAN_SLICE2, WARM_EVERY_MS, TICK_MS2, defaultMacAway, deps3, state12, enabled, reason2, map3, mapBuilt, allDirty2, dirty2, unlisten, lastWarmAt, warmedOnce, chain4, yieldLoop;
297993
+ var STATE_FILE3, MASS_REMOVE_FLOOR2, SCAN_SLICE2, WARM_EVERY_MS, TICK_MS2, defaultMacAway, deps3, state13, enabled, reason2, map3, mapBuilt, allDirty2, dirty2, unlisten, lastWarmAt, warmedOnce, chain4, yieldLoop;
297639
297994
  var init_search_replica_store = __esm({
297640
297995
  "src/core/replication/search-replica-store.ts"() {
297641
297996
  "use strict";
@@ -297647,7 +298002,7 @@ var init_search_replica_store = __esm({
297647
298002
  init_replica_refs();
297648
298003
  init_search_digest();
297649
298004
  init_search_replica_wire();
297650
- STATE_FILE2 = () => path264.join(WALNUT_HOME, "cache", "search-replica.json");
298005
+ STATE_FILE3 = () => path265.join(WALNUT_HOME, "cache", "search-replica.json");
297651
298006
  MASS_REMOVE_FLOOR2 = 200;
297652
298007
  SCAN_SLICE2 = 500;
297653
298008
  WARM_EVERY_MS = 4 * 6e4;
@@ -297657,7 +298012,7 @@ var init_search_replica_store = __esm({
297657
298012
  totalMb: () => Math.round(os64.totalmem() / (1024 * 1024)),
297658
298013
  macAway: defaultMacAway
297659
298014
  };
297660
- state12 = null;
298015
+ state13 = null;
297661
298016
  enabled = false;
297662
298017
  reason2 = "off";
297663
298018
  map3 = new DigestMap();
@@ -297673,10 +298028,10 @@ var init_search_replica_store = __esm({
297673
298028
  });
297674
298029
 
297675
298030
  // src/core/replication/kinds/boards.ts
297676
- import fsp142 from "fs/promises";
297677
- import path265 from "path";
298031
+ import fsp143 from "fs/promises";
298032
+ import path266 from "path";
297678
298033
  async function leaderBoards(dir4 = boardsDir2()) {
297679
- const names2 = await fsp142.readdir(dir4).catch(() => []);
298034
+ const names2 = await fsp143.readdir(dir4).catch(() => []);
297680
298035
  const out = [];
297681
298036
  const unreadable = [];
297682
298037
  const seen2 = /* @__PURE__ */ new Set();
@@ -297685,9 +298040,9 @@ async function leaderBoards(dir4 = boardsDir2()) {
297685
298040
  const id = name.slice(0, -".json".length);
297686
298041
  if (!TASK_ID_RE3.test(id)) continue;
297687
298042
  seen2.add(id);
297688
- const file = path265.join(dir4, name);
298043
+ const file = path266.join(dir4, name);
297689
298044
  try {
297690
- const st2 = await fsp142.stat(file);
298045
+ const st2 = await fsp143.stat(file);
297691
298046
  if (!st2.isFile()) continue;
297692
298047
  if (st2.size > BOARD_COPY_MAX_BYTES) {
297693
298048
  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 });
@@ -297696,14 +298051,14 @@ async function leaderBoards(dir4 = boardsDir2()) {
297696
298051
  }
297697
298052
  let c8 = cache16.get(id);
297698
298053
  if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
297699
- const row = JSON.parse(await fsp142.readFile(file, "utf8"));
297700
- if (!isRow6(row) || row.task_id !== id) {
298054
+ const row = JSON.parse(await fsp143.readFile(file, "utf8"));
298055
+ if (!isRow8(row) || row.task_id !== id) {
297701
298056
  unreadable.push(id);
297702
298057
  continue;
297703
298058
  }
297704
298059
  c8 = { size: st2.size, mtimeMs: st2.mtimeMs, row, hash: sha12(JSON.stringify(row)) };
297705
298060
  cache16.set(id, c8);
297706
- hashOf6.set(row, c8.hash);
298061
+ hashOf8.set(row, c8.hash);
297707
298062
  }
297708
298063
  out.push(c8.row);
297709
298064
  } catch (err2) {
@@ -297718,56 +298073,56 @@ async function leaderBoards(dir4 = boardsDir2()) {
297718
298073
  if (fresh.length > 0) log.session.warn("boards copy: a board could not be read, the host keeps its copy of it", { taskIds: fresh });
297719
298074
  return out;
297720
298075
  }
297721
- function isRow6(v3) {
298076
+ function isRow8(v3) {
297722
298077
  const b8 = v3;
297723
298078
  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";
297724
298079
  }
297725
- async function load7() {
297726
- if (state13) return state13;
298080
+ async function load8() {
298081
+ if (state14) return state14;
297727
298082
  let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
297728
298083
  try {
297729
- const raw = JSON.parse(await fsp142.readFile(STATE_FILE3(), "utf8"));
298084
+ const raw = JSON.parse(await fsp143.readFile(STATE_FILE4(), "utf8"));
297730
298085
  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 };
297731
298086
  } catch {
297732
298087
  }
297733
- state13 = s4;
298088
+ state14 = s4;
297734
298089
  return s4;
297735
298090
  }
297736
- async function save2() {
297737
- if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
298091
+ async function save3() {
298092
+ if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
297738
298093
  }
297739
298094
  async function localIds() {
297740
- const names2 = await fsp142.readdir(boardsDir2()).catch(() => []);
298095
+ const names2 = await fsp143.readdir(boardsDir2()).catch(() => []);
297741
298096
  return names2.filter((n6) => n6.endsWith(".json")).map((n6) => n6.slice(0, -".json".length)).filter((id) => TASK_ID_RE3.test(id));
297742
298097
  }
297743
298098
  function changed4() {
297744
298099
  }
297745
298100
  function boardsFollower() {
297746
- follower3 ??= createRowSetFollower({
298101
+ follower4 ??= createRowSetFollower({
297747
298102
  kind: "boards",
297748
298103
  schemaVersion: BOARDS_SCHEMA_VERSION,
297749
298104
  label: "boards copy",
297750
298105
  log: log.session,
297751
298106
  removalFloor: BOARDS_REMOVAL_FLOOR,
297752
298107
  ordered: false,
297753
- serial: (fn) => serial6(fn),
298108
+ serial: (fn) => serial7(fn),
297754
298109
  refuse: copyRefusal,
297755
- load: load7,
297756
- save: save2,
297757
- isRow: isRow6,
298110
+ load: load8,
298111
+ save: save3,
298112
+ isRow: isRow8,
297758
298113
  key: (b8) => b8.task_id,
297759
298114
  localKeys: localIds,
297760
298115
  apply: async ({ rows, removeIds }) => {
297761
298116
  const skipped = [];
297762
298117
  for (const id of removeIds ?? []) {
297763
- if (TASK_ID_RE3.test(id)) await fsp142.rm(path265.join(boardsDir2(), `${id}.json`), { force: true });
298118
+ if (TASK_ID_RE3.test(id)) await fsp143.rm(path266.join(boardsDir2(), `${id}.json`), { force: true });
297764
298119
  }
297765
298120
  for (const b8 of rows ?? []) {
297766
298121
  if (Buffer.byteLength(JSON.stringify(b8)) > BOARD_COPY_MAX_BYTES) {
297767
298122
  skipped.push(b8.task_id);
297768
298123
  continue;
297769
298124
  }
297770
- await writeCopyFile(path265.join(boardsDir2(), `${b8.task_id}.json`), b8);
298125
+ await writeCopyFile(path266.join(boardsDir2(), `${b8.task_id}.json`), b8);
297771
298126
  }
297772
298127
  return { skipped };
297773
298128
  },
@@ -297775,15 +298130,15 @@ function boardsFollower() {
297775
298130
  changed: changed4,
297776
298131
  purge: async () => {
297777
298132
  const ids2 = await localIds();
297778
- for (const id of ids2) await fsp142.rm(path265.join(boardsDir2(), `${id}.json`), { force: true });
298133
+ for (const id of ids2) await fsp143.rm(path266.join(boardsDir2(), `${id}.json`), { force: true });
297779
298134
  await markCopyOff("boards");
297780
- state13 = null;
298135
+ state14 = null;
297781
298136
  return { removed: ids2.length };
297782
298137
  }
297783
298138
  });
297784
- return follower3;
298139
+ return follower4;
297785
298140
  }
297786
- var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16, hashOf6, warnedTooBig, unreadableOf2, warnedUnreadable, BOARDS_KIND, STATE_FILE3, state13, serial6, follower3;
298141
+ var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16, hashOf8, warnedTooBig, unreadableOf2, warnedUnreadable, BOARDS_KIND, STATE_FILE4, state14, serial7, follower4;
297787
298142
  var init_boards2 = __esm({
297788
298143
  "src/core/replication/kinds/boards.ts"() {
297789
298144
  "use strict";
@@ -297796,9 +298151,9 @@ var init_boards2 = __esm({
297796
298151
  BOARDS_REMOVAL_FLOOR = 20;
297797
298152
  BOARD_COPY_MAX_BYTES = 2 * 1024 * 1024;
297798
298153
  TASK_ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
297799
- boardsDir2 = () => path265.join(WALNUT_HOME, "boards");
298154
+ boardsDir2 = () => path266.join(WALNUT_HOME, "boards");
297800
298155
  cache16 = /* @__PURE__ */ new Map();
297801
- hashOf6 = /* @__PURE__ */ new WeakMap();
298156
+ hashOf8 = /* @__PURE__ */ new WeakMap();
297802
298157
  warnedTooBig = /* @__PURE__ */ new Set();
297803
298158
  unreadableOf2 = /* @__PURE__ */ new WeakMap();
297804
298159
  warnedUnreadable = /* @__PURE__ */ new Set();
@@ -297806,7 +298161,7 @@ var init_boards2 = __esm({
297806
298161
  kind: "boards",
297807
298162
  schemaVersion: BOARDS_SCHEMA_VERSION,
297808
298163
  key: (b8) => b8.task_id,
297809
- hash: (b8) => hashOf6.get(b8) ?? sha12(JSON.stringify(b8)),
298164
+ hash: (b8) => hashOf8.get(b8) ?? sha12(JSON.stringify(b8)),
297810
298165
  ordered: false,
297811
298166
  digest: false,
297812
298167
  choice: "boards",
@@ -297826,16 +298181,16 @@ var init_boards2 = __esm({
297826
298181
  };
297827
298182
  }
297828
298183
  };
297829
- STATE_FILE3 = () => path265.join(WALNUT_HOME, "cache", "replica", "boards.json");
297830
- state13 = null;
297831
- serial6 = serialChain();
297832
- follower3 = null;
298184
+ STATE_FILE4 = () => path266.join(WALNUT_HOME, "cache", "replica", "boards.json");
298185
+ state14 = null;
298186
+ serial7 = serialChain();
298187
+ follower4 = null;
297833
298188
  }
297834
298189
  });
297835
298190
 
297836
298191
  // src/core/replication/kinds/inbox.ts
297837
- import fsp143 from "fs/promises";
297838
- import path266 from "path";
298192
+ import fsp144 from "fs/promises";
298193
+ import path267 from "path";
297839
298194
  function watchLetters(soon) {
297840
298195
  let stop2 = null;
297841
298196
  let stopped2 = false;
@@ -297848,18 +298203,18 @@ function watchLetters(soon) {
297848
298203
  };
297849
298204
  }
297850
298205
  async function leaderBodies(dir4 = bodiesDir()) {
297851
- const names2 = (await fsp143.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
298206
+ const names2 = (await fsp144.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
297852
298207
  const out = [];
297853
298208
  const unreadable = [];
297854
298209
  const seen2 = new Set(names2);
297855
298210
  for (const name of names2) {
297856
- const file = path266.join(dir4, name);
298211
+ const file = path267.join(dir4, name);
297857
298212
  try {
297858
- const st2 = await fsp143.stat(file);
298213
+ const st2 = await fsp144.stat(file);
297859
298214
  if (!st2.isFile() || st2.size > INBOX_BODY_COPY_MAX_BYTES) continue;
297860
298215
  let c8 = bodyCache.get(name);
297861
298216
  if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
297862
- c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp143.readFile(file, "utf8")) };
298217
+ c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp144.readFile(file, "utf8")) };
297863
298218
  bodyCache.set(name, c8);
297864
298219
  }
297865
298220
  const row = { name };
@@ -297878,21 +298233,21 @@ async function loadBody(b8) {
297878
298233
  const file = bodyFiles.get(b8);
297879
298234
  if (!file) return typeof b8.body === "string" ? b8 : void 0;
297880
298235
  try {
297881
- const body7 = await fsp143.readFile(file, "utf8");
298236
+ const body7 = await fsp144.readFile(file, "utf8");
297882
298237
  return Buffer.byteLength(body7) > INBOX_BODY_COPY_MAX_BYTES ? void 0 : { name: b8.name, body: body7 };
297883
298238
  } catch {
297884
298239
  return void 0;
297885
298240
  }
297886
298241
  }
297887
298242
  function stateIo(name) {
297888
- const file = () => path266.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
298243
+ const file = () => path267.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
297889
298244
  let state17 = null;
297890
298245
  return {
297891
298246
  load: async () => {
297892
298247
  if (state17) return state17;
297893
298248
  let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
297894
298249
  try {
297895
- const raw = JSON.parse(await fsp143.readFile(file(), "utf8"));
298250
+ const raw = JSON.parse(await fsp144.readFile(file(), "utf8"));
297896
298251
  if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") {
297897
298252
  s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: Array.isArray(raw.order) ? raw.order.map(String) : [], hashes: raw.hashes };
297898
298253
  }
@@ -297911,7 +298266,7 @@ function stateIo(name) {
297911
298266
  }
297912
298267
  async function readIndex3() {
297913
298268
  try {
297914
- const raw = JSON.parse(await fsp143.readFile(indexFile3(), "utf8"));
298269
+ const raw = JSON.parse(await fsp144.readFile(indexFile3(), "utf8"));
297915
298270
  return Array.isArray(raw?.letters) ? raw.letters.filter(isLetter) : [];
297916
298271
  } catch {
297917
298272
  return [];
@@ -297934,7 +298289,7 @@ function inboxFollower() {
297934
298289
  removalFloor: INBOX_REMOVAL_FLOOR,
297935
298290
  ordered: true,
297936
298291
  digest: true,
297937
- serial: (fn) => serial7(fn),
298292
+ serial: (fn) => serial8(fn),
297938
298293
  refuse: refuse15,
297939
298294
  load: () => indexIo.load(),
297940
298295
  save: () => indexIo.save(),
@@ -297964,7 +298319,7 @@ function inboxFollower() {
297964
298319
  },
297965
298320
  purge: async () => {
297966
298321
  const removed = (await readIndex3()).length;
297967
- await fsp143.rm(indexFile3(), { force: true });
298322
+ await fsp144.rm(indexFile3(), { force: true });
297968
298323
  await markCopyOff("inbox");
297969
298324
  indexIo.reset();
297970
298325
  return { removed };
@@ -297980,23 +298335,23 @@ function inboxBodiesFollower() {
297980
298335
  log: log.notif,
297981
298336
  removalFloor: INBOX_REMOVAL_FLOOR,
297982
298337
  ordered: false,
297983
- serial: (fn) => serial7(fn),
298338
+ serial: (fn) => serial8(fn),
297984
298339
  refuse: refuse15,
297985
298340
  load: () => bodiesIo.load(),
297986
298341
  save: () => bodiesIo.save(),
297987
298342
  isRow: isBody,
297988
298343
  key: (b8) => b8.name,
297989
298344
  hash: (b8) => sha12(b8.body),
297990
- localKeys: async () => (await fsp143.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
298345
+ localKeys: async () => (await fsp144.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
297991
298346
  apply: async ({ rows, removeIds }) => {
297992
- for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp143.rm(path266.join(bodiesDir(), name), { force: true });
298347
+ for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp144.rm(path267.join(bodiesDir(), name), { force: true });
297993
298348
  const skipped = [];
297994
298349
  for (const b8 of rows ?? []) {
297995
298350
  if (Buffer.byteLength(b8.body) > INBOX_BODY_COPY_MAX_BYTES) {
297996
298351
  skipped.push(b8.name);
297997
298352
  continue;
297998
298353
  }
297999
- await writeCopyText(path266.join(bodiesDir(), b8.name), b8.body);
298354
+ await writeCopyText(path267.join(bodiesDir(), b8.name), b8.body);
298000
298355
  }
298001
298356
  return { skipped };
298002
298357
  },
@@ -298004,8 +298359,8 @@ function inboxBodiesFollower() {
298004
298359
  changed: () => {
298005
298360
  },
298006
298361
  purge: async () => {
298007
- const names2 = (await fsp143.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
298008
- for (const name of names2) await fsp143.rm(path266.join(bodiesDir(), name), { force: true });
298362
+ const names2 = (await fsp144.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
298363
+ for (const name of names2) await fsp144.rm(path267.join(bodiesDir(), name), { force: true });
298009
298364
  await markCopyOff("inbox-bodies");
298010
298365
  bodiesIo.reset();
298011
298366
  return { removed: names2.length };
@@ -298013,7 +298368,7 @@ function inboxBodiesFollower() {
298013
298368
  });
298014
298369
  return bodiesF;
298015
298370
  }
298016
- 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, refuse15, indexIo, bodiesIo, serial7, inboxF, bodiesF;
298371
+ 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, refuse15, indexIo, bodiesIo, serial8, inboxF, bodiesF;
298017
298372
  var init_inbox = __esm({
298018
298373
  "src/core/replication/kinds/inbox.ts"() {
298019
298374
  "use strict";
@@ -298026,9 +298381,9 @@ var init_inbox = __esm({
298026
298381
  INBOX_SCHEMA_VERSION = 1;
298027
298382
  INBOX_REMOVAL_FLOOR = 50;
298028
298383
  INBOX_BODY_COPY_MAX_BYTES = 4 * 1024 * 1024;
298029
- inboxDir = () => path266.join(WALNUT_HOME, "human-inbox");
298030
- indexFile3 = () => path266.join(inboxDir(), "index.json");
298031
- bodiesDir = () => path266.join(inboxDir(), "bodies");
298384
+ inboxDir = () => path267.join(WALNUT_HOME, "human-inbox");
298385
+ indexFile3 = () => path267.join(inboxDir(), "index.json");
298386
+ bodiesDir = () => path267.join(inboxDir(), "bodies");
298032
298387
  letterHashes = /* @__PURE__ */ new WeakMap();
298033
298388
  INBOX_KIND = {
298034
298389
  kind: "inbox",
@@ -298070,134 +298425,12 @@ var init_inbox = __esm({
298070
298425
  refuse15 = copyRefusal;
298071
298426
  indexIo = stateIo("inbox");
298072
298427
  bodiesIo = stateIo("inbox-bodies");
298073
- serial7 = serialChain();
298428
+ serial8 = serialChain();
298074
298429
  inboxF = null;
298075
298430
  bodiesF = null;
298076
298431
  }
298077
298432
  });
298078
298433
 
298079
- // src/core/replication/kinds/requests.ts
298080
- import fsp144 from "fs/promises";
298081
- import path267 from "path";
298082
- function forwardRequest(local, incoming) {
298083
- if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
298084
- return incoming;
298085
- }
298086
- function hashOf7(row) {
298087
- let h8 = hashes5.get(row);
298088
- if (h8 === void 0) {
298089
- h8 = sha12(JSON.stringify(row));
298090
- hashes5.set(row, h8);
298091
- }
298092
- return h8;
298093
- }
298094
- async function load8() {
298095
- if (state14) return state14;
298096
- let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
298097
- try {
298098
- const raw = JSON.parse(await fsp144.readFile(STATE_FILE4(), "utf8"));
298099
- 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 };
298100
- } catch {
298101
- }
298102
- state14 = s4;
298103
- return s4;
298104
- }
298105
- async function save3() {
298106
- if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
298107
- }
298108
- async function readStore10() {
298109
- try {
298110
- const raw = JSON.parse(await fsp144.readFile(STORE_FILE(), "utf8"));
298111
- return Array.isArray(raw?.requests) ? raw.requests.filter(isRow7) : [];
298112
- } catch {
298113
- return [];
298114
- }
298115
- }
298116
- function isRow7(v3) {
298117
- const r8 = v3;
298118
- return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
298119
- }
298120
- function requestsFollower() {
298121
- follower4 ??= createRowSetFollower({
298122
- kind: "requests",
298123
- schemaVersion: REQUESTS_SCHEMA_VERSION,
298124
- label: "requests copy",
298125
- log: log.session,
298126
- removalFloor: REQUESTS_REMOVAL_FLOOR,
298127
- ordered: false,
298128
- serial: (fn) => serial8(fn),
298129
- refuse: copyRefusal,
298130
- load: load8,
298131
- save: save3,
298132
- isRow: isRow7,
298133
- key: (r8) => r8.id,
298134
- localKeys: async () => (await readStore10()).map((r8) => r8.id),
298135
- apply: async ({ rows, removeIds }) => {
298136
- const byId = new Map((await readStore10()).map((r8) => [r8.id, r8]));
298137
- for (const id of removeIds ?? []) byId.delete(id);
298138
- for (const r8 of rows ?? []) {
298139
- const kept = forwardRequest(byId.get(r8.id), r8);
298140
- 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 });
298141
- byId.set(r8.id, kept);
298142
- }
298143
- await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
298144
- return { skipped: [] };
298145
- },
298146
- held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
298147
- changed: () => {
298148
- },
298149
- purge: async () => {
298150
- const removed = (await readStore10()).length;
298151
- await fsp144.rm(STORE_FILE(), { force: true });
298152
- await markCopyOff("requests");
298153
- state14 = null;
298154
- return { removed };
298155
- }
298156
- });
298157
- return follower4;
298158
- }
298159
- var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes5, REQUESTS_KIND, STATE_FILE4, STORE_FILE, state14, serial8, follower4;
298160
- var init_requests = __esm({
298161
- "src/core/replication/kinds/requests.ts"() {
298162
- "use strict";
298163
- init_constants();
298164
- init_logging();
298165
- init_kind();
298166
- init_kind_follower();
298167
- init_gate();
298168
- REQUESTS_SCHEMA_VERSION = 1;
298169
- REQUESTS_REMOVAL_FLOOR = 50;
298170
- FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
298171
- hashes5 = /* @__PURE__ */ new WeakMap();
298172
- REQUESTS_KIND = {
298173
- kind: "requests",
298174
- schemaVersion: REQUESTS_SCHEMA_VERSION,
298175
- key: (r8) => r8.id,
298176
- hash: hashOf7,
298177
- ordered: false,
298178
- digest: false,
298179
- choice: "requests",
298180
- rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
298181
- watch: (soon) => {
298182
- let stop2 = null;
298183
- let stopped2 = false;
298184
- void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
298185
- if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
298186
- });
298187
- return () => {
298188
- stopped2 = true;
298189
- stop2?.();
298190
- };
298191
- }
298192
- };
298193
- STATE_FILE4 = () => path267.join(WALNUT_HOME, "cache", "replica", "requests.json");
298194
- STORE_FILE = () => path267.join(WALNUT_HOME, "session-requests.json");
298195
- state14 = null;
298196
- serial8 = serialChain();
298197
- follower4 = null;
298198
- }
298199
- });
298200
-
298201
298434
  // src/core/replication/kinds/sessions.ts
298202
298435
  import fsp145 from "fs/promises";
298203
298436
  import path268 from "path";
@@ -298228,11 +298461,11 @@ function projectedOf(row) {
298228
298461
  }
298229
298462
  return p6;
298230
298463
  }
298231
- function hashOf8(row) {
298232
- let h8 = hashes6.get(row);
298464
+ function hashOf9(row) {
298465
+ let h8 = hashes7.get(row);
298233
298466
  if (h8 === void 0) {
298234
298467
  h8 = sessionCopyHash(row);
298235
- hashes6.set(row, h8);
298468
+ hashes7.set(row, h8);
298236
298469
  }
298237
298470
  return h8;
298238
298471
  }
@@ -298252,7 +298485,7 @@ async function load9() {
298252
298485
  async function save4() {
298253
298486
  if (state15) await writeCopyFile(STATE_FILE5(), { v: 1, asOf: state15.asOf, at: state15.at, hashes: state15.hashes });
298254
298487
  }
298255
- function isRow8(v3) {
298488
+ function isRow9(v3) {
298256
298489
  const r8 = v3;
298257
298490
  return !!r8 && typeof r8 === "object" && !Array.isArray(r8) && typeof r8.claudeSessionId === "string" && r8.claudeSessionId.length > 0 && r8.claudeSessionId.length <= 200;
298258
298491
  }
@@ -298272,7 +298505,7 @@ function sessionsFollower() {
298272
298505
  refuse: copyRefusal,
298273
298506
  load: load9,
298274
298507
  save: save4,
298275
- isRow: isRow8,
298508
+ isRow: isRow9,
298276
298509
  key: (r8) => r8.claudeSessionId,
298277
298510
  hash: sessionCopyHash,
298278
298511
  localKeys: async () => (await Promise.resolve().then(() => (init_session_db(), session_db_exports))).sessionIdsInStore(),
@@ -298294,7 +298527,7 @@ function sessionsFollower() {
298294
298527
  });
298295
298528
  return follower5;
298296
298529
  }
298297
- var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected, hashes6, SESSIONS_KIND, STATE_FILE5, state15, serial9, follower5;
298530
+ var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected, hashes7, SESSIONS_KIND, STATE_FILE5, state15, serial9, follower5;
298298
298531
  var init_sessions2 = __esm({
298299
298532
  "src/core/replication/kinds/sessions.ts"() {
298300
298533
  "use strict";
@@ -298331,12 +298564,12 @@ var init_sessions2 = __esm({
298331
298564
  VOLATILE_SESSION_FIELDS = ["lastActiveAt", "activity", "contextTokens"];
298332
298565
  VOLATILE_SET = new Set(VOLATILE_SESSION_FIELDS);
298333
298566
  projected = /* @__PURE__ */ new WeakMap();
298334
- hashes6 = /* @__PURE__ */ new WeakMap();
298567
+ hashes7 = /* @__PURE__ */ new WeakMap();
298335
298568
  SESSIONS_KIND = {
298336
298569
  kind: "sessions",
298337
298570
  schemaVersion: SESSIONS_SCHEMA_VERSION,
298338
298571
  key: (s4) => s4.claudeSessionId,
298339
- hash: hashOf8,
298572
+ hash: hashOf9,
298340
298573
  ordered: false,
298341
298574
  digest: true,
298342
298575
  choice: "sessions",
@@ -298368,137 +298601,11 @@ var init_sessions2 = __esm({
298368
298601
  }
298369
298602
  });
298370
298603
 
298371
- // src/core/replication/kinds/personas.ts
298372
- var personas_exports = {};
298373
- __export(personas_exports, {
298374
- PERSONAS_KIND: () => PERSONAS_KIND,
298375
- PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
298376
- PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
298377
- _resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
298378
- personasFollower: () => personasFollower,
298379
- readPersonaCopy: () => readPersonaCopy
298380
- });
298381
- function tools(v3) {
298382
- return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
298383
- }
298384
- async function leaderRows3() {
298385
- const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
298386
- Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
298387
- Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
298388
- Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
298389
- Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
298390
- ]);
298391
- const config = await getConfig2();
298392
- const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
298393
- const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
298394
- const rows = [];
298395
- for (const a8 of agents) {
298396
- if (!ID_RE5.test(a8.id)) continue;
298397
- try {
298398
- const { profile, effort } = await buildLaneProfile2(config, a8.id);
298399
- const prompt = profile.systemPrompt ?? "";
298400
- if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
298401
- rows.push({
298402
- key: a8.id,
298403
- agentId: a8.id,
298404
- name: String(a8.name ?? a8.id).slice(0, 120),
298405
- systemPrompt: prompt,
298406
- systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
298407
- ...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
298408
- ...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
298409
- ...effort ? { effort } : {},
298410
- ...launch.model ? { launchModel: launch.model } : {},
298411
- ...launch.effort ? { launchEffort: launch.effort } : {}
298412
- });
298413
- } catch (err2) {
298414
- log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
298415
- }
298416
- }
298417
- return rows;
298418
- }
298419
- function hashOf9(row) {
298420
- let h8 = hashes7.get(row);
298421
- if (h8 === void 0) {
298422
- h8 = sha12(JSON.stringify(row));
298423
- hashes7.set(row, h8);
298424
- }
298425
- return h8;
298426
- }
298427
- function isRow9(v3) {
298428
- const r8 = v3;
298429
- if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
298430
- if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
298431
- if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE5.test(r8.key) || typeof r8.name !== "string") return false;
298432
- if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
298433
- if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
298434
- for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
298435
- 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;
298436
- return true;
298437
- }
298438
- function admit2(r8) {
298439
- return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
298440
- }
298441
- async function readPersonaCopy(agentId) {
298442
- const rows = await copy4.read();
298443
- return rows?.[agentId] ?? null;
298444
- }
298445
- function _resetPersonasCopyForTesting() {
298446
- copy4.reset();
298447
- }
298448
- var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE5, TOOL_RE, hashes7, PERSONAS_KIND, ROW_KEYS, copy4, personasFollower;
298449
- var init_personas = __esm({
298450
- "src/core/replication/kinds/personas.ts"() {
298451
- "use strict";
298452
- init_logging();
298453
- init_config_allowlist();
298454
- init_kind();
298455
- init_file_copy();
298456
- PERSONAS_SCHEMA_VERSION = 1;
298457
- PERSONAS_REMOVAL_FLOOR = 0;
298458
- MAX_PROMPT_BYTES = 120 * 1024;
298459
- ID_RE5 = /^[A-Za-z0-9_-]{1,80}$/;
298460
- TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
298461
- hashes7 = /* @__PURE__ */ new WeakMap();
298462
- PERSONAS_KIND = {
298463
- kind: "personas",
298464
- schemaVersion: PERSONAS_SCHEMA_VERSION,
298465
- key: (r8) => r8.key,
298466
- hash: hashOf9,
298467
- ordered: false,
298468
- digest: false,
298469
- choice: "personas",
298470
- rows: leaderRows3,
298471
- watch: (soon) => {
298472
- let stop2 = null;
298473
- let stopped2 = false;
298474
- void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
298475
- if (!stopped2) stop2 = cm.onConfigWritten(soon);
298476
- });
298477
- return () => {
298478
- stopped2 = true;
298479
- stop2?.();
298480
- };
298481
- }
298482
- };
298483
- ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
298484
- copy4 = createFileCopy({
298485
- kind: "personas",
298486
- schemaVersion: PERSONAS_SCHEMA_VERSION,
298487
- label: "personas copy",
298488
- removalFloor: PERSONAS_REMOVAL_FLOOR,
298489
- isRow: isRow9,
298490
- key: (r8) => r8.key,
298491
- admit: admit2
298492
- });
298493
- personasFollower = copy4.follower;
298494
- }
298495
- });
298496
-
298497
298604
  // src/core/replication/kinds/index.ts
298498
298605
  var kinds_exports = {};
298499
298606
  __export(kinds_exports, {
298607
+ copyKeepersOnly: () => copyKeepersOnly,
298500
298608
  copyKinds: () => copyKinds,
298501
- hostReplicaOnly: () => hostReplicaOnly,
298502
298609
  registerCopyFollowerKinds: () => registerCopyFollowerKinds,
298503
298610
  startCopyKinds: () => startCopyKinds
298504
298611
  });
@@ -298516,14 +298623,14 @@ function copyKinds() {
298516
298623
  PERSONAS_KIND
298517
298624
  ];
298518
298625
  }
298519
- function hostReplicaOnly(h8) {
298626
+ function copyKeepersOnly(h8) {
298520
298627
  return {
298521
298628
  kind: h8.kind,
298522
- // followerStep checks the version before the step: never `schema_newer` off a host replica.
298629
+ // followerStep checks the version before the step: never `schema_newer` where the kind is not kept.
298523
298630
  get schemaVersion() {
298524
- return keepsCopies() ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
298631
+ return keepsCopies(h8.kind) ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
298525
298632
  },
298526
- step: (op2, body7) => keepsCopies() ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
298633
+ step: (op2, body7) => keepsCopies(h8.kind) ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
298527
298634
  };
298528
298635
  }
298529
298636
  function registerCopyFollowerKinds() {
@@ -298538,7 +298645,7 @@ function registerCopyFollowerKinds() {
298538
298645
  prefsFollower(),
298539
298646
  configFollower(),
298540
298647
  personasFollower()
298541
- ].map((h8) => registerFollowerKind(hostReplicaOnly(h8)));
298648
+ ].map((h8) => registerFollowerKind(copyKeepersOnly(h8)));
298542
298649
  return () => {
298543
298650
  for (const u3 of off) u3();
298544
298651
  };