negotium 0.2.13 → 0.2.14

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.
Files changed (41) hide show
  1. package/dist/agent-helpers.js +13 -12
  2. package/dist/agent-helpers.js.map +6 -6
  3. package/dist/background-bash.js +11 -11
  4. package/dist/background-bash.js.map +4 -4
  5. package/dist/browser-runtime.js +2 -3
  6. package/dist/browser-runtime.js.map +3 -3
  7. package/dist/{chunk-rnsnhcye.js → chunk-5g5a63vv.js} +11 -11
  8. package/dist/{chunk-rnsnhcye.js.map → chunk-5g5a63vv.js.map} +4 -4
  9. package/dist/hosted-agent.js +12 -12
  10. package/dist/hosted-agent.js.map +5 -5
  11. package/dist/main.js +582 -357
  12. package/dist/main.js.map +12 -11
  13. package/dist/mcp-factories.js +13 -12
  14. package/dist/mcp-factories.js.map +6 -6
  15. package/dist/mcp-servers.js +3 -2
  16. package/dist/mcp-servers.js.map +3 -3
  17. package/dist/prompts.js +2 -3
  18. package/dist/prompts.js.map +3 -3
  19. package/dist/query-runtime.js +2 -3
  20. package/dist/query-runtime.js.map +3 -3
  21. package/dist/registry.js +3 -3
  22. package/dist/registry.js.map +2 -2
  23. package/dist/rollout.js +1 -1
  24. package/dist/runtime/src/index.ts +9 -0
  25. package/dist/runtime/src/node-host.ts +9 -0
  26. package/dist/runtime/src/platform/background-bash/manager.ts +30 -22
  27. package/dist/runtime/src/platform/config.ts +8 -7
  28. package/dist/runtime/src/runtime/bashrs-completions.ts +74 -14
  29. package/dist/runtime/src/runtime/turn-runner.ts +6 -0
  30. package/dist/runtime/src/version.ts +1 -1
  31. package/dist/runtime-helpers.js +2 -3
  32. package/dist/runtime-helpers.js.map +3 -3
  33. package/dist/types/apps/negotium/src/mcp-servers.d.ts +16 -3
  34. package/dist/types/packages/core/src/platform/background-bash/manager.d.ts +6 -1
  35. package/dist/types/packages/core/src/platform/config.d.ts +8 -6
  36. package/dist/types/packages/core/src/version.d.ts +1 -1
  37. package/dist/vault.js +2 -3
  38. package/dist/vault.js.map +3 -3
  39. package/install-bash-rs.mjs +5 -5
  40. package/package.json +1 -1
  41. package/dist/runtime/src/mcp/background-bash-server.ts +0 -756
package/dist/main.js CHANGED
@@ -263,7 +263,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
263
263
  function codexAuthFilePath() {
264
264
  return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
265
265
  }
266
- var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.2", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, BACKGROUND_BASH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
266
+ var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.19", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.5", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, BROWSER_MCP_SSE_PROXY_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
267
267
  var init_config = __esm(() => {
268
268
  init_config_helpers();
269
269
  init_logger();
@@ -300,7 +300,6 @@ var init_config = __esm(() => {
300
300
  COMPACTION_LOG_SERVER = resolve(PROJECT_ROOT, "src/mcp/compaction-log-server.ts");
301
301
  SYSTEM_HEALTH_SERVER = resolve(PROJECT_ROOT, "src/mcp/system-health-server.ts");
302
302
  AGENT_HEALTH_SERVER = resolve(PROJECT_ROOT, "src/mcp/agent-health-server.ts");
303
- BACKGROUND_BASH_SERVER = resolve(PROJECT_ROOT, "src/mcp/background-bash-server.ts");
304
303
  VAULT_SERVER = resolve(PROJECT_ROOT, "src/mcp/vault-server.ts");
305
304
  BG_BASH_BASE_PORT = parsePortEnv(process.env.BG_BASH_BASE_PORT, 9700);
306
305
  BG_BASH_MAX_PORT = parsePortEnv(process.env.BG_BASH_MAX_PORT, 9799);
@@ -1573,7 +1572,7 @@ var exports_version = {};
1573
1572
  __export(exports_version, {
1574
1573
  NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
1575
1574
  });
1576
- var NEGOTIUM_VERSION = "0.2.13";
1575
+ var NEGOTIUM_VERSION = "0.2.14";
1577
1576
 
1578
1577
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
1579
1578
  import { spawn } from "child_process";
@@ -2117,7 +2116,7 @@ function createBackgroundBashManager(options = {}) {
2117
2116
  const knownContexts = new Map;
2118
2117
  const runtimeCapability = options.capability ?? randomBytes3(32).toString("hex");
2119
2118
  const runtimeServerId = options.serverId ?? randomBytes3(16).toString("hex");
2120
- const serverFile = options.serverFile ?? BACKGROUND_BASH_SERVER;
2119
+ const bashRsBin = options.bashRsBin ?? BASH_RS_BIN;
2121
2120
  const basePort = options.basePort ?? BG_BASH_BASE_PORT;
2122
2121
  const maxPort = options.maxPort ?? BG_BASH_MAX_PORT;
2123
2122
  const fetchImpl = options.fetch ?? globalThis.fetch;
@@ -2154,11 +2153,10 @@ function createBackgroundBashManager(options = {}) {
2154
2153
  const body = await response.text();
2155
2154
  try {
2156
2155
  const parsed = JSON.parse(body);
2157
- if (parsed && typeof parsed === "object" && "instance_id" in parsed) {
2158
- return parsed.instance_id === runtimeServerId;
2159
- }
2160
- } catch {}
2161
- return body === runtimeServerId;
2156
+ return Boolean(parsed) && typeof parsed === "object" && parsed.instance_id === runtimeServerId;
2157
+ } catch {
2158
+ return false;
2159
+ }
2162
2160
  } catch {
2163
2161
  return false;
2164
2162
  }
@@ -2176,9 +2174,11 @@ function createBackgroundBashManager(options = {}) {
2176
2174
  logger.info({ key, port: instance.port }, "background-bash server killed");
2177
2175
  }
2178
2176
  async function spawnServer(key, reservedPort, excludedPorts = new Set) {
2177
+ if (!bashRsBin) {
2178
+ throw new Error(`background-bash requires the bash-rs ${BASH_RS_VERSION} binary; run install-bash-rs.mjs (or set NEGOTIUM_BASH_RS_BIN)`);
2179
+ }
2179
2180
  const port = reservedPort ?? await allocatePort(excludedPorts);
2180
- const [command, args] = BASH_RS_BIN ? [BASH_RS_BIN, [String(port)]] : ["bun", ["run", serverFile, `--port=${port}`]];
2181
- const process2 = spawnImpl(command, args, {
2181
+ const process2 = spawnImpl(bashRsBin, [String(port)], {
2182
2182
  stdio: "ignore",
2183
2183
  detached: false,
2184
2184
  env: {
@@ -18642,6 +18642,7 @@ function startAiTurn(params) {
18642
18642
  bgBashPort = await ensureBgBash(userId, topic.id);
18643
18643
  } catch (err2) {
18644
18644
  logger.warn({ topicId, err: err2 }, "ai: ensureBgBash failed \u2014 proceeding without background bash tools");
18645
+ turnReminders.push("<system-reminder>Background bash tools are UNAVAILABLE this turn. The `background_bash_*` tools could not be prepared, most often because the bash-rs binary is not installed on this host. Do not attempt to call them; run short commands in the foreground instead, and tell the user if the work genuinely needs a background job.</system-reminder>");
18645
18646
  }
18646
18647
  }
18647
18648
  if (playwrightRequested && !browserProfileOwner) {
@@ -20984,6 +20985,276 @@ var init_node_plugins = __esm(() => {
20984
20985
  plugins = [];
20985
20986
  });
20986
20987
 
20988
+ // ../../packages/core/src/outbox/utils.ts
20989
+ import { mkdirSync as mkdirSync22, watch } from "fs";
20990
+ function createOutboxWatchOps(host) {
20991
+ function debouncedFlush(fn, label, delayMs) {
20992
+ let timer = null;
20993
+ let running = false;
20994
+ let pending = false;
20995
+ async function run() {
20996
+ if (running) {
20997
+ pending = true;
20998
+ return;
20999
+ }
21000
+ while (true) {
21001
+ running = true;
21002
+ pending = false;
21003
+ try {
21004
+ await fn();
21005
+ } catch (e) {
21006
+ host.logger.error({ err: e }, `${label}: Unhandled error`);
21007
+ } finally {
21008
+ running = false;
21009
+ }
21010
+ if (!pending)
21011
+ break;
21012
+ }
21013
+ }
21014
+ return () => {
21015
+ if (timer)
21016
+ clearTimeout(timer);
21017
+ timer = setTimeout(() => {
21018
+ timer = null;
21019
+ run();
21020
+ }, delayMs);
21021
+ };
21022
+ }
21023
+ function watchDir(dir, onChange) {
21024
+ try {
21025
+ mkdirSync22(dir, { recursive: true });
21026
+ const watcher = watch(dir, { recursive: true }, () => onChange());
21027
+ watcher.on("error", (e) => {
21028
+ host.logger.warn({ err: e, dir }, "outbox: fs.watch error");
21029
+ });
21030
+ return watcher;
21031
+ } catch (e) {
21032
+ host.logger.warn({ err: e, dir }, "outbox: Failed to watch dir");
21033
+ return null;
21034
+ }
21035
+ }
21036
+ return { debouncedFlush, watchDir };
21037
+ }
21038
+ var FALLBACK_INTERVAL_MS = 5000, defaultWatchOps, debouncedFlush, watchDir;
21039
+ var init_utils = __esm(() => {
21040
+ init_logger();
21041
+ defaultWatchOps = createOutboxWatchOps({ logger });
21042
+ debouncedFlush = defaultWatchOps.debouncedFlush;
21043
+ watchDir = defaultWatchOps.watchDir;
21044
+ });
21045
+
21046
+ // ../../packages/core/src/runtime/bashrs-completions.ts
21047
+ import {
21048
+ closeSync as closeSync3,
21049
+ openSync as openSync3,
21050
+ readdirSync as readdirSync7,
21051
+ readFileSync as readFileSync18,
21052
+ readSync,
21053
+ renameSync as renameSync9,
21054
+ rmSync as rmSync8,
21055
+ statSync as statSync12
21056
+ } from "fs";
21057
+ import { join as join31 } from "path";
21058
+ function setBashrsCompletionSink(sink) {
21059
+ completionSink = sink ?? defaultSink;
21060
+ }
21061
+ function isJobResult(value) {
21062
+ if (!value || typeof value !== "object")
21063
+ return false;
21064
+ const v = value;
21065
+ return typeof v.bash_id === "string" && typeof v.owner === "string";
21066
+ }
21067
+ function readTail(filePath) {
21068
+ try {
21069
+ const { size } = statSync12(filePath);
21070
+ const fd = openSync3(filePath, "r");
21071
+ try {
21072
+ const start = Math.max(0, size - TAIL_BYTES);
21073
+ const buf = Buffer.alloc(size - start);
21074
+ readSync(fd, buf, 0, buf.length, start);
21075
+ return { text: buf.toString("utf8"), truncated: start > 0 };
21076
+ } finally {
21077
+ closeSync3(fd);
21078
+ }
21079
+ } catch {
21080
+ return { text: "", truncated: false };
21081
+ }
21082
+ }
21083
+ function buildMessage(dir, result) {
21084
+ const stdout = readTail(join31(dir, "stdout.log"));
21085
+ const stderr = readTail(join31(dir, "stderr.log"));
21086
+ const parts = [];
21087
+ if (stdout.text.trim() || stdout.truncated) {
21088
+ parts.push(`stdout${stdout.truncated ? ` (truncated, full output: ${join31(dir, "stdout.log")})` : ""}:
21089
+ ${stdout.text.trim()}`);
21090
+ }
21091
+ if (stderr.text.trim() || stderr.truncated) {
21092
+ parts.push(`stderr${stderr.truncated ? ` (truncated, full output: ${join31(dir, "stderr.log")})` : ""}:
21093
+ ${stderr.text.trim()}`);
21094
+ }
21095
+ const header = watchHeader(result) ?? `[background_bash ${result.bash_id} finished]`;
21096
+ const exitLine = result.unknown ? "exit code: unknown (bash-rs restarted while this job was running)" : `exit code: ${result.exit_code ?? "unknown"}`;
21097
+ return `${header}
21098
+ ${exitLine}
21099
+ ${parts.join(`
21100
+ `) || "(no output)"}`;
21101
+ }
21102
+ function watchHeader(result) {
21103
+ if (result.matched_line) {
21104
+ return `[background_bash_watch ${result.bash_id} matched]
21105
+ matched line: ${result.matched_line.slice(0, 500)}`;
21106
+ }
21107
+ if (result.watch_outcome === "timeout") {
21108
+ return `[background_bash_watch ${result.bash_id} timed out without a match]`;
21109
+ }
21110
+ if (result.watch_outcome === "exited") {
21111
+ return `[background_bash_watch ${result.bash_id} exited before matching]`;
21112
+ }
21113
+ return null;
21114
+ }
21115
+ function parseOwner(owner) {
21116
+ const nul = owner.indexOf("\x00");
21117
+ if (nul < 0)
21118
+ return null;
21119
+ const userId = owner.slice(0, nul);
21120
+ const topicId = owner.slice(nul + 1);
21121
+ if (!userId || !topicId)
21122
+ return null;
21123
+ return { userId, topicId };
21124
+ }
21125
+ function injectedMarker(dir) {
21126
+ return join31(dir, "result.json.injected");
21127
+ }
21128
+ async function flushBashrsCompletions() {
21129
+ let entries;
21130
+ try {
21131
+ entries = readdirSync7(BASHRS_SPILL_ROOT);
21132
+ } catch {
21133
+ return;
21134
+ }
21135
+ const now = Date.now();
21136
+ for (const bashId of entries) {
21137
+ const dir = join31(BASHRS_SPILL_ROOT, bashId);
21138
+ const resultPath = join31(dir, "result.json");
21139
+ const marker = injectedMarker(dir);
21140
+ try {
21141
+ const markerStat = statSync12(marker);
21142
+ if (now - markerStat.mtimeMs > RETENTION_MS) {
21143
+ rmSync8(dir, { recursive: true, force: true });
21144
+ }
21145
+ continue;
21146
+ } catch {}
21147
+ let raw;
21148
+ try {
21149
+ raw = readFileSync18(resultPath, "utf8");
21150
+ } catch {
21151
+ continue;
21152
+ }
21153
+ let result;
21154
+ try {
21155
+ result = JSON.parse(raw);
21156
+ } catch (err2) {
21157
+ logger.warn({ err: err2, dir }, "bashrs-completions: corrupt result.json, skipping");
21158
+ continue;
21159
+ }
21160
+ if (!isJobResult(result)) {
21161
+ logger.warn({ dir }, "bashrs-completions: result.json missing bash_id/owner, skipping");
21162
+ continue;
21163
+ }
21164
+ const parsed = parseOwner(result.owner);
21165
+ if (!parsed) {
21166
+ continue;
21167
+ }
21168
+ try {
21169
+ completionSink({
21170
+ userId: parsed.userId,
21171
+ topicId: parsed.topicId,
21172
+ bashId: result.bash_id,
21173
+ message: buildMessage(dir, result)
21174
+ });
21175
+ renameSync9(resultPath, marker);
21176
+ logger.info({ bashId: result.bash_id, userId: parsed.userId, topicId: parsed.topicId }, "bashrs-completions: delivered");
21177
+ } catch (err2) {
21178
+ logger.warn({ err: err2, dir }, "bashrs-completions: delivery failed, will retry");
21179
+ }
21180
+ }
21181
+ }
21182
+ function stopLeaderResources() {
21183
+ if (watcher) {
21184
+ watcher.close();
21185
+ watcher = null;
21186
+ }
21187
+ if (fallbackTimer) {
21188
+ clearInterval(fallbackTimer);
21189
+ fallbackTimer = null;
21190
+ }
21191
+ debouncedTrigger = null;
21192
+ }
21193
+ function tryBecomeLeader() {
21194
+ if (!workerStarted || workerLease)
21195
+ return;
21196
+ const acquired = acquireRuntimeProcessLease(PROCESS_ROLE, {
21197
+ onLost: () => {
21198
+ if (workerLease !== acquired)
21199
+ return;
21200
+ workerLease = null;
21201
+ stopLeaderResources();
21202
+ logger.warn("bashrs-completions: worker leadership lost");
21203
+ }
21204
+ });
21205
+ if (!acquired)
21206
+ return;
21207
+ workerLease = acquired;
21208
+ debouncedTrigger = debouncedFlush(flushBashrsCompletions, "bashrs-completions", 200);
21209
+ watcher = watchDir(BASHRS_SPILL_ROOT, () => debouncedTrigger?.());
21210
+ fallbackTimer = setInterval(() => debouncedTrigger?.(), FALLBACK_INTERVAL_MS);
21211
+ fallbackTimer.unref?.();
21212
+ logger.info({ dir: BASHRS_SPILL_ROOT, role: PROCESS_ROLE }, "bashrs-completions: worker leadership acquired");
21213
+ flushBashrsCompletions();
21214
+ }
21215
+ function startBashrsCompletionsWorker() {
21216
+ if (workerStarted)
21217
+ return () => {};
21218
+ workerStarted = true;
21219
+ tryBecomeLeader();
21220
+ leadershipTimer = setInterval(tryBecomeLeader, PROCESS_LEASE_HEARTBEAT_MS);
21221
+ leadershipTimer.unref?.();
21222
+ return () => {
21223
+ if (!workerStarted)
21224
+ return;
21225
+ workerStarted = false;
21226
+ if (leadershipTimer) {
21227
+ clearInterval(leadershipTimer);
21228
+ leadershipTimer = null;
21229
+ }
21230
+ stopLeaderResources();
21231
+ workerLease?.stop();
21232
+ workerLease = null;
21233
+ logger.info("bashrs-completions: worker stopped");
21234
+ };
21235
+ }
21236
+ var defaultSink = ({ userId, topicId, bashId, message }) => {
21237
+ appendJsonlEntry(sessionInboxPath(userId, topicId), {
21238
+ type: "tell",
21239
+ from: "__bg_bash__",
21240
+ message,
21241
+ depth: 0,
21242
+ requestId: bashId,
21243
+ timestamp: new Date().toISOString()
21244
+ });
21245
+ }, completionSink, PROCESS_ROLE = "worker:bashrs-completions", RETENTION_MS, TAIL_BYTES, watcher = null, fallbackTimer = null, debouncedTrigger = null, leadershipTimer = null, workerLease = null, workerStarted = false;
21246
+ var init_bashrs_completions = __esm(async () => {
21247
+ init_utils();
21248
+ init_config();
21249
+ init_jsonl();
21250
+ init_logger();
21251
+ init_session_inbox_path();
21252
+ await init_runtime_process_leases();
21253
+ completionSink = defaultSink;
21254
+ RETENTION_MS = 15 * 60000;
21255
+ TAIL_BYTES = 8 * 1024;
21256
+ });
21257
+
20987
21258
  // ../../packages/core/src/runtime/delivery-ack.ts
20988
21259
  function signalForMessage(payload, messageId) {
20989
21260
  if (!payload || typeof payload !== "object")
@@ -21070,7 +21341,7 @@ function renderTurnFooter(msg) {
21070
21341
 
21071
21342
  // ../../packages/core/src/outbox/file-ops.ts
21072
21343
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
21073
- import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as readFileSync18, renameSync as renameSync9, unlinkSync as unlinkSync17 } from "fs";
21344
+ import { appendFileSync as appendFileSync2, existsSync as existsSync22, readFileSync as readFileSync19, renameSync as renameSync10, unlinkSync as unlinkSync17 } from "fs";
21074
21345
  function host() {
21075
21346
  return hostContext.getStore() ?? defaultHost2;
21076
21347
  }
@@ -21097,7 +21368,7 @@ function drainOutboxFile(filePath, label) {
21097
21368
  else
21098
21369
  host().logger.info(logCtx, logMsg);
21099
21370
  try {
21100
- const leftover = readFileSync18(processingPath, "utf-8");
21371
+ const leftover = readFileSync19(processingPath, "utf-8");
21101
21372
  if (leftover)
21102
21373
  appendFileSync2(filePath, leftover.endsWith(`
21103
21374
  `) ? leftover : `${leftover}
@@ -21111,7 +21382,7 @@ function drainOutboxFile(filePath, label) {
21111
21382
  if (!existsSync22(filePath))
21112
21383
  return null;
21113
21384
  try {
21114
- renameSync9(filePath, processingPath);
21385
+ renameSync10(filePath, processingPath);
21115
21386
  } catch (e) {
21116
21387
  host().logger.warn({ err: e, filePath }, `${label}: failed to rename for processing`);
21117
21388
  return null;
@@ -21159,68 +21430,10 @@ var init_file_ops = __esm(() => {
21159
21430
  hostContext = new AsyncLocalStorage2;
21160
21431
  });
21161
21432
 
21162
- // ../../packages/core/src/outbox/utils.ts
21163
- import { mkdirSync as mkdirSync22, watch } from "fs";
21164
- function createOutboxWatchOps(host2) {
21165
- function debouncedFlush(fn, label, delayMs) {
21166
- let timer = null;
21167
- let running = false;
21168
- let pending = false;
21169
- async function run() {
21170
- if (running) {
21171
- pending = true;
21172
- return;
21173
- }
21174
- while (true) {
21175
- running = true;
21176
- pending = false;
21177
- try {
21178
- await fn();
21179
- } catch (e) {
21180
- host2.logger.error({ err: e }, `${label}: Unhandled error`);
21181
- } finally {
21182
- running = false;
21183
- }
21184
- if (!pending)
21185
- break;
21186
- }
21187
- }
21188
- return () => {
21189
- if (timer)
21190
- clearTimeout(timer);
21191
- timer = setTimeout(() => {
21192
- timer = null;
21193
- run();
21194
- }, delayMs);
21195
- };
21196
- }
21197
- function watchDir(dir, onChange) {
21198
- try {
21199
- mkdirSync22(dir, { recursive: true });
21200
- const watcher = watch(dir, { recursive: true }, () => onChange());
21201
- watcher.on("error", (e) => {
21202
- host2.logger.warn({ err: e, dir }, "outbox: fs.watch error");
21203
- });
21204
- return watcher;
21205
- } catch (e) {
21206
- host2.logger.warn({ err: e, dir }, "outbox: Failed to watch dir");
21207
- return null;
21208
- }
21209
- }
21210
- return { debouncedFlush, watchDir };
21211
- }
21212
- var FALLBACK_INTERVAL_MS = 5000, defaultWatchOps, debouncedFlush, watchDir;
21213
- var init_utils = __esm(() => {
21214
- init_logger();
21215
- defaultWatchOps = createOutboxWatchOps({ logger });
21216
- debouncedFlush = defaultWatchOps.debouncedFlush;
21217
- watchDir = defaultWatchOps.watchDir;
21218
- });
21219
-
21220
21433
  // ../../packages/core/src/runtime/inbox.ts
21221
21434
  import { createHash as createHash8, randomUUID as randomUUID20 } from "crypto";
21222
- import { readdirSync as readdirSync7, statSync as statSync12, writeFileSync as writeFileSync16 } from "fs";
21223
- import { join as join31 } from "path";
21435
+ import { readdirSync as readdirSync8, statSync as statSync13, writeFileSync as writeFileSync16 } from "fs";
21436
+ import { join as join32 } from "path";
21224
21437
  async function createAskForkPlan(options) {
21225
21438
  const snapshot = structuredClone(options.entries);
21226
21439
  const prepareSession = async () => options.synthesize(structuredClone(snapshot));
@@ -21340,23 +21553,23 @@ async function flushSessionInbox() {
21340
21553
  sweepScheduledSessionInbox();
21341
21554
  let userDirs;
21342
21555
  try {
21343
- userDirs = readdirSync7(SESSION_INBOX_DIR);
21556
+ userDirs = readdirSync8(SESSION_INBOX_DIR);
21344
21557
  } catch {
21345
21558
  return;
21346
21559
  }
21347
21560
  for (const uid of userDirs) {
21348
- const userInboxDir = join31(SESSION_INBOX_DIR, uid);
21561
+ const userInboxDir = join32(SESSION_INBOX_DIR, uid);
21349
21562
  let entries;
21350
21563
  try {
21351
- entries = readdirSync7(userInboxDir);
21564
+ entries = readdirSync8(userInboxDir);
21352
21565
  } catch {
21353
21566
  continue;
21354
21567
  }
21355
21568
  for (const entry of entries) {
21356
- const entryPath = join31(userInboxDir, entry);
21569
+ const entryPath = join32(userInboxDir, entry);
21357
21570
  let isDir = false;
21358
21571
  try {
21359
- isDir = statSync12(entryPath).isDirectory();
21572
+ isDir = statSync13(entryPath).isDirectory();
21360
21573
  } catch {
21361
21574
  continue;
21362
21575
  }
@@ -21438,15 +21651,15 @@ ${schedule.message}`, topic.agent, {
21438
21651
  function sweepScheduledSessionInbox(nowMs = Date.now()) {
21439
21652
  let userDirs;
21440
21653
  try {
21441
- userDirs = readdirSync7(SESSION_INBOX_DIR);
21654
+ userDirs = readdirSync8(SESSION_INBOX_DIR);
21442
21655
  } catch {
21443
21656
  return;
21444
21657
  }
21445
21658
  for (const userId of userDirs) {
21446
- const userInboxDir = join31(SESSION_INBOX_DIR, userId);
21659
+ const userInboxDir = join32(SESSION_INBOX_DIR, userId);
21447
21660
  let files;
21448
21661
  try {
21449
- files = readdirSync7(userInboxDir);
21662
+ files = readdirSync8(userInboxDir);
21450
21663
  } catch {
21451
21664
  continue;
21452
21665
  }
@@ -21455,7 +21668,7 @@ function sweepScheduledSessionInbox(nowMs = Date.now()) {
21455
21668
  const topicId = topicIdFromScheduledSessionInboxFileName(file);
21456
21669
  if (!topicId)
21457
21670
  continue;
21458
- const schedulePath = join31(userInboxDir, file);
21671
+ const schedulePath = join32(userInboxDir, file);
21459
21672
  const hasProcessingClaim = files.includes(`${file}.processing`);
21460
21673
  if (!hasProcessingClaim && !scheduledFileNeedsClaim(schedulePath, nowMs))
21461
21674
  continue;
@@ -21809,62 +22022,62 @@ ${entry.message}
21809
22022
  });
21810
22023
  logger.info({ topicName, from: entry.from, requestId, callerTopicId }, "session-inbox: ask delivered");
21811
22024
  }
21812
- function stopLeaderResources() {
21813
- if (watcher) {
21814
- watcher.close();
21815
- watcher = null;
22025
+ function stopLeaderResources2() {
22026
+ if (watcher2) {
22027
+ watcher2.close();
22028
+ watcher2 = null;
21816
22029
  }
21817
- if (fallbackTimer) {
21818
- clearInterval(fallbackTimer);
21819
- fallbackTimer = null;
22030
+ if (fallbackTimer2) {
22031
+ clearInterval(fallbackTimer2);
22032
+ fallbackTimer2 = null;
21820
22033
  }
21821
- debouncedTrigger = null;
22034
+ debouncedTrigger2 = null;
21822
22035
  }
21823
22036
  function tryBecomeSessionInboxLeader() {
21824
- if (!workerStarted || workerLease)
22037
+ if (!workerStarted2 || workerLease2)
21825
22038
  return;
21826
22039
  let acquired = null;
21827
22040
  acquired = acquireRuntimeProcessLease(SESSION_INBOX_PROCESS_ROLE, {
21828
22041
  onLost: () => {
21829
- if (workerLease !== acquired)
22042
+ if (workerLease2 !== acquired)
21830
22043
  return;
21831
- workerLease = null;
21832
- stopLeaderResources();
22044
+ workerLease2 = null;
22045
+ stopLeaderResources2();
21833
22046
  logger.warn("session-inbox: worker leadership lost");
21834
22047
  }
21835
22048
  });
21836
22049
  if (!acquired)
21837
22050
  return;
21838
- workerLease = acquired;
21839
- debouncedTrigger = debouncedFlush(flushSessionInbox, "session-inbox", 200);
21840
- watcher = watchDir(SESSION_INBOX_DIR, () => debouncedTrigger?.());
21841
- fallbackTimer = setInterval(() => debouncedTrigger?.(), FALLBACK_INTERVAL_MS);
21842
- fallbackTimer.unref?.();
22051
+ workerLease2 = acquired;
22052
+ debouncedTrigger2 = debouncedFlush(flushSessionInbox, "session-inbox", 200);
22053
+ watcher2 = watchDir(SESSION_INBOX_DIR, () => debouncedTrigger2?.());
22054
+ fallbackTimer2 = setInterval(() => debouncedTrigger2?.(), FALLBACK_INTERVAL_MS);
22055
+ fallbackTimer2.unref?.();
21843
22056
  logger.info({ dir: SESSION_INBOX_DIR, role: SESSION_INBOX_PROCESS_ROLE }, "session-inbox: worker leadership acquired");
21844
22057
  flushSessionInbox();
21845
22058
  }
21846
22059
  function startSessionInboxWorker() {
21847
- if (workerStarted)
22060
+ if (workerStarted2)
21848
22061
  return () => {};
21849
- workerStarted = true;
22062
+ workerStarted2 = true;
21850
22063
  tryBecomeSessionInboxLeader();
21851
- leadershipTimer = setInterval(tryBecomeSessionInboxLeader, PROCESS_LEASE_HEARTBEAT_MS);
21852
- leadershipTimer.unref?.();
22064
+ leadershipTimer2 = setInterval(tryBecomeSessionInboxLeader, PROCESS_LEASE_HEARTBEAT_MS);
22065
+ leadershipTimer2.unref?.();
21853
22066
  return () => {
21854
- if (!workerStarted)
22067
+ if (!workerStarted2)
21855
22068
  return;
21856
- workerStarted = false;
21857
- if (leadershipTimer) {
21858
- clearInterval(leadershipTimer);
21859
- leadershipTimer = null;
22069
+ workerStarted2 = false;
22070
+ if (leadershipTimer2) {
22071
+ clearInterval(leadershipTimer2);
22072
+ leadershipTimer2 = null;
21860
22073
  }
21861
- stopLeaderResources();
21862
- workerLease?.stop();
21863
- workerLease = null;
22074
+ stopLeaderResources2();
22075
+ workerLease2?.stop();
22076
+ workerLease2 = null;
21864
22077
  logger.info("session-inbox: worker stopped");
21865
22078
  };
21866
22079
  }
21867
- var topicWorkerBusy, watcher = null, fallbackTimer = null, debouncedTrigger = null, leadershipTimer = null, workerLease = null, workerStarted = false, SESSION_INBOX_PROCESS_ROLE = "worker:session-inbox";
22080
+ var topicWorkerBusy, watcher2 = null, fallbackTimer2 = null, debouncedTrigger2 = null, leadershipTimer2 = null, workerLease2 = null, workerStarted2 = false, SESSION_INBOX_PROCESS_ROLE = "worker:session-inbox";
21868
22081
  var init_inbox = __esm(async () => {
21869
22082
  init_file_ops();
21870
22083
  init_utils();
@@ -21916,6 +22129,7 @@ __export(exports_src, {
21916
22129
  startSessionInboxWorker: () => startSessionInboxWorker,
21917
22130
  startNegotiumNodeModules: () => startNegotiumNodeModules,
21918
22131
  startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
22132
+ startBashrsCompletionsWorker: () => startBashrsCompletionsWorker,
21919
22133
  startAskUserQuestionGateOwner: () => startAskUserQuestionGateOwner,
21920
22134
  startAiTurn: () => startAiTurn,
21921
22135
  setTopicSessionId: () => setTopicSessionId,
@@ -21924,6 +22138,7 @@ __export(exports_src, {
21924
22138
  setPlaywrightUnavailableNotifier: () => setPlaywrightUnavailableNotifier,
21925
22139
  setNodeMcpServers: () => setNodeMcpServers,
21926
22140
  setFileHooks: () => setFileHooks,
22141
+ setBashrsCompletionSink: () => setBashrsCompletionSink,
21927
22142
  setApiTopicConfig: () => setApiTopicConfig,
21928
22143
  sessionInboxPath: () => sessionInboxPath,
21929
22144
  selectableModel: () => selectableModel,
@@ -22016,6 +22231,7 @@ __export(exports_src, {
22016
22231
  forkAgentSession: () => forkAgentSession,
22017
22232
  flushSessionInbox: () => flushSessionInbox,
22018
22233
  flushPeerRuntimeEvents: () => flushPeerRuntimeEvents,
22234
+ flushBashrsCompletions: () => flushBashrsCompletions,
22019
22235
  findTopicTitleConflict: () => findTopicTitleConflict,
22020
22236
  fileHooks: () => fileHooks,
22021
22237
  failInterruptedRemoteAskCallbacks: () => failInterruptedRemoteAskCallbacks,
@@ -22158,6 +22374,7 @@ var init_src = __esm(async () => {
22158
22374
  init_active_rooms(),
22159
22375
  init_ask_callbacks(),
22160
22376
  init_background_sessions(),
22377
+ init_bashrs_completions(),
22161
22378
  init_delivery_ack(),
22162
22379
  init_inbox(),
22163
22380
  init_turn_runner(),
@@ -22181,11 +22398,11 @@ var init_src = __esm(async () => {
22181
22398
  });
22182
22399
 
22183
22400
  // ../../packages/core/src/storage/conversation-migration.ts
22184
- import { copyFileSync as copyFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync23, readFileSync as readFileSync19 } from "fs";
22185
- import { dirname as dirname15, join as join32 } from "path";
22401
+ import { copyFileSync as copyFileSync3, existsSync as existsSync23, mkdirSync as mkdirSync23, readFileSync as readFileSync20 } from "fs";
22402
+ import { dirname as dirname15, join as join33 } from "path";
22186
22403
  function readEntries(path) {
22187
22404
  const entries = [];
22188
- for (const [index, line] of readFileSync19(path, "utf8").split(`
22405
+ for (const [index, line] of readFileSync20(path, "utf8").split(`
22189
22406
  `).entries()) {
22190
22407
  if (!line.trim())
22191
22408
  continue;
@@ -22249,7 +22466,7 @@ function migrateLegacyCompactedConversations() {
22249
22466
  result.skipped++;
22250
22467
  continue;
22251
22468
  }
22252
- const backupPath = join32(resolveStorageDataDir(), "conversation-migration-backups", MIGRATION_NAME, userId, `${sanitizeTopicName(topic.title, true)}.jsonl`);
22469
+ const backupPath = join33(resolveStorageDataDir(), "conversation-migration-backups", MIGRATION_NAME, userId, `${sanitizeTopicName(topic.title, true)}.jsonl`);
22253
22470
  const sourcePath = existsSync23(backupPath) ? backupPath : rawPath;
22254
22471
  const legacyEntries = readEntries(sourcePath);
22255
22472
  const compactIndex = compactionEntryIndex(legacyEntries);
@@ -22308,11 +22525,13 @@ __export(exports_node_host, {
22308
22525
  startSessionInboxWorker: () => startSessionInboxWorker,
22309
22526
  startNegotiumNodeModules: () => startNegotiumNodeModules,
22310
22527
  startDurableTurnRequestWorker: () => startDurableTurnRequestWorker,
22528
+ startBashrsCompletionsWorker: () => startBashrsCompletionsWorker,
22311
22529
  startAskUserQuestionGateOwner: () => startAskUserQuestionGateOwner,
22312
22530
  startAiTurn: () => startAiTurn,
22313
22531
  setRuntimeMcpPort: () => setRuntimeMcpPort,
22314
22532
  setNodeMcpServers: () => setNodeMcpServers,
22315
22533
  setFileHooks: () => setFileHooks,
22534
+ setBashrsCompletionSink: () => setBashrsCompletionSink,
22316
22535
  saveVaultEntry: () => saveVaultEntry,
22317
22536
  runtimeBus: () => runtimeBus,
22318
22537
  runShutdown: () => runShutdown,
@@ -22335,6 +22554,7 @@ __export(exports_node_host, {
22335
22554
  isParticipant: () => isParticipant,
22336
22555
  getVisibleTopics: () => getVisibleTopics,
22337
22556
  getTopic: () => getTopic,
22557
+ flushBashrsCompletions: () => flushBashrsCompletions,
22338
22558
  executeVaultCommand: () => executeVaultCommand,
22339
22559
  ensurePersonalGeneral: () => ensurePersonalGeneral,
22340
22560
  deleteVaultEntry: () => deleteVaultEntry,
@@ -22380,6 +22600,7 @@ var init_node_host = __esm(async () => {
22380
22600
  init_manager2(),
22381
22601
  init_active_rooms(),
22382
22602
  init_background_sessions(),
22603
+ init_bashrs_completions(),
22383
22604
  init_inbox(),
22384
22605
  init_turn_runner(),
22385
22606
  init_api_messages(),
@@ -22393,7 +22614,7 @@ var init_node_host = __esm(async () => {
22393
22614
  });
22394
22615
 
22395
22616
  // ../../packages/core/src/agents/mcp-tools/inline-assets.ts
22396
- import { existsSync as existsSync24, readFileSync as readFileSync20, statSync as statSync13 } from "fs";
22617
+ import { existsSync as existsSync24, readFileSync as readFileSync21, statSync as statSync14 } from "fs";
22397
22618
  import { extname as extname2, isAbsolute as isAbsolute6, resolve as resolve16 } from "path";
22398
22619
  function isNonLocal(ref) {
22399
22620
  return /^(?:[a-z][a-z0-9+.-]*:|\/\/|#)/i.test(ref.trim());
@@ -22421,12 +22642,12 @@ function inlineLocalAssets(html, options) {
22421
22642
  const abs = isAbsolute6(relPath) ? relPath : resolve16(baseDir, relPath);
22422
22643
  let bytes;
22423
22644
  try {
22424
- if (!existsSync24(abs) || !statSync13(abs).isFile()) {
22645
+ if (!existsSync24(abs) || !statSync14(abs).isFile()) {
22425
22646
  unresolved.push(ref);
22426
22647
  cache.set(ref, null);
22427
22648
  return null;
22428
22649
  }
22429
- bytes = statSync13(abs).size;
22650
+ bytes = statSync14(abs).size;
22430
22651
  } catch {
22431
22652
  unresolved.push(ref);
22432
22653
  cache.set(ref, null);
@@ -22446,7 +22667,7 @@ function inlineLocalAssets(html, options) {
22446
22667
  let uri;
22447
22668
  try {
22448
22669
  const mime = MIME_BY_EXT[extname2(abs).toLowerCase()] ?? "application/octet-stream";
22449
- uri = `data:${mime};base64,${readFileSync20(abs).toString("base64")}`;
22670
+ uri = `data:${mime};base64,${readFileSync21(abs).toString("base64")}`;
22450
22671
  } catch {
22451
22672
  unresolved.push(ref);
22452
22673
  cache.set(ref, null);
@@ -23232,8 +23453,8 @@ __export(exports_agent_health, {
23232
23453
  createAgentHealthMcpServer: () => createAgentHealthMcpServer
23233
23454
  });
23234
23455
  import { spawn as spawn6 } from "child_process";
23235
- import { existsSync as existsSync25, readdirSync as readdirSync8 } from "fs";
23236
- import { join as join33 } from "path";
23456
+ import { existsSync as existsSync25, readdirSync as readdirSync9 } from "fs";
23457
+ import { join as join34 } from "path";
23237
23458
  import { McpServer as McpServer4 } from "@modelcontextprotocol/sdk/server/mcp.js";
23238
23459
  import { z as z9 } from "zod";
23239
23460
  function signalProcessTree2(child, signal) {
@@ -23477,12 +23698,12 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
23477
23698
  server.tool("list_active_queries", "\uD604\uC7AC \uC0AC\uC6A9\uC790 \uBC94\uC704\uC5D0\uC11C \uC2E4\uD589 \uC911\uC778 \uD1A0\uD53D \uCFFC\uB9AC \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.", {}, async () => {
23478
23699
  if (!context.userId)
23479
23700
  return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC870\uD68C \uBD88\uAC00 (user context \uC5C6\uC74C)");
23480
- const stateDir = join33(USERS_LOG_DIR, context.userId, "active-queries");
23701
+ const stateDir = join34(USERS_LOG_DIR, context.userId, "active-queries");
23481
23702
  if (!existsSync25(stateDir))
23482
23703
  return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
23483
23704
  let files;
23484
23705
  try {
23485
- files = readdirSync8(stateDir);
23706
+ files = readdirSync9(stateDir);
23486
23707
  } catch {
23487
23708
  return mcpOk("\uC2E4\uD589 \uC911\uC778 \uCFFC\uB9AC \uC5C6\uC74C");
23488
23709
  }
@@ -23490,7 +23711,7 @@ ${results.every((result) => result.ok) ? "All agents healthy" : "Some agents fai
23490
23711
  const entries = files.flatMap((file) => {
23491
23712
  if (!file.endsWith(".json"))
23492
23713
  return [];
23493
- const state = readJsonFile(join33(stateDir, file));
23714
+ const state = readJsonFile(join34(stateDir, file));
23494
23715
  if (!state)
23495
23716
  return [];
23496
23717
  const sinceMs = new Date(state.since).getTime();
@@ -23726,7 +23947,7 @@ var exports_default_host = {};
23726
23947
  __export(exports_default_host, {
23727
23948
  createDefaultSessionCommMcpHost: () => createDefaultSessionCommMcpHost
23728
23949
  });
23729
- import { basename as basename6, join as join34 } from "path";
23950
+ import { basename as basename6, join as join35 } from "path";
23730
23951
  function ok2(text2) {
23731
23952
  return { content: [{ type: "text", text: text2 }] };
23732
23953
  }
@@ -23768,10 +23989,10 @@ function remoteTarget(context, to) {
23768
23989
  return { node: to.slice(0, slash), topic: to.slice(slash + 1) };
23769
23990
  }
23770
23991
  function activeQuery(context, topicId, title) {
23771
- const dir = join34(USERS_LOG_DIR, context.userId, "active-queries");
23772
- const candidates = [join34(dir, `${sanitizeId(topicId)}.json`)];
23992
+ const dir = join35(USERS_LOG_DIR, context.userId, "active-queries");
23993
+ const candidates = [join35(dir, `${sanitizeId(topicId)}.json`)];
23773
23994
  if (title && basename6(title) === title && title !== "." && title !== "..") {
23774
- candidates.push(join34(dir, `${title}.json`));
23995
+ candidates.push(join35(dir, `${title}.json`));
23775
23996
  }
23776
23997
  for (const path of candidates) {
23777
23998
  const state = readJsonFile(path);
@@ -24421,18 +24642,18 @@ __export(exports_wiki_server, {
24421
24642
  import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
24422
24643
  import { randomUUID as randomUUID21 } from "crypto";
24423
24644
  import {
24424
- closeSync as closeSync3,
24645
+ closeSync as closeSync4,
24425
24646
  existsSync as existsSync26,
24426
24647
  mkdirSync as mkdirSync24,
24427
- openSync as openSync3,
24428
- readdirSync as readdirSync9,
24429
- readFileSync as readFileSync21,
24430
- renameSync as renameSync10,
24431
- statSync as statSync14,
24648
+ openSync as openSync4,
24649
+ readdirSync as readdirSync10,
24650
+ readFileSync as readFileSync22,
24651
+ renameSync as renameSync11,
24652
+ statSync as statSync15,
24432
24653
  unlinkSync as unlinkSync18,
24433
24654
  writeFileSync as writeFileSync17
24434
24655
  } from "fs";
24435
- import { basename as basename7, dirname as dirname16, join as join35, resolve as resolve17 } from "path";
24656
+ import { basename as basename7, dirname as dirname16, join as join36, resolve as resolve17 } from "path";
24436
24657
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
24437
24658
  import { StdioServerTransport as StdioServerTransport2 } from "@modelcontextprotocol/sdk/server/stdio.js";
24438
24659
  import {
@@ -24466,20 +24687,20 @@ function acquireRecoveryGuard(lockPath) {
24466
24687
  const deadline = Date.now() + FILE_LOCK_TIMEOUT_MS;
24467
24688
  while (true) {
24468
24689
  try {
24469
- const fd = openSync3(guardPath, "wx");
24690
+ const fd = openSync4(guardPath, "wx");
24470
24691
  try {
24471
24692
  writeFileSync17(fd, ownerToken, "utf-8");
24472
24693
  } catch (error2) {
24473
- closeSync3(fd);
24694
+ closeSync4(fd);
24474
24695
  try {
24475
24696
  unlinkSync18(guardPath);
24476
24697
  } catch {}
24477
24698
  throw error2;
24478
24699
  }
24479
24700
  return () => {
24480
- closeSync3(fd);
24701
+ closeSync4(fd);
24481
24702
  try {
24482
- if (readFileSync21(guardPath, "utf-8") === ownerToken)
24703
+ if (readFileSync22(guardPath, "utf-8") === ownerToken)
24483
24704
  unlinkSync18(guardPath);
24484
24705
  } catch {}
24485
24706
  };
@@ -24499,21 +24720,21 @@ function acquireFileLock(path) {
24499
24720
  const deadline = Date.now() + FILE_LOCK_TIMEOUT_MS;
24500
24721
  while (true) {
24501
24722
  try {
24502
- const fd = openSync3(lockPath, "wx");
24723
+ const fd = openSync4(lockPath, "wx");
24503
24724
  try {
24504
24725
  writeFileSync17(fd, ownerToken, "utf-8");
24505
24726
  } catch (error2) {
24506
- closeSync3(fd);
24727
+ closeSync4(fd);
24507
24728
  try {
24508
24729
  unlinkSync18(lockPath);
24509
24730
  } catch {}
24510
24731
  throw error2;
24511
24732
  }
24512
24733
  return () => {
24513
- closeSync3(fd);
24734
+ closeSync4(fd);
24514
24735
  const releaseGuard = acquireRecoveryGuard(lockPath);
24515
24736
  try {
24516
- if (readFileSync21(lockPath, "utf-8") === ownerToken)
24737
+ if (readFileSync22(lockPath, "utf-8") === ownerToken)
24517
24738
  unlinkSync18(lockPath);
24518
24739
  } catch {} finally {
24519
24740
  releaseGuard();
@@ -24525,8 +24746,8 @@ function acquireFileLock(path) {
24525
24746
  const releaseGuard = acquireRecoveryGuard(lockPath);
24526
24747
  try {
24527
24748
  try {
24528
- const staleToken = readFileSync21(lockPath, "utf-8");
24529
- if (Date.now() - statSync14(lockPath).mtimeMs > FILE_LOCK_STALE_MS && readFileSync21(lockPath, "utf-8") === staleToken) {
24749
+ const staleToken = readFileSync22(lockPath, "utf-8");
24750
+ if (Date.now() - statSync15(lockPath).mtimeMs > FILE_LOCK_STALE_MS && readFileSync22(lockPath, "utf-8") === staleToken) {
24530
24751
  unlinkSync18(lockPath);
24531
24752
  continue;
24532
24753
  }
@@ -24547,7 +24768,7 @@ function atomicWriteFile(path, content) {
24547
24768
  const temporaryPath = `${path}.tmp.${process.pid}.${Date.now()}`;
24548
24769
  writeFileSync17(temporaryPath, content, "utf-8");
24549
24770
  try {
24550
- renameSync10(temporaryPath, path);
24771
+ renameSync11(temporaryPath, path);
24551
24772
  } catch (error2) {
24552
24773
  try {
24553
24774
  unlinkSync18(temporaryPath);
@@ -24579,17 +24800,17 @@ function wikiQuery(args) {
24579
24800
  function scan(dir, label) {
24580
24801
  ensureDir(dir);
24581
24802
  try {
24582
- for (const entry of readdirSync9(dir, { withFileTypes: true })) {
24803
+ for (const entry of readdirSync10(dir, { withFileTypes: true })) {
24583
24804
  if (entry.isDirectory()) {
24584
- const sub = join35(dir, entry.name);
24805
+ const sub = join36(dir, entry.name);
24585
24806
  if (label === "articles" || label === "skills") {
24586
24807
  try {
24587
- for (const f of readdirSync9(sub, { withFileTypes: true })) {
24808
+ for (const f of readdirSync10(sub, { withFileTypes: true })) {
24588
24809
  if (!f.isFile() || !f.name.endsWith(".md"))
24589
24810
  continue;
24590
- const fp = join35(sub, f.name);
24811
+ const fp = join36(sub, f.name);
24591
24812
  try {
24592
- const text2 = readFileSync21(fp, "utf-8");
24813
+ const text2 = readFileSync22(fp, "utf-8");
24593
24814
  scored.push({
24594
24815
  score: scoreMatch(text2),
24595
24816
  path: `${label}/${entry.name}/${f.name}`,
@@ -24600,9 +24821,9 @@ function wikiQuery(args) {
24600
24821
  } catch {}
24601
24822
  }
24602
24823
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
24603
- const fp = join35(dir, entry.name);
24824
+ const fp = join36(dir, entry.name);
24604
24825
  try {
24605
- const text2 = readFileSync21(fp, "utf-8");
24826
+ const text2 = readFileSync22(fp, "utf-8");
24606
24827
  scored.push({
24607
24828
  score: scoreMatch(text2),
24608
24829
  path: `${label}/${entry.name}`,
@@ -24710,18 +24931,18 @@ function wikiLastConversation(args) {
24710
24931
  const name = slugify(topicNameFrom(rawTopic));
24711
24932
  const archiveDir = resolve17(runtime().archiveDir, name);
24712
24933
  try {
24713
- let files = existsSync26(archiveDir) ? readdirSync9(archiveDir).filter((f) => f.endsWith(".jsonl")).sort().reverse() : [];
24934
+ let files = existsSync26(archiveDir) ? readdirSync10(archiveDir).filter((f) => f.endsWith(".jsonl")).sort().reverse() : [];
24714
24935
  if (files.length === 0) {
24715
- files = existsSync26(runtime().archiveDir) ? readdirSync9(runtime().archiveDir).filter((f) => f.startsWith(name) && f.endsWith(".jsonl")).sort().reverse() : [];
24936
+ files = existsSync26(runtime().archiveDir) ? readdirSync10(runtime().archiveDir).filter((f) => f.startsWith(name) && f.endsWith(".jsonl")).sort().reverse() : [];
24716
24937
  }
24717
24938
  if (files.length === 0) {
24718
24939
  return {
24719
24940
  content: [{ type: "text", text: `No archive found for topic: ${rawTopic}` }]
24720
24941
  };
24721
24942
  }
24722
- const actualPath = files[0].includes("/") ? files[0] : resolve17(existsSync26(archiveDir) && readdirSync9(archiveDir).includes(files[0]) ? archiveDir : runtime().archiveDir, files[0]);
24943
+ const actualPath = files[0].includes("/") ? files[0] : resolve17(existsSync26(archiveDir) && readdirSync10(archiveDir).includes(files[0]) ? archiveDir : runtime().archiveDir, files[0]);
24723
24944
  try {
24724
- const raw = readFileSync21(actualPath, "utf-8");
24945
+ const raw = readFileSync22(actualPath, "utf-8");
24725
24946
  const lines = raw.trim().split(`
24726
24947
  `).filter(Boolean);
24727
24948
  const turns2 = [];
@@ -24787,14 +25008,14 @@ function skillQuery(args) {
24787
25008
  ensureDir(runtime().skillsDir);
24788
25009
  const matches = [];
24789
25010
  try {
24790
- for (const entry of readdirSync9(runtime().skillsDir, {
25011
+ for (const entry of readdirSync10(runtime().skillsDir, {
24791
25012
  withFileTypes: true
24792
25013
  })) {
24793
25014
  if (!entry.isDirectory())
24794
25015
  continue;
24795
25016
  const skillFile = resolve17(runtime().skillsDir, entry.name, "skill.md");
24796
25017
  try {
24797
- const text2 = readFileSync21(skillFile, "utf-8");
25018
+ const text2 = readFileSync22(skillFile, "utf-8");
24798
25019
  const lower = text2.toLowerCase();
24799
25020
  let score = 0;
24800
25021
  for (const w of query2.split(/\s+/).filter(Boolean)) {
@@ -24865,7 +25086,7 @@ ${fresh.join(`
24865
25086
  const skillPath = resolve17(skillDir, "skill.md");
24866
25087
  let finalContent = content;
24867
25088
  try {
24868
- const existing = readFileSync21(skillPath, "utf-8");
25089
+ const existing = readFileSync22(skillPath, "utf-8");
24869
25090
  finalContent = mergeGotchas(content, extractGotchas(existing));
24870
25091
  } catch {}
24871
25092
  writeFileSync17(skillPath, finalContent, "utf-8");
@@ -24913,7 +25134,7 @@ function saveWikiEntry(args) {
24913
25134
  if (topicId && setTopicBrief2) {
24914
25135
  try {
24915
25136
  const briefPath = resolve17(runtime().topicsDir, `${fileSlug}.md`);
24916
- let briefMd = existsSync26(briefPath) ? readFileSync21(briefPath, "utf-8") : undefined;
25137
+ let briefMd = existsSync26(briefPath) ? readFileSync22(briefPath, "utf-8") : undefined;
24917
25138
  if (briefMd === undefined && getTopicBrief2 && !getTopicBrief2(fileSlug)?.briefMd) {
24918
25139
  const legacy = getTopicBrief2(topicId)?.briefMd;
24919
25140
  if (legacy)
@@ -24990,7 +25211,7 @@ function indexUpsert(args) {
24990
25211
  try {
24991
25212
  let index;
24992
25213
  try {
24993
- index = readFileSync21(indexPath, "utf-8");
25214
+ index = readFileSync22(indexPath, "utf-8");
24994
25215
  } catch {
24995
25216
  index = "";
24996
25217
  }
@@ -25277,13 +25498,13 @@ __export(exports_activity_log, {
25277
25498
  import {
25278
25499
  existsSync as existsSync27,
25279
25500
  mkdirSync as mkdirSync25,
25280
- readdirSync as readdirSync10,
25281
- renameSync as renameSync11,
25282
- statSync as statSync15,
25501
+ readdirSync as readdirSync11,
25502
+ renameSync as renameSync12,
25503
+ statSync as statSync16,
25283
25504
  unlinkSync as unlinkSync19,
25284
25505
  writeFileSync as writeFileSync18
25285
25506
  } from "fs";
25286
- import { basename as basename8, join as join36 } from "path";
25507
+ import { basename as basename8, join as join37 } from "path";
25287
25508
  function startLogRotation() {
25288
25509
  if (rotationTimer)
25289
25510
  return;
@@ -25297,12 +25518,12 @@ function writeLog(entry) {
25297
25518
  mkdirSync25(logDir, { recursive: true });
25298
25519
  const safeSession = sanitizeTopicName(entry.session);
25299
25520
  const sidShort = entry.sessionId ? entry.sessionId.slice(0, 8) : "new";
25300
- const file = join36(logDir, `${entry.userId}_${safeSession}_${sidShort}.jsonl`);
25521
+ const file = join37(logDir, `${entry.userId}_${safeSession}_${sidShort}.jsonl`);
25301
25522
  try {
25302
- const stat = statSync15(file);
25523
+ const stat = statSync16(file);
25303
25524
  if (stat.size >= MAX_FILE_SIZE) {
25304
25525
  const rotated = file.replace(/\.jsonl$/, `.${Date.now()}.jsonl`);
25305
- renameSync11(file, rotated);
25526
+ renameSync12(file, rotated);
25306
25527
  }
25307
25528
  } catch {}
25308
25529
  try {
@@ -25315,9 +25536,9 @@ function rotateOldLogs() {
25315
25536
  const logDir = resolveStorageLogDir();
25316
25537
  mkdirSync25(logDir, { recursive: true });
25317
25538
  try {
25318
- const files = readdirSync10(logDir).filter((f) => f.endsWith(".jsonl")).map((f) => {
25539
+ const files = readdirSync11(logDir).filter((f) => f.endsWith(".jsonl")).map((f) => {
25319
25540
  try {
25320
- const stat = statSync15(join36(logDir, f));
25541
+ const stat = statSync16(join37(logDir, f));
25321
25542
  return { name: f, size: stat.size, mtimeMs: stat.mtimeMs };
25322
25543
  } catch {
25323
25544
  return null;
@@ -25333,7 +25554,7 @@ function rotateOldLogs() {
25333
25554
  if (freed >= toFree)
25334
25555
  break;
25335
25556
  try {
25336
- unlinkSync19(join36(logDir, file.name));
25557
+ unlinkSync19(join37(logDir, file.name));
25337
25558
  freed += file.size;
25338
25559
  logger.info({ file: file.name, sizeKB: (file.size / 1024).toFixed(0) }, "Rotated out old log");
25339
25560
  } catch (e) {
@@ -25345,9 +25566,9 @@ function rotateOldLogs() {
25345
25566
  }
25346
25567
  }
25347
25568
  function writeSentFileLog(entry) {
25348
- const dir = join36(resolveStorageUsersLogDir(), String(entry.userId));
25569
+ const dir = join37(resolveStorageUsersLogDir(), String(entry.userId));
25349
25570
  mkdirSync25(dir, { recursive: true });
25350
- const file = join36(dir, "sent-files.jsonl");
25571
+ const file = join37(dir, "sent-files.jsonl");
25351
25572
  try {
25352
25573
  appendJsonlEntry(file, { ...entry, fileName: basename8(entry.filePath) });
25353
25574
  } catch (e) {
@@ -25358,7 +25579,7 @@ function entryMatchesTopic(e, topicName) {
25358
25579
  return e.topicName === topicName;
25359
25580
  }
25360
25581
  function readSentFilesForTopic(userId, topicName) {
25361
- const file = join36(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
25582
+ const file = join37(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
25362
25583
  if (!existsSync27(file))
25363
25584
  return [];
25364
25585
  try {
@@ -25369,7 +25590,7 @@ function readSentFilesForTopic(userId, topicName) {
25369
25590
  }
25370
25591
  }
25371
25592
  function removeSentFilesForTopic(userId, topicName) {
25372
- const file = join36(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
25593
+ const file = join37(resolveStorageUsersLogDir(), String(userId), "sent-files.jsonl");
25373
25594
  if (!existsSync27(file))
25374
25595
  return;
25375
25596
  try {
@@ -26329,7 +26550,7 @@ var init_sse_transport = () => {};
26329
26550
 
26330
26551
  // ../../packages/mcp/src/server.ts
26331
26552
  import { createHash as createHash9, randomUUID as randomUUID23 } from "crypto";
26332
- import { realpathSync as realpathSync6, statSync as statSync16 } from "fs";
26553
+ import { realpathSync as realpathSync6, statSync as statSync17 } from "fs";
26333
26554
  import { basename as basename9, extname as extname3, resolve as resolve19 } from "path";
26334
26555
  import { McpServer as McpServer7 } from "@modelcontextprotocol/sdk/server/mcp.js";
26335
26556
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
@@ -26366,7 +26587,7 @@ function localFileInfo(ctx, filePath) {
26366
26587
  return { error: "Access denied. Path matches the sensitive-file blacklist." };
26367
26588
  }
26368
26589
  try {
26369
- const stats = statSync16(normalizedPath);
26590
+ const stats = statSync17(normalizedPath);
26370
26591
  if (!stats.isFile())
26371
26592
  return { error: `${filePath} is not a file` };
26372
26593
  return {
@@ -26893,7 +27114,7 @@ var init_spec = __esm(() => {
26893
27114
  });
26894
27115
 
26895
27116
  // ../../packages/mcp-host/src/manifest.ts
26896
- import { existsSync as existsSync28, mkdirSync as mkdirSync26, readFileSync as readFileSync22, renameSync as renameSync12, writeFileSync as writeFileSync19 } from "fs";
27117
+ import { existsSync as existsSync28, mkdirSync as mkdirSync26, readFileSync as readFileSync23, renameSync as renameSync13, writeFileSync as writeFileSync19 } from "fs";
26897
27118
  import { dirname as dirname17 } from "path";
26898
27119
  import { z as z14 } from "zod";
26899
27120
 
@@ -26942,7 +27163,7 @@ class McpManifest {
26942
27163
  return;
26943
27164
  let parsed;
26944
27165
  try {
26945
- parsed = manifestFileSchema.parse(JSON.parse(readFileSync22(this.file, "utf8")));
27166
+ parsed = manifestFileSchema.parse(JSON.parse(readFileSync23(this.file, "utf8")));
26946
27167
  } catch (e) {
26947
27168
  throw new Error(`Invalid MCP manifest at ${this.file}: ${e instanceof Error ? e.message : String(e)}`);
26948
27169
  }
@@ -26962,7 +27183,7 @@ class McpManifest {
26962
27183
  const tmp = `${this.file}.tmp-${process.pid}`;
26963
27184
  writeFileSync19(tmp, `${JSON.stringify(payload, null, 2)}
26964
27185
  `);
26965
- renameSync12(tmp, this.file);
27186
+ renameSync13(tmp, this.file);
26966
27187
  }
26967
27188
  }
26968
27189
  var manifestEntrySchema, manifestFileSchema;
@@ -26991,14 +27212,14 @@ function sanitizePathComponent(name) {
26991
27212
  import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
26992
27213
  import {
26993
27214
  mkdirSync as mkdirSync27,
26994
- readdirSync as readdirSync11,
26995
- readFileSync as readFileSync23,
26996
- renameSync as renameSync13,
27215
+ readdirSync as readdirSync12,
27216
+ readFileSync as readFileSync24,
27217
+ renameSync as renameSync14,
26997
27218
  unlinkSync as unlinkSync20,
26998
27219
  writeFileSync as writeFileSync20
26999
27220
  } from "fs";
27000
27221
  import { connect, createServer as createServer3 } from "net";
27001
- import { join as join37 } from "path";
27222
+ import { join as join38 } from "path";
27002
27223
  function regKey(key, instanceKey) {
27003
27224
  return `${key}\x00${instanceKey}`;
27004
27225
  }
@@ -27292,7 +27513,7 @@ class McpHost {
27292
27513
  const claims = new Map;
27293
27514
  let files;
27294
27515
  try {
27295
- files = readdirSync11(this.portsDir);
27516
+ files = readdirSync12(this.portsDir);
27296
27517
  } catch {
27297
27518
  return claims;
27298
27519
  }
@@ -27300,7 +27521,7 @@ class McpHost {
27300
27521
  if (file.includes(".tmp-"))
27301
27522
  continue;
27302
27523
  try {
27303
- const port = Number.parseInt(readFileSync23(join37(this.portsDir, file), "utf8").trim(), 10);
27524
+ const port = Number.parseInt(readFileSync24(join38(this.portsDir, file), "utf8").trim(), 10);
27304
27525
  if (!Number.isNaN(port))
27305
27526
  claims.set(file, port);
27306
27527
  } catch {}
@@ -27310,17 +27531,17 @@ class McpHost {
27310
27531
  writePortFile(fileName, port) {
27311
27532
  try {
27312
27533
  mkdirSync27(this.portsDir, { recursive: true });
27313
- const file = join37(this.portsDir, fileName);
27534
+ const file = join38(this.portsDir, fileName);
27314
27535
  const tmp = `${file}.tmp-${process.pid}`;
27315
27536
  writeFileSync20(tmp, String(port));
27316
- renameSync13(tmp, file);
27537
+ renameSync14(tmp, file);
27317
27538
  } catch (e) {
27318
27539
  this.log("warn", "Failed to write MCP port file", { fileName, port, err: String(e) });
27319
27540
  }
27320
27541
  }
27321
27542
  deletePortFile(fileName) {
27322
27543
  try {
27323
- unlinkSync20(join37(this.portsDir, fileName));
27544
+ unlinkSync20(join38(this.portsDir, fileName));
27324
27545
  } catch {}
27325
27546
  }
27326
27547
  cleanupRunning(rkey, inst) {
@@ -27427,12 +27648,12 @@ import {
27427
27648
  copyFileSync as copyFileSync4,
27428
27649
  existsSync as existsSync29,
27429
27650
  mkdirSync as mkdirSync28,
27430
- readFileSync as readFileSync24,
27431
- rmSync as rmSync8,
27432
- statSync as statSync17,
27651
+ readFileSync as readFileSync25,
27652
+ rmSync as rmSync9,
27653
+ statSync as statSync18,
27433
27654
  writeFileSync as writeFileSync21
27434
27655
  } from "fs";
27435
- import { basename as basename10, extname as extname4, join as join38 } from "path";
27656
+ import { basename as basename10, extname as extname4, join as join39 } from "path";
27436
27657
  function safeExtension(filename) {
27437
27658
  const extension = extname4(basename10(filename));
27438
27659
  return /^\.[A-Za-z0-9]{1,16}$/.test(extension) ? extension.toLowerCase() : "";
@@ -27450,20 +27671,20 @@ function contentDisposition(filename) {
27450
27671
 
27451
27672
  class NodeFileStore {
27452
27673
  uploadDir;
27453
- constructor(uploadDir = join38(DATA_DIR, "uploads")) {
27674
+ constructor(uploadDir = join39(DATA_DIR, "uploads")) {
27454
27675
  this.uploadDir = uploadDir;
27455
27676
  }
27456
27677
  #ensureDir() {
27457
27678
  mkdirSync28(this.uploadDir, { recursive: true });
27458
27679
  }
27459
27680
  #metadataPath(fileId) {
27460
- return join38(this.uploadDir, `${fileId}.meta.json`);
27681
+ return join39(this.uploadDir, `${fileId}.meta.json`);
27461
27682
  }
27462
27683
  #metadata(fileId) {
27463
27684
  if (!FILE_ID_RE.test(fileId))
27464
27685
  return null;
27465
27686
  try {
27466
- const parsed = JSON.parse(readFileSync24(this.#metadataPath(fileId), "utf8"));
27687
+ const parsed = JSON.parse(readFileSync25(this.#metadataPath(fileId), "utf8"));
27467
27688
  if (typeof parsed.filename !== "string" || typeof parsed.mimeType !== "string" || typeof parsed.sizeBytes !== "number" || typeof parsed.savedName !== "string") {
27468
27689
  return null;
27469
27690
  }
@@ -27486,7 +27707,7 @@ class NodeFileStore {
27486
27707
  hooks = {
27487
27708
  resolveAttachmentByFileId: (fileId) => {
27488
27709
  const metadata = this.#metadata(fileId);
27489
- if (!metadata || !existsSync29(join38(this.uploadDir, metadata.savedName)))
27710
+ if (!metadata || !existsSync29(join39(this.uploadDir, metadata.savedName)))
27490
27711
  return null;
27491
27712
  return this.#attachment(fileId, metadata);
27492
27713
  },
@@ -27494,7 +27715,7 @@ class NodeFileStore {
27494
27715
  const metadata = this.#metadata(fileId);
27495
27716
  if (!metadata)
27496
27717
  return null;
27497
- const path = join38(this.uploadDir, metadata.savedName);
27718
+ const path = join39(this.uploadDir, metadata.savedName);
27498
27719
  return existsSync29(path) ? path : null;
27499
27720
  },
27500
27721
  storeLocalFileAsUpload: (absPath, access = {}) => this.store(absPath, access),
@@ -27505,9 +27726,9 @@ class NodeFileStore {
27505
27726
  const fileId = randomUUID24();
27506
27727
  const extension = safeExtension(absPath);
27507
27728
  const savedName = `${fileId}${extension}`;
27508
- const savedPath = join38(this.uploadDir, savedName);
27729
+ const savedPath = join39(this.uploadDir, savedName);
27509
27730
  try {
27510
- const stats = statSync17(absPath);
27731
+ const stats = statSync18(absPath);
27511
27732
  if (!stats.isFile() || stats.size > MAX_UPLOAD_BYTES)
27512
27733
  return null;
27513
27734
  const metadata = {
@@ -27523,8 +27744,8 @@ class NodeFileStore {
27523
27744
  writeFileSync21(this.#metadataPath(fileId), JSON.stringify(metadata), { mode: 384 });
27524
27745
  return this.#attachment(fileId, metadata);
27525
27746
  } catch (error2) {
27526
- rmSync8(savedPath, { force: true });
27527
- rmSync8(this.#metadataPath(fileId), { force: true });
27747
+ rmSync9(savedPath, { force: true });
27748
+ rmSync9(this.#metadataPath(fileId), { force: true });
27528
27749
  logger.warn({ err: error2, absPath }, "node files: failed to store local upload");
27529
27750
  return null;
27530
27751
  }
@@ -27537,7 +27758,7 @@ class NodeFileStore {
27537
27758
  const allowed = metadata.visibility === "workspace" || metadata.ownerUserId === userId || Boolean(topic && isParticipant(topic, userId));
27538
27759
  if (!allowed)
27539
27760
  return null;
27540
- const path = join38(this.uploadDir, metadata.savedName);
27761
+ const path = join39(this.uploadDir, metadata.savedName);
27541
27762
  if (!existsSync29(path))
27542
27763
  return null;
27543
27764
  return new Response(Bun.file(path), {
@@ -27556,8 +27777,8 @@ class NodeFileStore {
27556
27777
  const metadata = this.#metadata(fileId);
27557
27778
  if (metadata?.topicId !== topicId)
27558
27779
  continue;
27559
- rmSync8(join38(this.uploadDir, metadata.savedName), { force: true });
27560
- rmSync8(this.#metadataPath(fileId), { force: true });
27780
+ rmSync9(join39(this.uploadDir, metadata.savedName), { force: true });
27781
+ rmSync9(this.#metadataPath(fileId), { force: true });
27561
27782
  }
27562
27783
  }
27563
27784
  }
@@ -27710,8 +27931,8 @@ import {
27710
27931
  chmodSync as chmodSync5,
27711
27932
  existsSync as existsSync30,
27712
27933
  mkdirSync as mkdirSync29,
27713
- readFileSync as readFileSync25,
27714
- renameSync as renameSync14,
27934
+ readFileSync as readFileSync26,
27935
+ renameSync as renameSync15,
27715
27936
  unlinkSync as unlinkSync21,
27716
27937
  writeFileSync as writeFileSync22
27717
27938
  } from "fs";
@@ -28212,7 +28433,7 @@ function writeNodeDaemonInfo(port, startedAt) {
28212
28433
  writeFileSync22(temporary, `${JSON.stringify(info, null, 2)}
28213
28434
  `, { mode: 384 });
28214
28435
  chmodSync5(temporary, 384);
28215
- renameSync14(temporary, NODE_DAEMON_INFO_PATH);
28436
+ renameSync15(temporary, NODE_DAEMON_INFO_PATH);
28216
28437
  chmodSync5(NODE_DAEMON_INFO_PATH, 384);
28217
28438
  return info;
28218
28439
  }
@@ -28220,7 +28441,7 @@ function readNodeDaemonInfo() {
28220
28441
  if (!existsSync30(NODE_DAEMON_INFO_PATH))
28221
28442
  return null;
28222
28443
  try {
28223
- const value = JSON.parse(readFileSync25(NODE_DAEMON_INFO_PATH, "utf8"));
28444
+ const value = JSON.parse(readFileSync26(NODE_DAEMON_INFO_PATH, "utf8"));
28224
28445
  if (value?.schemaVersion !== 1 || value.stateDir !== STATE_DIR || !Number.isInteger(value.protocolVersion) || !Number.isInteger(value.pid) || !Number.isInteger(value.port) || value.port <= 0) {
28225
28446
  return null;
28226
28447
  }
@@ -28508,7 +28729,7 @@ var init_schedule = __esm(() => {
28508
28729
 
28509
28730
  // ../../packages/module-cron/src/scripts.ts
28510
28731
  import { spawn as spawn9 } from "child_process";
28511
- import { existsSync as existsSync31, mkdirSync as mkdirSync30, readdirSync as readdirSync12 } from "fs";
28732
+ import { existsSync as existsSync31, mkdirSync as mkdirSync30, readdirSync as readdirSync13 } from "fs";
28512
28733
  import { resolve as resolve22, sep as sep2 } from "path";
28513
28734
  function validateCronScriptName(script) {
28514
28735
  if (!/^[A-Za-z0-9_][A-Za-z0-9_.-]*\.py$/.test(script) || script.includes("..") || script.includes("/") || script.includes("\\")) {
@@ -28527,7 +28748,7 @@ function resolveCronScriptPath(script) {
28527
28748
  }
28528
28749
  function listCronScripts() {
28529
28750
  mkdirSync30(CRON_JOBS_DIR, { recursive: true });
28530
- return readdirSync12(CRON_JOBS_DIR, { withFileTypes: true }).filter((entry) => entry.isFile() && validateCronScriptName(entry.name).ok).map((entry) => entry.name).sort();
28751
+ return readdirSync13(CRON_JOBS_DIR, { withFileTypes: true }).filter((entry) => entry.isFile() && validateCronScriptName(entry.name).ok).map((entry) => entry.name).sort();
28531
28752
  }
28532
28753
  function cronScriptExists(script) {
28533
28754
  try {
@@ -30209,6 +30430,7 @@ function startNode(opts = {}) {
30209
30430
  setRuntimeMcpPort(port);
30210
30431
  const stopTurnRequests = startDurableTurnRequestWorker();
30211
30432
  const stopInbox = startSessionInboxWorker();
30433
+ const stopBashrsCompletions = startBashrsCompletionsWorker();
30212
30434
  let modules;
30213
30435
  try {
30214
30436
  modules = startNegotiumNodeModules(opts.modules ?? [], {
@@ -30222,6 +30444,7 @@ function startNode(opts = {}) {
30222
30444
  } catch (error2) {
30223
30445
  stopTurnRequests();
30224
30446
  stopInbox();
30447
+ stopBashrsCompletions();
30225
30448
  server.stop(true);
30226
30449
  processLease?.stop();
30227
30450
  stopAskUserQuestionGateOwner();
@@ -30241,6 +30464,7 @@ function startNode(opts = {}) {
30241
30464
  stopSweeper();
30242
30465
  stopTurnRequests();
30243
30466
  stopInbox();
30467
+ stopBashrsCompletions();
30244
30468
  server.stop(true);
30245
30469
  processLease?.stop();
30246
30470
  stopAskUserQuestionGateOwner();
@@ -30252,6 +30476,7 @@ function startNode(opts = {}) {
30252
30476
  onShutdown("node-server", 130, () => {
30253
30477
  stopTurnRequests();
30254
30478
  stopInbox();
30479
+ stopBashrsCompletions();
30255
30480
  server.stop(true);
30256
30481
  });
30257
30482
  if (advertised) {
@@ -30469,9 +30694,9 @@ var init_commands = __esm(() => {
30469
30694
 
30470
30695
  // ../../adapters/terminal/src/path-suggest.ts
30471
30696
  import { execFile as execFile3 } from "child_process";
30472
- import { existsSync as existsSync33, readdirSync as readdirSync13, statSync as statSync18 } from "fs";
30697
+ import { existsSync as existsSync33, readdirSync as readdirSync14, statSync as statSync19 } from "fs";
30473
30698
  import { homedir as homedir10 } from "os";
30474
- import { basename as basename11, dirname as dirname19, join as join39, sep as sep3 } from "path";
30699
+ import { basename as basename11, dirname as dirname19, join as join40, sep as sep3 } from "path";
30475
30700
  import { promisify as promisify3 } from "util";
30476
30701
  function indexRecursivePaths(files) {
30477
30702
  const paths = [];
@@ -30572,11 +30797,11 @@ function resolveFragment(frag) {
30572
30797
  else if (frag === "~/")
30573
30798
  path = home;
30574
30799
  else if (frag.startsWith("~/"))
30575
- path = join39(home, frag.slice(2));
30800
+ path = join40(home, frag.slice(2));
30576
30801
  else if (frag.startsWith("/"))
30577
30802
  path = frag;
30578
30803
  else
30579
- path = join39(home, frag);
30804
+ path = join40(home, frag);
30580
30805
  if (frag.endsWith("/") || frag === "" || frag === "~") {
30581
30806
  return { dir: path, prefix: "" };
30582
30807
  }
@@ -30605,7 +30830,7 @@ function rankAndSlice(dir, candidates) {
30605
30830
  });
30606
30831
  return candidates.slice(0, MAX_SUGGESTIONS).map(({ relPath, isDir }) => ({
30607
30832
  label: `${relPath}${isDir ? "/" : ""}`,
30608
- value: toToken(join39(dir, relPath), isDir),
30833
+ value: toToken(join40(dir, relPath), isDir),
30609
30834
  isDir
30610
30835
  }));
30611
30836
  }
@@ -30652,7 +30877,7 @@ async function warmPathSuggestions(lineText, col, loader = listFilesWithRipgrep)
30652
30877
  return false;
30653
30878
  const { dir } = resolveFragment(token.frag);
30654
30879
  try {
30655
- if (!statSync18(dir).isDirectory())
30880
+ if (!statSync19(dir).isDirectory())
30656
30881
  return false;
30657
30882
  } catch {
30658
30883
  return false;
@@ -30666,7 +30891,7 @@ function pathSuggestions(lineText, col) {
30666
30891
  const { dir, prefix } = resolveFragment(token.frag);
30667
30892
  let entries;
30668
30893
  try {
30669
- entries = readdirSync13(dir, { withFileTypes: true });
30894
+ entries = readdirSync14(dir, { withFileTypes: true });
30670
30895
  } catch {
30671
30896
  return { start: token.start, end: col, items: [], truncated: 0, searching: false };
30672
30897
  }
@@ -30684,7 +30909,7 @@ function pathSuggestions(lineText, col) {
30684
30909
  let isDir = entry.isDirectory();
30685
30910
  if (!isDir && entry.isSymbolicLink()) {
30686
30911
  try {
30687
- isDir = statSync18(join39(dir, entry.name)).isDirectory();
30912
+ isDir = statSync19(join40(dir, entry.name)).isDirectory();
30688
30913
  } catch {}
30689
30914
  }
30690
30915
  return {
@@ -30711,10 +30936,10 @@ function fragmentToAbsolutePath(frag) {
30711
30936
  if (frag === "~" || frag === "~/")
30712
30937
  return home;
30713
30938
  if (frag.startsWith("~/"))
30714
- return join39(home, frag.slice(2));
30939
+ return join40(home, frag.slice(2));
30715
30940
  if (frag.startsWith("/"))
30716
30941
  return frag;
30717
- return join39(home, frag);
30942
+ return join40(home, frag);
30718
30943
  }
30719
30944
  function fragmentResolves(frag) {
30720
30945
  try {
@@ -37590,7 +37815,7 @@ var init_commands2 = __esm(async () => {
37590
37815
  // ../../adapters/telegram/src/mapping-store.ts
37591
37816
  import { Database as Database2 } from "bun:sqlite";
37592
37817
  import { mkdirSync as mkdirSync31 } from "fs";
37593
- import { dirname as dirname20, join as join40 } from "path";
37818
+ import { dirname as dirname20, join as join41 } from "path";
37594
37819
  function outboxRowToEntry(row) {
37595
37820
  return {
37596
37821
  id: row.id,
@@ -37656,7 +37881,7 @@ function migrateOutboxSchema(db4) {
37656
37881
  db4.run("CREATE INDEX IF NOT EXISTS idx_telegram_outbox_runtime_message ON outbox(runtime_message_id)");
37657
37882
  }
37658
37883
  function openMappingStore(path) {
37659
- const dbPath = path ?? join40(DATA_DIR, "adapter-telegram.db");
37884
+ const dbPath = path ?? join41(DATA_DIR, "adapter-telegram.db");
37660
37885
  if (dbPath !== ":memory:")
37661
37886
  mkdirSync31(dirname20(dbPath), { recursive: true });
37662
37887
  const db4 = new Database2(dbPath);
@@ -39521,8 +39746,8 @@ __export(exports_central, {
39521
39746
  listPeerNodes: () => listPeerNodes,
39522
39747
  configureOtiumCentral: () => configureOtiumCentral
39523
39748
  });
39524
- function configureOtiumCentral(join41) {
39525
- joinConfig = join41;
39749
+ function configureOtiumCentral(join42) {
39750
+ joinConfig = join42;
39526
39751
  resetPeerCentralCaches();
39527
39752
  }
39528
39753
  function otiumCentralConfig() {
@@ -39678,17 +39903,17 @@ __export(exports_join, {
39678
39903
  import { createHash as createHash10, randomUUID as randomUUID27 } from "crypto";
39679
39904
  import {
39680
39905
  chmodSync as chmodSync6,
39681
- closeSync as closeSync4,
39906
+ closeSync as closeSync5,
39682
39907
  existsSync as existsSync35,
39683
39908
  fsyncSync as fsyncSync2,
39684
39909
  linkSync,
39685
39910
  lstatSync,
39686
39911
  mkdirSync as mkdirSync32,
39687
- openSync as openSync4,
39688
- readFileSync as readFileSync26,
39689
- renameSync as renameSync15,
39690
- rmSync as rmSync9,
39691
- statSync as statSync19,
39912
+ openSync as openSync5,
39913
+ readFileSync as readFileSync27,
39914
+ renameSync as renameSync16,
39915
+ rmSync as rmSync10,
39916
+ statSync as statSync20,
39692
39917
  unlinkSync as unlinkSync22,
39693
39918
  writeFileSync as writeFileSync23
39694
39919
  } from "fs";
@@ -39773,27 +39998,27 @@ function withJoinCredentialLock(operation) {
39773
39998
  created = true;
39774
39999
  writeFileSync23(ownerPath, `${JSON.stringify(owner)}
39775
40000
  `, { mode: 384 });
39776
- const ownerFd = openSync4(ownerPath, "r");
40001
+ const ownerFd = openSync5(ownerPath, "r");
39777
40002
  try {
39778
40003
  fsyncSync2(ownerFd);
39779
40004
  } finally {
39780
- closeSync4(ownerFd);
40005
+ closeSync5(ownerFd);
39781
40006
  }
39782
40007
  break;
39783
40008
  } catch (error2) {
39784
40009
  if (created) {
39785
- rmSync9(lockPath, { recursive: true, force: true });
40010
+ rmSync10(lockPath, { recursive: true, force: true });
39786
40011
  throw error2;
39787
40012
  }
39788
40013
  if (error2.code !== "EEXIST")
39789
40014
  throw error2;
39790
40015
  let current3 = null;
39791
40016
  try {
39792
- current3 = JSON.parse(readFileSync26(ownerPath, "utf8"));
40017
+ current3 = JSON.parse(readFileSync27(ownerPath, "utf8"));
39793
40018
  } catch {}
39794
40019
  let ageMs;
39795
40020
  try {
39796
- ageMs = Date.now() - statSync19(lockPath).mtimeMs;
40021
+ ageMs = Date.now() - statSync20(lockPath).mtimeMs;
39797
40022
  } catch (statError) {
39798
40023
  if (statError.code === "ENOENT")
39799
40024
  continue;
@@ -39807,8 +40032,8 @@ function withJoinCredentialLock(operation) {
39807
40032
  }
39808
40033
  const stalePath = `${lockPath}.stale.${process.pid}.${randomUUID27()}`;
39809
40034
  try {
39810
- renameSync15(lockPath, stalePath);
39811
- rmSync9(stalePath, { recursive: true, force: true });
40035
+ renameSync16(lockPath, stalePath);
40036
+ rmSync10(stalePath, { recursive: true, force: true });
39812
40037
  } catch (staleError) {
39813
40038
  if (staleError.code !== "ENOENT")
39814
40039
  throw staleError;
@@ -39819,9 +40044,9 @@ function withJoinCredentialLock(operation) {
39819
40044
  return operation();
39820
40045
  } finally {
39821
40046
  try {
39822
- const current3 = JSON.parse(readFileSync26(ownerPath, "utf8"));
40047
+ const current3 = JSON.parse(readFileSync27(ownerPath, "utf8"));
39823
40048
  if (current3.pid === owner.pid && current3.token === owner.token) {
39824
- rmSync9(lockPath, { recursive: true, force: true });
40049
+ rmSync10(lockPath, { recursive: true, force: true });
39825
40050
  }
39826
40051
  } catch {}
39827
40052
  }
@@ -39829,39 +40054,39 @@ function withJoinCredentialLock(operation) {
39829
40054
  function joinsEqual(left, right) {
39830
40055
  return left.central === right.central && left.relay === right.relay && left.cellId === right.cellId && left.secret === right.secret;
39831
40056
  }
39832
- function normalizedJoin(join41) {
40057
+ function normalizedJoin(join42) {
39833
40058
  return normalizeJoin({
39834
- v: join41.v,
39835
- central: join41.central,
39836
- relay: join41.relay,
39837
- cellId: join41.cellId,
39838
- secret: join41.secret
40059
+ v: join42.v,
40060
+ central: join42.central,
40061
+ relay: join42.relay,
40062
+ cellId: join42.cellId,
40063
+ secret: join42.secret
39839
40064
  });
39840
40065
  }
39841
- function joinCredentialDigest(join41) {
39842
- return createHash10("sha256").update(JSON.stringify(normalizedJoin(join41))).digest("base64url");
40066
+ function joinCredentialDigest(join42) {
40067
+ return createHash10("sha256").update(JSON.stringify(normalizedJoin(join42))).digest("base64url");
39843
40068
  }
39844
40069
  function readPersistedJoin(path = joinFilePath()) {
39845
40070
  if (!existsSync35(path))
39846
40071
  return null;
39847
- const parsed = JSON.parse(readFileSync26(path, "utf-8"));
40072
+ const parsed = JSON.parse(readFileSync27(path, "utf-8"));
39848
40073
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
39849
40074
  throw new Error("persisted join credentials are not a JSON object");
39850
40075
  }
39851
40076
  return normalizeJoin(parsed);
39852
40077
  }
39853
- function isJoinPersisted(join41) {
40078
+ function isJoinPersisted(join42) {
39854
40079
  try {
39855
40080
  const persisted = readPersistedJoin();
39856
- return persisted !== null && joinsEqual(persisted, normalizedJoin(join41));
40081
+ return persisted !== null && joinsEqual(persisted, normalizedJoin(join42));
39857
40082
  } catch {
39858
40083
  return false;
39859
40084
  }
39860
40085
  }
39861
- function saveJoinWhileLocked(join41, options = {}) {
40086
+ function saveJoinWhileLocked(join42, options = {}) {
39862
40087
  const path = joinFilePath();
39863
40088
  const directory = dirname21(path);
39864
- const normalized = normalizedJoin(join41);
40089
+ const normalized = normalizedJoin(join42);
39865
40090
  mkdirSync32(directory, { recursive: true });
39866
40091
  if (existsSync35(path)) {
39867
40092
  if (lstatSync(path).isSymbolicLink()) {
@@ -39877,17 +40102,17 @@ function saveJoinWhileLocked(join41, options = {}) {
39877
40102
  }
39878
40103
  if (existing && joinsEqual(existing, normalized)) {
39879
40104
  chmodSync6(path, 384);
39880
- const fileFd = openSync4(path, "r");
40105
+ const fileFd = openSync5(path, "r");
39881
40106
  try {
39882
40107
  fsyncSync2(fileFd);
39883
40108
  } finally {
39884
- closeSync4(fileFd);
40109
+ closeSync5(fileFd);
39885
40110
  }
39886
- const directoryFd = openSync4(directory, "r");
40111
+ const directoryFd = openSync5(directory, "r");
39887
40112
  try {
39888
40113
  fsyncSync2(directoryFd);
39889
40114
  } finally {
39890
- closeSync4(directoryFd);
40115
+ closeSync5(directoryFd);
39891
40116
  }
39892
40117
  return path;
39893
40118
  }
@@ -39898,36 +40123,36 @@ function saveJoinWhileLocked(join41, options = {}) {
39898
40123
  const temporaryPath = resolve23(directory, `.otium-join.json.${process.pid}.${randomUUID27()}.tmp`);
39899
40124
  let fd;
39900
40125
  try {
39901
- fd = openSync4(temporaryPath, "wx", 384);
40126
+ fd = openSync5(temporaryPath, "wx", 384);
39902
40127
  writeFileSync23(fd, `${JSON.stringify(normalized, null, 2)}
39903
40128
  `, "utf8");
39904
40129
  fsyncSync2(fd);
39905
- closeSync4(fd);
40130
+ closeSync5(fd);
39906
40131
  fd = undefined;
39907
40132
  if (options.replaceExisting) {
39908
- renameSync15(temporaryPath, path);
40133
+ renameSync16(temporaryPath, path);
39909
40134
  } else {
39910
40135
  linkSync(temporaryPath, path);
39911
40136
  unlinkSync22(temporaryPath);
39912
40137
  }
39913
40138
  chmodSync6(path, 384);
39914
- const directoryFd = openSync4(directory, "r");
40139
+ const directoryFd = openSync5(directory, "r");
39915
40140
  try {
39916
40141
  fsyncSync2(directoryFd);
39917
40142
  } finally {
39918
- closeSync4(directoryFd);
40143
+ closeSync5(directoryFd);
39919
40144
  }
39920
40145
  } catch (error2) {
39921
40146
  if (fd !== undefined)
39922
- closeSync4(fd);
40147
+ closeSync5(fd);
39923
40148
  if (existsSync35(temporaryPath))
39924
40149
  unlinkSync22(temporaryPath);
39925
40150
  throw error2;
39926
40151
  }
39927
40152
  return path;
39928
40153
  }
39929
- function saveJoin(join41, options = {}) {
39930
- return withJoinCredentialLock(() => saveJoinWhileLocked(join41, options));
40154
+ function saveJoin(join42, options = {}) {
40155
+ return withJoinCredentialLock(() => saveJoinWhileLocked(join42, options));
39931
40156
  }
39932
40157
  function removeJoin() {
39933
40158
  return withJoinCredentialLock(() => {
@@ -39938,11 +40163,11 @@ function removeJoin() {
39938
40163
  throw new Error(`refusing to remove symlinked Otium join file at ${path}`);
39939
40164
  }
39940
40165
  unlinkSync22(path);
39941
- const directoryFd = openSync4(dirname21(path), "r");
40166
+ const directoryFd = openSync5(dirname21(path), "r");
39942
40167
  try {
39943
40168
  fsyncSync2(directoryFd);
39944
40169
  } finally {
39945
- closeSync4(directoryFd);
40170
+ closeSync5(directoryFd);
39946
40171
  }
39947
40172
  return true;
39948
40173
  });
@@ -39967,7 +40192,7 @@ function loadJoin() {
39967
40192
  if (!existsSync35(path))
39968
40193
  return null;
39969
40194
  try {
39970
- const parsed = JSON.parse(readFileSync26(path, "utf-8"));
40195
+ const parsed = JSON.parse(readFileSync27(path, "utf-8"));
39971
40196
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
39972
40197
  return null;
39973
40198
  return normalizeJoin(parsed);
@@ -40944,8 +41169,8 @@ var init_event_backflow = __esm(async () => {
40944
41169
 
40945
41170
  // ../../adapters/otium/src/peer-files.ts
40946
41171
  import { randomUUID as randomUUID29 } from "crypto";
40947
- import { copyFileSync as copyFileSync5, mkdirSync as mkdirSync33, rmSync as rmSync10, statSync as statSync20 } from "fs";
40948
- import { basename as basename13, extname as extname6, join as join41 } from "path";
41172
+ import { copyFileSync as copyFileSync5, mkdirSync as mkdirSync33, rmSync as rmSync11, statSync as statSync21 } from "fs";
41173
+ import { basename as basename13, extname as extname6, join as join42 } from "path";
40949
41174
  function fileType(mimeType) {
40950
41175
  if (mimeType.startsWith("image/"))
40951
41176
  return "image";
@@ -41015,21 +41240,21 @@ function recordFile(args) {
41015
41240
  function insertLocalFile(args) {
41016
41241
  const id = randomUUID29();
41017
41242
  mkdirSync33(PEER_FILES_DIR, { recursive: true });
41018
- const path = join41(PEER_FILES_DIR, `${id}-${safeFilename(args.filename)}`);
41243
+ const path = join42(PEER_FILES_DIR, `${id}-${safeFilename(args.filename)}`);
41019
41244
  copyFileSync5(args.sourcePath, path);
41020
- return recordFile({ id, path, sizeBytes: statSync20(path).size, ...args });
41245
+ return recordFile({ id, path, sizeBytes: statSync21(path).size, ...args });
41021
41246
  }
41022
41247
  function deletePeerFilesForTopic(topicId) {
41023
41248
  const rows = db.query("SELECT path FROM otium_peer_files WHERE topic_id = ?").all(topicId);
41024
41249
  db.run("DELETE FROM otium_peer_files WHERE topic_id = ?", [topicId]);
41025
41250
  for (const row of rows)
41026
- rmSync10(row.path, { force: true });
41251
+ rmSync11(row.path, { force: true });
41027
41252
  }
41028
41253
  async function storePeerInputFile(file, access) {
41029
41254
  const id = randomUUID29();
41030
41255
  mkdirSync33(PEER_FILES_DIR, { recursive: true });
41031
41256
  const filename = file.name || "upload";
41032
- const path = join41(PEER_FILES_DIR, `${id}-${safeFilename(filename)}`);
41257
+ const path = join42(PEER_FILES_DIR, `${id}-${safeFilename(filename)}`);
41033
41258
  const sizeBytes = await Bun.write(path, file);
41034
41259
  return recordFile({
41035
41260
  id,
@@ -41076,7 +41301,7 @@ function installPeerFileHooks() {
41076
41301
  var PEER_FILES_DIR;
41077
41302
  var init_peer_files = __esm(async () => {
41078
41303
  await init_src();
41079
- PEER_FILES_DIR = join41(DATA_DIR, "otium-peer-files");
41304
+ PEER_FILES_DIR = join42(DATA_DIR, "otium-peer-files");
41080
41305
  db.exec(`
41081
41306
  CREATE TABLE IF NOT EXISTS otium_peer_files (
41082
41307
  id TEXT PRIMARY KEY,
@@ -41780,7 +42005,7 @@ function messageEnvelope(message) {
41780
42005
  ...message.kind ? { kind: message.kind } : {}
41781
42006
  };
41782
42007
  }
41783
- async function publishTopic(join42, topicId, node) {
42008
+ async function publishTopic(join43, topicId, node) {
41784
42009
  const topic = getTopic(topicId);
41785
42010
  if (!topic || topic.kind !== "agent" || !topic.agent || !isTopicShared(topic) || !topic.visibility || topic.visibility === "hidden" || isMirrorTopic(topicId))
41786
42011
  return;
@@ -41828,10 +42053,10 @@ async function publishTopic(join42, topicId, node) {
41828
42053
  }
41829
42054
  } catch (error2) {
41830
42055
  logger.warn({ error: error2, topicId }, "otium: shared topic publish deferred");
41831
- setTimeout(() => void reconcileTopic(join42, topicId), RETRY_MS).unref?.();
42056
+ setTimeout(() => void reconcileTopic(join43, topicId), RETRY_MS).unref?.();
41832
42057
  }
41833
42058
  }
41834
- async function unpublishTopic(join42, topicId, node) {
42059
+ async function unpublishTopic(join43, topicId, node) {
41835
42060
  const state2 = getSharedTopicState(topicId);
41836
42061
  if (!state2)
41837
42062
  return;
@@ -41847,26 +42072,26 @@ async function unpublishTopic(join42, topicId, node) {
41847
42072
  deleteSharedTopicState(topicId);
41848
42073
  } catch (error2) {
41849
42074
  logger.warn({ error: error2, topicId }, "otium: shared topic unpublish deferred");
41850
- setTimeout(() => void reconcileTopic(join42, topicId), RETRY_MS).unref?.();
42075
+ setTimeout(() => void reconcileTopic(join43, topicId), RETRY_MS).unref?.();
41851
42076
  }
41852
42077
  }
41853
- async function reconcileTopic(join42, topicId, explicit = false) {
42078
+ async function reconcileTopic(join43, topicId, explicit = false) {
41854
42079
  if (!otiumCentralConfig())
41855
42080
  return;
41856
- if (!explicit && isPeerDetached(join42.cellId))
42081
+ if (!explicit && isPeerDetached(join43.cellId))
41857
42082
  return;
41858
42083
  const target = (await listPeerNodes()).find((node) => node.isPrimary) ?? null;
41859
42084
  if (!target)
41860
42085
  return;
41861
42086
  const topic = getTopic(topicId);
41862
42087
  if (topic?.kind === "agent" && topic.agent && isTopicShared(topic) && topic.visibility !== "hidden" && !isMirrorTopic(topicId))
41863
- return publishTopic(join42, topicId, target);
41864
- return unpublishTopic(join42, topicId, target);
42088
+ return publishTopic(join43, topicId, target);
42089
+ return unpublishTopic(join43, topicId, target);
41865
42090
  }
41866
- function disconnectSharedTopics(join42) {
42091
+ function disconnectSharedTopics(join43) {
41867
42092
  const states = listSharedTopicStates();
41868
42093
  const hubPromise = listPeerNodes({ fresh: true }).then((nodes) => nodes.find((node) => node.isPrimary) ?? null, () => null);
41869
- const updated = downgradeSharedTopicsLocally(join42.cellId);
42094
+ const updated = downgradeSharedTopicsLocally(join43.cellId);
41870
42095
  for (const topicId of updated)
41871
42096
  WsHub.get().broadcastTopicUpdated(topicId);
41872
42097
  const deletions = states.map(async (state2) => {
@@ -41889,16 +42114,16 @@ function downgradeSharedTopicsForHub(hubNodeId) {
41889
42114
  WsHub.get().broadcastTopicUpdated(topicId);
41890
42115
  return updated.length;
41891
42116
  }
41892
- async function checkPeerAttachment(join42) {
42117
+ async function checkPeerAttachment(join43) {
41893
42118
  const nodes = await listPeerNodes({ fresh: true });
41894
- if (nodes.some((node) => node.cellId === join42.cellId))
42119
+ if (nodes.some((node) => node.cellId === join43.cellId))
41895
42120
  return true;
41896
- downgradeSharedTopicsForHub(join42.cellId);
42121
+ downgradeSharedTopicsForHub(join43.cellId);
41897
42122
  return false;
41898
42123
  }
41899
- function startSharedTopicSync(join42) {
42124
+ function startSharedTopicSync(join43) {
41900
42125
  let stopped = false;
41901
- let detached = isPeerDetached(join42.cellId);
42126
+ let detached = isPeerDetached(join43.cellId);
41902
42127
  const queue = new Set;
41903
42128
  const schedule = (topicId, explicit = false) => {
41904
42129
  if (stopped || queue.has(topicId))
@@ -41907,7 +42132,7 @@ function startSharedTopicSync(join42) {
41907
42132
  queueMicrotask(async () => {
41908
42133
  queue.delete(topicId);
41909
42134
  try {
41910
- await reconcileTopic(join42, topicId, explicit);
42135
+ await reconcileTopic(join43, topicId, explicit);
41911
42136
  } catch (error2) {
41912
42137
  logger.warn({ error: error2, topicId }, "otium: shared topic reconciliation failed");
41913
42138
  }
@@ -41921,7 +42146,7 @@ function startSharedTopicSync(join42) {
41921
42146
  if (stopped || detached)
41922
42147
  return;
41923
42148
  try {
41924
- if (!await checkPeerAttachment(join42))
42149
+ if (!await checkPeerAttachment(join43))
41925
42150
  detached = true;
41926
42151
  } catch {}
41927
42152
  }, 30000);
@@ -41933,7 +42158,7 @@ function startSharedTopicSync(join42) {
41933
42158
  const message = event.payload;
41934
42159
  if (!message.sourceNode) {
41935
42160
  schedule(event.topicId);
41936
- forwardSharedTopicMessage(join42, message).catch((error2) => logger.warn({ error: error2, topicId: event.topicId }, "otium: shared message deferred"));
42161
+ forwardSharedTopicMessage(join43, message).catch((error2) => logger.warn({ error: error2, topicId: event.topicId }, "otium: shared message deferred"));
41937
42162
  }
41938
42163
  }
41939
42164
  });
@@ -42684,14 +42909,14 @@ import {
42684
42909
  } from "crypto";
42685
42910
  import {
42686
42911
  chmodSync as chmodSync7,
42687
- closeSync as closeSync5,
42912
+ closeSync as closeSync6,
42688
42913
  existsSync as existsSync37,
42689
42914
  fsyncSync as fsyncSync3,
42690
42915
  linkSync as linkSync2,
42691
42916
  mkdirSync as mkdirSync34,
42692
- openSync as openSync5,
42693
- readFileSync as readFileSync27,
42694
- renameSync as renameSync16,
42917
+ openSync as openSync6,
42918
+ readFileSync as readFileSync28,
42919
+ renameSync as renameSync17,
42695
42920
  unlinkSync as unlinkSync23,
42696
42921
  writeFileSync as writeFileSync24
42697
42922
  } from "fs";
@@ -42723,7 +42948,7 @@ function isEnrollmentPending(invite) {
42723
42948
  if (!existsSync37(path))
42724
42949
  return false;
42725
42950
  try {
42726
- const saved = JSON.parse(readFileSync27(path, "utf8"));
42951
+ const saved = JSON.parse(readFileSync28(path, "utf8"));
42727
42952
  return saved.central === invite.central && saved.token === invite.token;
42728
42953
  } catch {
42729
42954
  return false;
@@ -42732,7 +42957,7 @@ function isEnrollmentPending(invite) {
42732
42957
  function loadOrCreatePending(invite, nodeName) {
42733
42958
  const path = pendingEnrollmentPath();
42734
42959
  if (existsSync37(path)) {
42735
- const saved = JSON.parse(readFileSync27(path, "utf8"));
42960
+ const saved = JSON.parse(readFileSync28(path, "utf8"));
42736
42961
  if (saved.central === invite.central && saved.token === invite.token)
42737
42962
  return saved;
42738
42963
  throw new Error(`another Otium enrollment is pending at ${path}`);
@@ -42749,28 +42974,28 @@ function loadOrCreatePending(invite, nodeName) {
42749
42974
  const temporaryPath = resolve25(dirname22(path), `.otium-enrollment-pending.json.${process.pid}.${randomUUID31()}.tmp`);
42750
42975
  let fd;
42751
42976
  try {
42752
- fd = openSync5(temporaryPath, "wx", 384);
42977
+ fd = openSync6(temporaryPath, "wx", 384);
42753
42978
  writeFileSync24(fd, `${JSON.stringify(pending2, null, 2)}
42754
42979
  `, "utf8");
42755
42980
  fsyncSync3(fd);
42756
- closeSync5(fd);
42981
+ closeSync6(fd);
42757
42982
  fd = undefined;
42758
42983
  linkSync2(temporaryPath, path);
42759
42984
  unlinkSync23(temporaryPath);
42760
42985
  chmodSync7(path, 384);
42761
- const directoryFd = openSync5(dirname22(path), "r");
42986
+ const directoryFd = openSync6(dirname22(path), "r");
42762
42987
  try {
42763
42988
  fsyncSync3(directoryFd);
42764
42989
  } finally {
42765
- closeSync5(directoryFd);
42990
+ closeSync6(directoryFd);
42766
42991
  }
42767
42992
  } catch (error2) {
42768
42993
  if (fd !== undefined)
42769
- closeSync5(fd);
42994
+ closeSync6(fd);
42770
42995
  if (existsSync37(temporaryPath))
42771
42996
  unlinkSync23(temporaryPath);
42772
42997
  if (error2.code === "EEXIST" && existsSync37(path)) {
42773
- const saved = JSON.parse(readFileSync27(path, "utf8"));
42998
+ const saved = JSON.parse(readFileSync28(path, "utf8"));
42774
42999
  if (saved.central === invite.central && saved.token === invite.token)
42775
43000
  return saved;
42776
43001
  }
@@ -42784,34 +43009,34 @@ function replacePendingEnrollment(pending2) {
42784
43009
  const temporaryPath = resolve25(directory, `.otium-enrollment-pending.json.${process.pid}.${randomUUID31()}.tmp`);
42785
43010
  let fd;
42786
43011
  try {
42787
- fd = openSync5(temporaryPath, "wx", 384);
43012
+ fd = openSync6(temporaryPath, "wx", 384);
42788
43013
  writeFileSync24(fd, `${JSON.stringify(pending2, null, 2)}
42789
43014
  `, "utf8");
42790
43015
  fsyncSync3(fd);
42791
- closeSync5(fd);
43016
+ closeSync6(fd);
42792
43017
  fd = undefined;
42793
- renameSync16(temporaryPath, path);
42794
- const directoryFd = openSync5(directory, "r");
43018
+ renameSync17(temporaryPath, path);
43019
+ const directoryFd = openSync6(directory, "r");
42795
43020
  try {
42796
43021
  fsyncSync3(directoryFd);
42797
43022
  } finally {
42798
- closeSync5(directoryFd);
43023
+ closeSync6(directoryFd);
42799
43024
  }
42800
43025
  } catch (error2) {
42801
43026
  if (fd !== undefined)
42802
- closeSync5(fd);
43027
+ closeSync6(fd);
42803
43028
  if (existsSync37(temporaryPath))
42804
43029
  unlinkSync23(temporaryPath);
42805
43030
  throw error2;
42806
43031
  }
42807
43032
  }
42808
- function recordClaimedCredential(pending2, join42) {
43033
+ function recordClaimedCredential(pending2, join43) {
42809
43034
  withJoinCredentialLock(() => {
42810
- const current3 = JSON.parse(readFileSync27(pendingEnrollmentPath(), "utf8"));
43035
+ const current3 = JSON.parse(readFileSync28(pendingEnrollmentPath(), "utf8"));
42811
43036
  if (current3.central !== pending2.central || current3.token !== pending2.token || current3.idempotencyKey !== pending2.idempotencyKey || current3.publicKey !== pending2.publicKey) {
42812
43037
  throw new Error("pending Otium enrollment changed while its claim was in flight");
42813
43038
  }
42814
- const claimed = { digest: joinCredentialDigest(join42), cellId: join42.cellId };
43039
+ const claimed = { digest: joinCredentialDigest(join43), cellId: join43.cellId };
42815
43040
  if (current3.claimed && (current3.claimed.digest !== claimed.digest || current3.claimed.cellId !== claimed.cellId)) {
42816
43041
  throw new Error("central returned different credentials for an idempotent enrollment claim");
42817
43042
  }
@@ -42869,40 +43094,40 @@ async function claimEnrollment(invite, nodeName) {
42869
43094
  const secret = openCredential(credential, pending2.privateKey);
42870
43095
  if (!secret.startsWith("rcs_"))
42871
43096
  throw new Error("central returned an invalid runtime credential");
42872
- const join42 = {
43097
+ const join43 = {
42873
43098
  v: 2,
42874
43099
  central: invite.central,
42875
43100
  relay: String(response.relayUrl),
42876
43101
  cellId: String(response.cell?.id),
42877
43102
  secret
42878
43103
  };
42879
- if (!join42.relay || !join42.cellId || join42.cellId === "undefined") {
43104
+ if (!join43.relay || !join43.cellId || join43.cellId === "undefined") {
42880
43105
  throw new Error("central returned an incomplete enrollment response");
42881
43106
  }
42882
- assertSecureRelayUrl(join42.relay);
42883
- recordClaimedCredential(pending2, join42);
42884
- return join42;
43107
+ assertSecureRelayUrl(join43.relay);
43108
+ recordClaimedCredential(pending2, join43);
43109
+ return join43;
42885
43110
  }
42886
- function commitEnrollment(join42, options = {}) {
43111
+ function commitEnrollment(join43, options = {}) {
42887
43112
  return withJoinCredentialLock(() => {
42888
43113
  const pendingPath = pendingEnrollmentPath();
42889
- const pending2 = existsSync37(pendingPath) ? JSON.parse(readFileSync27(pendingPath, "utf8")) : null;
42890
- const digest = joinCredentialDigest(join42);
42891
- if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !== join42.cellId)) {
43114
+ const pending2 = existsSync37(pendingPath) ? JSON.parse(readFileSync28(pendingPath, "utf8")) : null;
43115
+ const digest = joinCredentialDigest(join43);
43116
+ if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !== join43.cellId)) {
42892
43117
  throw new Error(`pending Otium enrollment at ${pendingPath} does not match these credentials`);
42893
43118
  }
42894
- const path = saveJoinWhileLocked(join42, options);
42895
- if (!isJoinPersisted(join42)) {
43119
+ const path = saveJoinWhileLocked(join43, options);
43120
+ if (!isJoinPersisted(join43)) {
42896
43121
  throw new Error("Otium join credentials were not durably persisted");
42897
43122
  }
42898
43123
  if (!pending2)
42899
43124
  return path;
42900
43125
  unlinkSync23(pendingPath);
42901
- const directoryFd = openSync5(dirname22(pendingPath), "r");
43126
+ const directoryFd = openSync6(dirname22(pendingPath), "r");
42902
43127
  try {
42903
43128
  fsyncSync3(directoryFd);
42904
43129
  } finally {
42905
- closeSync5(directoryFd);
43130
+ closeSync6(directoryFd);
42906
43131
  }
42907
43132
  return path;
42908
43133
  });
@@ -43783,14 +44008,14 @@ var init_peer_server = __esm(async () => {
43783
44008
 
43784
44009
  // ../../adapters/otium/src/index.ts
43785
44010
  function startOtiumNodeRuntime(options) {
43786
- const { join: join42 } = options;
43787
- configureOtiumCentral(join42);
44011
+ const { join: join43 } = options;
44012
+ configureOtiumCentral(join43);
43788
44013
  const failed = failInterruptedPeerTurnRequestsOnStartup();
43789
44014
  if (failed > 0) {
43790
44015
  logger.warn({ failed }, "otium: failed interrupted peer turns from previous process");
43791
44016
  }
43792
44017
  const stopBackflow = startEventBackflow();
43793
- const stopSharedTopicSync = startSharedTopicSync(join42);
44018
+ const stopSharedTopicSync = startSharedTopicSync(join43);
43794
44019
  const unregisterRuntimeBridge = registerPeerRuntimeBridge(otiumPeerRuntimeBridge);
43795
44020
  const unregisterSessionBridge = registerPeerSessionBridge(otiumPeerSessionBridge);
43796
44021
  const sessionBridgeIpc = startPeerSessionBridgeIpc(otiumPeerSessionBridge);
@@ -43811,7 +44036,7 @@ function startOtiumNodeRuntime(options) {
43811
44036
  }
43812
44037
  });
43813
44038
  let stopped = false;
43814
- logger.info({ central: join42.central, cellId: join42.cellId }, "otium: worker mode enabled");
44039
+ logger.info({ central: join43.central, cellId: join43.cellId }, "otium: worker mode enabled");
43815
44040
  selfPeerNode().then((self) => {
43816
44041
  if (self) {
43817
44042
  logger.info({ nodeName: self.nodeName, baseUrl: self.baseUrl }, "otium: attached to workspace");
@@ -43821,7 +44046,7 @@ function startOtiumNodeRuntime(options) {
43821
44046
  });
43822
44047
  return {
43823
44048
  name: "otium",
43824
- join: join42,
44049
+ join: join43,
43825
44050
  stop: () => {
43826
44051
  if (stopped)
43827
44052
  return;
@@ -43943,10 +44168,10 @@ async function handleOtiumAdapterControlRequest(req) {
43943
44168
  return await handleOtiumPeerRequest(new Request(peerUrl.toString(), { method: req.method, headers, body, signal: req.signal })) ?? Response.json({ ok: false, error: "Otium route not found" }, { status: 404 });
43944
44169
  }
43945
44170
  function mountConfiguredOtiumNodeRuntime() {
43946
- const join42 = loadJoin();
43947
- if (!join42)
44171
+ const join43 = loadJoin();
44172
+ if (!join43)
43948
44173
  return null;
43949
- const runtime2 = startOtiumNodeRuntime({ join: join42 });
44174
+ const runtime2 = startOtiumNodeRuntime({ join: join43 });
43950
44175
  registerNodeRequestHandler("otium-adapter-control", handleOtiumAdapterControlRequest);
43951
44176
  let stopped = false;
43952
44177
  return {
@@ -43997,11 +44222,11 @@ async function joinCommand(args) {
43997
44222
  process.exitCode = 1;
43998
44223
  return;
43999
44224
  }
44000
- let join42;
44225
+ let join43;
44001
44226
  let productionEnrollment = false;
44002
44227
  if (args.includes("--legacy")) {
44003
44228
  try {
44004
- join42 = parseInviteCode(code);
44229
+ join43 = parseInviteCode(code);
44005
44230
  } catch (err2) {
44006
44231
  console.error(`invalid legacy invite code: ${err2 instanceof Error ? err2.message : err2}`);
44007
44232
  process.exitCode = 1;
@@ -44028,7 +44253,7 @@ async function joinCommand(args) {
44028
44253
  return;
44029
44254
  }
44030
44255
  }
44031
- join42 = await claimEnrollment(invite, nodeName);
44256
+ join43 = await claimEnrollment(invite, nodeName);
44032
44257
  productionEnrollment = true;
44033
44258
  } catch (err2) {
44034
44259
  console.error(`enrollment failed: ${err2 instanceof Error ? err2.message : err2}`);
@@ -44039,16 +44264,16 @@ async function joinCommand(args) {
44039
44264
  let path;
44040
44265
  try {
44041
44266
  const saveOptions = { replaceExisting: args.includes("--replace") };
44042
- path = productionEnrollment ? commitEnrollment(join42, saveOptions) : saveJoin(join42, saveOptions);
44267
+ path = productionEnrollment ? commitEnrollment(join43, saveOptions) : saveJoin(join43, saveOptions);
44043
44268
  } catch (err2) {
44044
44269
  console.error(`could not save join credentials: ${err2 instanceof Error ? err2.message : err2}`);
44045
44270
  process.exitCode = 1;
44046
44271
  return;
44047
44272
  }
44048
44273
  console.log(`otium join credentials saved to ${path}`);
44049
- console.log(` central: ${join42.central}`);
44050
- console.log(` cellId: ${join42.cellId}`);
44051
- configureOtiumCentral(join42);
44274
+ console.log(` central: ${join43.central}`);
44275
+ console.log(` cellId: ${join43.cellId}`);
44276
+ configureOtiumCentral(join43);
44052
44277
  try {
44053
44278
  const self = await selfPeerNode();
44054
44279
  if (self) {
@@ -44103,8 +44328,8 @@ async function proxyOtiumPeerRequest(req, dependencies = {}) {
44103
44328
  }
44104
44329
  }
44105
44330
  async function runOtiumSidecar(options) {
44106
- const join42 = loadJoin();
44107
- if (!join42) {
44331
+ const join43 = loadJoin();
44332
+ if (!join43) {
44108
44333
  throw new Error("not joined to an Otium workspace \u2014 run `negotium otium join <code>` first");
44109
44334
  }
44110
44335
  const initialNode = await inspectNodeDaemon();
@@ -44136,10 +44361,10 @@ async function runOtiumSidecar(options) {
44136
44361
  lease.stop();
44137
44362
  throw error2;
44138
44363
  }
44139
- const selectedRelay = options.relayUrl?.trim() || join42.relay || process.env.OTIUM_RELAY_URL?.trim();
44364
+ const selectedRelay = options.relayUrl?.trim() || join43.relay || process.env.OTIUM_RELAY_URL?.trim();
44140
44365
  const tunnel = selectedRelay ? new TunnelClient({
44141
44366
  relayUrl: selectedRelay,
44142
- token: join42.secret,
44367
+ token: join43.secret,
44143
44368
  targetOrigin: `http://127.0.0.1:${server.port}`,
44144
44369
  nodeVersion: `negotium@${NEGOTIUM_VERSION}`,
44145
44370
  logger
@@ -44230,10 +44455,10 @@ async function resolveHostNodeId(explicit) {
44230
44455
  init_central().then(() => exports_central),
44231
44456
  init_join().then(() => exports_join)
44232
44457
  ]);
44233
- const join42 = loadJoin2();
44234
- if (!join42)
44458
+ const join43 = loadJoin2();
44459
+ if (!join43)
44235
44460
  throw new Error("not joined to an Otium workspace; pass --host-node or join first");
44236
- configureOtiumCentral2(join42);
44461
+ configureOtiumCentral2(join43);
44237
44462
  try {
44238
44463
  const nodes = await listPeerNodes2({ fresh: true });
44239
44464
  const primary = nodes.find((node) => node.isPrimary && !node.self) ?? nodes.find((node) => node.isPrimary);
@@ -44304,12 +44529,12 @@ async function runOtiumCli(args = process.argv.slice(2)) {
44304
44529
  const { configureOtiumCentral: configureOtiumCentral2 } = await init_central().then(() => exports_central);
44305
44530
  const { loadJoin: loadJoin2, removeJoin: removeJoin2 } = await init_join().then(() => exports_join);
44306
44531
  const { disconnectSharedTopics: disconnectSharedTopics2 } = await init_shared_topic_sync().then(() => exports_shared_topic_sync);
44307
- const join42 = loadJoin2();
44308
- if (!join42)
44532
+ const join43 = loadJoin2();
44533
+ if (!join43)
44309
44534
  throw new Error("not joined to an Otium workspace");
44310
- configureOtiumCentral2(join42);
44535
+ configureOtiumCentral2(join43);
44311
44536
  try {
44312
- await disconnectSharedTopics2(join42);
44537
+ await disconnectSharedTopics2(join43);
44313
44538
  removeJoin2();
44314
44539
  } finally {
44315
44540
  configureOtiumCentral2(null);
@@ -45086,4 +45311,4 @@ switch (command) {
45086
45311
  }
45087
45312
  }
45088
45313
 
45089
- //# debugId=41725DFC7CF611BE64756E2164756E21
45314
+ //# debugId=C6B36BE30E72B26A64756E2164756E21