open-walnut 0.6.16 → 0.6.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/actions/inbox-triage-batch.js +556 -449
- package/dist/build-info.json +3 -3
- package/dist/cli-fast.js +2 -2
- package/dist/cli.js +564 -457
- package/dist/daemon-binaries/acp-worker.js.version +1 -1
- package/dist/daemon-binaries/dtach-linux-x64 +0 -0
- package/dist/integrations/calendar/index.js +556 -449
- package/dist/integrations/jira/index.js +556 -449
- package/dist/integrations/mail/index.js +2 -2
- package/dist/integrations/ms-todo/index.js +556 -449
- package/dist/web/server.js +577 -470
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8397,6 +8397,7 @@ function createOfflineHostCore(deps4) {
|
|
|
8397
8397
|
const MAX_ARGS_BYTES = 256 * 1024;
|
|
8398
8398
|
const WRITE_BUDGET = 30;
|
|
8399
8399
|
const WRITE_WINDOW_MS = 6e4;
|
|
8400
|
+
const LOCK_RETRY_MS = [100, 300, 900];
|
|
8400
8401
|
const DEFAULT_REPLY_SECS = 3600;
|
|
8401
8402
|
const IMPLICIT_REPLY_SECS = 6 * 3600;
|
|
8402
8403
|
const DRAIN_BATCH = 200;
|
|
@@ -8543,7 +8544,7 @@ function createOfflineHostCore(deps4) {
|
|
|
8543
8544
|
...opts2.admit ? { admit: opts2.admit } : {}
|
|
8544
8545
|
});
|
|
8545
8546
|
if (!r8.ok) {
|
|
8546
|
-
if (r8.code === "journal_unwritable") deps4.log("error", "offline host: journal write refused", { home, kind, code: r8.code, why: r8.why, error: r8.message });
|
|
8547
|
+
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 });
|
|
8547
8548
|
return r8;
|
|
8548
8549
|
}
|
|
8549
8550
|
if (!r8.duplicate) {
|
|
@@ -8558,6 +8559,19 @@ function createOfflineHostCore(deps4) {
|
|
|
8558
8559
|
if (r8.ok) return null;
|
|
8559
8560
|
return fail7(r8.code, r8.message, { ...r8.retryAfterMs !== void 0 ? { retryAfterMs: r8.retryAfterMs } : {}, ...r8.why ? { detail: { why: r8.why } } : {} });
|
|
8560
8561
|
}
|
|
8562
|
+
const lockRefused = (r8) => !r8.ok && r8.error.code === "journal_unwritable" && r8.error.detail?.why === "locked";
|
|
8563
|
+
async function whenUnlocked(home, op2, run12) {
|
|
8564
|
+
const t0 = Date.now();
|
|
8565
|
+
let r8 = run12();
|
|
8566
|
+
for (const ms2 of LOCK_RETRY_MS) {
|
|
8567
|
+
if (!lockRefused(r8)) return r8;
|
|
8568
|
+
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 });
|
|
8569
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms2));
|
|
8570
|
+
r8 = run12();
|
|
8571
|
+
}
|
|
8572
|
+
if (lockRefused(r8)) deps4.log("error", "offline host: the journal stayed locked; write refused", { home, op: op2, waitedMs: Date.now() - t0 });
|
|
8573
|
+
return r8;
|
|
8574
|
+
}
|
|
8561
8575
|
function configure(slice) {
|
|
8562
8576
|
if (!slice || slice.v !== 1 || typeof slice.home !== "string" || !slice.home) throw new Error("host.slice: bad slice");
|
|
8563
8577
|
const prev = slices.get(slice.home);
|
|
@@ -9291,10 +9305,8 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
9291
9305
|
if (no) return no;
|
|
9292
9306
|
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 });
|
|
9293
9307
|
} else {
|
|
9294
|
-
const denied = admitWrite(callerSid5) ?? roomFor(home);
|
|
9295
|
-
if (denied) return denied;
|
|
9296
9308
|
const base = slices.get(home)?.tasks.find((t3) => t3.id === task.id)?.updated_at;
|
|
9297
|
-
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args2, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }));
|
|
9309
|
+
const no = refusal2(append(home, { kind: "op", op: name, args: { ...args2, id: task.id }, callerSid: callerSid5, ...base ? { base } : {} }, false, { admit: () => admitWrite(callerSid5) ?? roomFor(home) }));
|
|
9298
9310
|
if (no) return no;
|
|
9299
9311
|
deps4.log("info", "offline host: write queued", { home, op: name, taskId: task.id, callerSid: callerSid5 });
|
|
9300
9312
|
}
|
|
@@ -9736,7 +9748,7 @@ ${kit10.buildReplyTrailer(row)}`;
|
|
|
9736
9748
|
const fromCopy = deps4.replica ? deps4.replica.answer(home, name, args2, offlineNote(home)) : null;
|
|
9737
9749
|
if (fromCopy) return fromCopy;
|
|
9738
9750
|
if (deps4.boards && deps4.boards.BOARD_OPS.indexOf(name) !== -1) return opBoard(home, callerSid5, name, args2);
|
|
9739
|
-
if (QUEUED_OPS.includes(name)) return opQueued(home, callerSid5, name, args2);
|
|
9751
|
+
if (QUEUED_OPS.includes(name)) return whenUnlocked(home, name, () => opQueued(home, callerSid5, name, args2));
|
|
9740
9752
|
return needsServer(name ? `"${name}"` : "That call");
|
|
9741
9753
|
}
|
|
9742
9754
|
}
|
|
@@ -10249,6 +10261,10 @@ ${mid}` : "";
|
|
|
10249
10261
|
handle: handle4,
|
|
10250
10262
|
handleLocal,
|
|
10251
10263
|
handleFollower,
|
|
10264
|
+
/** handleFollower, waiting out another process's journal lock (whenUnlocked): the twins' follower.op. */
|
|
10265
|
+
handleFollowerWaiting: (home, req) => whenUnlocked(home, String(req.op ?? ""), () => handleFollower(home, req)),
|
|
10266
|
+
/** noteSession, waiting out another process's journal lock (whenUnlocked): the twins' host ask. */
|
|
10267
|
+
noteSessionWaiting: (home, rec3, opId, by) => whenUnlocked(home, "session", () => noteSession(home, rec3, opId, by)),
|
|
10252
10268
|
pendingFor,
|
|
10253
10269
|
journalStats,
|
|
10254
10270
|
onResult,
|
|
@@ -78788,7 +78804,7 @@ function dispatchCommand(ws, id, cmd) {
|
|
|
78788
78804
|
case 'follower.sessions': return cmdFollowerSessions(ws, id);
|
|
78789
78805
|
case 'follower.send': return daemonCommands.run(function () { return cmdFollowerSend(ws, id, cmd); });
|
|
78790
78806
|
case 'follower.permission': return daemonCommands.run(function () { return cmdFollowerPermission(ws, id, cmd); });
|
|
78791
|
-
case 'follower.op': return cmdFollowerOp(ws, id, cmd);
|
|
78807
|
+
case 'follower.op': return daemonCommands.run(function () { return cmdFollowerOp(ws, id, cmd); });
|
|
78792
78808
|
case 'follower.pending': return cmdFollowerPending(ws, id, cmd);
|
|
78793
78809
|
// A new ask while the Mac is away ('replica-start-v1', WP12). Twin of daemon-standalone.ts.
|
|
78794
78810
|
case 'follower.start': return daemonCommands.run(function () { return cmdFollowerStart(ws, id, cmd); });
|
|
@@ -80202,14 +80218,15 @@ async function cmdFollowerPermission(ws, id, cmd) {
|
|
|
80202
80218
|
// The replica's write while the Mac is away (replica-ops-v1, journal v2). Its own gate:
|
|
80203
80219
|
// the follower's own Walnut, the quiet window unless the Mac is still taking the
|
|
80204
80220
|
// journal, and the daemon dir's owner. Twin of daemon-standalone.ts cmdFollowerOp.
|
|
80205
|
-
function cmdFollowerOp(ws, id, cmd) {
|
|
80221
|
+
async function cmdFollowerOp(ws, id, cmd) {
|
|
80206
80222
|
var home = followerHomeOf(ws);
|
|
80207
80223
|
if (!home) return sendError(ws, id, 'follower.op: send follower.hello first');
|
|
80208
80224
|
if (!followerMayWrite(home)) return sendError(ws, id, 'follower.op: your Mac answers again; write through it', { errorKind: 'leader_answers' });
|
|
80209
80225
|
if (!ownsDaemonDir()) {
|
|
80210
80226
|
return sendError(ws, id, 'follower.op: this daemon no longer owns its directory', { errorKind: 'journal_unwritable', detail: { why: 'not_owner' } });
|
|
80211
80227
|
}
|
|
80212
|
-
|
|
80228
|
+
// Waits out another process's journal lock (about 1.3 s) before it answers.
|
|
80229
|
+
var r = await offlineHost.handleFollowerWaiting(home, { op: cmd.op, args: cmd.args, actor: cmd.actor, opId: cmd.opId, base: cmd.base });
|
|
80213
80230
|
if (r.ok) return sendOk(ws, id, r.result);
|
|
80214
80231
|
sendError(ws, id, 'follower.op: ' + r.error.message, Object.assign({ errorKind: r.error.code },
|
|
80215
80232
|
r.error.detail !== undefined ? { detail: r.error.detail } : {}, r.error.retryAfterMs !== undefined ? { retryAfterMs: r.error.retryAfterMs } : {}));
|
|
@@ -80359,7 +80376,7 @@ async function startHostAsk(home, p, cmd) {
|
|
|
80359
80376
|
throw err;
|
|
80360
80377
|
}
|
|
80361
80378
|
if (DIE_AFTER_ASK_SPAWN) process.kill(process.pid, 'SIGKILL');
|
|
80362
|
-
var saved = offlineHost.
|
|
80379
|
+
var saved = await offlineHost.noteSessionWaiting(home, p.record, opId, cmd.actor);
|
|
80363
80380
|
hostStart.releasePending(home, p.sid);
|
|
80364
80381
|
if (!saved.ok) {
|
|
80365
80382
|
// Nothing would tell the Mac about this CLI: it must not run unseen. Not stamped as an
|
|
@@ -122881,10 +122898,13 @@ async function cleanupLaneClaudeMd(homeDir2 = WALNUT_HOME) {
|
|
|
122881
122898
|
}
|
|
122882
122899
|
}
|
|
122883
122900
|
async function buildLaneProfile(config, agentId, opts2) {
|
|
122884
|
-
const
|
|
122885
|
-
const
|
|
122901
|
+
const persona = opts2?.persona;
|
|
122902
|
+
const skillsIndex = persona ? "" : await buildSessionSkillsPrompt().catch(() => "");
|
|
122903
|
+
const memoryContext = persona ? "" : await buildLaneMemoryContext().catch(() => "");
|
|
122886
122904
|
let profile;
|
|
122887
|
-
if (
|
|
122905
|
+
if (persona) {
|
|
122906
|
+
profile = mergeProfiles({ systemPrompt: persona.systemPrompt, systemPromptMode: persona.systemPromptMode }, walnutMcpProfile());
|
|
122907
|
+
} else if (agentId === "general") {
|
|
122888
122908
|
profile = personalAiProfile(config.user?.name ?? "the user", skillsIndex, memoryContext);
|
|
122889
122909
|
} else {
|
|
122890
122910
|
const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports));
|
|
@@ -122894,7 +122914,8 @@ async function buildLaneProfile(config, agentId, opts2) {
|
|
|
122894
122914
|
const contextBlock = await loadContextSources2(agentDef, {}).catch(() => "");
|
|
122895
122915
|
profile = consoleAgentProfile(agentDef, skillsIndex, contextBlock);
|
|
122896
122916
|
}
|
|
122897
|
-
const
|
|
122917
|
+
const personaEffort = persona?.effort && LANE_EFFORTS.has(persona.effort) ? persona.effort : void 0;
|
|
122918
|
+
const effort = personaEffort ?? config.agent?.session_effort ?? "medium";
|
|
122898
122919
|
if (!opts2?.conversationId) return { profile, effort };
|
|
122899
122920
|
const base = profile.systemPrompt ?? "";
|
|
122900
122921
|
const headroom = MAX_LANE_PROMPT_BYTES - Buffer.byteLength(base, "utf-8") - LANE_SEED_RESERVE_BYTES;
|
|
@@ -123164,7 +123185,7 @@ async function resolveLane(lane, agentId, conversationId, firstMessage, engine)
|
|
|
123164
123185
|
});
|
|
123165
123186
|
return { sessionId, created: true, engine: "claude" };
|
|
123166
123187
|
}
|
|
123167
|
-
var inFlight7, 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;
|
|
123188
|
+
var LANE_EFFORTS, inFlight7, 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;
|
|
123168
123189
|
var init_personal_ai_lane = __esm({
|
|
123169
123190
|
"src/core/sessions/personal-ai-lane.ts"() {
|
|
123170
123191
|
"use strict";
|
|
@@ -123179,6 +123200,7 @@ var init_personal_ai_lane = __esm({
|
|
|
123179
123200
|
init_default_engine();
|
|
123180
123201
|
init_ask_profile_prefix();
|
|
123181
123202
|
init_logging();
|
|
123203
|
+
LANE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
123182
123204
|
inFlight7 = /* @__PURE__ */ new Map();
|
|
123183
123205
|
LANE_MEMORY_HEADER = "## Standing memory (injected by Walnut)";
|
|
123184
123206
|
MANAGED_LANE_CONTEXT_MARKERS = [
|
|
@@ -139289,8 +139311,9 @@ async function buildCopyManifest(kind) {
|
|
|
139289
139311
|
}
|
|
139290
139312
|
return manifest;
|
|
139291
139313
|
}
|
|
139292
|
-
function keepsCopiesTarget(t3) {
|
|
139293
|
-
|
|
139314
|
+
function keepsCopiesTarget(t3, kind) {
|
|
139315
|
+
if (t3.kind === "host") return t3.program?.() === "replica";
|
|
139316
|
+
return t3.kind === "companion" && (kind === void 0 || COMPANION_COPY_KINDS.has(kind));
|
|
139294
139317
|
}
|
|
139295
139318
|
function manifestDigest(manifest, ordered = false) {
|
|
139296
139319
|
let d8 = manifestDigests.get(manifest);
|
|
@@ -139404,7 +139427,7 @@ async function choiceOf(target2) {
|
|
|
139404
139427
|
}
|
|
139405
139428
|
async function syncCopyKinds(kinds, deps4 = {}) {
|
|
139406
139429
|
const now = deps4.now ?? Date.now;
|
|
139407
|
-
const all = (deps4.targets ?? await defaultTargets())().filter(keepsCopiesTarget);
|
|
139430
|
+
const all = (deps4.targets ?? await defaultTargets())().filter((t3) => kinds.some((k8) => keepsCopiesTarget(t3, k8.kind)));
|
|
139408
139431
|
const ready2 = [];
|
|
139409
139432
|
for (const target2 of all) if (await target2.available()) ready2.push({ target: target2, choice: await choiceOf(target2) });
|
|
139410
139433
|
const results = [];
|
|
@@ -139412,7 +139435,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
139412
139435
|
const asOf2 = now();
|
|
139413
139436
|
const manifests = /* @__PURE__ */ new Map();
|
|
139414
139437
|
for (const kind of kinds) {
|
|
139415
|
-
if (!ready2.some((r8) => r8.choice[kind.choice])) continue;
|
|
139438
|
+
if (!ready2.some((r8) => r8.choice[kind.choice] && keepsCopiesTarget(r8.target, kind.kind))) continue;
|
|
139416
139439
|
try {
|
|
139417
139440
|
manifests.set(kind.kind, await buildCopyManifest(kind));
|
|
139418
139441
|
} catch (err2) {
|
|
@@ -139421,6 +139444,7 @@ async function syncCopyKinds(kinds, deps4 = {}) {
|
|
|
139421
139444
|
}
|
|
139422
139445
|
for (const { target: target2, choice } of ready2) {
|
|
139423
139446
|
for (const kind of kinds) {
|
|
139447
|
+
if (!keepsCopiesTarget(target2, kind.kind)) continue;
|
|
139424
139448
|
const manifest = manifests.get(kind.kind);
|
|
139425
139449
|
const st2 = kindState(target2, kind.kind);
|
|
139426
139450
|
if (!choice[kind.choice]) {
|
|
@@ -139466,7 +139490,7 @@ async function purgeKind(kind, target2, st2) {
|
|
|
139466
139490
|
async function confirmCopyKindRemoval(targetId, kind, opts2 = {}) {
|
|
139467
139491
|
const { replicaTargets: replicaTargets2 } = await Promise.resolve().then(() => (init_replica_targets(), replica_targets_exports));
|
|
139468
139492
|
const target2 = replicaTargets2().find((t3) => t3.id === targetId);
|
|
139469
|
-
if (!target2 || target2
|
|
139493
|
+
if (!target2 || !keepsCopiesTarget(target2, kind) || !peekKindState(targetId, kind)) return false;
|
|
139470
139494
|
if (!confirmKindRemoval(target2, kind, opts2)) return false;
|
|
139471
139495
|
log.session.warn("copies: the user confirmed a removal of most rows", { target: targetId, kind, entries: peekKindState(targetId, kind)?.confirmFor?.entries });
|
|
139472
139496
|
copySoon(kind);
|
|
@@ -139581,6 +139605,7 @@ var init_copy_kind = __esm({
|
|
|
139581
139605
|
init_kind_leader();
|
|
139582
139606
|
init_search_digest();
|
|
139583
139607
|
init_replica_status();
|
|
139608
|
+
init_gate();
|
|
139584
139609
|
COPY_DEBOUNCE_MS = 3e3;
|
|
139585
139610
|
COPY_SWEEP_MS = 5 * 6e4;
|
|
139586
139611
|
COPY_FIRST_ROUND_MS = 15e3;
|
|
@@ -162196,6 +162221,7 @@ var init_routines = __esm({
|
|
|
162196
162221
|
var routines_follower_exports = {};
|
|
162197
162222
|
__export(routines_follower_exports, {
|
|
162198
162223
|
_resetRoutinesCopyForTesting: () => _resetRoutinesCopyForTesting,
|
|
162224
|
+
companionRoutinesCopy: () => companionRoutinesCopy,
|
|
162199
162225
|
readRoutinesCopy: () => readRoutinesCopy,
|
|
162200
162226
|
routinesFollower: () => routinesFollower
|
|
162201
162227
|
});
|
|
@@ -162291,6 +162317,10 @@ async function readRoutinesCopy(opts2 = {}) {
|
|
|
162291
162317
|
const shown = opts2.includeDisabled ? all : all.filter((j8) => j8.enabled);
|
|
162292
162318
|
return shown.sort((a8, b8) => (a8.state.nextRunAtMs ?? 0) - (b8.state.nextRunAtMs ?? 0));
|
|
162293
162319
|
}
|
|
162320
|
+
async function companionRoutinesCopy(opts2 = {}) {
|
|
162321
|
+
if (!await copyKindHeld("routines")) return null;
|
|
162322
|
+
return await readRoutinesCopy(opts2) ?? [];
|
|
162323
|
+
}
|
|
162294
162324
|
function _resetRoutinesCopyForTesting() {
|
|
162295
162325
|
io3 = copyStateIo("routines");
|
|
162296
162326
|
serial3 = serialChain();
|
|
@@ -162306,8 +162336,8 @@ var init_routines_follower = __esm({
|
|
|
162306
162336
|
init_gate();
|
|
162307
162337
|
init_state_io();
|
|
162308
162338
|
init_routines();
|
|
162309
|
-
jobsFile = () => CRON_FILE;
|
|
162310
|
-
statesFile = () => path120.join(path120.dirname(CRON_FILE), "cron-state.json");
|
|
162339
|
+
jobsFile = () => copyPath(CRON_FILE);
|
|
162340
|
+
statesFile = () => copyPath(path120.join(path120.dirname(CRON_FILE), "cron-state.json"));
|
|
162311
162341
|
io3 = copyStateIo("routines");
|
|
162312
162342
|
serial3 = serialChain();
|
|
162313
162343
|
follower2 = null;
|
|
@@ -178645,8 +178675,8 @@ import path137 from "path";
|
|
|
178645
178675
|
import { fileURLToPath as fileURLToPath10 } from "url";
|
|
178646
178676
|
function getVersion() {
|
|
178647
178677
|
if (cachedVersion) return cachedVersion;
|
|
178648
|
-
if ("0.6.
|
|
178649
|
-
cachedVersion = "0.6.
|
|
178678
|
+
if ("0.6.17") {
|
|
178679
|
+
cachedVersion = "0.6.17";
|
|
178650
178680
|
versionKnown = true;
|
|
178651
178681
|
return cachedVersion;
|
|
178652
178682
|
}
|
|
@@ -202063,6 +202093,132 @@ var init_agent_turn_queue = __esm({
|
|
|
202063
202093
|
}
|
|
202064
202094
|
});
|
|
202065
202095
|
|
|
202096
|
+
// src/core/replication/kinds/personas.ts
|
|
202097
|
+
var personas_exports = {};
|
|
202098
|
+
__export(personas_exports, {
|
|
202099
|
+
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
202100
|
+
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
202101
|
+
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
202102
|
+
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
202103
|
+
personasFollower: () => personasFollower,
|
|
202104
|
+
readPersonaCopy: () => readPersonaCopy
|
|
202105
|
+
});
|
|
202106
|
+
function tools(v3) {
|
|
202107
|
+
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
202108
|
+
}
|
|
202109
|
+
async function leaderRows() {
|
|
202110
|
+
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
202111
|
+
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
202112
|
+
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
202113
|
+
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
202114
|
+
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
202115
|
+
]);
|
|
202116
|
+
const config = await getConfig2();
|
|
202117
|
+
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
202118
|
+
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
202119
|
+
const rows = [];
|
|
202120
|
+
for (const a8 of agents) {
|
|
202121
|
+
if (!ID_RE.test(a8.id)) continue;
|
|
202122
|
+
try {
|
|
202123
|
+
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
202124
|
+
const prompt = profile.systemPrompt ?? "";
|
|
202125
|
+
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
202126
|
+
rows.push({
|
|
202127
|
+
key: a8.id,
|
|
202128
|
+
agentId: a8.id,
|
|
202129
|
+
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
202130
|
+
systemPrompt: prompt,
|
|
202131
|
+
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
202132
|
+
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
202133
|
+
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
202134
|
+
...effort ? { effort } : {},
|
|
202135
|
+
...launch.model ? { launchModel: launch.model } : {},
|
|
202136
|
+
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
202137
|
+
});
|
|
202138
|
+
} catch (err2) {
|
|
202139
|
+
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
202140
|
+
}
|
|
202141
|
+
}
|
|
202142
|
+
return rows;
|
|
202143
|
+
}
|
|
202144
|
+
function hashOf3(row) {
|
|
202145
|
+
let h8 = hashes3.get(row);
|
|
202146
|
+
if (h8 === void 0) {
|
|
202147
|
+
h8 = sha12(JSON.stringify(row));
|
|
202148
|
+
hashes3.set(row, h8);
|
|
202149
|
+
}
|
|
202150
|
+
return h8;
|
|
202151
|
+
}
|
|
202152
|
+
function isRow3(v3) {
|
|
202153
|
+
const r8 = v3;
|
|
202154
|
+
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
202155
|
+
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
202156
|
+
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE.test(r8.key) || typeof r8.name !== "string") return false;
|
|
202157
|
+
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
202158
|
+
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
202159
|
+
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
202160
|
+
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;
|
|
202161
|
+
return true;
|
|
202162
|
+
}
|
|
202163
|
+
function admit(r8) {
|
|
202164
|
+
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
202165
|
+
}
|
|
202166
|
+
async function readPersonaCopy(agentId) {
|
|
202167
|
+
const rows = await copy.read();
|
|
202168
|
+
return rows?.[agentId] ?? null;
|
|
202169
|
+
}
|
|
202170
|
+
function _resetPersonasCopyForTesting() {
|
|
202171
|
+
copy.reset();
|
|
202172
|
+
}
|
|
202173
|
+
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE, TOOL_RE, hashes3, PERSONAS_KIND, ROW_KEYS, copy, personasFollower;
|
|
202174
|
+
var init_personas = __esm({
|
|
202175
|
+
"src/core/replication/kinds/personas.ts"() {
|
|
202176
|
+
"use strict";
|
|
202177
|
+
init_logging();
|
|
202178
|
+
init_config_allowlist();
|
|
202179
|
+
init_kind();
|
|
202180
|
+
init_file_copy();
|
|
202181
|
+
PERSONAS_SCHEMA_VERSION = 1;
|
|
202182
|
+
PERSONAS_REMOVAL_FLOOR = 0;
|
|
202183
|
+
MAX_PROMPT_BYTES = 120 * 1024;
|
|
202184
|
+
ID_RE = /^[A-Za-z0-9_-]{1,80}$/;
|
|
202185
|
+
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
202186
|
+
hashes3 = /* @__PURE__ */ new WeakMap();
|
|
202187
|
+
PERSONAS_KIND = {
|
|
202188
|
+
kind: "personas",
|
|
202189
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
202190
|
+
key: (r8) => r8.key,
|
|
202191
|
+
hash: hashOf3,
|
|
202192
|
+
ordered: false,
|
|
202193
|
+
digest: false,
|
|
202194
|
+
choice: "personas",
|
|
202195
|
+
rows: leaderRows,
|
|
202196
|
+
watch: (soon) => {
|
|
202197
|
+
let stop2 = null;
|
|
202198
|
+
let stopped2 = false;
|
|
202199
|
+
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
202200
|
+
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
202201
|
+
});
|
|
202202
|
+
return () => {
|
|
202203
|
+
stopped2 = true;
|
|
202204
|
+
stop2?.();
|
|
202205
|
+
};
|
|
202206
|
+
}
|
|
202207
|
+
};
|
|
202208
|
+
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
202209
|
+
copy = createFileCopy({
|
|
202210
|
+
kind: "personas",
|
|
202211
|
+
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
202212
|
+
label: "personas copy",
|
|
202213
|
+
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
202214
|
+
isRow: isRow3,
|
|
202215
|
+
key: (r8) => r8.key,
|
|
202216
|
+
admit
|
|
202217
|
+
});
|
|
202218
|
+
personasFollower = copy.follower;
|
|
202219
|
+
}
|
|
202220
|
+
});
|
|
202221
|
+
|
|
202066
202222
|
// src/core/sessions/cloud-chat-lane.ts
|
|
202067
202223
|
var cloud_chat_lane_exports = {};
|
|
202068
202224
|
__export(cloud_chat_lane_exports, {
|
|
@@ -202201,7 +202357,9 @@ async function resolveCloudChatLane(lane, agentId, conversationId, cwd, firstMes
|
|
|
202201
202357
|
CATCH_UP_BANNER_CLOSE: CATCH_UP_BANNER_CLOSE2,
|
|
202202
202358
|
buildConversationSeed: buildConversationSeed2
|
|
202203
202359
|
} = await Promise.resolve().then(() => (init_chat_history(), chat_history_exports));
|
|
202204
|
-
const {
|
|
202360
|
+
const { readPersonaCopy: readPersonaCopy2 } = await Promise.resolve().then(() => (init_personas(), personas_exports));
|
|
202361
|
+
const persona = await readPersonaCopy2(agentId).catch(() => null);
|
|
202362
|
+
const { profile: base, effort, seed } = await buildLaneProfile2(config, agentId, { conversationId, ...persona ? { persona } : {} });
|
|
202205
202363
|
const profile = toCloudChatProfile(base, CONVERSATION_SEED_HEADER2);
|
|
202206
202364
|
const sessionId = crypto47.randomUUID();
|
|
202207
202365
|
const seedInProfile = !!seed && (seed.text !== "" || seed.stats.turnsTotal === 0);
|
|
@@ -209746,9 +209904,9 @@ function sanitizeHealthSync(body7, now = Date.now()) {
|
|
|
209746
209904
|
const tz = isValidTz(b8.tz) ? b8.tz : "";
|
|
209747
209905
|
const spec = metricSpec(type);
|
|
209748
209906
|
const generic = isGenericType(type);
|
|
209749
|
-
const storeId = typeof b8.storeId === "string" &&
|
|
209907
|
+
const storeId = typeof b8.storeId === "string" && ID_RE2.test(b8.storeId) ? b8.storeId : void 0;
|
|
209750
209908
|
const dev = b8.device && typeof b8.device === "object" ? b8.device : {};
|
|
209751
|
-
const installId = typeof dev.installId === "string" &&
|
|
209909
|
+
const installId = typeof dev.installId === "string" && ID_RE2.test(dev.installId) ? dev.installId : void 0;
|
|
209752
209910
|
const device = { installId, model: str10(dev.model, 64), os: str10(dev.os, 64) };
|
|
209753
209911
|
const hasDevice = Object.values(device).some((v3) => v3 !== void 0);
|
|
209754
209912
|
const deleted = [...new Set(deletedIn.filter((u3) => typeof u3 === "string" && UUID_RE3.test(u3)))];
|
|
@@ -209816,14 +209974,14 @@ function relayPayload(batch) {
|
|
|
209816
209974
|
samples: batch.samples.map(({ tz, ...rest }) => tz === batch.tz ? rest : { ...rest, tz })
|
|
209817
209975
|
};
|
|
209818
209976
|
}
|
|
209819
|
-
var UUID_RE3,
|
|
209977
|
+
var UUID_RE3, ID_RE2, MIN_INSTANT, FUTURE_SLACK_MS2, MAX_SPAN_MS;
|
|
209820
209978
|
var init_sanitize = __esm({
|
|
209821
209979
|
"src/core/health/sanitize.ts"() {
|
|
209822
209980
|
"use strict";
|
|
209823
209981
|
init_catalog();
|
|
209824
209982
|
init_day_key();
|
|
209825
209983
|
UUID_RE3 = /^[A-Za-z0-9][A-Za-z0-9-]{0,63}$/;
|
|
209826
|
-
|
|
209984
|
+
ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/;
|
|
209827
209985
|
MIN_INSTANT = Date.UTC(2010, 0, 1);
|
|
209828
209986
|
FUTURE_SLACK_MS2 = 36 * 36e5;
|
|
209829
209987
|
MAX_SPAN_MS = 2 * 864e5;
|
|
@@ -225310,7 +225468,7 @@ function prefAdmissible(p6) {
|
|
|
225310
225468
|
function strings(v3) {
|
|
225311
225469
|
return Array.isArray(v3) ? v3.filter((x3) => typeof x3 === "string") : [];
|
|
225312
225470
|
}
|
|
225313
|
-
async function
|
|
225471
|
+
async function leaderRows2() {
|
|
225314
225472
|
const raw = await readJsonFile(UI_PREFS_FILE, {}, { readErrors: "throw" });
|
|
225315
225473
|
const rows = [];
|
|
225316
225474
|
for (const [k8, v3] of Object.entries(raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {})) {
|
|
@@ -225322,15 +225480,15 @@ async function leaderRows() {
|
|
|
225322
225480
|
rows.push({ key: "favorites", favorites: { projects: strings(fav?.projects), notes: strings(fav?.notes) } });
|
|
225323
225481
|
return rows;
|
|
225324
225482
|
}
|
|
225325
|
-
function
|
|
225326
|
-
let h8 =
|
|
225483
|
+
function hashOf4(row) {
|
|
225484
|
+
let h8 = hashes4.get(row);
|
|
225327
225485
|
if (h8 === void 0) {
|
|
225328
225486
|
h8 = sha12(JSON.stringify(row));
|
|
225329
|
-
|
|
225487
|
+
hashes4.set(row, h8);
|
|
225330
225488
|
}
|
|
225331
225489
|
return h8;
|
|
225332
225490
|
}
|
|
225333
|
-
function
|
|
225491
|
+
function isRow4(v3) {
|
|
225334
225492
|
const r8 = v3;
|
|
225335
225493
|
if (!r8 || typeof r8 !== "object" || typeof r8.key !== "string") return false;
|
|
225336
225494
|
if (r8.key === "favorites") {
|
|
@@ -225340,27 +225498,27 @@ function isRow3(v3) {
|
|
|
225340
225498
|
const p6 = prefOf(r8.pref);
|
|
225341
225499
|
return Object.keys(r8).length === 2 && r8.key.startsWith(UI) && copyableUiPrefKey(r8.key.slice(UI.length)) && !!p6 && typeof r8.pref === "object";
|
|
225342
225500
|
}
|
|
225343
|
-
function
|
|
225501
|
+
function admit2(r8) {
|
|
225344
225502
|
if ("favorites" in r8) return [...r8.favorites.projects, ...r8.favorites.notes].every((s4) => typeof s4 === "string" && secretShapedValue(s4) === null);
|
|
225345
225503
|
return prefAdmissible(r8.pref);
|
|
225346
225504
|
}
|
|
225347
225505
|
async function readUiPrefsCopy() {
|
|
225348
|
-
const rows = await
|
|
225506
|
+
const rows = await copy2.read();
|
|
225349
225507
|
if (!rows) return null;
|
|
225350
225508
|
const out = {};
|
|
225351
225509
|
for (const r8 of Object.values(rows)) if ("pref" in r8) out[r8.key.slice(UI.length)] = r8.pref;
|
|
225352
225510
|
return out;
|
|
225353
225511
|
}
|
|
225354
225512
|
async function readFavoritesCopy() {
|
|
225355
|
-
const rows = await
|
|
225513
|
+
const rows = await copy2.read();
|
|
225356
225514
|
if (!rows) return null;
|
|
225357
225515
|
const f8 = rows.favorites;
|
|
225358
225516
|
return f8 && "favorites" in f8 ? f8.favorites : { projects: [], notes: [] };
|
|
225359
225517
|
}
|
|
225360
225518
|
function _resetPrefsCopyForTesting() {
|
|
225361
|
-
|
|
225519
|
+
copy2.reset();
|
|
225362
225520
|
}
|
|
225363
|
-
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2,
|
|
225521
|
+
var PREFS_SCHEMA_VERSION, PREFS_REMOVAL_FLOOR, UI, MAX_VALUE_LEN2, hashes4, PREFS_KIND, copy2, prefsFollower;
|
|
225364
225522
|
var init_prefs = __esm({
|
|
225365
225523
|
"src/core/replication/kinds/prefs.ts"() {
|
|
225366
225524
|
"use strict";
|
|
@@ -225374,16 +225532,16 @@ var init_prefs = __esm({
|
|
|
225374
225532
|
PREFS_REMOVAL_FLOOR = 0;
|
|
225375
225533
|
UI = "ui:";
|
|
225376
225534
|
MAX_VALUE_LEN2 = 8 * 1024;
|
|
225377
|
-
|
|
225535
|
+
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
225378
225536
|
PREFS_KIND = {
|
|
225379
225537
|
kind: "prefs",
|
|
225380
225538
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
225381
225539
|
key: (r8) => r8.key,
|
|
225382
|
-
hash:
|
|
225540
|
+
hash: hashOf4,
|
|
225383
225541
|
ordered: false,
|
|
225384
225542
|
digest: false,
|
|
225385
225543
|
choice: "prefs",
|
|
225386
|
-
rows:
|
|
225544
|
+
rows: leaderRows2,
|
|
225387
225545
|
watch: (soon) => {
|
|
225388
225546
|
const stops = [];
|
|
225389
225547
|
let stopped2 = false;
|
|
@@ -225396,16 +225554,16 @@ var init_prefs = __esm({
|
|
|
225396
225554
|
};
|
|
225397
225555
|
}
|
|
225398
225556
|
};
|
|
225399
|
-
|
|
225557
|
+
copy2 = createFileCopy({
|
|
225400
225558
|
kind: "prefs",
|
|
225401
225559
|
schemaVersion: PREFS_SCHEMA_VERSION,
|
|
225402
225560
|
label: "prefs copy",
|
|
225403
225561
|
removalFloor: PREFS_REMOVAL_FLOOR,
|
|
225404
|
-
isRow:
|
|
225562
|
+
isRow: isRow4,
|
|
225405
225563
|
key: (r8) => r8.key,
|
|
225406
|
-
admit
|
|
225564
|
+
admit: admit2
|
|
225407
225565
|
});
|
|
225408
|
-
prefsFollower =
|
|
225566
|
+
prefsFollower = copy2.follower;
|
|
225409
225567
|
}
|
|
225410
225568
|
});
|
|
225411
225569
|
|
|
@@ -226140,7 +226298,7 @@ async function adoptDeviceRecord(input, opts2 = {}) {
|
|
|
226140
226298
|
const existing = devices.find((d8) => d8.tokenHash === tokenHash);
|
|
226141
226299
|
if (existing) return { result: { name: existing.name, adopted: false } };
|
|
226142
226300
|
const finalName = freeName(devices, name);
|
|
226143
|
-
const wanted = typeof input.id === "string" &&
|
|
226301
|
+
const wanted = typeof input.id === "string" && ID_RE3.test(input.id) ? input.id : void 0;
|
|
226144
226302
|
const idFree = wanted !== void 0 && !devices.some((d8) => d8.id === wanted || d8.ownerId === wanted);
|
|
226145
226303
|
const record2 = {
|
|
226146
226304
|
name: finalName,
|
|
@@ -226175,7 +226333,7 @@ async function revokeAdopted(tokenHash) {
|
|
|
226175
226333
|
if (out.revoked) log.web.info("device-adoption: twin pairing revoked", { name: record2.name, adoptedFrom: record2.adoptedFrom ?? null });
|
|
226176
226334
|
return out.revoked ? { name: record2.name, refused: false, push: out.push } : { name: null, refused: false, push: null };
|
|
226177
226335
|
}
|
|
226178
|
-
var AdoptionError, HASH_RE,
|
|
226336
|
+
var AdoptionError, HASH_RE, ID_RE3, INFO_FIELD_MAX2, NAME_MAX;
|
|
226179
226337
|
var init_device_adoption = __esm({
|
|
226180
226338
|
"src/core/device-adoption.ts"() {
|
|
226181
226339
|
"use strict";
|
|
@@ -226193,7 +226351,7 @@ var init_device_adoption = __esm({
|
|
|
226193
226351
|
}
|
|
226194
226352
|
};
|
|
226195
226353
|
HASH_RE = /^[0-9a-f]{64}$/;
|
|
226196
|
-
|
|
226354
|
+
ID_RE3 = /^d[0-9a-f]{16}$/;
|
|
226197
226355
|
INFO_FIELD_MAX2 = 120;
|
|
226198
226356
|
NAME_MAX = 64;
|
|
226199
226357
|
}
|
|
@@ -245454,7 +245612,7 @@ import crypto64 from "crypto";
|
|
|
245454
245612
|
import fs121 from "fs";
|
|
245455
245613
|
import path225 from "path";
|
|
245456
245614
|
function isDeviceCopyId(id) {
|
|
245457
|
-
return typeof id === "string" &&
|
|
245615
|
+
return typeof id === "string" && ID_RE4.test(id);
|
|
245458
245616
|
}
|
|
245459
245617
|
function sha256Hex2(text5) {
|
|
245460
245618
|
return crypto64.createHash("sha256").update(text5, "utf-8").digest("hex");
|
|
@@ -245544,14 +245702,14 @@ function createDeviceCopy(file) {
|
|
|
245544
245702
|
}
|
|
245545
245703
|
};
|
|
245546
245704
|
}
|
|
245547
|
-
var HASH_RE2, NAME_MAX2, MAX_DEVICES,
|
|
245705
|
+
var HASH_RE2, NAME_MAX2, MAX_DEVICES, ID_RE4;
|
|
245548
245706
|
var init_device_copy = __esm({
|
|
245549
245707
|
"src/host-server/device-copy.ts"() {
|
|
245550
245708
|
"use strict";
|
|
245551
245709
|
HASH_RE2 = /^[0-9a-f]{64}$/;
|
|
245552
245710
|
NAME_MAX2 = 64;
|
|
245553
245711
|
MAX_DEVICES = 500;
|
|
245554
|
-
|
|
245712
|
+
ID_RE4 = /^[A-Za-z0-9._:-]{1,80}$/;
|
|
245555
245713
|
}
|
|
245556
245714
|
});
|
|
245557
245715
|
|
|
@@ -245572,11 +245730,11 @@ function replicaDeviceCopyFile(home = WALNUT_HOME) {
|
|
|
245572
245730
|
return path226.join(home, "replica", "devices.json");
|
|
245573
245731
|
}
|
|
245574
245732
|
function replicaDeviceCopy() {
|
|
245575
|
-
|
|
245576
|
-
return
|
|
245733
|
+
copy3 ??= createDeviceCopy(replicaDeviceCopyFile());
|
|
245734
|
+
return copy3;
|
|
245577
245735
|
}
|
|
245578
245736
|
function _resetReplicaAuthForTesting() {
|
|
245579
|
-
|
|
245737
|
+
copy3 = null;
|
|
245580
245738
|
}
|
|
245581
245739
|
function verifyReplicaToken(token) {
|
|
245582
245740
|
const name = replicaDeviceCopy().verify(token);
|
|
@@ -245619,14 +245777,14 @@ async function replicaAuthMiddleware(req, res, next) {
|
|
|
245619
245777
|
req.deviceName = cred.name;
|
|
245620
245778
|
next();
|
|
245621
245779
|
}
|
|
245622
|
-
var
|
|
245780
|
+
var copy3, PUBLIC_GET_PATHS, REPLICA_FAILURE_KEY;
|
|
245623
245781
|
var init_auth11 = __esm({
|
|
245624
245782
|
"src/replica/auth.ts"() {
|
|
245625
245783
|
"use strict";
|
|
245626
245784
|
init_constants();
|
|
245627
245785
|
init_device_copy();
|
|
245628
245786
|
init_logging();
|
|
245629
|
-
|
|
245787
|
+
copy3 = null;
|
|
245630
245788
|
PUBLIC_GET_PATHS = /* @__PURE__ */ new Set(["/v1/instance"]);
|
|
245631
245789
|
REPLICA_FAILURE_KEY = "host-replica";
|
|
245632
245790
|
}
|
|
@@ -252671,7 +252829,7 @@ async function saveRecordingAudio(audioBase64, format2) {
|
|
|
252671
252829
|
return { id, audioPath };
|
|
252672
252830
|
}
|
|
252673
252831
|
async function writeRecordingResult(id, meta) {
|
|
252674
|
-
if (!
|
|
252832
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
252675
252833
|
await mkdir7(dir3(), { recursive: true });
|
|
252676
252834
|
const stamped = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...meta };
|
|
252677
252835
|
await writeFile6(join16(dir3(), `${id}.json`), JSON.stringify(stamped, null, 2));
|
|
@@ -252680,7 +252838,7 @@ async function writeRecordingResult(id, meta) {
|
|
|
252680
252838
|
return stamped.timestamp;
|
|
252681
252839
|
}
|
|
252682
252840
|
async function writeRecordingSecondary(id, secondary, expectTimestamp) {
|
|
252683
|
-
if (!
|
|
252841
|
+
if (!ID_RE5.test(id)) throw new Error(`Invalid recording id: ${id}`);
|
|
252684
252842
|
const path305 = join16(dir3(), `${id}.json`);
|
|
252685
252843
|
let existing;
|
|
252686
252844
|
try {
|
|
@@ -252702,7 +252860,7 @@ async function listRecordings(limit = 20) {
|
|
|
252702
252860
|
const out = [];
|
|
252703
252861
|
for (const jf of jsonFiles) {
|
|
252704
252862
|
const id = jf.slice(0, -5);
|
|
252705
|
-
if (!
|
|
252863
|
+
if (!ID_RE5.test(id)) continue;
|
|
252706
252864
|
try {
|
|
252707
252865
|
const raw = JSON.parse(await readFile8(join16(dir3(), jf), "utf-8"));
|
|
252708
252866
|
out.push({
|
|
@@ -252722,7 +252880,7 @@ async function listRecordings(limit = 20) {
|
|
|
252722
252880
|
return out;
|
|
252723
252881
|
}
|
|
252724
252882
|
async function readRecordingAudio(id) {
|
|
252725
|
-
if (!
|
|
252883
|
+
if (!ID_RE5.test(id)) return null;
|
|
252726
252884
|
let files;
|
|
252727
252885
|
try {
|
|
252728
252886
|
files = await readdir3(dir3());
|
|
@@ -252750,13 +252908,13 @@ async function pruneOldRecordings() {
|
|
|
252750
252908
|
}
|
|
252751
252909
|
}
|
|
252752
252910
|
}
|
|
252753
|
-
var MAX_RECORDINGS,
|
|
252911
|
+
var MAX_RECORDINGS, ID_RE5, AUDIO_EXTS;
|
|
252754
252912
|
var init_recordings = __esm({
|
|
252755
252913
|
"src/core/stt/recordings.ts"() {
|
|
252756
252914
|
"use strict";
|
|
252757
252915
|
init_constants();
|
|
252758
252916
|
MAX_RECORDINGS = 100;
|
|
252759
|
-
|
|
252917
|
+
ID_RE5 = /^[0-9A-Za-z-]+$/;
|
|
252760
252918
|
AUDIO_EXTS = ["webm", "mp4", "ogg", "wav", "mp3", "m4a", "flac"];
|
|
252761
252919
|
}
|
|
252762
252920
|
});
|
|
@@ -258872,6 +259030,147 @@ var init_task_v1 = __esm({
|
|
|
258872
259030
|
}
|
|
258873
259031
|
});
|
|
258874
259032
|
|
|
259033
|
+
// src/core/replication/kinds/requests.ts
|
|
259034
|
+
var requests_exports = {};
|
|
259035
|
+
__export(requests_exports, {
|
|
259036
|
+
REQUESTS_KIND: () => REQUESTS_KIND,
|
|
259037
|
+
REQUESTS_REMOVAL_FLOOR: () => REQUESTS_REMOVAL_FLOOR,
|
|
259038
|
+
REQUESTS_SCHEMA_VERSION: () => REQUESTS_SCHEMA_VERSION,
|
|
259039
|
+
_resetRequestsCopyForTesting: () => _resetRequestsCopyForTesting,
|
|
259040
|
+
forwardRequest: () => forwardRequest,
|
|
259041
|
+
readRequestCopy: () => readRequestCopy,
|
|
259042
|
+
requestsFollower: () => requestsFollower
|
|
259043
|
+
});
|
|
259044
|
+
import fsp123 from "fs/promises";
|
|
259045
|
+
import path236 from "path";
|
|
259046
|
+
function forwardRequest(local, incoming) {
|
|
259047
|
+
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
259048
|
+
return incoming;
|
|
259049
|
+
}
|
|
259050
|
+
function hashOf5(row) {
|
|
259051
|
+
let h8 = hashes5.get(row);
|
|
259052
|
+
if (h8 === void 0) {
|
|
259053
|
+
h8 = sha12(JSON.stringify(row));
|
|
259054
|
+
hashes5.set(row, h8);
|
|
259055
|
+
}
|
|
259056
|
+
return h8;
|
|
259057
|
+
}
|
|
259058
|
+
async function load6() {
|
|
259059
|
+
if (state11) return state11;
|
|
259060
|
+
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
259061
|
+
try {
|
|
259062
|
+
const raw = JSON.parse(await fsp123.readFile(STATE_FILE(), "utf8"));
|
|
259063
|
+
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 };
|
|
259064
|
+
} catch {
|
|
259065
|
+
}
|
|
259066
|
+
state11 = s4;
|
|
259067
|
+
return s4;
|
|
259068
|
+
}
|
|
259069
|
+
async function save() {
|
|
259070
|
+
if (state11) await writeCopyFile(STATE_FILE(), { v: 1, asOf: state11.asOf, at: state11.at, hashes: state11.hashes });
|
|
259071
|
+
}
|
|
259072
|
+
async function readStore7() {
|
|
259073
|
+
try {
|
|
259074
|
+
const raw = JSON.parse(await fsp123.readFile(STORE_FILE(), "utf8"));
|
|
259075
|
+
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
259076
|
+
} catch {
|
|
259077
|
+
return [];
|
|
259078
|
+
}
|
|
259079
|
+
}
|
|
259080
|
+
function isRow5(v3) {
|
|
259081
|
+
const r8 = v3;
|
|
259082
|
+
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
259083
|
+
}
|
|
259084
|
+
function requestsFollower() {
|
|
259085
|
+
follower3 ??= createRowSetFollower({
|
|
259086
|
+
kind: "requests",
|
|
259087
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
259088
|
+
label: "requests copy",
|
|
259089
|
+
log: log.session,
|
|
259090
|
+
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
259091
|
+
ordered: false,
|
|
259092
|
+
serial: (fn) => serial4(fn),
|
|
259093
|
+
refuse: copyRefusal,
|
|
259094
|
+
load: load6,
|
|
259095
|
+
save,
|
|
259096
|
+
isRow: isRow5,
|
|
259097
|
+
key: (r8) => r8.id,
|
|
259098
|
+
localKeys: async () => (await readStore7()).map((r8) => r8.id),
|
|
259099
|
+
apply: async ({ rows, removeIds }) => {
|
|
259100
|
+
const byId = new Map((await readStore7()).map((r8) => [r8.id, r8]));
|
|
259101
|
+
for (const id of removeIds ?? []) byId.delete(id);
|
|
259102
|
+
for (const r8 of rows ?? []) {
|
|
259103
|
+
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
259104
|
+
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 });
|
|
259105
|
+
byId.set(r8.id, kept);
|
|
259106
|
+
}
|
|
259107
|
+
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
259108
|
+
return { skipped: [] };
|
|
259109
|
+
},
|
|
259110
|
+
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
259111
|
+
changed: () => {
|
|
259112
|
+
},
|
|
259113
|
+
purge: async () => {
|
|
259114
|
+
const removed = (await readStore7()).length;
|
|
259115
|
+
await fsp123.rm(STORE_FILE(), { force: true });
|
|
259116
|
+
await markCopyOff("requests");
|
|
259117
|
+
state11 = null;
|
|
259118
|
+
return { removed };
|
|
259119
|
+
}
|
|
259120
|
+
});
|
|
259121
|
+
return follower3;
|
|
259122
|
+
}
|
|
259123
|
+
async function readRequestCopy(id) {
|
|
259124
|
+
if (!await copyKindHeld("requests")) return null;
|
|
259125
|
+
return (await readStore7()).find((r8) => r8.id === id) ?? null;
|
|
259126
|
+
}
|
|
259127
|
+
function _resetRequestsCopyForTesting() {
|
|
259128
|
+
state11 = null;
|
|
259129
|
+
follower3 = null;
|
|
259130
|
+
serial4 = serialChain();
|
|
259131
|
+
}
|
|
259132
|
+
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes5, REQUESTS_KIND, STATE_FILE, STORE_FILE, state11, serial4, follower3;
|
|
259133
|
+
var init_requests = __esm({
|
|
259134
|
+
"src/core/replication/kinds/requests.ts"() {
|
|
259135
|
+
"use strict";
|
|
259136
|
+
init_constants();
|
|
259137
|
+
init_logging();
|
|
259138
|
+
init_kind();
|
|
259139
|
+
init_kind_follower();
|
|
259140
|
+
init_gate();
|
|
259141
|
+
REQUESTS_SCHEMA_VERSION = 1;
|
|
259142
|
+
REQUESTS_REMOVAL_FLOOR = 50;
|
|
259143
|
+
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
259144
|
+
hashes5 = /* @__PURE__ */ new WeakMap();
|
|
259145
|
+
REQUESTS_KIND = {
|
|
259146
|
+
kind: "requests",
|
|
259147
|
+
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
259148
|
+
key: (r8) => r8.id,
|
|
259149
|
+
hash: hashOf5,
|
|
259150
|
+
ordered: false,
|
|
259151
|
+
digest: false,
|
|
259152
|
+
choice: "requests",
|
|
259153
|
+
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
259154
|
+
watch: (soon) => {
|
|
259155
|
+
let stop2 = null;
|
|
259156
|
+
let stopped2 = false;
|
|
259157
|
+
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
259158
|
+
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
259159
|
+
});
|
|
259160
|
+
return () => {
|
|
259161
|
+
stopped2 = true;
|
|
259162
|
+
stop2?.();
|
|
259163
|
+
};
|
|
259164
|
+
}
|
|
259165
|
+
};
|
|
259166
|
+
STATE_FILE = () => path236.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
259167
|
+
STORE_FILE = () => copyPath(path236.join(WALNUT_HOME, "session-requests.json"));
|
|
259168
|
+
state11 = null;
|
|
259169
|
+
serial4 = serialChain();
|
|
259170
|
+
follower3 = null;
|
|
259171
|
+
}
|
|
259172
|
+
});
|
|
259173
|
+
|
|
258875
259174
|
// src/web/routes/messages-v1.ts
|
|
258876
259175
|
import { Router as Router82 } from "express";
|
|
258877
259176
|
function header(req, name) {
|
|
@@ -258932,7 +259231,15 @@ var init_messages_v1 = __esm({
|
|
|
258932
259231
|
return;
|
|
258933
259232
|
}
|
|
258934
259233
|
const { getSessionRequest: getSessionRequest2 } = await Promise.resolve().then(() => (init_session_requests(), session_requests_exports));
|
|
258935
|
-
|
|
259234
|
+
let request4 = await getSessionRequest2(id);
|
|
259235
|
+
if (!request4) {
|
|
259236
|
+
const [{ readRequestCopy: readRequestCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
259237
|
+
Promise.resolve().then(() => (init_requests(), requests_exports)),
|
|
259238
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
259239
|
+
]);
|
|
259240
|
+
request4 = await readRequestCopy2(id) ?? void 0;
|
|
259241
|
+
if (request4) res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("requests") ?? 0));
|
|
259242
|
+
}
|
|
258936
259243
|
if (!request4) {
|
|
258937
259244
|
sendV1Error(res, 404, "not_found", `No such request: ${id}`);
|
|
258938
259245
|
return;
|
|
@@ -260607,6 +260914,17 @@ var init_search_memory_v1 = __esm({
|
|
|
260607
260914
|
});
|
|
260608
260915
|
searchMemoryV1Router.get("/favorites", async (_req, res, next) => {
|
|
260609
260916
|
try {
|
|
260917
|
+
const [{ readFavoritesCopy: readFavoritesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
260918
|
+
Promise.resolve().then(() => (init_prefs(), prefs_exports)),
|
|
260919
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
260920
|
+
]);
|
|
260921
|
+
const asOf2 = await copyKindAsOf2("prefs");
|
|
260922
|
+
const fav = asOf2 === null ? null : await readFavoritesCopy2();
|
|
260923
|
+
if (fav) {
|
|
260924
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(asOf2));
|
|
260925
|
+
res.json({ projects: fav.projects ?? [], notes: fav.notes ?? [] });
|
|
260926
|
+
return;
|
|
260927
|
+
}
|
|
260610
260928
|
const { readFavorites: readFavorites2 } = await Promise.resolve().then(() => (init_favorites(), favorites_exports));
|
|
260611
260929
|
res.json(await readFavorites2());
|
|
260612
260930
|
} catch (err2) {
|
|
@@ -261639,9 +261957,9 @@ var init_stt_v1 = __esm({
|
|
|
261639
261957
|
|
|
261640
261958
|
// src/web/routes/pastes.ts
|
|
261641
261959
|
import { Router as Router89 } from "express";
|
|
261642
|
-
import
|
|
261960
|
+
import path237 from "path";
|
|
261643
261961
|
import { createHash as createHash37 } from "crypto";
|
|
261644
|
-
import
|
|
261962
|
+
import fsp124 from "fs/promises";
|
|
261645
261963
|
var pastesRouter, MAX_PASTE_CHARS;
|
|
261646
261964
|
var init_pastes = __esm({
|
|
261647
261965
|
"src/web/routes/pastes.ts"() {
|
|
@@ -261661,11 +261979,11 @@ var init_pastes = __esm({
|
|
|
261661
261979
|
res.status(413).json({ error: `Paste too large (max ${MAX_PASTE_CHARS} chars)` });
|
|
261662
261980
|
return;
|
|
261663
261981
|
}
|
|
261664
|
-
await
|
|
261982
|
+
await fsp124.mkdir(PASTES_DIR, { recursive: true });
|
|
261665
261983
|
const hash3 = createHash37("sha256").update(text5).digest("hex").slice(0, 12);
|
|
261666
261984
|
const filename = `${Date.now()}-${hash3}.txt`;
|
|
261667
|
-
const filePath =
|
|
261668
|
-
await
|
|
261985
|
+
const filePath = path237.join(PASTES_DIR, filename);
|
|
261986
|
+
await fsp124.writeFile(filePath, text5, "utf8");
|
|
261669
261987
|
log.web.info("paste spilled to disk", { filePath, chars: text5.length });
|
|
261670
261988
|
res.json({ path: filePath, filename, chars: text5.length });
|
|
261671
261989
|
} catch (err2) {
|
|
@@ -261681,8 +261999,8 @@ __export(file_content_replica_copy_exports, {
|
|
|
261681
261999
|
primaryDataDirRelPath: () => primaryDataDirRelPath,
|
|
261682
262000
|
resolveReplicaCopy: () => resolveReplicaCopy
|
|
261683
262001
|
});
|
|
261684
|
-
import
|
|
261685
|
-
import
|
|
262002
|
+
import path238 from "path";
|
|
262003
|
+
import fsp125 from "fs/promises";
|
|
261686
262004
|
function dataDirIndex(parts, tilde) {
|
|
261687
262005
|
if (tilde) return parts[1] === DATA_DIR_NAME ? 1 : -1;
|
|
261688
262006
|
if ((parts[0] === "Users" || parts[0] === "home") && parts[2] === DATA_DIR_NAME) return 2;
|
|
@@ -261712,12 +262030,12 @@ async function resolveReplicaCopy(requestPath) {
|
|
|
261712
262030
|
const rel = primaryDataDirRelPath(requestPath);
|
|
261713
262031
|
if (rel === null || deniedName(rel)) return null;
|
|
261714
262032
|
try {
|
|
261715
|
-
const root6 = await
|
|
261716
|
-
const real = await
|
|
261717
|
-
if (!real.startsWith(root6 +
|
|
261718
|
-
const realRel =
|
|
261719
|
-
if (isSecretPath(
|
|
261720
|
-
const st2 = await
|
|
262033
|
+
const root6 = await fsp125.realpath(WALNUT_HOME);
|
|
262034
|
+
const real = await fsp125.realpath(path238.join(WALNUT_HOME, rel));
|
|
262035
|
+
if (!real.startsWith(root6 + path238.sep)) return null;
|
|
262036
|
+
const realRel = path238.relative(root6, real).split(path238.sep).join("/");
|
|
262037
|
+
if (isSecretPath(path238.join(WALNUT_HOME, realRel)) || deniedName(realRel)) return null;
|
|
262038
|
+
const st2 = await fsp125.stat(real);
|
|
261721
262039
|
if (!st2.isFile()) return null;
|
|
261722
262040
|
if (!await isTracked(root6, realRel)) return null;
|
|
261723
262041
|
return { localPath: real, size: st2.size };
|
|
@@ -261757,11 +262075,11 @@ var init_file_content_replica_copy = __esm({
|
|
|
261757
262075
|
// src/web/routes/media-v1.ts
|
|
261758
262076
|
import { Router as Router90 } from "express";
|
|
261759
262077
|
import crypto69 from "crypto";
|
|
261760
|
-
import
|
|
261761
|
-
import
|
|
262078
|
+
import path239 from "path";
|
|
262079
|
+
import fsp126 from "fs/promises";
|
|
261762
262080
|
function cachePathFor(host, filePath) {
|
|
261763
262081
|
const hash3 = crypto69.createHash("sha256").update(filePath).digest("hex").slice(0, 16);
|
|
261764
|
-
return
|
|
262082
|
+
return path239.join(REMOTE_IMAGES_DIR, host, `${hash3}-${path239.basename(filePath)}`);
|
|
261765
262083
|
}
|
|
261766
262084
|
async function hostForSession(sessionId) {
|
|
261767
262085
|
if (CLOUD_MODE) {
|
|
@@ -261826,11 +262144,11 @@ var init_media_v1 = __esm({
|
|
|
261826
262144
|
try {
|
|
261827
262145
|
const filePath = req.query.path;
|
|
261828
262146
|
const session2 = typeof req.query.session === "string" && SID_RE6.test(req.query.session) ? req.query.session : void 0;
|
|
261829
|
-
if (!filePath || typeof filePath !== "string" || !
|
|
262147
|
+
if (!filePath || typeof filePath !== "string" || !path239.isAbsolute(filePath) || filePath.includes("..")) {
|
|
261830
262148
|
res.status(400).json({ error: { code: "bad_request", message: "path must be an absolute file path" } });
|
|
261831
262149
|
return;
|
|
261832
262150
|
}
|
|
261833
|
-
const ext2 =
|
|
262151
|
+
const ext2 = path239.extname(filePath).slice(1).toLowerCase();
|
|
261834
262152
|
const mime = EXT_TO_MIME3[ext2];
|
|
261835
262153
|
if (!mime) {
|
|
261836
262154
|
res.status(400).json({ error: { code: "bad_request", message: "file type not allowed" } });
|
|
@@ -261838,8 +262156,8 @@ var init_media_v1 = __esm({
|
|
|
261838
262156
|
}
|
|
261839
262157
|
let buffer2 = null;
|
|
261840
262158
|
try {
|
|
261841
|
-
const st2 = await
|
|
261842
|
-
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
262159
|
+
const st2 = await fsp126.stat(filePath);
|
|
262160
|
+
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) buffer2 = await fsp126.readFile(filePath);
|
|
261843
262161
|
} catch {
|
|
261844
262162
|
}
|
|
261845
262163
|
let waitedOnPending = false;
|
|
@@ -261860,8 +262178,8 @@ var init_media_v1 = __esm({
|
|
|
261860
262178
|
if (buffer2) {
|
|
261861
262179
|
try {
|
|
261862
262180
|
const cachePath3 = cachePathFor(host, filePath);
|
|
261863
|
-
await
|
|
261864
|
-
await
|
|
262181
|
+
await fsp126.mkdir(path239.dirname(cachePath3), { recursive: true });
|
|
262182
|
+
await fsp126.writeFile(cachePath3, buffer2);
|
|
261865
262183
|
} catch {
|
|
261866
262184
|
}
|
|
261867
262185
|
break;
|
|
@@ -261871,9 +262189,9 @@ var init_media_v1 = __esm({
|
|
|
261871
262189
|
for (const host of hosts2) {
|
|
261872
262190
|
try {
|
|
261873
262191
|
const cached8 = cachePathFor(host, filePath);
|
|
261874
|
-
const st2 = await
|
|
262192
|
+
const st2 = await fsp126.stat(cached8);
|
|
261875
262193
|
if (st2.isFile() && st2.size <= MAX_FILE_SIZE3) {
|
|
261876
|
-
buffer2 = await
|
|
262194
|
+
buffer2 = await fsp126.readFile(cached8);
|
|
261877
262195
|
break;
|
|
261878
262196
|
}
|
|
261879
262197
|
} catch {
|
|
@@ -261883,7 +262201,7 @@ var init_media_v1 = __esm({
|
|
|
261883
262201
|
if (!buffer2 && hosts2.length > 0 && hosts2.every((h8) => h8 === "__local__") && !(await Promise.resolve().then(() => (init_bridge_registry(), bridge_registry_exports))).bridgeForHost("__local__").connected) {
|
|
261884
262202
|
const { resolveReplicaCopy: resolveReplicaCopy2 } = await Promise.resolve().then(() => (init_file_content_replica_copy(), file_content_replica_copy_exports));
|
|
261885
262203
|
const copy5 = await resolveReplicaCopy2(filePath);
|
|
261886
|
-
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await
|
|
262204
|
+
if (copy5 && copy5.size <= MAX_FILE_SIZE3) buffer2 = await fsp126.readFile(copy5.localPath);
|
|
261887
262205
|
}
|
|
261888
262206
|
}
|
|
261889
262207
|
if (!buffer2) {
|
|
@@ -261908,6 +262226,19 @@ var init_media_v1 = __esm({
|
|
|
261908
262226
|
|
|
261909
262227
|
// src/web/routes/routines-v1.ts
|
|
261910
262228
|
import { Router as Router91 } from "express";
|
|
262229
|
+
async function answeredFromCopy(res, includeDisabled, answer5) {
|
|
262230
|
+
const [{ companionRoutinesCopy: companionRoutinesCopy2 }, { copyKindAsOf: copyKindAsOf2, COPY_AS_OF_HEADER: COPY_AS_OF_HEADER2 }] = await Promise.all([
|
|
262231
|
+
Promise.resolve().then(() => (init_routines_follower(), routines_follower_exports)),
|
|
262232
|
+
Promise.resolve().then(() => (init_gate(), gate_exports))
|
|
262233
|
+
]);
|
|
262234
|
+
const jobs2 = await companionRoutinesCopy2({ includeDisabled });
|
|
262235
|
+
if (!jobs2) return false;
|
|
262236
|
+
res.setHeader(COPY_AS_OF_HEADER2, String(await copyKindAsOf2("routines") ?? 0));
|
|
262237
|
+
const body7 = answer5(jobs2);
|
|
262238
|
+
if (body7 === null) sendV1Error(res, 404, "not_found", "No such routine in the copy of your Mac's routines");
|
|
262239
|
+
else res.json(body7);
|
|
262240
|
+
return true;
|
|
262241
|
+
}
|
|
261911
262242
|
function validRid(req, res) {
|
|
261912
262243
|
const id = String(req.params.id ?? "");
|
|
261913
262244
|
if (!RID_RE.test(id)) {
|
|
@@ -261954,6 +262285,7 @@ var init_routines_v1 = __esm({
|
|
|
261954
262285
|
try {
|
|
261955
262286
|
const includeDisabled = req.query.includeDisabled === "true";
|
|
261956
262287
|
if (CLOUD_MODE) {
|
|
262288
|
+
if (await answeredFromCopy(res, includeDisabled, (jobs2) => ({ jobs: jobs2 }))) return;
|
|
261957
262289
|
await relayControlAction(res, "server.routines", SERVER_RELAY_SID14, { includeDisabled }, 200);
|
|
261958
262290
|
return;
|
|
261959
262291
|
}
|
|
@@ -261978,6 +262310,7 @@ var init_routines_v1 = __esm({
|
|
|
261978
262310
|
routinesV1Router.get("/routines/status", async (_req, res, next) => {
|
|
261979
262311
|
try {
|
|
261980
262312
|
if (CLOUD_MODE) {
|
|
262313
|
+
if (await answeredFromCopy(res, true, (jobs2) => ({ enabled: false, storePath: "", jobs: jobs2.length, nextWakeAtMs: null }))) return;
|
|
261981
262314
|
await relayControlAction(res, "server.routines.status", SERVER_RELAY_SID14, void 0, 200);
|
|
261982
262315
|
return;
|
|
261983
262316
|
}
|
|
@@ -262049,6 +262382,10 @@ var init_routines_v1 = __esm({
|
|
|
262049
262382
|
const id = validRid(req, res);
|
|
262050
262383
|
if (!id) return;
|
|
262051
262384
|
if (CLOUD_MODE) {
|
|
262385
|
+
if (await answeredFromCopy(res, true, (jobs2) => {
|
|
262386
|
+
const job2 = jobs2.find((j8) => j8.id === id);
|
|
262387
|
+
return job2 ? { job: job2 } : null;
|
|
262388
|
+
})) return;
|
|
262052
262389
|
await relayControlAction(res, "server.routines.get", SERVER_RELAY_SID14, { id }, 200);
|
|
262053
262390
|
return;
|
|
262054
262391
|
}
|
|
@@ -263243,8 +263580,8 @@ __export(file_content_bridge_exports, {
|
|
|
263243
263580
|
resolveBridgeHost: () => resolveBridgeHost,
|
|
263244
263581
|
serveCloudFileContent: () => serveCloudFileContent
|
|
263245
263582
|
});
|
|
263246
|
-
import
|
|
263247
|
-
import
|
|
263583
|
+
import path240 from "path";
|
|
263584
|
+
import fsp127 from "fs/promises";
|
|
263248
263585
|
function resolveBridgeHost(host) {
|
|
263249
263586
|
return typeof host === "string" && host.length > 0 ? host : PRIMARY_BRIDGE_ALIAS3;
|
|
263250
263587
|
}
|
|
@@ -263315,7 +263652,7 @@ function precheckPath(res, rawPath) {
|
|
|
263315
263652
|
sendV1Error(res, 400, "bad_request", "Invalid path");
|
|
263316
263653
|
return null;
|
|
263317
263654
|
}
|
|
263318
|
-
if (rawPath !== "~" && !rawPath.startsWith("~/") && !
|
|
263655
|
+
if (rawPath !== "~" && !rawPath.startsWith("~/") && !path240.isAbsolute(rawPath)) {
|
|
263319
263656
|
sendV1Error(res, 400, "bad_request", "Path must be absolute");
|
|
263320
263657
|
return null;
|
|
263321
263658
|
}
|
|
@@ -263359,7 +263696,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
263359
263696
|
const hostAlias2 = resolveBridgeHost(req.query.host);
|
|
263360
263697
|
const raw = req.query.raw === "1" || req.query.raw === "true";
|
|
263361
263698
|
const download = req.query.download === "1" || req.query.download === "true";
|
|
263362
|
-
const ext2 =
|
|
263699
|
+
const ext2 = path240.extname(filePath).slice(1).toLowerCase();
|
|
263363
263700
|
const {
|
|
263364
263701
|
assertPathAllowed: assertPathAllowed2,
|
|
263365
263702
|
isSecretPath: isSecretPath2,
|
|
@@ -263369,7 +263706,7 @@ async function serveCloudFileContent(req, res) {
|
|
|
263369
263706
|
FileContentError: FileContentError2
|
|
263370
263707
|
} = await Promise.resolve().then(() => (init_file_content(), file_content_exports));
|
|
263371
263708
|
const explicitHost = typeof req.query.host === "string" && req.query.host.length > 0;
|
|
263372
|
-
const locallyPresent = await
|
|
263709
|
+
const locallyPresent = await fsp127.stat(filePath).then((st2) => st2.isFile()).catch(() => false);
|
|
263373
263710
|
if (!explicitHost && locallyPresent && cloudLocalReadAllowed2(filePath) && !isSecretPath2(filePath)) {
|
|
263374
263711
|
try {
|
|
263375
263712
|
if (raw) {
|
|
@@ -263467,10 +263804,10 @@ async function serveReplicaCopy(req, res, requestPath, copy5, opts2) {
|
|
|
263467
263804
|
return;
|
|
263468
263805
|
}
|
|
263469
263806
|
if (copy5.size <= MAX_BRIDGE_FILE_BYTES) {
|
|
263470
|
-
res.json(jsonPayloadFromBuffer(await
|
|
263807
|
+
res.json(jsonPayloadFromBuffer(await fsp127.readFile(copy5.localPath), opts2.ext, false));
|
|
263471
263808
|
return;
|
|
263472
263809
|
}
|
|
263473
|
-
const fh = await
|
|
263810
|
+
const fh = await fsp127.open(copy5.localPath, "r");
|
|
263474
263811
|
try {
|
|
263475
263812
|
const head2 = Buffer.alloc(MAX_TEXT_PAYLOAD);
|
|
263476
263813
|
const { bytesRead } = await fh.read(head2, 0, head2.length, 0);
|
|
@@ -264544,17 +264881,17 @@ __export(checklist_io_exports, {
|
|
|
264544
264881
|
readHeartbeatChecklist: () => readHeartbeatChecklist,
|
|
264545
264882
|
writeHeartbeatChecklist: () => writeHeartbeatChecklist
|
|
264546
264883
|
});
|
|
264547
|
-
import
|
|
264884
|
+
import fsp128 from "fs/promises";
|
|
264548
264885
|
async function readHeartbeatChecklist() {
|
|
264549
264886
|
try {
|
|
264550
|
-
return await
|
|
264887
|
+
return await fsp128.readFile(HEARTBEAT_FILE, "utf-8");
|
|
264551
264888
|
} catch (err2) {
|
|
264552
264889
|
if (err2.code === "ENOENT") return "";
|
|
264553
264890
|
throw err2;
|
|
264554
264891
|
}
|
|
264555
264892
|
}
|
|
264556
264893
|
async function writeHeartbeatChecklist(content) {
|
|
264557
|
-
await
|
|
264894
|
+
await fsp128.writeFile(HEARTBEAT_FILE, content, "utf-8");
|
|
264558
264895
|
}
|
|
264559
264896
|
var init_checklist_io = __esm({
|
|
264560
264897
|
"src/heartbeat/checklist-io.ts"() {
|
|
@@ -266334,11 +266671,11 @@ __export(ephemeral_guard_exports, {
|
|
|
266334
266671
|
});
|
|
266335
266672
|
import fs129 from "fs";
|
|
266336
266673
|
import os60 from "os";
|
|
266337
|
-
import
|
|
266674
|
+
import path241 from "path";
|
|
266338
266675
|
function productionWalnutHomes() {
|
|
266339
266676
|
const homes = /* @__PURE__ */ new Set();
|
|
266340
266677
|
const add3 = (home) => {
|
|
266341
|
-
if (home) homes.add(
|
|
266678
|
+
if (home) homes.add(path241.join(home, ".open-walnut"));
|
|
266342
266679
|
};
|
|
266343
266680
|
add3(os60.homedir());
|
|
266344
266681
|
try {
|
|
@@ -266348,7 +266685,7 @@ function productionWalnutHomes() {
|
|
|
266348
266685
|
return [...homes];
|
|
266349
266686
|
}
|
|
266350
266687
|
function canonical2(dir4) {
|
|
266351
|
-
const resolved =
|
|
266688
|
+
const resolved = path241.resolve(dir4);
|
|
266352
266689
|
try {
|
|
266353
266690
|
return fs129.realpathSync(resolved);
|
|
266354
266691
|
} catch {
|
|
@@ -266384,28 +266721,28 @@ __export(boot_guard_exports, {
|
|
|
266384
266721
|
});
|
|
266385
266722
|
import fs130 from "fs";
|
|
266386
266723
|
import os61 from "os";
|
|
266387
|
-
import
|
|
266724
|
+
import path242 from "path";
|
|
266388
266725
|
function canonical3(dir4) {
|
|
266389
|
-
let head2 =
|
|
266726
|
+
let head2 = path242.resolve(dir4);
|
|
266390
266727
|
const rest = [];
|
|
266391
266728
|
for (; ; ) {
|
|
266392
266729
|
try {
|
|
266393
|
-
return
|
|
266730
|
+
return path242.join(fs130.realpathSync(head2), ...rest);
|
|
266394
266731
|
} catch {
|
|
266395
266732
|
}
|
|
266396
|
-
const up =
|
|
266397
|
-
if (up === head2) return
|
|
266398
|
-
rest.unshift(
|
|
266733
|
+
const up = path242.dirname(head2);
|
|
266734
|
+
if (up === head2) return path242.resolve(dir4);
|
|
266735
|
+
rest.unshift(path242.basename(head2));
|
|
266399
266736
|
head2 = up;
|
|
266400
266737
|
}
|
|
266401
266738
|
}
|
|
266402
266739
|
function spellings(dir4) {
|
|
266403
|
-
const resolved =
|
|
266740
|
+
const resolved = path242.resolve(dir4);
|
|
266404
266741
|
return [.../* @__PURE__ */ new Set([resolved, canonical3(resolved), `/private${resolved}`])];
|
|
266405
266742
|
}
|
|
266406
266743
|
function within5(child2, parent) {
|
|
266407
|
-
const rel =
|
|
266408
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
266744
|
+
const rel = path242.relative(parent, child2);
|
|
266745
|
+
return rel === "" || !rel.startsWith("..") && !path242.isAbsolute(rel);
|
|
266409
266746
|
}
|
|
266410
266747
|
function overlaps(a8, b8) {
|
|
266411
266748
|
return spellings(a8).some((x3) => spellings(b8).some((y3) => within5(x3, y3) || within5(y3, x3)));
|
|
@@ -266416,7 +266753,7 @@ function holdsOrIs(outer, inner2) {
|
|
|
266416
266753
|
function accountHomes(env3) {
|
|
266417
266754
|
const homes = /* @__PURE__ */ new Set();
|
|
266418
266755
|
const add3 = (h8) => {
|
|
266419
|
-
if (h8 && h8.trim()) homes.add(
|
|
266756
|
+
if (h8 && h8.trim()) homes.add(path242.resolve(h8.trim()));
|
|
266420
266757
|
};
|
|
266421
266758
|
add3(env3.HOME);
|
|
266422
266759
|
add3(os61.homedir());
|
|
@@ -266474,7 +266811,7 @@ function assertReplicaBootSafe(input) {
|
|
|
266474
266811
|
if (why2) throw new Error(`Host replica refused to start: ${why2}.`);
|
|
266475
266812
|
}
|
|
266476
266813
|
function claimReplicaDir(dir4) {
|
|
266477
|
-
const marker =
|
|
266814
|
+
const marker = path242.join(dir4, REPLICA_DIR_MARKER);
|
|
266478
266815
|
try {
|
|
266479
266816
|
return fs130.lstatSync(marker).isFile();
|
|
266480
266817
|
} catch {
|
|
@@ -266499,7 +266836,7 @@ function claimReplicaDir(dir4) {
|
|
|
266499
266836
|
function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
266500
266837
|
const marked = dirs2.filter((d8) => {
|
|
266501
266838
|
try {
|
|
266502
|
-
return fs130.lstatSync(
|
|
266839
|
+
return fs130.lstatSync(path242.join(d8, REPLICA_DIR_MARKER)).isFile();
|
|
266503
266840
|
} catch {
|
|
266504
266841
|
return false;
|
|
266505
266842
|
}
|
|
@@ -266529,7 +266866,7 @@ function tightenReplicaModes(dirs2, limit = 2e4) {
|
|
|
266529
266866
|
} catch {
|
|
266530
266867
|
return;
|
|
266531
266868
|
}
|
|
266532
|
-
for (const n6 of names2) visit(
|
|
266869
|
+
for (const n6 of names2) visit(path242.join(p6, n6));
|
|
266533
266870
|
} else if (st2.isFile() && (st2.mode & 63) !== 0) {
|
|
266534
266871
|
try {
|
|
266535
266872
|
fs130.chmodSync(p6, st2.mode & 448 | 384);
|
|
@@ -266716,29 +267053,29 @@ __export(search_replica_store_exports, {
|
|
|
266716
267053
|
searchReplicaSync: () => searchReplicaSync,
|
|
266717
267054
|
startSearchReplicaStore: () => startSearchReplicaStore
|
|
266718
267055
|
});
|
|
266719
|
-
import
|
|
267056
|
+
import fsp129 from "fs/promises";
|
|
266720
267057
|
import os62 from "os";
|
|
266721
|
-
import
|
|
267058
|
+
import path243 from "path";
|
|
266722
267059
|
async function wiring() {
|
|
266723
267060
|
return Promise.resolve().then(() => (init_wiring(), wiring_exports));
|
|
266724
267061
|
}
|
|
266725
267062
|
async function loadState() {
|
|
266726
|
-
if (
|
|
267063
|
+
if (state12) return state12;
|
|
266727
267064
|
let s4 = { v: 1, mode: null, syncedAt: null };
|
|
266728
267065
|
try {
|
|
266729
|
-
const raw = JSON.parse(await
|
|
267066
|
+
const raw = JSON.parse(await fsp129.readFile(STATE_FILE2(), "utf8"));
|
|
266730
267067
|
if (raw && raw.v === 1) {
|
|
266731
267068
|
s4 = { v: 1, mode: raw.mode ? companionSearchMode(raw.mode) : null, syncedAt: typeof raw.syncedAt === "number" ? raw.syncedAt : null };
|
|
266732
267069
|
}
|
|
266733
267070
|
} catch {
|
|
266734
267071
|
}
|
|
266735
|
-
|
|
267072
|
+
state12 = s4;
|
|
266736
267073
|
return s4;
|
|
266737
267074
|
}
|
|
266738
267075
|
async function saveState() {
|
|
266739
|
-
if (
|
|
267076
|
+
if (state12) await writeJsonFile(STATE_FILE2(), state12);
|
|
266740
267077
|
}
|
|
266741
|
-
function
|
|
267078
|
+
function serial5(fn) {
|
|
266742
267079
|
const run12 = chain4.then(fn, fn);
|
|
266743
267080
|
chain4 = run12.catch(() => {
|
|
266744
267081
|
});
|
|
@@ -266802,8 +267139,8 @@ async function closeIndex() {
|
|
|
266802
267139
|
allDirty2 = true;
|
|
266803
267140
|
}
|
|
266804
267141
|
function publishReady() {
|
|
266805
|
-
const ready2 = enabled && mapBuilt && map3.size > 0 &&
|
|
266806
|
-
setCompanionSearchReady(ready2, ready2 ?
|
|
267142
|
+
const ready2 = enabled && mapBuilt && map3.size > 0 && state12?.syncedAt != null;
|
|
267143
|
+
setCompanionSearchReady(ready2, ready2 ? state12.syncedAt : null);
|
|
266807
267144
|
}
|
|
266808
267145
|
async function markInSync() {
|
|
266809
267146
|
const s4 = await loadState();
|
|
@@ -266830,7 +267167,7 @@ async function warm(why2) {
|
|
|
266830
267167
|
}
|
|
266831
267168
|
}
|
|
266832
267169
|
function searchReplicaStatus(body7) {
|
|
266833
|
-
return
|
|
267170
|
+
return serial5(async () => {
|
|
266834
267171
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
266835
267172
|
const s4 = await loadState();
|
|
266836
267173
|
const mode = companionSearchMode(body7.mode);
|
|
@@ -266878,7 +267215,7 @@ function searchReplicaStatus(body7) {
|
|
|
266878
267215
|
});
|
|
266879
267216
|
}
|
|
266880
267217
|
function searchReplicaSync(body7) {
|
|
266881
|
-
return
|
|
267218
|
+
return serial5(async () => {
|
|
266882
267219
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
266883
267220
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
266884
267221
|
if (!Array.isArray(body7.entries)) return { ok: false, status: 400, error: "bad_entries" };
|
|
@@ -266923,7 +267260,7 @@ async function forgetSearchMemo() {
|
|
|
266923
267260
|
}
|
|
266924
267261
|
}
|
|
266925
267262
|
function searchReplicaPut(body7) {
|
|
266926
|
-
return
|
|
267263
|
+
return serial5(async () => {
|
|
266927
267264
|
if (!isFollower()) return { ok: false, status: 400, error: "not_a_replica" };
|
|
266928
267265
|
if (!enabled) return { ok: false, status: 400, error: "search_copy_off" };
|
|
266929
267266
|
if (!Array.isArray(body7.docs)) return { ok: false, status: 400, error: "bad_docs" };
|
|
@@ -266989,7 +267326,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
266989
267326
|
if (!s4.mode || stopped2) return;
|
|
266990
267327
|
const decision = companionSearchDecision(s4.mode, deps3.totalMb());
|
|
266991
267328
|
if (!decision.enabled) return;
|
|
266992
|
-
await
|
|
267329
|
+
await serial5(async () => {
|
|
266993
267330
|
enabled = true;
|
|
266994
267331
|
reason2 = decision.reason;
|
|
266995
267332
|
await refreshMap2(await openIndex());
|
|
@@ -267022,12 +267359,12 @@ function startSearchReplicaStore(options = {}) {
|
|
|
267022
267359
|
}));
|
|
267023
267360
|
}).catch((err2) => log.memory.warn("search replica: local writes not wired", { error: err2 instanceof Error ? err2.message : String(err2) }));
|
|
267024
267361
|
unsubs.push(onLeaderPresence((answers4) => {
|
|
267025
|
-
if (stopped2 || answers4 || !enabled ||
|
|
267362
|
+
if (stopped2 || answers4 || !enabled || state12?.syncedAt == null) return;
|
|
267026
267363
|
void warm("leader away");
|
|
267027
267364
|
}));
|
|
267028
267365
|
const tick = setInterval(() => {
|
|
267029
267366
|
void (async () => {
|
|
267030
|
-
if (stopped2 || !enabled ||
|
|
267367
|
+
if (stopped2 || !enabled || state12?.syncedAt == null) return;
|
|
267031
267368
|
if (Date.now() - lastWarmAt < WARM_EVERY_MS) return;
|
|
267032
267369
|
if (!await deps3.macAway()) return;
|
|
267033
267370
|
await warm("mac away");
|
|
@@ -267046,7 +267383,7 @@ function startSearchReplicaStore(options = {}) {
|
|
|
267046
267383
|
};
|
|
267047
267384
|
}
|
|
267048
267385
|
function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
267049
|
-
|
|
267386
|
+
state12 = null;
|
|
267050
267387
|
enabled = false;
|
|
267051
267388
|
reason2 = "off";
|
|
267052
267389
|
map3.clear();
|
|
@@ -267061,7 +267398,7 @@ function _resetSearchReplicaStoreForTesting(overrides = {}) {
|
|
|
267061
267398
|
deps3 = { totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)), macAway: defaultMacAway, ...overrides };
|
|
267062
267399
|
setCompanionSearchReady(false, null);
|
|
267063
267400
|
}
|
|
267064
|
-
var
|
|
267401
|
+
var STATE_FILE2, MASS_REMOVE_FLOOR, SCAN_SLICE2, WARM_EVERY_MS, TICK_MS2, defaultMacAway, deps3, state12, enabled, reason2, map3, mapBuilt, allDirty2, dirty2, unlisten, lastWarmAt, warmedOnce, chain4, yieldLoop;
|
|
267065
267402
|
var init_search_replica_store = __esm({
|
|
267066
267403
|
"src/core/replication/search-replica-store.ts"() {
|
|
267067
267404
|
"use strict";
|
|
@@ -267073,7 +267410,7 @@ var init_search_replica_store = __esm({
|
|
|
267073
267410
|
init_replica_refs();
|
|
267074
267411
|
init_search_digest();
|
|
267075
267412
|
init_search_replica_wire();
|
|
267076
|
-
|
|
267413
|
+
STATE_FILE2 = () => path243.join(WALNUT_HOME, "cache", "search-replica.json");
|
|
267077
267414
|
MASS_REMOVE_FLOOR = 200;
|
|
267078
267415
|
SCAN_SLICE2 = 500;
|
|
267079
267416
|
WARM_EVERY_MS = 4 * 6e4;
|
|
@@ -267083,7 +267420,7 @@ var init_search_replica_store = __esm({
|
|
|
267083
267420
|
totalMb: () => Math.round(os62.totalmem() / (1024 * 1024)),
|
|
267084
267421
|
macAway: defaultMacAway
|
|
267085
267422
|
};
|
|
267086
|
-
|
|
267423
|
+
state12 = null;
|
|
267087
267424
|
enabled = false;
|
|
267088
267425
|
reason2 = "off";
|
|
267089
267426
|
map3 = new DigestMap();
|
|
@@ -267099,10 +267436,10 @@ var init_search_replica_store = __esm({
|
|
|
267099
267436
|
});
|
|
267100
267437
|
|
|
267101
267438
|
// src/core/replication/kinds/boards.ts
|
|
267102
|
-
import
|
|
267103
|
-
import
|
|
267439
|
+
import fsp130 from "fs/promises";
|
|
267440
|
+
import path244 from "path";
|
|
267104
267441
|
async function leaderBoards(dir4 = boardsDir2()) {
|
|
267105
|
-
const names2 = await
|
|
267442
|
+
const names2 = await fsp130.readdir(dir4).catch(() => []);
|
|
267106
267443
|
const out = [];
|
|
267107
267444
|
const unreadable = [];
|
|
267108
267445
|
const seen2 = /* @__PURE__ */ new Set();
|
|
@@ -267111,9 +267448,9 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
267111
267448
|
const id = name.slice(0, -".json".length);
|
|
267112
267449
|
if (!TASK_ID_RE3.test(id)) continue;
|
|
267113
267450
|
seen2.add(id);
|
|
267114
|
-
const file =
|
|
267451
|
+
const file = path244.join(dir4, name);
|
|
267115
267452
|
try {
|
|
267116
|
-
const st2 = await
|
|
267453
|
+
const st2 = await fsp130.stat(file);
|
|
267117
267454
|
if (!st2.isFile()) continue;
|
|
267118
267455
|
if (st2.size > BOARD_COPY_MAX_BYTES) {
|
|
267119
267456
|
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 });
|
|
@@ -267122,14 +267459,14 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
267122
267459
|
}
|
|
267123
267460
|
let c8 = cache16.get(id);
|
|
267124
267461
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
267125
|
-
const row = JSON.parse(await
|
|
267126
|
-
if (!
|
|
267462
|
+
const row = JSON.parse(await fsp130.readFile(file, "utf8"));
|
|
267463
|
+
if (!isRow6(row) || row.task_id !== id) {
|
|
267127
267464
|
unreadable.push(id);
|
|
267128
267465
|
continue;
|
|
267129
267466
|
}
|
|
267130
267467
|
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, row, hash: sha12(JSON.stringify(row)) };
|
|
267131
267468
|
cache16.set(id, c8);
|
|
267132
|
-
|
|
267469
|
+
hashOf6.set(row, c8.hash);
|
|
267133
267470
|
}
|
|
267134
267471
|
out.push(c8.row);
|
|
267135
267472
|
} catch (err2) {
|
|
@@ -267144,56 +267481,56 @@ async function leaderBoards(dir4 = boardsDir2()) {
|
|
|
267144
267481
|
if (fresh.length > 0) log.session.warn("boards copy: a board could not be read, the host keeps its copy of it", { taskIds: fresh });
|
|
267145
267482
|
return out;
|
|
267146
267483
|
}
|
|
267147
|
-
function
|
|
267484
|
+
function isRow6(v3) {
|
|
267148
267485
|
const b8 = v3;
|
|
267149
267486
|
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";
|
|
267150
267487
|
}
|
|
267151
|
-
async function
|
|
267152
|
-
if (
|
|
267488
|
+
async function load7() {
|
|
267489
|
+
if (state13) return state13;
|
|
267153
267490
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
267154
267491
|
try {
|
|
267155
|
-
const raw = JSON.parse(await
|
|
267492
|
+
const raw = JSON.parse(await fsp130.readFile(STATE_FILE3(), "utf8"));
|
|
267156
267493
|
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 };
|
|
267157
267494
|
} catch {
|
|
267158
267495
|
}
|
|
267159
|
-
|
|
267496
|
+
state13 = s4;
|
|
267160
267497
|
return s4;
|
|
267161
267498
|
}
|
|
267162
|
-
async function
|
|
267163
|
-
if (
|
|
267499
|
+
async function save2() {
|
|
267500
|
+
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
267164
267501
|
}
|
|
267165
267502
|
async function localIds() {
|
|
267166
|
-
const names2 = await
|
|
267503
|
+
const names2 = await fsp130.readdir(boardsDir2()).catch(() => []);
|
|
267167
267504
|
return names2.filter((n6) => n6.endsWith(".json")).map((n6) => n6.slice(0, -".json".length)).filter((id) => TASK_ID_RE3.test(id));
|
|
267168
267505
|
}
|
|
267169
267506
|
function changed2() {
|
|
267170
267507
|
}
|
|
267171
267508
|
function boardsFollower() {
|
|
267172
|
-
|
|
267509
|
+
follower4 ??= createRowSetFollower({
|
|
267173
267510
|
kind: "boards",
|
|
267174
267511
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
267175
267512
|
label: "boards copy",
|
|
267176
267513
|
log: log.session,
|
|
267177
267514
|
removalFloor: BOARDS_REMOVAL_FLOOR,
|
|
267178
267515
|
ordered: false,
|
|
267179
|
-
serial: (fn) =>
|
|
267516
|
+
serial: (fn) => serial6(fn),
|
|
267180
267517
|
refuse: copyRefusal,
|
|
267181
|
-
load:
|
|
267182
|
-
save,
|
|
267183
|
-
isRow:
|
|
267518
|
+
load: load7,
|
|
267519
|
+
save: save2,
|
|
267520
|
+
isRow: isRow6,
|
|
267184
267521
|
key: (b8) => b8.task_id,
|
|
267185
267522
|
localKeys: localIds,
|
|
267186
267523
|
apply: async ({ rows, removeIds }) => {
|
|
267187
267524
|
const skipped = [];
|
|
267188
267525
|
for (const id of removeIds ?? []) {
|
|
267189
|
-
if (TASK_ID_RE3.test(id)) await
|
|
267526
|
+
if (TASK_ID_RE3.test(id)) await fsp130.rm(path244.join(boardsDir2(), `${id}.json`), { force: true });
|
|
267190
267527
|
}
|
|
267191
267528
|
for (const b8 of rows ?? []) {
|
|
267192
267529
|
if (Buffer.byteLength(JSON.stringify(b8)) > BOARD_COPY_MAX_BYTES) {
|
|
267193
267530
|
skipped.push(b8.task_id);
|
|
267194
267531
|
continue;
|
|
267195
267532
|
}
|
|
267196
|
-
await writeCopyFile(
|
|
267533
|
+
await writeCopyFile(path244.join(boardsDir2(), `${b8.task_id}.json`), b8);
|
|
267197
267534
|
}
|
|
267198
267535
|
return { skipped };
|
|
267199
267536
|
},
|
|
@@ -267201,15 +267538,15 @@ function boardsFollower() {
|
|
|
267201
267538
|
changed: changed2,
|
|
267202
267539
|
purge: async () => {
|
|
267203
267540
|
const ids2 = await localIds();
|
|
267204
|
-
for (const id of ids2) await
|
|
267541
|
+
for (const id of ids2) await fsp130.rm(path244.join(boardsDir2(), `${id}.json`), { force: true });
|
|
267205
267542
|
await markCopyOff("boards");
|
|
267206
|
-
|
|
267543
|
+
state13 = null;
|
|
267207
267544
|
return { removed: ids2.length };
|
|
267208
267545
|
}
|
|
267209
267546
|
});
|
|
267210
|
-
return
|
|
267547
|
+
return follower4;
|
|
267211
267548
|
}
|
|
267212
|
-
var BOARDS_SCHEMA_VERSION, BOARDS_REMOVAL_FLOOR, BOARD_COPY_MAX_BYTES, TASK_ID_RE3, boardsDir2, cache16,
|
|
267549
|
+
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, follower4;
|
|
267213
267550
|
var init_boards = __esm({
|
|
267214
267551
|
"src/core/replication/kinds/boards.ts"() {
|
|
267215
267552
|
"use strict";
|
|
@@ -267222,9 +267559,9 @@ var init_boards = __esm({
|
|
|
267222
267559
|
BOARDS_REMOVAL_FLOOR = 20;
|
|
267223
267560
|
BOARD_COPY_MAX_BYTES = 2 * 1024 * 1024;
|
|
267224
267561
|
TASK_ID_RE3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
267225
|
-
boardsDir2 = () =>
|
|
267562
|
+
boardsDir2 = () => path244.join(WALNUT_HOME, "boards");
|
|
267226
267563
|
cache16 = /* @__PURE__ */ new Map();
|
|
267227
|
-
|
|
267564
|
+
hashOf6 = /* @__PURE__ */ new WeakMap();
|
|
267228
267565
|
warnedTooBig = /* @__PURE__ */ new Set();
|
|
267229
267566
|
unreadableOf2 = /* @__PURE__ */ new WeakMap();
|
|
267230
267567
|
warnedUnreadable = /* @__PURE__ */ new Set();
|
|
@@ -267232,7 +267569,7 @@ var init_boards = __esm({
|
|
|
267232
267569
|
kind: "boards",
|
|
267233
267570
|
schemaVersion: BOARDS_SCHEMA_VERSION,
|
|
267234
267571
|
key: (b8) => b8.task_id,
|
|
267235
|
-
hash: (b8) =>
|
|
267572
|
+
hash: (b8) => hashOf6.get(b8) ?? sha12(JSON.stringify(b8)),
|
|
267236
267573
|
ordered: false,
|
|
267237
267574
|
digest: false,
|
|
267238
267575
|
choice: "boards",
|
|
@@ -267252,16 +267589,16 @@ var init_boards = __esm({
|
|
|
267252
267589
|
};
|
|
267253
267590
|
}
|
|
267254
267591
|
};
|
|
267255
|
-
|
|
267256
|
-
|
|
267257
|
-
|
|
267258
|
-
|
|
267592
|
+
STATE_FILE3 = () => path244.join(WALNUT_HOME, "cache", "replica", "boards.json");
|
|
267593
|
+
state13 = null;
|
|
267594
|
+
serial6 = serialChain();
|
|
267595
|
+
follower4 = null;
|
|
267259
267596
|
}
|
|
267260
267597
|
});
|
|
267261
267598
|
|
|
267262
267599
|
// src/core/replication/kinds/inbox.ts
|
|
267263
|
-
import
|
|
267264
|
-
import
|
|
267600
|
+
import fsp131 from "fs/promises";
|
|
267601
|
+
import path245 from "path";
|
|
267265
267602
|
function watchLetters(soon) {
|
|
267266
267603
|
let stop2 = null;
|
|
267267
267604
|
let stopped2 = false;
|
|
@@ -267274,18 +267611,18 @@ function watchLetters(soon) {
|
|
|
267274
267611
|
};
|
|
267275
267612
|
}
|
|
267276
267613
|
async function leaderBodies(dir4 = bodiesDir()) {
|
|
267277
|
-
const names2 = (await
|
|
267614
|
+
const names2 = (await fsp131.readdir(dir4).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)).sort();
|
|
267278
267615
|
const out = [];
|
|
267279
267616
|
const unreadable = [];
|
|
267280
267617
|
const seen2 = new Set(names2);
|
|
267281
267618
|
for (const name of names2) {
|
|
267282
|
-
const file =
|
|
267619
|
+
const file = path245.join(dir4, name);
|
|
267283
267620
|
try {
|
|
267284
|
-
const st2 = await
|
|
267621
|
+
const st2 = await fsp131.stat(file);
|
|
267285
267622
|
if (!st2.isFile() || st2.size > INBOX_BODY_COPY_MAX_BYTES) continue;
|
|
267286
267623
|
let c8 = bodyCache.get(name);
|
|
267287
267624
|
if (!c8 || c8.size !== st2.size || c8.mtimeMs !== st2.mtimeMs) {
|
|
267288
|
-
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await
|
|
267625
|
+
c8 = { size: st2.size, mtimeMs: st2.mtimeMs, hash: sha12(await fsp131.readFile(file, "utf8")) };
|
|
267289
267626
|
bodyCache.set(name, c8);
|
|
267290
267627
|
}
|
|
267291
267628
|
const row = { name };
|
|
@@ -267304,21 +267641,21 @@ async function loadBody(b8) {
|
|
|
267304
267641
|
const file = bodyFiles.get(b8);
|
|
267305
267642
|
if (!file) return typeof b8.body === "string" ? b8 : void 0;
|
|
267306
267643
|
try {
|
|
267307
|
-
const body7 = await
|
|
267644
|
+
const body7 = await fsp131.readFile(file, "utf8");
|
|
267308
267645
|
return Buffer.byteLength(body7) > INBOX_BODY_COPY_MAX_BYTES ? void 0 : { name: b8.name, body: body7 };
|
|
267309
267646
|
} catch {
|
|
267310
267647
|
return void 0;
|
|
267311
267648
|
}
|
|
267312
267649
|
}
|
|
267313
267650
|
function stateIo(name) {
|
|
267314
|
-
const file = () =>
|
|
267651
|
+
const file = () => path245.join(WALNUT_HOME, "cache", "replica", `${name}.json`);
|
|
267315
267652
|
let state17 = null;
|
|
267316
267653
|
return {
|
|
267317
267654
|
load: async () => {
|
|
267318
267655
|
if (state17) return state17;
|
|
267319
267656
|
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
267320
267657
|
try {
|
|
267321
|
-
const raw = JSON.parse(await
|
|
267658
|
+
const raw = JSON.parse(await fsp131.readFile(file(), "utf8"));
|
|
267322
267659
|
if (raw?.v === 1 && raw.hashes && typeof raw.hashes === "object") {
|
|
267323
267660
|
s4 = { asOf: Number(raw.asOf) || 0, at: Number(raw.at) || 0, order: Array.isArray(raw.order) ? raw.order.map(String) : [], hashes: raw.hashes };
|
|
267324
267661
|
}
|
|
@@ -267337,7 +267674,7 @@ function stateIo(name) {
|
|
|
267337
267674
|
}
|
|
267338
267675
|
async function readIndex3() {
|
|
267339
267676
|
try {
|
|
267340
|
-
const raw = JSON.parse(await
|
|
267677
|
+
const raw = JSON.parse(await fsp131.readFile(indexFile3(), "utf8"));
|
|
267341
267678
|
return Array.isArray(raw?.letters) ? raw.letters.filter(isLetter) : [];
|
|
267342
267679
|
} catch {
|
|
267343
267680
|
return [];
|
|
@@ -267360,7 +267697,7 @@ function inboxFollower() {
|
|
|
267360
267697
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
267361
267698
|
ordered: true,
|
|
267362
267699
|
digest: true,
|
|
267363
|
-
serial: (fn) =>
|
|
267700
|
+
serial: (fn) => serial7(fn),
|
|
267364
267701
|
refuse: refuse11,
|
|
267365
267702
|
load: () => indexIo.load(),
|
|
267366
267703
|
save: () => indexIo.save(),
|
|
@@ -267390,7 +267727,7 @@ function inboxFollower() {
|
|
|
267390
267727
|
},
|
|
267391
267728
|
purge: async () => {
|
|
267392
267729
|
const removed = (await readIndex3()).length;
|
|
267393
|
-
await
|
|
267730
|
+
await fsp131.rm(indexFile3(), { force: true });
|
|
267394
267731
|
await markCopyOff("inbox");
|
|
267395
267732
|
indexIo.reset();
|
|
267396
267733
|
return { removed };
|
|
@@ -267406,23 +267743,23 @@ function inboxBodiesFollower() {
|
|
|
267406
267743
|
log: log.notif,
|
|
267407
267744
|
removalFloor: INBOX_REMOVAL_FLOOR,
|
|
267408
267745
|
ordered: false,
|
|
267409
|
-
serial: (fn) =>
|
|
267746
|
+
serial: (fn) => serial7(fn),
|
|
267410
267747
|
refuse: refuse11,
|
|
267411
267748
|
load: () => bodiesIo.load(),
|
|
267412
267749
|
save: () => bodiesIo.save(),
|
|
267413
267750
|
isRow: isBody,
|
|
267414
267751
|
key: (b8) => b8.name,
|
|
267415
267752
|
hash: (b8) => sha12(b8.body),
|
|
267416
|
-
localKeys: async () => (await
|
|
267753
|
+
localKeys: async () => (await fsp131.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6)),
|
|
267417
267754
|
apply: async ({ rows, removeIds }) => {
|
|
267418
|
-
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await
|
|
267755
|
+
for (const name of removeIds ?? []) if (BODY_FILE_RE.test(name)) await fsp131.rm(path245.join(bodiesDir(), name), { force: true });
|
|
267419
267756
|
const skipped = [];
|
|
267420
267757
|
for (const b8 of rows ?? []) {
|
|
267421
267758
|
if (Buffer.byteLength(b8.body) > INBOX_BODY_COPY_MAX_BYTES) {
|
|
267422
267759
|
skipped.push(b8.name);
|
|
267423
267760
|
continue;
|
|
267424
267761
|
}
|
|
267425
|
-
await writeCopyText(
|
|
267762
|
+
await writeCopyText(path245.join(bodiesDir(), b8.name), b8.body);
|
|
267426
267763
|
}
|
|
267427
267764
|
return { skipped };
|
|
267428
267765
|
},
|
|
@@ -267430,8 +267767,8 @@ function inboxBodiesFollower() {
|
|
|
267430
267767
|
changed: () => {
|
|
267431
267768
|
},
|
|
267432
267769
|
purge: async () => {
|
|
267433
|
-
const names2 = (await
|
|
267434
|
-
for (const name of names2) await
|
|
267770
|
+
const names2 = (await fsp131.readdir(bodiesDir()).catch(() => [])).filter((n6) => BODY_FILE_RE.test(n6));
|
|
267771
|
+
for (const name of names2) await fsp131.rm(path245.join(bodiesDir(), name), { force: true });
|
|
267435
267772
|
await markCopyOff("inbox-bodies");
|
|
267436
267773
|
bodiesIo.reset();
|
|
267437
267774
|
return { removed: names2.length };
|
|
@@ -267439,7 +267776,7 @@ function inboxBodiesFollower() {
|
|
|
267439
267776
|
});
|
|
267440
267777
|
return bodiesF;
|
|
267441
267778
|
}
|
|
267442
|
-
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, refuse11, indexIo, bodiesIo,
|
|
267779
|
+
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, refuse11, indexIo, bodiesIo, serial7, inboxF, bodiesF;
|
|
267443
267780
|
var init_inbox = __esm({
|
|
267444
267781
|
"src/core/replication/kinds/inbox.ts"() {
|
|
267445
267782
|
"use strict";
|
|
@@ -267452,9 +267789,9 @@ var init_inbox = __esm({
|
|
|
267452
267789
|
INBOX_SCHEMA_VERSION = 1;
|
|
267453
267790
|
INBOX_REMOVAL_FLOOR = 50;
|
|
267454
267791
|
INBOX_BODY_COPY_MAX_BYTES = 4 * 1024 * 1024;
|
|
267455
|
-
inboxDir = () =>
|
|
267456
|
-
indexFile3 = () =>
|
|
267457
|
-
bodiesDir = () =>
|
|
267792
|
+
inboxDir = () => path245.join(WALNUT_HOME, "human-inbox");
|
|
267793
|
+
indexFile3 = () => path245.join(inboxDir(), "index.json");
|
|
267794
|
+
bodiesDir = () => path245.join(inboxDir(), "bodies");
|
|
267458
267795
|
letterHashes = /* @__PURE__ */ new WeakMap();
|
|
267459
267796
|
INBOX_KIND = {
|
|
267460
267797
|
kind: "inbox",
|
|
@@ -267496,134 +267833,12 @@ var init_inbox = __esm({
|
|
|
267496
267833
|
refuse11 = copyRefusal;
|
|
267497
267834
|
indexIo = stateIo("inbox");
|
|
267498
267835
|
bodiesIo = stateIo("inbox-bodies");
|
|
267499
|
-
|
|
267836
|
+
serial7 = serialChain();
|
|
267500
267837
|
inboxF = null;
|
|
267501
267838
|
bodiesF = null;
|
|
267502
267839
|
}
|
|
267503
267840
|
});
|
|
267504
267841
|
|
|
267505
|
-
// src/core/replication/kinds/requests.ts
|
|
267506
|
-
import fsp131 from "fs/promises";
|
|
267507
|
-
import path245 from "path";
|
|
267508
|
-
function forwardRequest(local, incoming) {
|
|
267509
|
-
if (local && FINAL.has(local.status) && !FINAL.has(incoming.status)) return local;
|
|
267510
|
-
return incoming;
|
|
267511
|
-
}
|
|
267512
|
-
function hashOf5(row) {
|
|
267513
|
-
let h8 = hashes4.get(row);
|
|
267514
|
-
if (h8 === void 0) {
|
|
267515
|
-
h8 = sha12(JSON.stringify(row));
|
|
267516
|
-
hashes4.set(row, h8);
|
|
267517
|
-
}
|
|
267518
|
-
return h8;
|
|
267519
|
-
}
|
|
267520
|
-
async function load7() {
|
|
267521
|
-
if (state13) return state13;
|
|
267522
|
-
let s4 = { asOf: 0, at: 0, order: [], hashes: {} };
|
|
267523
|
-
try {
|
|
267524
|
-
const raw = JSON.parse(await fsp131.readFile(STATE_FILE3(), "utf8"));
|
|
267525
|
-
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 };
|
|
267526
|
-
} catch {
|
|
267527
|
-
}
|
|
267528
|
-
state13 = s4;
|
|
267529
|
-
return s4;
|
|
267530
|
-
}
|
|
267531
|
-
async function save2() {
|
|
267532
|
-
if (state13) await writeCopyFile(STATE_FILE3(), { v: 1, asOf: state13.asOf, at: state13.at, hashes: state13.hashes });
|
|
267533
|
-
}
|
|
267534
|
-
async function readStore7() {
|
|
267535
|
-
try {
|
|
267536
|
-
const raw = JSON.parse(await fsp131.readFile(STORE_FILE(), "utf8"));
|
|
267537
|
-
return Array.isArray(raw?.requests) ? raw.requests.filter(isRow5) : [];
|
|
267538
|
-
} catch {
|
|
267539
|
-
return [];
|
|
267540
|
-
}
|
|
267541
|
-
}
|
|
267542
|
-
function isRow5(v3) {
|
|
267543
|
-
const r8 = v3;
|
|
267544
|
-
return !!r8 && typeof r8 === "object" && typeof r8.id === "string" && !!r8.id && typeof r8.fromSessionId === "string" && typeof r8.status === "string" && typeof r8.createdAt === "string";
|
|
267545
|
-
}
|
|
267546
|
-
function requestsFollower() {
|
|
267547
|
-
follower4 ??= createRowSetFollower({
|
|
267548
|
-
kind: "requests",
|
|
267549
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
267550
|
-
label: "requests copy",
|
|
267551
|
-
log: log.session,
|
|
267552
|
-
removalFloor: REQUESTS_REMOVAL_FLOOR,
|
|
267553
|
-
ordered: false,
|
|
267554
|
-
serial: (fn) => serial7(fn),
|
|
267555
|
-
refuse: copyRefusal,
|
|
267556
|
-
load: load7,
|
|
267557
|
-
save: save2,
|
|
267558
|
-
isRow: isRow5,
|
|
267559
|
-
key: (r8) => r8.id,
|
|
267560
|
-
localKeys: async () => (await readStore7()).map((r8) => r8.id),
|
|
267561
|
-
apply: async ({ rows, removeIds }) => {
|
|
267562
|
-
const byId = new Map((await readStore7()).map((r8) => [r8.id, r8]));
|
|
267563
|
-
for (const id of removeIds ?? []) byId.delete(id);
|
|
267564
|
-
for (const r8 of rows ?? []) {
|
|
267565
|
-
const kept = forwardRequest(byId.get(r8.id), r8);
|
|
267566
|
-
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 });
|
|
267567
|
-
byId.set(r8.id, kept);
|
|
267568
|
-
}
|
|
267569
|
-
await writeCopyFile(STORE_FILE(), { requests: [...byId.values()] });
|
|
267570
|
-
return { skipped: [] };
|
|
267571
|
-
},
|
|
267572
|
-
held: async () => (await Promise.resolve().then(() => (init_journal_overlay(), journal_overlay_exports))).journalHeld("requests"),
|
|
267573
|
-
changed: () => {
|
|
267574
|
-
},
|
|
267575
|
-
purge: async () => {
|
|
267576
|
-
const removed = (await readStore7()).length;
|
|
267577
|
-
await fsp131.rm(STORE_FILE(), { force: true });
|
|
267578
|
-
await markCopyOff("requests");
|
|
267579
|
-
state13 = null;
|
|
267580
|
-
return { removed };
|
|
267581
|
-
}
|
|
267582
|
-
});
|
|
267583
|
-
return follower4;
|
|
267584
|
-
}
|
|
267585
|
-
var REQUESTS_SCHEMA_VERSION, REQUESTS_REMOVAL_FLOOR, FINAL, hashes4, REQUESTS_KIND, STATE_FILE3, STORE_FILE, state13, serial7, follower4;
|
|
267586
|
-
var init_requests = __esm({
|
|
267587
|
-
"src/core/replication/kinds/requests.ts"() {
|
|
267588
|
-
"use strict";
|
|
267589
|
-
init_constants();
|
|
267590
|
-
init_logging();
|
|
267591
|
-
init_kind();
|
|
267592
|
-
init_kind_follower();
|
|
267593
|
-
init_gate();
|
|
267594
|
-
REQUESTS_SCHEMA_VERSION = 1;
|
|
267595
|
-
REQUESTS_REMOVAL_FLOOR = 50;
|
|
267596
|
-
FINAL = /* @__PURE__ */ new Set(["replied", "notified", "expired"]);
|
|
267597
|
-
hashes4 = /* @__PURE__ */ new WeakMap();
|
|
267598
|
-
REQUESTS_KIND = {
|
|
267599
|
-
kind: "requests",
|
|
267600
|
-
schemaVersion: REQUESTS_SCHEMA_VERSION,
|
|
267601
|
-
key: (r8) => r8.id,
|
|
267602
|
-
hash: hashOf5,
|
|
267603
|
-
ordered: false,
|
|
267604
|
-
digest: false,
|
|
267605
|
-
choice: "requests",
|
|
267606
|
-
rows: async () => (await Promise.resolve().then(() => (init_session_requests(), session_requests_exports))).listAllSessionRequests(),
|
|
267607
|
-
watch: (soon) => {
|
|
267608
|
-
let stop2 = null;
|
|
267609
|
-
let stopped2 = false;
|
|
267610
|
-
void Promise.resolve().then(() => (init_session_requests(), session_requests_exports)).then(({ onSessionRequestsWritten: onSessionRequestsWritten2 }) => {
|
|
267611
|
-
if (!stopped2) stop2 = onSessionRequestsWritten2(soon);
|
|
267612
|
-
});
|
|
267613
|
-
return () => {
|
|
267614
|
-
stopped2 = true;
|
|
267615
|
-
stop2?.();
|
|
267616
|
-
};
|
|
267617
|
-
}
|
|
267618
|
-
};
|
|
267619
|
-
STATE_FILE3 = () => path245.join(WALNUT_HOME, "cache", "replica", "requests.json");
|
|
267620
|
-
STORE_FILE = () => path245.join(WALNUT_HOME, "session-requests.json");
|
|
267621
|
-
state13 = null;
|
|
267622
|
-
serial7 = serialChain();
|
|
267623
|
-
follower4 = null;
|
|
267624
|
-
}
|
|
267625
|
-
});
|
|
267626
|
-
|
|
267627
267842
|
// src/core/replication/kinds/sessions.ts
|
|
267628
267843
|
import fsp132 from "fs/promises";
|
|
267629
267844
|
import path246 from "path";
|
|
@@ -267654,11 +267869,11 @@ function projectedOf(row) {
|
|
|
267654
267869
|
}
|
|
267655
267870
|
return p6;
|
|
267656
267871
|
}
|
|
267657
|
-
function
|
|
267658
|
-
let h8 =
|
|
267872
|
+
function hashOf7(row) {
|
|
267873
|
+
let h8 = hashes6.get(row);
|
|
267659
267874
|
if (h8 === void 0) {
|
|
267660
267875
|
h8 = sessionCopyHash(row);
|
|
267661
|
-
|
|
267876
|
+
hashes6.set(row, h8);
|
|
267662
267877
|
}
|
|
267663
267878
|
return h8;
|
|
267664
267879
|
}
|
|
@@ -267678,7 +267893,7 @@ async function load8() {
|
|
|
267678
267893
|
async function save3() {
|
|
267679
267894
|
if (state14) await writeCopyFile(STATE_FILE4(), { v: 1, asOf: state14.asOf, at: state14.at, hashes: state14.hashes });
|
|
267680
267895
|
}
|
|
267681
|
-
function
|
|
267896
|
+
function isRow7(v3) {
|
|
267682
267897
|
const r8 = v3;
|
|
267683
267898
|
return !!r8 && typeof r8 === "object" && !Array.isArray(r8) && typeof r8.claudeSessionId === "string" && r8.claudeSessionId.length > 0 && r8.claudeSessionId.length <= 200;
|
|
267684
267899
|
}
|
|
@@ -267698,7 +267913,7 @@ function sessionsFollower() {
|
|
|
267698
267913
|
refuse: copyRefusal,
|
|
267699
267914
|
load: load8,
|
|
267700
267915
|
save: save3,
|
|
267701
|
-
isRow:
|
|
267916
|
+
isRow: isRow7,
|
|
267702
267917
|
key: (r8) => r8.claudeSessionId,
|
|
267703
267918
|
hash: sessionCopyHash,
|
|
267704
267919
|
localKeys: async () => (await Promise.resolve().then(() => (init_session_db(), session_db_exports))).sessionIdsInStore(),
|
|
@@ -267720,7 +267935,7 @@ function sessionsFollower() {
|
|
|
267720
267935
|
});
|
|
267721
267936
|
return follower5;
|
|
267722
267937
|
}
|
|
267723
|
-
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected,
|
|
267938
|
+
var SESSIONS_SCHEMA_VERSION, SESSIONS_REMOVAL_FLOOR, PROCESS_FIELDS, PROCESS_SET, VOLATILE_SESSION_FIELDS, VOLATILE_SET, projected, hashes6, SESSIONS_KIND, STATE_FILE4, state14, serial8, follower5;
|
|
267724
267939
|
var init_sessions3 = __esm({
|
|
267725
267940
|
"src/core/replication/kinds/sessions.ts"() {
|
|
267726
267941
|
"use strict";
|
|
@@ -267757,12 +267972,12 @@ var init_sessions3 = __esm({
|
|
|
267757
267972
|
VOLATILE_SESSION_FIELDS = ["lastActiveAt", "activity", "contextTokens"];
|
|
267758
267973
|
VOLATILE_SET = new Set(VOLATILE_SESSION_FIELDS);
|
|
267759
267974
|
projected = /* @__PURE__ */ new WeakMap();
|
|
267760
|
-
|
|
267975
|
+
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
267761
267976
|
SESSIONS_KIND = {
|
|
267762
267977
|
kind: "sessions",
|
|
267763
267978
|
schemaVersion: SESSIONS_SCHEMA_VERSION,
|
|
267764
267979
|
key: (s4) => s4.claudeSessionId,
|
|
267765
|
-
hash:
|
|
267980
|
+
hash: hashOf7,
|
|
267766
267981
|
ordered: false,
|
|
267767
267982
|
digest: true,
|
|
267768
267983
|
choice: "sessions",
|
|
@@ -267794,137 +268009,11 @@ var init_sessions3 = __esm({
|
|
|
267794
268009
|
}
|
|
267795
268010
|
});
|
|
267796
268011
|
|
|
267797
|
-
// src/core/replication/kinds/personas.ts
|
|
267798
|
-
var personas_exports = {};
|
|
267799
|
-
__export(personas_exports, {
|
|
267800
|
-
PERSONAS_KIND: () => PERSONAS_KIND,
|
|
267801
|
-
PERSONAS_REMOVAL_FLOOR: () => PERSONAS_REMOVAL_FLOOR,
|
|
267802
|
-
PERSONAS_SCHEMA_VERSION: () => PERSONAS_SCHEMA_VERSION,
|
|
267803
|
-
_resetPersonasCopyForTesting: () => _resetPersonasCopyForTesting,
|
|
267804
|
-
personasFollower: () => personasFollower,
|
|
267805
|
-
readPersonaCopy: () => readPersonaCopy
|
|
267806
|
-
});
|
|
267807
|
-
function tools(v3) {
|
|
267808
|
-
return Array.isArray(v3) && v3.length > 0 && v3.every((t3) => typeof t3 === "string" && TOOL_RE.test(t3)) ? [...v3] : void 0;
|
|
267809
|
-
}
|
|
267810
|
-
async function leaderRows2() {
|
|
267811
|
-
const [{ getConsoleAgents: getConsoleAgents2 }, { buildLaneProfile: buildLaneProfile2 }, { getConfig: getConfig2 }, { getAskWalnutLaunchPrefs: getAskWalnutLaunchPrefs2 }] = await Promise.all([
|
|
267812
|
-
Promise.resolve().then(() => (init_agent_registry(), agent_registry_exports)),
|
|
267813
|
-
Promise.resolve().then(() => (init_personal_ai_lane(), personal_ai_lane_exports)),
|
|
267814
|
-
Promise.resolve().then(() => (init_config_manager(), config_manager_exports)),
|
|
267815
|
-
Promise.resolve().then(() => (init_ask_walnut_launch(), ask_walnut_launch_exports))
|
|
267816
|
-
]);
|
|
267817
|
-
const config = await getConfig2();
|
|
267818
|
-
const launch = await getAskWalnutLaunchPrefs2().catch(() => ({}));
|
|
267819
|
-
const agents = [{ id: "general", name: "Walnut" }, ...(await getConsoleAgents2()).filter((a8) => a8.id !== "general").map((a8) => ({ id: a8.id, name: a8.name }))];
|
|
267820
|
-
const rows = [];
|
|
267821
|
-
for (const a8 of agents) {
|
|
267822
|
-
if (!ID_RE5.test(a8.id)) continue;
|
|
267823
|
-
try {
|
|
267824
|
-
const { profile, effort } = await buildLaneProfile2(config, a8.id);
|
|
267825
|
-
const prompt = profile.systemPrompt ?? "";
|
|
267826
|
-
if (!prompt || Buffer.byteLength(prompt, "utf8") > MAX_PROMPT_BYTES) continue;
|
|
267827
|
-
rows.push({
|
|
267828
|
-
key: a8.id,
|
|
267829
|
-
agentId: a8.id,
|
|
267830
|
-
name: String(a8.name ?? a8.id).slice(0, 120),
|
|
267831
|
-
systemPrompt: prompt,
|
|
267832
|
-
systemPromptMode: profile.systemPromptMode === "replace" ? "replace" : "append",
|
|
267833
|
-
...tools(profile.allowedTools) ? { allowedTools: tools(profile.allowedTools) } : {},
|
|
267834
|
-
...tools(profile.tools) ? { tools: tools(profile.tools) } : {},
|
|
267835
|
-
...effort ? { effort } : {},
|
|
267836
|
-
...launch.model ? { launchModel: launch.model } : {},
|
|
267837
|
-
...launch.effort ? { launchEffort: launch.effort } : {}
|
|
267838
|
-
});
|
|
267839
|
-
} catch (err2) {
|
|
267840
|
-
log.session.warn("copies: an agent persona was not rendered for the host", { agentId: a8.id, error: err2 instanceof Error ? err2.message : String(err2) });
|
|
267841
|
-
}
|
|
267842
|
-
}
|
|
267843
|
-
return rows;
|
|
267844
|
-
}
|
|
267845
|
-
function hashOf7(row) {
|
|
267846
|
-
let h8 = hashes6.get(row);
|
|
267847
|
-
if (h8 === void 0) {
|
|
267848
|
-
h8 = sha12(JSON.stringify(row));
|
|
267849
|
-
hashes6.set(row, h8);
|
|
267850
|
-
}
|
|
267851
|
-
return h8;
|
|
267852
|
-
}
|
|
267853
|
-
function isRow7(v3) {
|
|
267854
|
-
const r8 = v3;
|
|
267855
|
-
if (!r8 || typeof r8 !== "object" || Array.isArray(r8)) return false;
|
|
267856
|
-
if (Object.keys(r8).some((k8) => !ROW_KEYS.has(k8))) return false;
|
|
267857
|
-
if (typeof r8.key !== "string" || r8.key !== r8.agentId || !ID_RE5.test(r8.key) || typeof r8.name !== "string") return false;
|
|
267858
|
-
if (typeof r8.systemPrompt !== "string" || !r8.systemPrompt || Buffer.byteLength(r8.systemPrompt, "utf8") > MAX_PROMPT_BYTES) return false;
|
|
267859
|
-
if (r8.systemPromptMode !== "append" && r8.systemPromptMode !== "replace") return false;
|
|
267860
|
-
for (const k8 of ["allowedTools", "tools"]) if (r8[k8] !== void 0 && !tools(r8[k8])) return false;
|
|
267861
|
-
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;
|
|
267862
|
-
return true;
|
|
267863
|
-
}
|
|
267864
|
-
function admit2(r8) {
|
|
267865
|
-
return secretShapedValue(r8.systemPrompt) === null && secretShapedValue(r8.name) === null;
|
|
267866
|
-
}
|
|
267867
|
-
async function readPersonaCopy(agentId) {
|
|
267868
|
-
const rows = await copy3.read();
|
|
267869
|
-
return rows?.[agentId] ?? null;
|
|
267870
|
-
}
|
|
267871
|
-
function _resetPersonasCopyForTesting() {
|
|
267872
|
-
copy3.reset();
|
|
267873
|
-
}
|
|
267874
|
-
var PERSONAS_SCHEMA_VERSION, PERSONAS_REMOVAL_FLOOR, MAX_PROMPT_BYTES, ID_RE5, TOOL_RE, hashes6, PERSONAS_KIND, ROW_KEYS, copy3, personasFollower;
|
|
267875
|
-
var init_personas = __esm({
|
|
267876
|
-
"src/core/replication/kinds/personas.ts"() {
|
|
267877
|
-
"use strict";
|
|
267878
|
-
init_logging();
|
|
267879
|
-
init_config_allowlist();
|
|
267880
|
-
init_kind();
|
|
267881
|
-
init_file_copy();
|
|
267882
|
-
PERSONAS_SCHEMA_VERSION = 1;
|
|
267883
|
-
PERSONAS_REMOVAL_FLOOR = 0;
|
|
267884
|
-
MAX_PROMPT_BYTES = 120 * 1024;
|
|
267885
|
-
ID_RE5 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
267886
|
-
TOOL_RE = /^[A-Za-z0-9_.:*()/ -]{1,200}$/;
|
|
267887
|
-
hashes6 = /* @__PURE__ */ new WeakMap();
|
|
267888
|
-
PERSONAS_KIND = {
|
|
267889
|
-
kind: "personas",
|
|
267890
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
267891
|
-
key: (r8) => r8.key,
|
|
267892
|
-
hash: hashOf7,
|
|
267893
|
-
ordered: false,
|
|
267894
|
-
digest: false,
|
|
267895
|
-
choice: "personas",
|
|
267896
|
-
rows: leaderRows2,
|
|
267897
|
-
watch: (soon) => {
|
|
267898
|
-
let stop2 = null;
|
|
267899
|
-
let stopped2 = false;
|
|
267900
|
-
void Promise.resolve().then(() => (init_config_manager(), config_manager_exports)).then((cm) => {
|
|
267901
|
-
if (!stopped2) stop2 = cm.onConfigWritten(soon);
|
|
267902
|
-
});
|
|
267903
|
-
return () => {
|
|
267904
|
-
stopped2 = true;
|
|
267905
|
-
stop2?.();
|
|
267906
|
-
};
|
|
267907
|
-
}
|
|
267908
|
-
};
|
|
267909
|
-
ROW_KEYS = /* @__PURE__ */ new Set(["key", "agentId", "name", "systemPrompt", "systemPromptMode", "allowedTools", "tools", "effort", "launchModel", "launchEffort"]);
|
|
267910
|
-
copy3 = createFileCopy({
|
|
267911
|
-
kind: "personas",
|
|
267912
|
-
schemaVersion: PERSONAS_SCHEMA_VERSION,
|
|
267913
|
-
label: "personas copy",
|
|
267914
|
-
removalFloor: PERSONAS_REMOVAL_FLOOR,
|
|
267915
|
-
isRow: isRow7,
|
|
267916
|
-
key: (r8) => r8.key,
|
|
267917
|
-
admit: admit2
|
|
267918
|
-
});
|
|
267919
|
-
personasFollower = copy3.follower;
|
|
267920
|
-
}
|
|
267921
|
-
});
|
|
267922
|
-
|
|
267923
268012
|
// src/core/replication/kinds/index.ts
|
|
267924
268013
|
var kinds_exports = {};
|
|
267925
268014
|
__export(kinds_exports, {
|
|
268015
|
+
copyKeepersOnly: () => copyKeepersOnly,
|
|
267926
268016
|
copyKinds: () => copyKinds,
|
|
267927
|
-
hostReplicaOnly: () => hostReplicaOnly,
|
|
267928
268017
|
registerCopyFollowerKinds: () => registerCopyFollowerKinds,
|
|
267929
268018
|
startCopyKinds: () => startCopyKinds
|
|
267930
268019
|
});
|
|
@@ -267942,14 +268031,14 @@ function copyKinds() {
|
|
|
267942
268031
|
PERSONAS_KIND
|
|
267943
268032
|
];
|
|
267944
268033
|
}
|
|
267945
|
-
function
|
|
268034
|
+
function copyKeepersOnly(h8) {
|
|
267946
268035
|
return {
|
|
267947
268036
|
kind: h8.kind,
|
|
267948
|
-
// followerStep checks the version before the step: never `schema_newer`
|
|
268037
|
+
// followerStep checks the version before the step: never `schema_newer` where the kind is not kept.
|
|
267949
268038
|
get schemaVersion() {
|
|
267950
|
-
return keepsCopies() ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
268039
|
+
return keepsCopies(h8.kind) ? h8.schemaVersion : Number.MAX_SAFE_INTEGER;
|
|
267951
268040
|
},
|
|
267952
|
-
step: (op2, body7) => keepsCopies() ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
268041
|
+
step: (op2, body7) => keepsCopies(h8.kind) ? h8.step(op2, body7) : { ok: false, status: 404, error: "unknown_kind" }
|
|
267953
268042
|
};
|
|
267954
268043
|
}
|
|
267955
268044
|
function registerCopyFollowerKinds() {
|
|
@@ -267964,7 +268053,7 @@ function registerCopyFollowerKinds() {
|
|
|
267964
268053
|
prefsFollower(),
|
|
267965
268054
|
configFollower(),
|
|
267966
268055
|
personasFollower()
|
|
267967
|
-
].map((h8) => registerFollowerKind(
|
|
268056
|
+
].map((h8) => registerFollowerKind(copyKeepersOnly(h8)));
|
|
267968
268057
|
return () => {
|
|
267969
268058
|
for (const u3 of off) u3();
|
|
267970
268059
|
};
|
|
@@ -313047,9 +313136,13 @@ var init_task_replica_store = __esm({
|
|
|
313047
313136
|
// src/core/replication/kinds/gate.ts
|
|
313048
313137
|
var gate_exports = {};
|
|
313049
313138
|
__export(gate_exports, {
|
|
313139
|
+
COMPANION_COPY_KINDS: () => COMPANION_COPY_KINDS,
|
|
313140
|
+
COPY_AS_OF_HEADER: () => COPY_AS_OF_HEADER,
|
|
313050
313141
|
KIND_NOT_COPIED: () => KIND_NOT_COPIED,
|
|
313142
|
+
copyKindAsOf: () => copyKindAsOf,
|
|
313051
313143
|
copyKindHeld: () => copyKindHeld,
|
|
313052
313144
|
copyKindOff: () => copyKindOff,
|
|
313145
|
+
copyPath: () => copyPath,
|
|
313053
313146
|
copyRefusal: () => copyRefusal,
|
|
313054
313147
|
copyStateFile: () => copyStateFile,
|
|
313055
313148
|
keepsCopies: () => keepsCopies,
|
|
@@ -313057,8 +313150,16 @@ __export(gate_exports, {
|
|
|
313057
313150
|
});
|
|
313058
313151
|
import fsp149 from "fs/promises";
|
|
313059
313152
|
import path293 from "path";
|
|
313060
|
-
function keepsCopies() {
|
|
313061
|
-
|
|
313153
|
+
function keepsCopies(kind) {
|
|
313154
|
+
if (isHostReplicaProgram()) return true;
|
|
313155
|
+
if (followerKind() !== "companion") return false;
|
|
313156
|
+
return kind === void 0 || COMPANION_COPY_KINDS.has(kind);
|
|
313157
|
+
}
|
|
313158
|
+
function copyPath(live6) {
|
|
313159
|
+
if (followerKind() !== "companion") return live6;
|
|
313160
|
+
const rel = path293.relative(WALNUT_HOME, live6);
|
|
313161
|
+
if (!rel || rel.startsWith("..") || path293.isAbsolute(rel)) throw new Error(`copyPath: ${live6} is not under the data dir`);
|
|
313162
|
+
return path293.join(WALNUT_HOME, "cache", "replica", "home", rel);
|
|
313062
313163
|
}
|
|
313063
313164
|
async function copyRefusal() {
|
|
313064
313165
|
if (!keepsCopies()) return { status: 404, error: "unknown_kind" };
|
|
@@ -313079,20 +313180,26 @@ async function copyKindOff(kind) {
|
|
|
313079
313180
|
}
|
|
313080
313181
|
}
|
|
313081
313182
|
async function copyKindHeld(kind) {
|
|
313183
|
+
return await copyKindAsOf(kind) !== null;
|
|
313184
|
+
}
|
|
313185
|
+
async function copyKindAsOf(kind) {
|
|
313082
313186
|
try {
|
|
313083
313187
|
const raw = JSON.parse(await fsp149.readFile(copyStateFile(kind), "utf8"));
|
|
313084
|
-
|
|
313188
|
+
if (!(raw?.v === 1 && raw.off !== true && !!raw.hashes && typeof raw.hashes === "object")) return null;
|
|
313189
|
+
return Number(raw.asOf) || 0;
|
|
313085
313190
|
} catch {
|
|
313086
|
-
return
|
|
313191
|
+
return null;
|
|
313087
313192
|
}
|
|
313088
313193
|
}
|
|
313089
|
-
var KIND_NOT_COPIED;
|
|
313194
|
+
var COMPANION_COPY_KINDS, COPY_AS_OF_HEADER, KIND_NOT_COPIED;
|
|
313090
313195
|
var init_gate = __esm({
|
|
313091
313196
|
"src/core/replication/kinds/gate.ts"() {
|
|
313092
313197
|
"use strict";
|
|
313093
313198
|
init_constants();
|
|
313094
313199
|
init_server_role();
|
|
313095
313200
|
init_kind_follower();
|
|
313201
|
+
COMPANION_COPY_KINDS = /* @__PURE__ */ new Set(["requests", "routines", "prefs", "personas"]);
|
|
313202
|
+
COPY_AS_OF_HEADER = "x-walnut-copy-as-of";
|
|
313096
313203
|
KIND_NOT_COPIED = "kind_not_copied";
|
|
313097
313204
|
}
|
|
313098
313205
|
});
|