negotium 0.1.25 → 0.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -3728,7 +3728,7 @@ var init_claude_provider = __esm(async () => {
3728
3728
  });
3729
3729
 
3730
3730
  // ../../packages/core/src/version.ts
3731
- var NEGOTIUM_VERSION = "0.1.25";
3731
+ var NEGOTIUM_VERSION = "0.1.26";
3732
3732
 
3733
3733
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
3734
3734
  import { spawn as spawn3 } from "child_process";
@@ -6747,6 +6747,38 @@ var init_self_schedules = __esm(async () => {
6747
6747
  `);
6748
6748
  });
6749
6749
 
6750
+ // ../../packages/core/src/platform/playwright/headed-launch.ts
6751
+ import { accessSync, constants } from "fs";
6752
+ import { delimiter, isAbsolute, resolve as resolve5 } from "path";
6753
+ function findExecutableOnPath(command, environment = process.env) {
6754
+ const candidates = isAbsolute(command) ? [command] : (environment.PATH ?? "").split(delimiter).filter(Boolean).map((directory) => resolve5(directory, command));
6755
+ for (const candidate of candidates) {
6756
+ try {
6757
+ accessSync(candidate, constants.X_OK);
6758
+ return candidate;
6759
+ } catch {}
6760
+ }
6761
+ return null;
6762
+ }
6763
+ function resolveHeadedPlaywrightSpawn(command, args, options = {}) {
6764
+ const platform2 = options.platform ?? process.platform;
6765
+ const environment = options.environment ?? process.env;
6766
+ const hasDisplay = Boolean(environment.DISPLAY?.trim() || environment.WAYLAND_DISPLAY?.trim());
6767
+ if (platform2 !== "linux" || hasDisplay) {
6768
+ return { command, args: [...args], virtualDisplay: false };
6769
+ }
6770
+ const xvfbRun = (options.findExecutable ?? findExecutableOnPath)("xvfb-run", environment);
6771
+ if (!xvfbRun) {
6772
+ throw new Error("Headed Playwright on Linux requires DISPLAY/WAYLAND_DISPLAY or xvfb-run; install Xvfb and ensure xvfb-run is on PATH");
6773
+ }
6774
+ return {
6775
+ command: xvfbRun,
6776
+ args: ["-a", "-s", "-screen 0 1440x1000x24", command, ...args],
6777
+ virtualDisplay: true
6778
+ };
6779
+ }
6780
+ var init_headed_launch = () => {};
6781
+
6750
6782
  // ../../packages/core/src/storage/browser-profiles.ts
6751
6783
  function normalizeBrowserProfileName(name) {
6752
6784
  const value = name.trim().toLowerCase();
@@ -6916,7 +6948,7 @@ async function waitForRuntimeProcessLease(role, options = {}) {
6916
6948
  const remaining = deadline - Date.now();
6917
6949
  if (remaining <= 0)
6918
6950
  return null;
6919
- await new Promise((resolve5) => setTimeout(resolve5, Math.min(interval, remaining)));
6951
+ await new Promise((resolve6) => setTimeout(resolve6, Math.min(interval, remaining)));
6920
6952
  }
6921
6953
  }
6922
6954
  async function waitForRequiredRuntimeProcessLease(role, options = {}) {
@@ -6957,7 +6989,7 @@ import {
6957
6989
  unlinkSync as unlinkSync10,
6958
6990
  writeFileSync as writeFileSync7
6959
6991
  } from "fs";
6960
- import { dirname as dirname8, join as join14, resolve as resolve5 } from "path";
6992
+ import { dirname as dirname8, join as join14, resolve as resolve6 } from "path";
6961
6993
  function makeInstanceKey(userId, topic) {
6962
6994
  if (!topic)
6963
6995
  return makeBrowserProfileInstanceKey(userId, "default");
@@ -6975,7 +7007,7 @@ function migrateLegacyTopicProfile(ownerId, topic) {
6975
7007
  const current2 = getTopicBrowserProfile(topic);
6976
7008
  if (current2 !== "default" || !hasBrowserProfileTopic(topic))
6977
7009
  return current2;
6978
- const legacyDir = resolve5(BROWSER_PROFILES_DIR, sanitizeTopicName(topic));
7010
+ const legacyDir = resolve6(BROWSER_PROFILES_DIR, sanitizeTopicName(topic));
6979
7011
  if (!existsSync13(legacyDir))
6980
7012
  return current2;
6981
7013
  const profile = legacyBrowserProfileName(topic);
@@ -7179,11 +7211,11 @@ async function killPlaywrightOnPort(port, expectedUserDataDir) {
7179
7211
  }
7180
7212
  function browserProcessMatchesExpectedProfile(cmdline, expectedUserDataDir) {
7181
7213
  const actualUserDataDir = extractUserDataDirArg(cmdline);
7182
- return actualUserDataDir !== null && resolve5(actualUserDataDir) === resolve5(expectedUserDataDir);
7214
+ return actualUserDataDir !== null && resolve6(actualUserDataDir) === resolve6(expectedUserDataDir);
7183
7215
  }
7184
7216
  function killBrowserProcsForUserDataDir(userDataDir) {
7185
- const target = resolve5(userDataDir);
7186
- if (!target.startsWith(resolve5(BROWSER_PROFILES_DIR)))
7217
+ const target = resolve6(userDataDir);
7218
+ if (!target.startsWith(resolve6(BROWSER_PROFILES_DIR)))
7187
7219
  return;
7188
7220
  let pids;
7189
7221
  try {
@@ -7203,7 +7235,7 @@ function killBrowserProcsForUserDataDir(userDataDir) {
7203
7235
  stdio: "pipe"
7204
7236
  }).toString().trim();
7205
7237
  const argDir = extractUserDataDirArg(cmdline);
7206
- if (!argDir || resolve5(argDir) !== target)
7238
+ if (!argDir || resolve6(argDir) !== target)
7207
7239
  continue;
7208
7240
  killProcessTreeChildren(pidNum);
7209
7241
  process.kill(pidNum, "SIGKILL");
@@ -7214,13 +7246,13 @@ function killBrowserProcsForUserDataDir(userDataDir) {
7214
7246
  }
7215
7247
  }
7216
7248
  function selectOrphanBrowserPids(procs, liveUserDataDirs, profileRoot, selfPid) {
7217
- const root = resolve5(profileRoot);
7218
- const live = new Set([...liveUserDataDirs].map((d) => resolve5(d)));
7249
+ const root = resolve6(profileRoot);
7250
+ const live = new Set([...liveUserDataDirs].map((d) => resolve6(d)));
7219
7251
  const out = [];
7220
7252
  for (const { pid, userDataDir } of procs) {
7221
7253
  if (pid === selfPid || !userDataDir)
7222
7254
  continue;
7223
- const dir = resolve5(userDataDir);
7255
+ const dir = resolve6(userDataDir);
7224
7256
  if (!dir.startsWith(root))
7225
7257
  continue;
7226
7258
  if (live.has(dir))
@@ -7236,7 +7268,7 @@ function reapOrphanBrowsers() {
7236
7268
  const daemonLease = getRuntimeProcessLease("node-daemon", Date.now(), Number.POSITIVE_INFINITY);
7237
7269
  if (!isBrowserJanitorOwner(daemonLease?.pid ?? null, process.pid))
7238
7270
  return;
7239
- const profileRoot = resolve5(BROWSER_PROFILES_DIR);
7271
+ const profileRoot = resolve6(BROWSER_PROFILES_DIR);
7240
7272
  let pids;
7241
7273
  try {
7242
7274
  pids = execFileSync4("pgrep", ["-f", "--", profileRoot], { stdio: "pipe" }).toString().trim();
@@ -7289,7 +7321,7 @@ function cleanSingletonFiles(userDataDir) {
7289
7321
  for (const f of files) {
7290
7322
  if (f.startsWith("Singleton")) {
7291
7323
  try {
7292
- unlinkSync10(resolve5(userDataDir, f));
7324
+ unlinkSync10(resolve6(userDataDir, f));
7293
7325
  logger.info({ file: f, userDataDir }, "Removed stale Singleton file");
7294
7326
  } catch (e) {
7295
7327
  logger.warn({ err: e, file: f }, "Failed to remove stale Chrome Singleton file");
@@ -7325,7 +7357,7 @@ function ownerDirectory(ownerId) {
7325
7357
  return `${sanitizeTopicName(ownerId).slice(0, 24)}_${digest}`;
7326
7358
  }
7327
7359
  function resolveProfileDir(ownerId, profile) {
7328
- return resolve5(BROWSER_PROFILES_DIR, "profiles", ownerDirectory(ownerId), profile);
7360
+ return resolve6(BROWSER_PROFILES_DIR, "profiles", ownerDirectory(ownerId), profile);
7329
7361
  }
7330
7362
  function resolveUserDataDir(instanceKey) {
7331
7363
  const { ownerId, profile } = parseInstanceKey(instanceKey);
@@ -7383,11 +7415,25 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
7383
7415
  }
7384
7416
  const command = browserBin.endsWith(".mjs") ? process.execPath : browserBin;
7385
7417
  const args = browserBin.endsWith(".mjs") ? [browserBin, ...mcpArgs] : mcpArgs;
7386
- const proc = spawn4(command, args, {
7387
- stdio: "ignore",
7388
- detached: false,
7389
- env: childEnv
7390
- });
7418
+ let spawnSpec;
7419
+ try {
7420
+ spawnSpec = resolveHeadedPlaywrightSpawn(command, args, { environment: childEnv });
7421
+ } catch (err) {
7422
+ releasePort(port);
7423
+ throw err;
7424
+ }
7425
+ let proc;
7426
+ try {
7427
+ proc = spawn4(spawnSpec.command, spawnSpec.args, {
7428
+ stdio: "ignore",
7429
+ detached: false,
7430
+ env: childEnv
7431
+ });
7432
+ } catch (err) {
7433
+ releasePort(port);
7434
+ throw err;
7435
+ }
7436
+ const spawnError = waitForChildProcessSpawnError(proc);
7391
7437
  const reapCrashedBrowser = () => {
7392
7438
  const userDataDir2 = resolveUserDataDir(instanceKey);
7393
7439
  killBrowserProcsForUserDataDir(userDataDir2);
@@ -7420,7 +7466,10 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
7420
7466
  lastUsedAt: now,
7421
7467
  capability
7422
7468
  });
7423
- const ready = await waitForServer(port, 1e4) && await supportsOwnerCleanup(port, capability);
7469
+ const ready = await Promise.race([
7470
+ (async () => await waitForServer(port, 1e4) && await supportsOwnerCleanup(port, capability))(),
7471
+ spawnError
7472
+ ]);
7424
7473
  if (!ready) {
7425
7474
  const exitCode = proc.exitCode;
7426
7475
  killInstance(instanceKey);
@@ -7431,7 +7480,7 @@ async function spawnPlaywright(instanceKey, userId, reservedPort, browserBin = P
7431
7480
  throw new Error(`Playwright MCP failed health check after spawn on port ${port}` + (exitCode === null ? "" : ` (exitCode=${exitCode})`));
7432
7481
  }
7433
7482
  writePortFile(instanceKey, port);
7434
- logger.info({ instanceKey, port, pid: proc.pid, ready }, "Playwright MCP started");
7483
+ logger.info({ instanceKey, port, pid: proc.pid, ready, virtualDisplay: spawnSpec.virtualDisplay }, "Playwright MCP started");
7435
7484
  return port;
7436
7485
  }
7437
7486
  async function supportsOwnerCleanup(port, capability) {
@@ -7587,7 +7636,7 @@ async function cloneProfileForChild(opts) {
7587
7636
  cleanSingletonFiles(dstDir);
7588
7637
  for (const f of ["DevToolsActivePort", "LOCK"]) {
7589
7638
  try {
7590
- unlinkSync10(resolve5(dstDir, f));
7639
+ unlinkSync10(resolve6(dstDir, f));
7591
7640
  } catch {}
7592
7641
  }
7593
7642
  logger.info({ srcKey, dstKey, srcDir, dstDir }, "Cloned Playwright profile for child topic");
@@ -7641,10 +7690,16 @@ function waitForChildProcessExit(proc, timeoutMs) {
7641
7690
  finish(true);
7642
7691
  });
7643
7692
  }
7693
+ function waitForChildProcessSpawnError(proc) {
7694
+ return new Promise((_resolve, reject) => {
7695
+ proc.once("error", reject);
7696
+ });
7697
+ }
7644
7698
  var BASE_PORT, MAX_PORT, MAX_IDLE_MS, instances, usedPorts, spawning, pinnedInstances, _onPlaywrightExit = null;
7645
7699
  var init_manager2 = __esm(async () => {
7646
7700
  init_config();
7647
7701
  init_logger();
7702
+ init_headed_launch();
7648
7703
  await init_browser_profiles();
7649
7704
  await init_runtime_process_leases();
7650
7705
  BASE_PORT = PLAYWRIGHT_BASE_PORT;
@@ -9022,9 +9077,9 @@ var init_runtime_turn_requests = __esm(async () => {
9022
9077
 
9023
9078
  // ../../packages/core/src/prompts/builders.ts
9024
9079
  import { readFileSync as readFileSync10 } from "fs";
9025
- import { resolve as resolve6 } from "path";
9080
+ import { resolve as resolve7 } from "path";
9026
9081
  function loadPrompt(filename, dir = SESSIONS_DIR) {
9027
- const raw = readFileSync10(resolve6(dir, filename), "utf-8");
9082
+ const raw = readFileSync10(resolve7(dir, filename), "utf-8");
9028
9083
  return raw.replace(/\{\{RESOURCES_DIR\}\}/g, RESOURCES_DIR);
9029
9084
  }
9030
9085
  function replaceVars(template, vars) {
@@ -9067,7 +9122,7 @@ function visualDesignGuide() {
9067
9122
  return _visualDesignGuide;
9068
9123
  }
9069
9124
  function loadAgentPrompt(filename) {
9070
- const raw = readFileSync10(resolve6(AGENTS_PROMPTS_DIR, filename), "utf-8");
9125
+ const raw = readFileSync10(resolve7(AGENTS_PROMPTS_DIR, filename), "utf-8");
9071
9126
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
9072
9127
  if (!match)
9073
9128
  throw new Error(`Agent prompt ${filename} is missing frontmatter`);
@@ -9267,8 +9322,8 @@ var init_builders = __esm(() => {
9267
9322
  init_model_catalog();
9268
9323
  init_config();
9269
9324
  init_logger();
9270
- PROMPTS_DIR = resolve6(PROJECT_ROOT, "src/prompts");
9271
- SESSIONS_DIR = resolve6(PROMPTS_DIR, "sessions");
9325
+ PROMPTS_DIR = resolve7(PROJECT_ROOT, "src/prompts");
9326
+ SESSIONS_DIR = resolve7(PROMPTS_DIR, "sessions");
9272
9327
  });
9273
9328
 
9274
9329
  // ../../packages/core/src/storage/api-topic-brief.ts
@@ -10678,12 +10733,12 @@ var init_errors = __esm(() => {
10678
10733
 
10679
10734
  // ../../packages/core/src/runtime/event-heartbeat.ts
10680
10735
  function nextOrHeartbeat(pending, intervalMs) {
10681
- return new Promise((resolve7, reject) => {
10682
- const timer = setTimeout(() => resolve7({ kind: "heartbeat" }), intervalMs);
10736
+ return new Promise((resolve8, reject) => {
10737
+ const timer = setTimeout(() => resolve8({ kind: "heartbeat" }), intervalMs);
10683
10738
  timer.unref?.();
10684
10739
  pending.then((result) => {
10685
10740
  clearTimeout(timer);
10686
- resolve7({ kind: "event", result });
10741
+ resolve8({ kind: "event", result });
10687
10742
  }, (error) => {
10688
10743
  clearTimeout(timer);
10689
10744
  reject(error);
@@ -11120,7 +11175,7 @@ var init_visual_html = __esm(() => {
11120
11175
 
11121
11176
  // ../../packages/core/src/runtime/visuals.ts
11122
11177
  import { realpathSync as realpathSync2 } from "fs";
11123
- import { isAbsolute, resolve as resolve7 } from "path";
11178
+ import { isAbsolute as isAbsolute2, resolve as resolve8 } from "path";
11124
11179
  function activeVisualHtmlForPrompt(html) {
11125
11180
  if (html.length <= ACTIVE_VISUAL_PROMPT_MAX_CHARS) {
11126
11181
  return { html, omittedChars: 0 };
@@ -11171,8 +11226,8 @@ function topicAllowsVisualFileId(topicId, fileId) {
11171
11226
  return topicHasAttachmentFileId(topicId, fileId) || topicHasVisualFileId(topicId, fileId);
11172
11227
  }
11173
11228
  function isPathInside(baseDir, filePath) {
11174
- const base = resolve7(baseDir);
11175
- const normalized = resolve7(filePath);
11229
+ const base = resolve8(baseDir);
11230
+ const normalized = resolve8(filePath);
11176
11231
  try {
11177
11232
  const realBase = realpathSync2(base);
11178
11233
  const real = realpathSync2(normalized);
@@ -11234,7 +11289,7 @@ function resolveVisualMediaInput(topicId, input) {
11234
11289
  }
11235
11290
  const rawPath = input.file_path.trim();
11236
11291
  const cwd = workspaceCwdFor(topicId);
11237
- const candidate = isAbsolute(rawPath) ? rawPath : resolve7(cwd, rawPath);
11292
+ const candidate = isAbsolute2(rawPath) ? rawPath : resolve8(cwd, rawPath);
11238
11293
  if (!isPathInside(cwd, candidate)) {
11239
11294
  return { error: "file_path must be inside the topic workspace" };
11240
11295
  }
@@ -11948,7 +12003,7 @@ __export(exports_turn_runner, {
11948
12003
  });
11949
12004
  import { randomUUID as randomUUID13 } from "crypto";
11950
12005
  import { mkdirSync as mkdirSync17, realpathSync as realpathSync3, statSync as statSync6 } from "fs";
11951
- import { isAbsolute as isAbsolute2, resolve as resolve8 } from "path";
12006
+ import { isAbsolute as isAbsolute3, resolve as resolve9 } from "path";
11952
12007
  function withDefaultPlaywright(configuredMcp, isManager) {
11953
12008
  if (isManager)
11954
12009
  return configuredMcp;
@@ -12292,7 +12347,7 @@ async function streamAgentEvents(topicId, topicTitle, queryId, events, control,
12292
12347
  case "file":
12293
12348
  if (!silent && peerBridge) {
12294
12349
  const cwd = workspaceCwdFor(topicId);
12295
- const path = isAbsolute2(event.path) ? event.path : resolve8(cwd, event.path);
12350
+ const path = isAbsolute3(event.path) ? event.path : resolve9(cwd, event.path);
12296
12351
  if (!isPathInside(cwd, path)) {
12297
12352
  logger.warn({ topicId, path }, "peer output file is outside the topic workspace");
12298
12353
  break;
@@ -14854,8 +14909,8 @@ async function waitForMemoryArchive(settled, timeoutMs) {
14854
14909
  try {
14855
14910
  return await Promise.race([
14856
14911
  settled.then(() => true),
14857
- new Promise((resolve9) => {
14858
- timer = setTimeout(() => resolve9(false), timeoutMs);
14912
+ new Promise((resolve10) => {
14913
+ timer = setTimeout(() => resolve10(false), timeoutMs);
14859
14914
  timer.unref?.();
14860
14915
  })
14861
14916
  ]);
@@ -14901,8 +14956,8 @@ async function restartTopicSession(topicId, userId, reason = "topic-session-rest
14901
14956
  return { text: fenceError, isError: true };
14902
14957
  cancelIdleArchiveForTopic(topicId);
14903
14958
  let settleMemoryArchive;
14904
- const memoryArchiveSettled = new Promise((resolve9) => {
14905
- settleMemoryArchive = resolve9;
14959
+ const memoryArchiveSettled = new Promise((resolve10) => {
14960
+ settleMemoryArchive = resolve10;
14906
14961
  });
14907
14962
  const archiveStatus = (options.archiveMemory ?? archiveActiveTopicForMemory)(topicId, userId, {
14908
14963
  reason: "reset",
@@ -15940,8 +15995,8 @@ function prepareDeliveryAck(messageId, claimTimeoutMs, deliveryTimeoutMs) {
15940
15995
  let finishPromise = () => {};
15941
15996
  let timer;
15942
15997
  let unsubscribe = () => {};
15943
- const promise = new Promise((resolve9) => {
15944
- finishPromise = resolve9;
15998
+ const promise = new Promise((resolve10) => {
15999
+ finishPromise = resolve10;
15945
16000
  });
15946
16001
  unsubscribe = runtimeBus().subscribe((event) => {
15947
16002
  if (event.type !== "ai-status")
@@ -17303,7 +17358,7 @@ var init_sse_transport = () => {};
17303
17358
  // ../../packages/mcp/src/server.ts
17304
17359
  import { randomUUID as randomUUID20 } from "crypto";
17305
17360
  import { realpathSync as realpathSync4, statSync as statSync8 } from "fs";
17306
- import { basename as basename4, extname as extname2, resolve as resolve9 } from "path";
17361
+ import { basename as basename4, extname as extname2, resolve as resolve10 } from "path";
17307
17362
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
17308
17363
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
17309
17364
  import { z as z6 } from "zod";
@@ -17317,8 +17372,8 @@ function requireTopicAccess(ctx) {
17317
17372
  return { topic };
17318
17373
  }
17319
17374
  function isPathInside2(baseDir, filePath) {
17320
- const cwd = resolve9(baseDir);
17321
- const normalized = resolve9(filePath);
17375
+ const cwd = resolve10(baseDir);
17376
+ const normalized = resolve10(filePath);
17322
17377
  try {
17323
17378
  const realCwd = realpathSync4(cwd);
17324
17379
  const real = realpathSync4(normalized);
@@ -17334,7 +17389,7 @@ function localFileInfo(ctx, filePath) {
17334
17389
  if (!isPathInside2(ctx.cwd, filePath)) {
17335
17390
  return { error: "Access denied. File must be within the topic workspace." };
17336
17391
  }
17337
- const normalizedPath = resolve9(filePath);
17392
+ const normalizedPath = resolve10(filePath);
17338
17393
  if (isSensitivePath(normalizedPath)) {
17339
17394
  return { error: "Access denied. Path matches the sensitive-file blacklist." };
17340
17395
  }
@@ -17684,16 +17739,16 @@ var init_src2 = __esm(async () => {
17684
17739
 
17685
17740
  // ../../packages/mcp-host/src/paths.ts
17686
17741
  import { homedir as homedir9 } from "os";
17687
- import { resolve as resolve10 } from "path";
17742
+ import { resolve as resolve11 } from "path";
17688
17743
  function stateDir() {
17689
17744
  const env = process.env.NEGOTIUM_STATE_DIR?.trim();
17690
- return env ? resolve10(env) : resolve10(homedir9(), ".negotium");
17745
+ return env ? resolve11(env) : resolve11(homedir9(), ".negotium");
17691
17746
  }
17692
17747
  function defaultPortsDir() {
17693
- return resolve10(stateDir(), "run", "mcp-ports");
17748
+ return resolve11(stateDir(), "run", "mcp-ports");
17694
17749
  }
17695
17750
  function defaultManifestFile() {
17696
- return resolve10(stateDir(), "data", "mcp-manifest.json");
17751
+ return resolve11(stateDir(), "data", "mcp-manifest.json");
17697
17752
  }
17698
17753
  var init_paths = () => {};
17699
17754
 
@@ -17856,16 +17911,16 @@ function resolveInstanceKey(spec, instanceKey) {
17856
17911
  return instanceKey;
17857
17912
  }
17858
17913
  function canBind(port) {
17859
- return new Promise((resolve11) => {
17914
+ return new Promise((resolve12) => {
17860
17915
  const srv = createServer();
17861
- srv.once("error", () => resolve11(false));
17916
+ srv.once("error", () => resolve12(false));
17862
17917
  srv.listen({ port, host: "127.0.0.1", exclusive: true }, () => {
17863
- srv.close(() => resolve11(true));
17918
+ srv.close(() => resolve12(true));
17864
17919
  });
17865
17920
  });
17866
17921
  }
17867
17922
  function tcpProbe(port, timeoutMs = PROBE_TIMEOUT_MS) {
17868
- return new Promise((resolve11) => {
17923
+ return new Promise((resolve12) => {
17869
17924
  const sock = connect({ port, host: "127.0.0.1" });
17870
17925
  let settled = false;
17871
17926
  const done = (ok2) => {
@@ -17873,7 +17928,7 @@ function tcpProbe(port, timeoutMs = PROBE_TIMEOUT_MS) {
17873
17928
  return;
17874
17929
  settled = true;
17875
17930
  sock.destroy();
17876
- resolve11(ok2);
17931
+ resolve12(ok2);
17877
17932
  };
17878
17933
  sock.once("connect", () => done(true));
17879
17934
  sock.once("error", () => done(false));
@@ -17901,12 +17956,12 @@ function killProcessTree(pid) {
17901
17956
  function waitExit(proc, timeoutMs) {
17902
17957
  if (proc.exitCode !== null || proc.signalCode !== null)
17903
17958
  return Promise.resolve(true);
17904
- return new Promise((resolve11) => {
17905
- const timer = setTimeout(() => resolve11(false), timeoutMs);
17959
+ return new Promise((resolve12) => {
17960
+ const timer = setTimeout(() => resolve12(false), timeoutMs);
17906
17961
  timer.unref?.();
17907
17962
  const settle = () => {
17908
17963
  clearTimeout(timer);
17909
- resolve11(true);
17964
+ resolve12(true);
17910
17965
  };
17911
17966
  proc.once("exit", settle);
17912
17967
  proc.once("error", settle);
@@ -18244,7 +18299,7 @@ var DEFAULT_READY_TIMEOUT_MS = 20000, READY_POLL_MS = 150, KILL_GRACE_MS = 5000,
18244
18299
  fn(`[mcp-host] ${msg}`, ctx);
18245
18300
  else
18246
18301
  fn(`[mcp-host] ${msg}`);
18247
- }, delay2 = (ms) => new Promise((resolve11) => setTimeout(resolve11, ms));
18302
+ }, delay2 = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
18248
18303
  var init_manager3 = __esm(() => {
18249
18304
  init_manifest();
18250
18305
  init_paths();
@@ -18437,7 +18492,7 @@ import {
18437
18492
  unlinkSync as unlinkSync17,
18438
18493
  writeFileSync as writeFileSync17
18439
18494
  } from "fs";
18440
- import { dirname as dirname14, resolve as resolve11 } from "path";
18495
+ import { dirname as dirname14, resolve as resolve12 } from "path";
18441
18496
  function jsonError(status, error) {
18442
18497
  return Response.json({ ok: false, error }, { status });
18443
18498
  }
@@ -19135,7 +19190,7 @@ var init_control = __esm(async () => {
19135
19190
  await init_src();
19136
19191
  await init_files();
19137
19192
  NODE_RUNTIME_CONTRACT_BASE_PATH = `${NODE_CONTROL_BASE_PATH}/runtime/v1`;
19138
- NODE_DAEMON_INFO_PATH = resolve11(RUN_DIR, "node-daemon.json");
19193
+ NODE_DAEMON_INFO_PATH = resolve12(RUN_DIR, "node-daemon.json");
19139
19194
  NODE_VERSION = NEGOTIUM_VERSION;
19140
19195
  });
19141
19196
 
@@ -19309,7 +19364,7 @@ var init_schedule = __esm(() => {
19309
19364
  // ../../packages/module-cron/src/scripts.ts
19310
19365
  import { spawn as spawn6 } from "child_process";
19311
19366
  import { existsSync as existsSync21, mkdirSync as mkdirSync26, readdirSync as readdirSync8 } from "fs";
19312
- import { resolve as resolve12, sep } from "path";
19367
+ import { resolve as resolve13, sep } from "path";
19313
19368
  function validateCronScriptName(script) {
19314
19369
  if (!/^[A-Za-z0-9_][A-Za-z0-9_.-]*\.py$/.test(script) || script.includes("..") || script.includes("/") || script.includes("\\")) {
19315
19370
  return { ok: false, error: `script must be a plain .py filename under ${CRON_JOBS_DIR}` };
@@ -19320,7 +19375,7 @@ function resolveCronScriptPath(script) {
19320
19375
  const valid = validateCronScriptName(script);
19321
19376
  if (!valid.ok)
19322
19377
  throw new Error(valid.error);
19323
- const path = resolve12(CRON_JOBS_DIR, script);
19378
+ const path = resolve13(CRON_JOBS_DIR, script);
19324
19379
  if (!path.startsWith(`${CRON_JOBS_DIR}${sep}`))
19325
19380
  throw new Error("script path escaped jobs directory");
19326
19381
  return path;
@@ -19436,7 +19491,7 @@ async function runCronPromptScript(options) {
19436
19491
  var CRON_JOBS_DIR, DEFAULT_SCRIPT_TIMEOUT_MS, DEFAULT_OUTPUT_LIMIT_BYTES, KILL_GRACE_MS2 = 2500, CronScriptError;
19437
19492
  var init_scripts = __esm(async () => {
19438
19493
  await init_src();
19439
- CRON_JOBS_DIR = resolve12(process.env.NEGOTIUM_CRON_JOBS_DIR?.trim() || resolve12(WORKSPACE_DIR, "cron", "jobs"));
19494
+ CRON_JOBS_DIR = resolve13(process.env.NEGOTIUM_CRON_JOBS_DIR?.trim() || resolve13(WORKSPACE_DIR, "cron", "jobs"));
19440
19495
  DEFAULT_SCRIPT_TIMEOUT_MS = 10 * 60000;
19441
19496
  DEFAULT_OUTPUT_LIMIT_BYTES = 1024 * 1024;
19442
19497
  CronScriptError = class CronScriptError extends Error {
@@ -20858,7 +20913,7 @@ __export(exports_src3, {
20858
20913
  });
20859
20914
  import { createServer as createServer2 } from "net";
20860
20915
  async function availableLoopbackPort() {
20861
- return new Promise((resolve13, reject) => {
20916
+ return new Promise((resolve14, reject) => {
20862
20917
  const probe = createServer2();
20863
20918
  probe.unref();
20864
20919
  probe.once("error", reject);
@@ -20869,7 +20924,7 @@ async function availableLoopbackPort() {
20869
20924
  if (error)
20870
20925
  reject(error);
20871
20926
  else if (port > 0)
20872
- resolve13(port);
20927
+ resolve14(port);
20873
20928
  else
20874
20929
  reject(new Error("failed to allocate a loopback port"));
20875
20930
  });
@@ -20989,8 +21044,8 @@ function startNode(opts = {}) {
20989
21044
  const manifest = new McpManifest;
20990
21045
  const stopSweeper = mcpHost.startSweeper();
20991
21046
  let resolveCompleted;
20992
- const completed = new Promise((resolve13) => {
20993
- resolveCompleted = resolve13;
21047
+ const completed = new Promise((resolve14) => {
21048
+ resolveCompleted = resolve14;
20994
21049
  });
20995
21050
  let advertised = null;
20996
21051
  try {
@@ -21064,7 +21119,7 @@ async function runNodeDaemon(opts = {}) {
21064
21119
  singleton: true
21065
21120
  });
21066
21121
  await node.completed;
21067
- await new Promise((resolve13) => setImmediate(resolve13));
21122
+ await new Promise((resolve14) => setImmediate(resolve14));
21068
21123
  process.exit(0);
21069
21124
  }
21070
21125
  var init_src5 = __esm(async () => {
@@ -23671,8 +23726,8 @@ class TerminalApp {
23671
23726
  this.#refreshBackgroundSessions();
23672
23727
  }, 1000);
23673
23728
  this.#backgroundRefreshTimer.unref?.();
23674
- await new Promise((resolve13) => {
23675
- this.#finishRun = resolve13;
23729
+ await new Promise((resolve14) => {
23730
+ this.#finishRun = resolve14;
23676
23731
  });
23677
23732
  } finally {
23678
23733
  this.#running = false;
@@ -25848,7 +25903,7 @@ function startTelegramAdapter(opts) {
25848
25903
  attempt += 1;
25849
25904
  const waitMs = Math.min(5000, 250 * 2 ** Math.min(attempt - 1, 5));
25850
25905
  logger.warn({ err: err2, attempt, waitMs }, "telegram adapter: getMe failed while resolving onboarding identity; retrying");
25851
- await new Promise((resolve13) => setTimeout(resolve13, waitMs));
25906
+ await new Promise((resolve14) => setTimeout(resolve14, waitMs));
25852
25907
  }
25853
25908
  }
25854
25909
  return;
@@ -26325,14 +26380,14 @@ function startTelegramAdapter(opts) {
26325
26380
  const sendQueues = new Map;
26326
26381
  function enqueueSend(topicId, task) {
26327
26382
  const prev = sendQueues.get(topicId) ?? Promise.resolve();
26328
- const next = prev.then(() => new Promise((resolve13) => {
26383
+ const next = prev.then(() => new Promise((resolve14) => {
26329
26384
  const timer = setTimeout(() => {
26330
26385
  logger.warn({ topicId, sendTimeoutMs }, "telegram adapter: send timed out \u2014 abandoning it and continuing the queue");
26331
- resolve13();
26386
+ resolve14();
26332
26387
  }, sendTimeoutMs);
26333
26388
  task().catch((err2) => logger.warn({ err: err2, topicId }, "telegram adapter: send task failed")).finally(() => {
26334
26389
  clearTimeout(timer);
26335
- resolve13();
26390
+ resolve14();
26336
26391
  });
26337
26392
  }));
26338
26393
  sendQueues.set(topicId, next);
@@ -26576,7 +26631,7 @@ ${suffix}`;
26576
26631
  continue;
26577
26632
  }
26578
26633
  if (retryDelayMs > 0) {
26579
- await new Promise((resolve13) => setTimeout(resolve13, retryDelayMs));
26634
+ await new Promise((resolve14) => setTimeout(resolve14, retryDelayMs));
26580
26635
  }
26581
26636
  try {
26582
26637
  await client.editMessageText(text2, editOptions);
@@ -26930,8 +26985,8 @@ ${caption}` : voiceText : caption;
26930
26985
  return;
26931
26986
  }
26932
26987
  let releaseReady;
26933
- const ready = new Promise((resolve13) => {
26934
- releaseReady = resolve13;
26988
+ const ready = new Promise((resolve14) => {
26989
+ releaseReady = resolve14;
26935
26990
  });
26936
26991
  const entry = {
26937
26992
  messages: [msg],
@@ -27500,8 +27555,8 @@ async function runTelegramCli(args = process.argv.slice(2)) {
27500
27555
  onShutdown("telegram-channel", 100, () => channel.stop());
27501
27556
  onShutdown("telegram-singleton", 90, () => singleton.stop());
27502
27557
  let resolveCompleted;
27503
- const completed = new Promise((resolve13) => {
27504
- resolveCompleted = resolve13;
27558
+ const completed = new Promise((resolve14) => {
27559
+ resolveCompleted = resolve14;
27505
27560
  });
27506
27561
  onShutdown("telegram-completed", -100, resolveCompleted);
27507
27562
  process.stdout.write(`negotium Telegram adapter connected to canonical node pid ${initialNode.info?.pid ?? "unknown"}
@@ -27698,9 +27753,9 @@ import {
27698
27753
  unlinkSync as unlinkSync18,
27699
27754
  writeFileSync as writeFileSync18
27700
27755
  } from "fs";
27701
- import { dirname as dirname17, resolve as resolve13 } from "path";
27756
+ import { dirname as dirname17, resolve as resolve14 } from "path";
27702
27757
  function joinFilePath() {
27703
- return resolve13(DATA_DIR, "otium-join.json");
27758
+ return resolve14(DATA_DIR, "otium-join.json");
27704
27759
  }
27705
27760
  function isHttpUrl(value) {
27706
27761
  return /^https?:\/\//.test(value);
@@ -27755,7 +27810,7 @@ function parseInviteCode(code) {
27755
27810
  return normalizeJoin(parsed);
27756
27811
  }
27757
27812
  function joinLockPath() {
27758
- return resolve13(DATA_DIR, ".otium-join.lock");
27813
+ return resolve14(DATA_DIR, ".otium-join.lock");
27759
27814
  }
27760
27815
  function processIsAlive(pid) {
27761
27816
  if (!Number.isSafeInteger(pid) || pid <= 0)
@@ -27769,7 +27824,7 @@ function processIsAlive(pid) {
27769
27824
  }
27770
27825
  function withJoinCredentialLock(operation) {
27771
27826
  const lockPath = joinLockPath();
27772
- const ownerPath = resolve13(lockPath, "owner.json");
27827
+ const ownerPath = resolve14(lockPath, "owner.json");
27773
27828
  const owner = { pid: process.pid, token: randomUUID24() };
27774
27829
  mkdirSync28(dirname17(lockPath), { recursive: true });
27775
27830
  for (let attempt = 0;; attempt += 1) {
@@ -27901,7 +27956,7 @@ function saveJoinWhileLocked(join31, options = {}) {
27901
27956
  throw new Error(`this node is already joined${existing ? ` as ${existing.cellId}` : " with an invalid join file"}; pass --replace to replace its credentials`);
27902
27957
  }
27903
27958
  }
27904
- const temporaryPath = resolve13(directory, `.otium-join.json.${process.pid}.${randomUUID24()}.tmp`);
27959
+ const temporaryPath = resolve14(directory, `.otium-join.json.${process.pid}.${randomUUID24()}.tmp`);
27905
27960
  let fd;
27906
27961
  try {
27907
27962
  fd = openSync3(temporaryPath, "wx", 384);
@@ -28786,7 +28841,7 @@ function createTurnForwarder(opts) {
28786
28841
  logger.warn({ requestId, seq, type: event.type, attempt, error: result.error }, "otium: peer event delivery to hub failed");
28787
28842
  if (attempt < PEER_EVENT_MAX_ATTEMPTS) {
28788
28843
  const delayMs = retryBaseMs * 2 ** (attempt - 1);
28789
- await new Promise((resolve14) => setTimeout(resolve14, delayMs));
28844
+ await new Promise((resolve15) => setTimeout(resolve15, delayMs));
28790
28845
  }
28791
28846
  }
28792
28847
  forwarder.deliveryBlocked = true;
@@ -30684,7 +30739,7 @@ import {
30684
30739
  unlinkSync as unlinkSync19,
30685
30740
  writeFileSync as writeFileSync19
30686
30741
  } from "fs";
30687
- import { dirname as dirname18, resolve as resolve14 } from "path";
30742
+ import { dirname as dirname18, resolve as resolve15 } from "path";
30688
30743
  function parseEnrollmentInvite(code) {
30689
30744
  let parsed;
30690
30745
  try {
@@ -30705,7 +30760,7 @@ function parseEnrollmentInvite(code) {
30705
30760
  return { v: 2, central, token };
30706
30761
  }
30707
30762
  function pendingEnrollmentPath() {
30708
- return resolve14(DATA_DIR, "otium-enrollment-pending.json");
30763
+ return resolve15(DATA_DIR, "otium-enrollment-pending.json");
30709
30764
  }
30710
30765
  function isEnrollmentPending(invite) {
30711
30766
  const path = pendingEnrollmentPath();
@@ -30735,7 +30790,7 @@ function loadOrCreatePending(invite, nodeName) {
30735
30790
  ...nodeName ? { nodeName } : {}
30736
30791
  };
30737
30792
  mkdirSync30(dirname18(path), { recursive: true });
30738
- const temporaryPath = resolve14(dirname18(path), `.otium-enrollment-pending.json.${process.pid}.${randomUUID28()}.tmp`);
30793
+ const temporaryPath = resolve15(dirname18(path), `.otium-enrollment-pending.json.${process.pid}.${randomUUID28()}.tmp`);
30739
30794
  let fd;
30740
30795
  try {
30741
30796
  fd = openSync4(temporaryPath, "wx", 384);
@@ -30770,7 +30825,7 @@ function loadOrCreatePending(invite, nodeName) {
30770
30825
  function replacePendingEnrollment(pending2) {
30771
30826
  const path = pendingEnrollmentPath();
30772
30827
  const directory = dirname18(path);
30773
- const temporaryPath = resolve14(directory, `.otium-enrollment-pending.json.${process.pid}.${randomUUID28()}.tmp`);
30828
+ const temporaryPath = resolve15(directory, `.otium-enrollment-pending.json.${process.pid}.${randomUUID28()}.tmp`);
30774
30829
  let fd;
30775
30830
  try {
30776
30831
  fd = openSync4(temporaryPath, "wx", 384);
@@ -32113,8 +32168,8 @@ async function runOtiumSidecar(options) {
32113
32168
  }) : null;
32114
32169
  tunnel?.start();
32115
32170
  let resolveCompleted;
32116
- const completed = new Promise((resolve15) => {
32117
- resolveCompleted = resolve15;
32171
+ const completed = new Promise((resolve16) => {
32172
+ resolveCompleted = resolve16;
32118
32173
  });
32119
32174
  onShutdown("otium-sidecar-server", 130, () => server?.stop(true));
32120
32175
  onShutdown("otium-sidecar-tunnel", 120, () => tunnel?.stop());
@@ -32906,7 +32961,7 @@ async function runCanonicalNode(port) {
32906
32961
  });
32907
32962
  console.log(`negotium node listening on 127.0.0.1:${node.port} (ctrl-c to stop)`);
32908
32963
  await node.completed;
32909
- await new Promise((resolve15) => setImmediate(resolve15));
32964
+ await new Promise((resolve16) => setImmediate(resolve16));
32910
32965
  process.exit(0);
32911
32966
  }
32912
32967
  async function stopAdapter(name) {
@@ -33036,4 +33091,4 @@ switch (command) {
33036
33091
  }
33037
33092
  }
33038
33093
 
33039
- //# debugId=1F3638C6DFC33C0A64756E2164756E21
33094
+ //# debugId=4312707E3B05EF9564756E2164756E21