negotium 0.4.4 → 0.4.6

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
@@ -1869,7 +1869,7 @@ var exports_version = {};
1869
1869
  __export(exports_version, {
1870
1870
  NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
1871
1871
  });
1872
- var NEGOTIUM_VERSION = "0.4.4";
1872
+ var NEGOTIUM_VERSION = "0.4.6";
1873
1873
 
1874
1874
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
1875
1875
  import { spawn } from "child_process";
@@ -2770,14 +2770,20 @@ function playwrightTransport(port, owner, capability, agent) {
2770
2770
  function longLivedHttpMcp(agent, port) {
2771
2771
  return agent === "codex" ? { url: `http://127.0.0.1:${port}/mcp` } : { type: "sse", url: `http://127.0.0.1:${port}/sse` };
2772
2772
  }
2773
- function setCuaRsMcpPort(port) {
2773
+ function setCuaRsMcpPort(port, token) {
2774
2774
  if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65535)) {
2775
2775
  throw new Error(`invalid cua-rs MCP port: ${port}`);
2776
2776
  }
2777
2777
  cuaRsMcpPort = port;
2778
+ cuaRsMcpToken = port === undefined ? undefined : token;
2778
2779
  }
2779
- function cuaRsHttpMcp(port) {
2780
- return { type: "http", url: `http://127.0.0.1:${port}/mcp` };
2780
+ function cuaRsHttpMcp(agent, port, token) {
2781
+ const url = `http://127.0.0.1:${port}/mcp`;
2782
+ const headers = token ? { Authorization: `Bearer ${token}` } : undefined;
2783
+ const base = { type: "http", url };
2784
+ if (!headers)
2785
+ return base;
2786
+ return agent === "codex" ? { ...base, http_headers: headers } : { ...base, headers };
2781
2787
  }
2782
2788
  function backgroundBashTransport(agent, port, userId, topic) {
2783
2789
  const capability = bgBashContextCapability(userId, topic);
@@ -3054,7 +3060,7 @@ function getMcpServersForQuery(opts) {
3054
3060
  peerBridge: opts.peerBridge
3055
3061
  });
3056
3062
  }
3057
- var _playwrightUnavailableNotifier, _playwrightUnavailableLastNotifiedAt, _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS, _playwrightUnavailableThisTurn, CODEX_BROWSER_CAPABILITY_ENV = "NEGOTIUM_BROWSER_CAPABILITY", cuaRsMcpPort, MCP_CATALOG, allForumMcpServerNames, requiredForumMcpServers, REQUIRED_FORUM_MCP_SERVERS, optionalForumMcpServers, OPTIONAL_FORUM_MCP_SERVERS, nodeMcpEntries;
3063
+ var _playwrightUnavailableNotifier, _playwrightUnavailableLastNotifiedAt, _PLAYWRIGHT_UNAVAILABLE_COOLDOWN_MS, _playwrightUnavailableThisTurn, CODEX_BROWSER_CAPABILITY_ENV = "NEGOTIUM_BROWSER_CAPABILITY", cuaRsMcpPort, cuaRsMcpToken, MCP_CATALOG, allForumMcpServerNames, requiredForumMcpServers, REQUIRED_FORUM_MCP_SERVERS, optionalForumMcpServers, OPTIONAL_FORUM_MCP_SERVERS, nodeMcpEntries;
3058
3064
  var init_mcp_config = __esm(() => {
3059
3065
  init_canonical_bridge_config();
3060
3066
  init_runtime_spec();
@@ -3272,8 +3278,8 @@ var init_mcp_config = __esm(() => {
3272
3278
  },
3273
3279
  "cua-rs": {
3274
3280
  ...commonRuntimeMcpPolicy("cua-rs"),
3275
- build() {
3276
- return cuaRsMcpPort ? cuaRsHttpMcp(cuaRsMcpPort) : null;
3281
+ build({ agent }) {
3282
+ return cuaRsMcpPort ? cuaRsHttpMcp(agent, cuaRsMcpPort, cuaRsMcpToken) : null;
3277
3283
  }
3278
3284
  }
3279
3285
  };
@@ -32618,7 +32624,8 @@ __export(exports_src3, {
32618
32624
  NODE_CONTROL_PROTOCOL_VERSION: () => NODE_CONTROL_PROTOCOL_VERSION,
32619
32625
  NODE_CONTROL_BASE_PATH: () => NODE_CONTROL_BASE_PATH
32620
32626
  });
32621
- import { rmSync as rmSync10 } from "fs";
32627
+ import { randomBytes as randomBytes8 } from "crypto";
32628
+ import { readFileSync as readFileSync29, rmSync as rmSync10, writeFileSync as writeFileSync25 } from "fs";
32622
32629
  import { createServer as createServer5 } from "net";
32623
32630
  import { join as join43 } from "path";
32624
32631
  async function availableLoopbackPort() {
@@ -32676,6 +32683,34 @@ async function wireNodeMcps(host2, manifest) {
32676
32683
  logger.info({ keys: entries.map((e) => e.key) }, "node mcp: manifest servers installed");
32677
32684
  }
32678
32685
  }
32686
+ function cuaRsToken() {
32687
+ const file = join43(RUN_DIR, CUA_RS_MCP_TOKEN_FILE);
32688
+ try {
32689
+ const existing = readFileSync29(file, "utf8").trim();
32690
+ if (/^[0-9a-f]{64}$/.test(existing))
32691
+ return existing;
32692
+ } catch {}
32693
+ const token = randomBytes8(32).toString("hex");
32694
+ writeFileSync25(file, token, { mode: 384 });
32695
+ return token;
32696
+ }
32697
+ async function cuaRsAuthOk(port, token) {
32698
+ try {
32699
+ const res = await fetch(`http://127.0.0.1:${port}/mcp`, {
32700
+ method: "POST",
32701
+ headers: {
32702
+ Authorization: `Bearer ${token}`,
32703
+ "Content-Type": "application/json",
32704
+ Accept: "application/json, text/event-stream"
32705
+ },
32706
+ body: "{}",
32707
+ signal: AbortSignal.timeout(2000)
32708
+ });
32709
+ return res.status !== 401;
32710
+ } catch {
32711
+ return true;
32712
+ }
32713
+ }
32679
32714
  async function wireCuaRsMcp() {
32680
32715
  setCuaRsMcpPort(undefined);
32681
32716
  const binary = resolveCuaRsBinary();
@@ -32684,11 +32719,13 @@ async function wireCuaRsMcp() {
32684
32719
  const manifestFile = join43(RUN_DIR, CUA_RS_MCP_MANIFEST_FILE);
32685
32720
  rmSync10(manifestFile, { force: true });
32686
32721
  const manifest = new McpManifest({ file: manifestFile });
32722
+ const token = cuaRsToken();
32687
32723
  const spec = {
32688
32724
  key: CUA_RS_MCP_KEY,
32689
32725
  transport: "http",
32690
32726
  command: binary,
32691
32727
  args: ["{port}"],
32728
+ env: { CUA_HTTP_TOKEN: token },
32692
32729
  portRange: CUA_RS_MCP_PORT_RANGE,
32693
32730
  scope: "node",
32694
32731
  healthIntervalMs: 15000
@@ -32697,10 +32734,20 @@ async function wireCuaRsMcp() {
32697
32734
  const host2 = new McpHost({ manifest });
32698
32735
  const stopSweeper = host2.startSweeper();
32699
32736
  try {
32700
- const instance = await host2.ensure(CUA_RS_MCP_KEY);
32737
+ let instance = await host2.ensure(CUA_RS_MCP_KEY);
32701
32738
  if (!instance.port)
32702
32739
  throw new Error("cua-rs started without an HTTP port");
32703
- setCuaRsMcpPort(instance.port);
32740
+ if (!await cuaRsAuthOk(instance.port, token)) {
32741
+ logger.warn({ port: instance.port }, "cua-rs rejected the node's token; restarting it");
32742
+ await host2.stop(CUA_RS_MCP_KEY);
32743
+ instance = await host2.ensure(CUA_RS_MCP_KEY);
32744
+ if (!instance.port)
32745
+ throw new Error("cua-rs restarted without an HTTP port");
32746
+ if (!await cuaRsAuthOk(instance.port, token)) {
32747
+ throw new Error("cua-rs will not accept the node's bearer token");
32748
+ }
32749
+ }
32750
+ setCuaRsMcpPort(instance.port, token);
32704
32751
  logger.info({ pid: instance.pid, port: instance.port }, "cua-rs MCP server ready");
32705
32752
  return { host: host2, stopSweeper };
32706
32753
  } catch (error2) {
@@ -32909,7 +32956,7 @@ async function runNodeDaemon(opts = {}) {
32909
32956
  await new Promise((resolve24) => setImmediate(resolve24));
32910
32957
  process.exit(0);
32911
32958
  }
32912
- var CUA_RS_MCP_KEY = "cua-rs", CUA_RS_MCP_MANIFEST_FILE = "cua-rs-mcp-manifest.json", CUA_RS_MCP_PORT_RANGE;
32959
+ var CUA_RS_MCP_KEY = "cua-rs", CUA_RS_MCP_MANIFEST_FILE = "cua-rs-mcp-manifest.json", CUA_RS_MCP_TOKEN_FILE = "cua-rs-mcp.token", CUA_RS_MCP_PORT_RANGE;
32913
32960
  var init_src5 = __esm(async () => {
32914
32961
  await init_conversation_migration();
32915
32962
  await init_node_host();
@@ -43108,12 +43155,12 @@ import {
43108
43155
  lstatSync,
43109
43156
  mkdirSync as mkdirSync33,
43110
43157
  openSync as openSync5,
43111
- readFileSync as readFileSync29,
43158
+ readFileSync as readFileSync30,
43112
43159
  renameSync as renameSync17,
43113
43160
  rmSync as rmSync11,
43114
43161
  statSync as statSync20,
43115
43162
  unlinkSync as unlinkSync23,
43116
- writeFileSync as writeFileSync25
43163
+ writeFileSync as writeFileSync26
43117
43164
  } from "fs";
43118
43165
  import { dirname as dirname23, resolve as resolve25 } from "path";
43119
43166
  function joinFilePath() {
@@ -43194,7 +43241,7 @@ function withJoinCredentialLock(operation) {
43194
43241
  try {
43195
43242
  mkdirSync33(lockPath, { mode: 448 });
43196
43243
  created = true;
43197
- writeFileSync25(ownerPath, `${JSON.stringify(owner)}
43244
+ writeFileSync26(ownerPath, `${JSON.stringify(owner)}
43198
43245
  `, { mode: 384 });
43199
43246
  const ownerFd = openSync5(ownerPath, "r");
43200
43247
  try {
@@ -43212,7 +43259,7 @@ function withJoinCredentialLock(operation) {
43212
43259
  throw error2;
43213
43260
  let current3 = null;
43214
43261
  try {
43215
- current3 = JSON.parse(readFileSync29(ownerPath, "utf8"));
43262
+ current3 = JSON.parse(readFileSync30(ownerPath, "utf8"));
43216
43263
  } catch {}
43217
43264
  let ageMs;
43218
43265
  try {
@@ -43242,7 +43289,7 @@ function withJoinCredentialLock(operation) {
43242
43289
  return operation();
43243
43290
  } finally {
43244
43291
  try {
43245
- const current3 = JSON.parse(readFileSync29(ownerPath, "utf8"));
43292
+ const current3 = JSON.parse(readFileSync30(ownerPath, "utf8"));
43246
43293
  if (current3.pid === owner.pid && current3.token === owner.token) {
43247
43294
  rmSync11(lockPath, { recursive: true, force: true });
43248
43295
  }
@@ -43267,7 +43314,7 @@ function joinCredentialDigest(join46) {
43267
43314
  function readPersistedJoins(path = joinFilePath()) {
43268
43315
  if (!existsSync39(path))
43269
43316
  return [];
43270
- const parsed = JSON.parse(readFileSync29(path, "utf-8"));
43317
+ const parsed = JSON.parse(readFileSync30(path, "utf-8"));
43271
43318
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
43272
43319
  throw new Error("persisted join credentials are not a JSON object");
43273
43320
  }
@@ -43305,7 +43352,7 @@ function writeJoins(joins, allowOverwrite) {
43305
43352
  let fd;
43306
43353
  try {
43307
43354
  fd = openSync5(temporaryPath, "wx", 384);
43308
- writeFileSync25(fd, `${JSON.stringify(payload, null, 2)}
43355
+ writeFileSync26(fd, `${JSON.stringify(payload, null, 2)}
43309
43356
  `, "utf8");
43310
43357
  fsyncSync2(fd);
43311
43358
  closeSync5(fd);
@@ -43931,7 +43978,7 @@ var init_store2 = __esm(async () => {
43931
43978
 
43932
43979
  // ../../adapters/otium/src/workspace-scope.ts
43933
43980
  import { createHash as createHash13 } from "crypto";
43934
- import { mkdirSync as mkdirSync35, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
43981
+ import { mkdirSync as mkdirSync35, readFileSync as readFileSync31, writeFileSync as writeFileSync27 } from "fs";
43935
43982
  import { dirname as dirname24, resolve as resolve26 } from "path";
43936
43983
  function surfaceScopeFor(central, workspaceId) {
43937
43984
  const digest = createHash13("sha256").update(`${central.trim().replace(/\/+$/, "")}
@@ -43943,7 +43990,7 @@ function scopeCachePath() {
43943
43990
  }
43944
43991
  function readCache() {
43945
43992
  try {
43946
- const parsed = JSON.parse(readFileSync30(scopeCachePath(), "utf-8"));
43993
+ const parsed = JSON.parse(readFileSync31(scopeCachePath(), "utf-8"));
43947
43994
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
43948
43995
  return {};
43949
43996
  return parsed;
@@ -43964,7 +44011,7 @@ function cacheSurfaceScope(join47, workspaceId) {
43964
44011
  mkdirSync35(dirname24(path), { recursive: true });
43965
44012
  const cache = readCache();
43966
44013
  cache[join47.cellId] = { central: join47.central, workspaceId, scope };
43967
- writeFileSync26(path, `${JSON.stringify(cache, null, 2)}
44014
+ writeFileSync27(path, `${JSON.stringify(cache, null, 2)}
43968
44015
  `, { mode: 384 });
43969
44016
  } catch (err2) {
43970
44017
  logger.warn({ err: err2, path }, "otium: could not cache the workspace scope");
@@ -45005,10 +45052,10 @@ import {
45005
45052
  linkSync as linkSync2,
45006
45053
  mkdirSync as mkdirSync36,
45007
45054
  openSync as openSync6,
45008
- readFileSync as readFileSync31,
45055
+ readFileSync as readFileSync32,
45009
45056
  renameSync as renameSync18,
45010
45057
  unlinkSync as unlinkSync24,
45011
- writeFileSync as writeFileSync27
45058
+ writeFileSync as writeFileSync28
45012
45059
  } from "fs";
45013
45060
  import { dirname as dirname25, resolve as resolve27 } from "path";
45014
45061
  function parseEnrollmentInvite(code) {
@@ -45038,7 +45085,7 @@ function isEnrollmentPending(invite) {
45038
45085
  if (!existsSync40(path))
45039
45086
  return false;
45040
45087
  try {
45041
- const saved = JSON.parse(readFileSync31(path, "utf8"));
45088
+ const saved = JSON.parse(readFileSync32(path, "utf8"));
45042
45089
  return saved.central === invite.central && saved.token === invite.token;
45043
45090
  } catch {
45044
45091
  return false;
@@ -45047,7 +45094,7 @@ function isEnrollmentPending(invite) {
45047
45094
  function loadOrCreatePending(invite, nodeName) {
45048
45095
  const path = pendingEnrollmentPath();
45049
45096
  if (existsSync40(path)) {
45050
- const saved = JSON.parse(readFileSync31(path, "utf8"));
45097
+ const saved = JSON.parse(readFileSync32(path, "utf8"));
45051
45098
  if (saved.central === invite.central && saved.token === invite.token)
45052
45099
  return saved;
45053
45100
  throw new Error(`another Otium enrollment is pending at ${path}`);
@@ -45065,7 +45112,7 @@ function loadOrCreatePending(invite, nodeName) {
45065
45112
  let fd;
45066
45113
  try {
45067
45114
  fd = openSync6(temporaryPath, "wx", 384);
45068
- writeFileSync27(fd, `${JSON.stringify(pending2, null, 2)}
45115
+ writeFileSync28(fd, `${JSON.stringify(pending2, null, 2)}
45069
45116
  `, "utf8");
45070
45117
  fsyncSync3(fd);
45071
45118
  closeSync6(fd);
@@ -45085,7 +45132,7 @@ function loadOrCreatePending(invite, nodeName) {
45085
45132
  if (existsSync40(temporaryPath))
45086
45133
  unlinkSync24(temporaryPath);
45087
45134
  if (error2.code === "EEXIST" && existsSync40(path)) {
45088
- const saved = JSON.parse(readFileSync31(path, "utf8"));
45135
+ const saved = JSON.parse(readFileSync32(path, "utf8"));
45089
45136
  if (saved.central === invite.central && saved.token === invite.token)
45090
45137
  return saved;
45091
45138
  }
@@ -45100,7 +45147,7 @@ function replacePendingEnrollment(pending2) {
45100
45147
  let fd;
45101
45148
  try {
45102
45149
  fd = openSync6(temporaryPath, "wx", 384);
45103
- writeFileSync27(fd, `${JSON.stringify(pending2, null, 2)}
45150
+ writeFileSync28(fd, `${JSON.stringify(pending2, null, 2)}
45104
45151
  `, "utf8");
45105
45152
  fsyncSync3(fd);
45106
45153
  closeSync6(fd);
@@ -45122,7 +45169,7 @@ function replacePendingEnrollment(pending2) {
45122
45169
  }
45123
45170
  function recordClaimedCredential(pending2, join47) {
45124
45171
  withJoinCredentialLock(() => {
45125
- const current3 = JSON.parse(readFileSync31(pendingEnrollmentPath(), "utf8"));
45172
+ const current3 = JSON.parse(readFileSync32(pendingEnrollmentPath(), "utf8"));
45126
45173
  if (current3.central !== pending2.central || current3.token !== pending2.token || current3.idempotencyKey !== pending2.idempotencyKey || current3.publicKey !== pending2.publicKey) {
45127
45174
  throw new Error("pending Otium enrollment changed while its claim was in flight");
45128
45175
  }
@@ -45201,7 +45248,7 @@ async function claimEnrollment(invite, nodeName) {
45201
45248
  function commitEnrollment(join47, options = {}) {
45202
45249
  return withJoinCredentialLock(() => {
45203
45250
  const pendingPath = pendingEnrollmentPath();
45204
- const pending2 = existsSync40(pendingPath) ? JSON.parse(readFileSync31(pendingPath, "utf8")) : null;
45251
+ const pending2 = existsSync40(pendingPath) ? JSON.parse(readFileSync32(pendingPath, "utf8")) : null;
45205
45252
  const digest = joinCredentialDigest(join47);
45206
45253
  if (pending2 && (!pending2.claimed || pending2.claimed.digest !== digest || pending2.claimed.cellId !== join47.cellId)) {
45207
45254
  throw new Error(`pending Otium enrollment at ${pendingPath} does not match these credentials`);
@@ -47292,4 +47339,4 @@ switch (command) {
47292
47339
  }
47293
47340
  }
47294
47341
 
47295
- //# debugId=FB1DC2846CA4438764756E2164756E21
47342
+ //# debugId=C1F343985A31393664756E2164756E21