negotium 0.22.5 → 0.22.7

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 (33) hide show
  1. package/dist/agent-helpers.js +56 -18
  2. package/dist/agent-helpers.js.map +7 -7
  3. package/dist/browser-runtime.js +38 -11
  4. package/dist/browser-runtime.js.map +4 -4
  5. package/dist/{chunk-7rpbcn1j.js → chunk-1gznvrth.js} +3 -3
  6. package/dist/{chunk-7rpbcn1j.js.map → chunk-1gznvrth.js.map} +2 -2
  7. package/dist/{chunk-vh8px000.js → chunk-pr8p6pap.js} +7 -2
  8. package/dist/{chunk-vh8px000.js.map → chunk-pr8p6pap.js.map} +3 -3
  9. package/dist/{chunk-a3me2mje.js → chunk-z4r7tt2p.js} +1 -1
  10. package/dist/hosted-agent.js +8 -3
  11. package/dist/hosted-agent.js.map +4 -4
  12. package/dist/main.js +86 -19
  13. package/dist/main.js.map +9 -9
  14. package/dist/mcp-factories.js +56 -18
  15. package/dist/mcp-factories.js.map +7 -7
  16. package/dist/registry.js +3 -3
  17. package/dist/rollout.js +2 -2
  18. package/dist/runtime/src/platform/playwright/manager.ts +77 -15
  19. package/dist/runtime/src/storage/api-topics.ts +6 -0
  20. package/dist/runtime/src/storage/browser-profiles.ts +18 -0
  21. package/dist/runtime/src/topics/lifecycle.ts +2 -5
  22. package/dist/runtime/src/topics/update.ts +37 -0
  23. package/dist/runtime/src/types/api.ts +6 -0
  24. package/dist/runtime/src/version.ts +1 -1
  25. package/dist/storage.js +7 -2
  26. package/dist/storage.js.map +3 -3
  27. package/dist/types/packages/core/src/platform/playwright/manager.d.ts +8 -0
  28. package/dist/types/packages/core/src/storage/api-topics.d.ts +1 -0
  29. package/dist/types/packages/core/src/storage/browser-profiles.d.ts +4 -0
  30. package/dist/types/packages/core/src/types/api.d.ts +6 -0
  31. package/dist/types/packages/core/src/version.d.ts +1 -1
  32. package/package.json +1 -1
  33. /package/dist/{chunk-a3me2mje.js.map → chunk-z4r7tt2p.js.map} +0 -0
package/dist/main.js CHANGED
@@ -4459,6 +4459,7 @@ function initializeApiTopicsSchema() {
4459
4459
  surface_scope TEXT,
4460
4460
  browser_profile TEXT NOT NULL DEFAULT 'default',
4461
4461
  browser_profile_owner TEXT,
4462
+ browser_connect_port INTEGER,
4462
4463
  session_id TEXT,
4463
4464
  CHECK (
4464
4465
  (kind = 'channel' AND response_policy = 'off' AND agent IS NULL) OR
@@ -4576,6 +4577,9 @@ function initializeApiTopicsSchema() {
4576
4577
  if (!tableColumns("api_topics").has("browser_profile_owner")) {
4577
4578
  db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
4578
4579
  }
4580
+ if (!tableColumns("api_topics").has("browser_connect_port")) {
4581
+ db.exec("ALTER TABLE api_topics ADD COLUMN browser_connect_port INTEGER");
4582
+ }
4579
4583
  if (!tableColumns("api_topics").has("subagent_report_mode")) {
4580
4584
  db.exec("ALTER TABLE api_topics ADD COLUMN subagent_report_mode TEXT NOT NULL DEFAULT 'auto'");
4581
4585
  }
@@ -4828,7 +4832,8 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
4828
4832
  } : {},
4829
4833
  visibility: normalizeTopicVisibility(r.visibility),
4830
4834
  surface: normalizeTopicSurface(r.surface),
4831
- surfaceScope: normalizeSurfaceScope(r.surface_scope)
4835
+ surfaceScope: normalizeSurfaceScope(r.surface_scope),
4836
+ ...r.browser_connect_port != null ? { browserConnectPort: r.browser_connect_port } : {}
4832
4837
  };
4833
4838
  }
4834
4839
  function normalizeTopicVisibility(value) {
@@ -6554,7 +6559,7 @@ var exports_version = {};
6554
6559
  __export(exports_version, {
6555
6560
  NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
6556
6561
  });
6557
- var NEGOTIUM_VERSION = "0.22.5";
6562
+ var NEGOTIUM_VERSION = "0.22.7";
6558
6563
 
6559
6564
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
6560
6565
  import { spawn as spawn2 } from "child_process";
@@ -13161,6 +13166,16 @@ function getTopicBrowserProfile(topicId) {
13161
13166
  const value = db.query("SELECT browser_profile FROM api_topics WHERE id = ?").get(topicId)?.browser_profile;
13162
13167
  return value || DEFAULT_BROWSER_PROFILE;
13163
13168
  }
13169
+ function isBrowserConnectPort(value) {
13170
+ return Number.isInteger(value) && value >= 1024 && value <= 65535;
13171
+ }
13172
+ function getTopicBrowserConnectPort(topicId) {
13173
+ const value = db.query("SELECT browser_connect_port FROM api_topics WHERE id = ?").get(topicId)?.browser_connect_port;
13174
+ return isBrowserConnectPort(value) ? value : undefined;
13175
+ }
13176
+ function setTopicBrowserConnectPort(topicId, port) {
13177
+ db.query("UPDATE api_topics SET browser_connect_port = ? WHERE id = ?").run(port, topicId);
13178
+ }
13164
13179
  function hasBrowserProfileTopic(topicId) {
13165
13180
  return Boolean(db.query("SELECT id FROM api_topics WHERE id = ?").get(topicId));
13166
13181
  }
@@ -13294,6 +13309,9 @@ function resolvePlaywrightTopicBinding(userId, topic) {
13294
13309
  function defaultTopicBinding(userId, topic) {
13295
13310
  if (!topic)
13296
13311
  return managerHost.resolveNamedBinding(userId, "default");
13312
+ const connectPort = getTopicBrowserConnectPort(topic);
13313
+ if (connectPort !== undefined)
13314
+ return connectBinding(connectPort);
13297
13315
  const ownerId = getBrowserProfileOwner(topic, userId);
13298
13316
  const profile = getTopicBrowserProfile(topic);
13299
13317
  return managerHost.resolveNamedBinding(ownerId, profile);
@@ -13307,6 +13325,26 @@ function validateProfileBinding(binding) {
13307
13325
  }
13308
13326
  return Object.freeze({ ...binding });
13309
13327
  }
13328
+ function connectBinding(port) {
13329
+ return { instanceKey: `connect:${port}`, ownerId: "local", profile: `connect-${port}` };
13330
+ }
13331
+ function parseConnectInstanceKey(instanceKey) {
13332
+ const match = /^connect:(\d+)$/.exec(instanceKey);
13333
+ return match ? Number(match[1]) : undefined;
13334
+ }
13335
+ function browserRsArgs(instanceKey, port, userDataDir) {
13336
+ const connectPort = parseConnectInstanceKey(instanceKey);
13337
+ return [
13338
+ "--port",
13339
+ String(port),
13340
+ "--host",
13341
+ "127.0.0.1",
13342
+ "--headed",
13343
+ "--user-data-dir",
13344
+ userDataDir,
13345
+ ...connectPort === undefined ? [] : ["--connect", String(connectPort)]
13346
+ ];
13347
+ }
13310
13348
  function defaultNamedBinding(_ownerId, rawProfile) {
13311
13349
  const profile = normalizeBrowserProfileName(rawProfile);
13312
13350
  const instanceKey = `profile:${profile}`;
@@ -13326,6 +13364,9 @@ function defaultChildEnvironment(context) {
13326
13364
  return childEnvironment;
13327
13365
  }
13328
13366
  function parseInstanceKey(instanceKey) {
13367
+ const connectPort = parseConnectInstanceKey(instanceKey);
13368
+ if (connectPort !== undefined)
13369
+ return { ownerId: "local", profile: `_connect-${connectPort}` };
13329
13370
  const shared = /^profile:(.+)$/.exec(instanceKey);
13330
13371
  if (shared && !shared[1].includes(":")) {
13331
13372
  return { ownerId: "local", profile: normalizeBrowserProfileName(shared[1]) };
@@ -13576,15 +13617,7 @@ async function spawnPlaywright(instanceKey, ownerId, reservedPort, browserBin =
13576
13617
  const userDataDir = resolveUserDataDir(instanceKey);
13577
13618
  const port = reservedPort ?? await allocatePort();
13578
13619
  mkdirSync10(userDataDir, { recursive: true });
13579
- const mcpArgs = [
13580
- "--port",
13581
- String(port),
13582
- "--host",
13583
- "127.0.0.1",
13584
- "--headed",
13585
- "--user-data-dir",
13586
- userDataDir
13587
- ];
13620
+ const mcpArgs = browserRsArgs(instanceKey, port, userDataDir);
13588
13621
  const proxy = managerHost.resolveProxy();
13589
13622
  if (proxy) {
13590
13623
  releasePort(port);
@@ -13773,7 +13806,14 @@ async function waitForPortRelease(port, timeoutMs = 3000) {
13773
13806
  }
13774
13807
  }
13775
13808
  async function closeBrowserOwnerTabs(ownerId, rawProfile, owner) {
13776
- const binding = resolvePlaywrightProfileBinding(ownerId, rawProfile);
13809
+ return closeBindingOwnerTabs(resolvePlaywrightProfileBinding(ownerId, rawProfile), owner);
13810
+ }
13811
+ function closeTopicBrowserTabs(userId, topicId) {
13812
+ const connectPort = getTopicBrowserConnectPort(topicId);
13813
+ const binding = connectPort === undefined ? resolvePlaywrightProfileBinding(getBrowserProfileOwner(topicId, userId), getTopicBrowserProfile(topicId)) : connectBinding(connectPort);
13814
+ return closeBindingOwnerTabs(binding, `topic:${topicId}`);
13815
+ }
13816
+ async function closeBindingOwnerTabs(binding, owner) {
13777
13817
  const instanceKey = binding.instanceKey;
13778
13818
  const inProgress = spawning.get(instanceKey);
13779
13819
  if (inProgress)
@@ -13847,6 +13887,7 @@ async function cloneProfileForChild(opts) {
13847
13887
  if (srcOwner === dstOwner && hasBrowserProfileTopic(opts.dstTopic)) {
13848
13888
  const profile = getTopicBrowserProfile(opts.srcTopic);
13849
13889
  assignTopicBrowserProfile({ topicId: opts.dstTopic, actorUserId: dstOwner, profile });
13890
+ setTopicBrowserConnectPort(opts.dstTopic, getTopicBrowserConnectPort(opts.srcTopic) ?? null);
13850
13891
  const binding = resolvePlaywrightProfileBinding(srcOwner, profile);
13851
13892
  const sharedDir = resolveUserDataDir(binding.instanceKey);
13852
13893
  return {
@@ -13863,6 +13904,9 @@ async function cloneProfileForChild(opts) {
13863
13904
  if (srcDir === dstDir) {
13864
13905
  return { copied: false, srcDir, dstDir, reason: "same-dir" };
13865
13906
  }
13907
+ if (parseConnectInstanceKey(srcKey) !== undefined || parseConnectInstanceKey(dstKey) !== undefined) {
13908
+ return { copied: false, srcDir, dstDir, reason: "connect-binding" };
13909
+ }
13866
13910
  return withPlaywrightInstanceMaintenance([srcKey, dstKey], async () => {
13867
13911
  const parentWasLive = instances.has(srcKey);
13868
13912
  if (parentWasLive) {
@@ -25279,10 +25323,8 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
25279
25323
  await deleteTopicCascadeImpl(child, userId, childOptions, deletingTopicIds);
25280
25324
  }
25281
25325
  killBgBash(userId, topicId);
25282
- const browserProfileOwner = getBrowserProfileOwner(topicId, userId);
25283
- const browserProfile = getTopicBrowserProfile(topicId);
25284
25326
  try {
25285
- await closeBrowserOwnerTabs(browserProfileOwner, browserProfile, `topic:${topicId}`);
25327
+ await closeTopicBrowserTabs(userId, topicId);
25286
25328
  } catch (err2) {
25287
25329
  logger.warn({ err: err2, topicId }, "deleteTopicCascade: browser owner cleanup failed");
25288
25330
  }
@@ -25364,7 +25406,6 @@ var init_lifecycle = __esm(async () => {
25364
25406
  init_api_topic_brief(),
25365
25407
  init_api_topic_config(),
25366
25408
  init_api_topics(),
25367
- init_browser_profiles(),
25368
25409
  init_forum_db(),
25369
25410
  init_runtime_leases(),
25370
25411
  init_runtime_topic_state(),
@@ -29050,6 +29091,17 @@ function updateTopicSettings(opts) {
29050
29091
  throw new TopicValidationError(`"${title}" is a reserved name`);
29051
29092
  }
29052
29093
  }
29094
+ let description = current3.description;
29095
+ if (opts.description !== undefined) {
29096
+ const trimmed = opts.description.trim();
29097
+ if (trimmed.length > MAX_TOPIC_DESCRIPTION_CHARS) {
29098
+ throw new TopicValidationError(`description must be at most ${MAX_TOPIC_DESCRIPTION_CHARS} characters`);
29099
+ }
29100
+ description = trimmed || undefined;
29101
+ }
29102
+ if (opts.browserConnectPort !== undefined && opts.browserConnectPort !== null && !isBrowserConnectPort(opts.browserConnectPort)) {
29103
+ throw new TopicValidationError("browserConnectPort must be an integer from 1024 to 65535");
29104
+ }
29053
29105
  if (opts.agent !== undefined && opts.agent !== null && !isAgentKind(opts.agent)) {
29054
29106
  throw new TopicValidationError(`Unknown agent '${opts.agent}'`);
29055
29107
  }
@@ -29093,6 +29145,7 @@ function updateTopicSettings(opts) {
29093
29145
  const next = {
29094
29146
  ...current3,
29095
29147
  title,
29148
+ description,
29096
29149
  kind,
29097
29150
  aiMode,
29098
29151
  agent,
@@ -29100,6 +29153,9 @@ function updateTopicSettings(opts) {
29100
29153
  defaultEffort
29101
29154
  };
29102
29155
  upsertTopic(next);
29156
+ if (opts.browserConnectPort !== undefined) {
29157
+ setTopicBrowserConnectPort(next.id, opts.browserConnectPort);
29158
+ }
29103
29159
  const config = getApiTopicConfig(next.id);
29104
29160
  if (config && (opts.defaultModel !== undefined || opts.defaultEffort !== undefined)) {
29105
29161
  setApiTopicConfig(next.id, {
@@ -29111,7 +29167,7 @@ function updateTopicSettings(opts) {
29111
29167
  WsHub.get().broadcastTopicUpdated(next.id);
29112
29168
  return getTopic(next.id) ?? next;
29113
29169
  }
29114
- var TopicUpdateConflictError;
29170
+ var MAX_TOPIC_DESCRIPTION_CHARS = 20000, TopicUpdateConflictError;
29115
29171
  var init_update = __esm(async () => {
29116
29172
  init_model_catalog();
29117
29173
  init_config_helpers();
@@ -29122,6 +29178,7 @@ var init_update = __esm(async () => {
29122
29178
  init_bus(),
29123
29179
  init_api_topic_config(),
29124
29180
  init_api_topics(),
29181
+ init_browser_profiles(),
29125
29182
  init_forum_db(),
29126
29183
  init_create()
29127
29184
  ]);
@@ -39402,6 +39459,8 @@ function createNodeControlHandler(options) {
39402
39459
  "canonical-manager-topic",
39403
39460
  ...process.env.NEGOTIUM_CRON === "0" ? [] : ["scheduler.cron.gateway.v1"],
39404
39461
  "canonical-topic-update",
39462
+ "canonical-topic-description",
39463
+ "canonical-topic-browser-connect",
39405
39464
  "canonical-topic-delete",
39406
39465
  "turn-submit-silent",
39407
39466
  "turn-submit-hidden",
@@ -40425,6 +40484,12 @@ function createNodeControlHandler(options) {
40425
40484
  if (body.aiMode !== undefined && !["always", "mention", "off"].includes(String(body.aiMode))) {
40426
40485
  return jsonError(400, "Invalid aiMode");
40427
40486
  }
40487
+ if (body.description !== undefined && typeof body.description !== "string") {
40488
+ return jsonError(400, "description must be a string");
40489
+ }
40490
+ if (body.browserConnectPort !== undefined && body.browserConnectPort !== null && typeof body.browserConnectPort !== "number") {
40491
+ return jsonError(400, "browserConnectPort must be a number or null");
40492
+ }
40428
40493
  try {
40429
40494
  const topic = updateTopicSettings({
40430
40495
  topicId,
@@ -40432,7 +40497,9 @@ function createNodeControlHandler(options) {
40432
40497
  ...body.agent !== undefined ? { agent: body.agent ?? null } : {},
40433
40498
  ...body.defaultModel !== undefined ? { defaultModel: body.defaultModel } : {},
40434
40499
  ...body.defaultEffort !== undefined ? { defaultEffort: body.defaultEffort } : {},
40435
- ...body.aiMode !== undefined ? { aiMode: body.aiMode } : {}
40500
+ ...body.aiMode !== undefined ? { aiMode: body.aiMode } : {},
40501
+ ...body.description !== undefined ? { description: body.description } : {},
40502
+ ...body.browserConnectPort !== undefined ? { browserConnectPort: body.browserConnectPort } : {}
40436
40503
  });
40437
40504
  return Response.json({ ok: true, v: NODE_RUNTIME_CONTRACT_VERSION, topic });
40438
40505
  } catch (err2) {
@@ -59086,4 +59153,4 @@ switch (command) {
59086
59153
  }
59087
59154
  }
59088
59155
 
59089
- //# debugId=B68892935362F4E964756E2164756E21
59156
+ //# debugId=CF8B8D72488623B764756E2164756E21