negotium 0.1.49 → 0.2.1

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 (55) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-helpers.js +72 -78
  3. package/dist/agent-helpers.js.map +18 -17
  4. package/dist/background-bash.js +22 -10
  5. package/dist/background-bash.js.map +3 -3
  6. package/dist/browser-runtime.js +47 -72
  7. package/dist/browser-runtime.js.map +10 -9
  8. package/dist/{chunk-5rpw9d1f.js → chunk-kc5kmr95.js} +28 -11
  9. package/dist/{chunk-5rpw9d1f.js.map → chunk-kc5kmr95.js.map} +4 -4
  10. package/dist/hosted-agent.js +48 -22
  11. package/dist/hosted-agent.js.map +10 -9
  12. package/dist/main.js +576 -102
  13. package/dist/main.js.map +23 -20
  14. package/dist/mcp-factories.js +76 -82
  15. package/dist/mcp-factories.js.map +19 -18
  16. package/dist/prompts.js +22 -10
  17. package/dist/prompts.js.map +3 -3
  18. package/dist/query-runtime.js +22 -10
  19. package/dist/query-runtime.js.map +4 -4
  20. package/dist/registry.js +5 -12
  21. package/dist/registry.js.map +5 -5
  22. package/dist/rollout.js +1 -1
  23. package/dist/runtime/cron/mcp-server.ts +1 -1
  24. package/dist/runtime/src/agents/maestro-registry.ts +1 -1
  25. package/dist/runtime/src/agents/rollout/shared.ts +12 -4
  26. package/dist/runtime/src/mcp/mcp-helpers.ts +1 -1
  27. package/dist/runtime/src/mcp/wiki-server.ts +1 -1
  28. package/dist/runtime/src/migration/single-user.ts +621 -0
  29. package/dist/runtime/src/platform/config.ts +24 -11
  30. package/dist/runtime/src/platform/mcp-config.ts +4 -4
  31. package/dist/runtime/src/platform/playwright/manager.ts +10 -28
  32. package/dist/runtime/src/runtime/attachments.ts +3 -3
  33. package/dist/runtime/src/storage/browser-profiles.ts +11 -9
  34. package/dist/runtime/src/storage/conversations.ts +5 -18
  35. package/dist/runtime/src/storage/storage-host.ts +1 -1
  36. package/dist/runtime/src/storage/tasks.ts +2 -14
  37. package/dist/runtime/src/storage/vault-crypto-core.ts +65 -0
  38. package/dist/runtime/src/storage/vault-crypto.ts +8 -48
  39. package/dist/runtime/src/storage/vault.ts +3 -2
  40. package/dist/runtime/src/version.ts +1 -1
  41. package/dist/runtime-helpers.js +22 -10
  42. package/dist/runtime-helpers.js.map +5 -5
  43. package/dist/storage.js +5 -19
  44. package/dist/storage.js.map +5 -5
  45. package/dist/types/packages/core/src/mcp/mcp-helpers.d.ts +1 -1
  46. package/dist/types/packages/core/src/platform/config.d.ts +9 -1
  47. package/dist/types/packages/core/src/runtime/attachments.d.ts +1 -1
  48. package/dist/types/packages/core/src/storage/conversations.d.ts +2 -2
  49. package/dist/types/packages/core/src/storage/vault-crypto-core.d.ts +6 -0
  50. package/dist/types/packages/core/src/storage/vault-crypto.d.ts +2 -1
  51. package/dist/types/packages/core/src/version.d.ts +1 -1
  52. package/dist/vault.js +37 -16
  53. package/dist/vault.js.map +7 -6
  54. package/install-browser-rs.mjs +1 -1
  55. package/package.json +2 -2
@@ -155,7 +155,7 @@ function resolveBrowserRsBin(envValue) {
155
155
  if (!override && !versionAtLeast(BROWSER_RS_VERSION.replace(/^v/, ""), BROWSER_RS_MIN_SECURE_VERSION)) {
156
156
  return;
157
157
  }
158
- const candidate = override ? resolve(override) : resolve(STATE_DIR, "bin", "browser-rs", BROWSER_RS_VERSION, "browser-rs");
158
+ const candidate = override ? resolve(override) : resolve(BINARIES_DIR, "browser-rs", BROWSER_RS_VERSION, "browser-rs");
159
159
  try {
160
160
  accessSync(candidate, constants.X_OK);
161
161
  return browserRsMeetsMinimumVersion(candidate) ? candidate : undefined;
@@ -167,7 +167,7 @@ function resolveBrowserMcpBin(envValue) {
167
167
  const override = envValue?.trim();
168
168
  if (override)
169
169
  return resolve(override);
170
- return BROWSER_RS_BIN ?? resolve(STATE_DIR, "bin", "browser-rs", BROWSER_RS_VERSION, "browser-rs");
170
+ return BROWSER_RS_BIN ?? resolve(BINARIES_DIR, "browser-rs", BROWSER_RS_VERSION, "browser-rs");
171
171
  }
172
172
  function resolveBrowserProxy() {
173
173
  const raw = envText("BROWSER_PROXY_URL");
@@ -199,7 +199,7 @@ function resolveTopicWorkspaceDir(topicId) {
199
199
  }
200
200
  function loadOrCreateLocalSecret(envKey, filename, options = {}) {
201
201
  const envValue = envText(envKey);
202
- const secretFile = resolve(STATE_DIR, filename);
202
+ const secretFile = resolve(SECRETS_DIR, filename);
203
203
  mkdirSync(dirname(secretFile), { recursive: true });
204
204
  if (envValue) {
205
205
  if (options.persistEnvValue) {
@@ -240,7 +240,7 @@ function resolveDefaultModel(agent, registryDefaultModel) {
240
240
  function codexAuthFilePath() {
241
241
  return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(homedir(), ".codex", "auth.json");
242
242
  }
243
- var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CONTEXTS_DIR, BROWSER_PROFILES_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.16", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_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, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, 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;
243
+ 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, CONTEXTS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.16", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_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, 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;
244
244
  var init_config = __esm(() => {
245
245
  init_config_helpers();
246
246
  init_logger();
@@ -252,10 +252,14 @@ var init_config = __esm(() => {
252
252
  WORKSPACE_DIR = resolveLocalStateDir("NEGOTIUM_WORKSPACE_DIR", "workspace");
253
253
  TOPIC_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "topics");
254
254
  SHARED_WIKI_DIR = resolve(WORKSPACE_DIR, "wiki");
255
- CONTEXTS_DIR = resolve(WORKSPACE_DIR, "contexts");
256
- BROWSER_PROFILES_DIR = resolve(WORKSPACE_DIR, "browser-profiles");
257
- DM_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "dm");
258
- SESSION_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "sessions");
255
+ CRON_WORKSPACE_DIR = resolve(WORKSPACE_DIR, "cron");
256
+ BROWSER_DIR = resolveLocalStateDir("NEGOTIUM_BROWSER_DIR", "browser");
257
+ BROWSER_PROFILES_DIR = resolve(BROWSER_DIR, "profiles");
258
+ BINARIES_DIR = resolve(STATE_DIR, "binaries");
259
+ SECRETS_DIR = resolve(STATE_DIR, "secrets");
260
+ CONTEXTS_DIR = resolve(STATE_DIR, "data", "contexts");
261
+ DM_WORKSPACE_DIR = resolve(STATE_DIR, "data", "dm");
262
+ SESSION_WORKSPACE_DIR = resolve(STATE_DIR, "data", "sessions");
259
263
  CLAUDE_EXECUTABLE_ENV = envText("NEGOTIUM_CLAUDE_EXECUTABLE");
260
264
  CLAUDE_EXECUTABLE = CLAUDE_EXECUTABLE_ENV ? resolve(CLAUDE_EXECUTABLE_ENV) : undefined;
261
265
  BROWSER_RS_BIN = resolveBrowserRsBin(envText("NEGOTIUM_BROWSER_RS_BIN"));
@@ -284,10 +288,12 @@ var init_config = __esm(() => {
284
288
  hostname = process.env.HOSTNAME || "127.0.0.1";
285
289
  DATA_DIR = resolveLocalStateDir("NEGOTIUM_DATA_DIR", "data");
286
290
  LOG_DIR = resolveLocalStateDir("NEGOTIUM_LOG_DIR", "logs");
291
+ UPLOADS_DIR = resolve(DATA_DIR, "uploads");
292
+ VAULT_DIR = resolve(DATA_DIR, "vault");
287
293
  SESSIONS_DB = process.env.SESSIONS_DB_PATH ? resolve(process.env.SESSIONS_DB_PATH) : resolve(DATA_DIR, "sessions.db");
288
294
  DEBUG_FILE = resolve(DATA_DIR, "debug-users.json");
289
295
  USERS_LOG_DIR = resolve(DATA_DIR, "users");
290
- RUN_DIR = resolveLocalStateDir("NEGOTIUM_RUN_DIR", "run");
296
+ RUN_DIR = resolveLocalStateDir("NEGOTIUM_RUN_DIR", "runtime");
291
297
  PROGRESS_DIR = resolve(RUN_DIR, "progress");
292
298
  DM_CMD_DIR = resolve(RUN_DIR, "dm-commands");
293
299
  DM_RESP_DIR = resolve(RUN_DIR, "dm-responses");
@@ -298,6 +304,8 @@ var init_config = __esm(() => {
298
304
  PLAYWRIGHT_PORTS_DIR = resolve(RUN_DIR, "playwright-ports");
299
305
  mkdirSync(STATE_DIR, { recursive: true });
300
306
  mkdirSync(DATA_DIR, { recursive: true });
307
+ mkdirSync(UPLOADS_DIR, { recursive: true });
308
+ mkdirSync(VAULT_DIR, { recursive: true, mode: 448 });
301
309
  mkdirSync(LOG_DIR, { recursive: true });
302
310
  mkdirSync(PROGRESS_DIR, { recursive: true });
303
311
  mkdirSync(DM_CMD_DIR, { recursive: true });
@@ -308,10 +316,14 @@ var init_config = __esm(() => {
308
316
  mkdirSync(WORKSPACE_DIR, { recursive: true });
309
317
  mkdirSync(TOPIC_WORKSPACE_DIR, { recursive: true });
310
318
  mkdirSync(SHARED_WIKI_DIR, { recursive: true });
319
+ mkdirSync(CRON_WORKSPACE_DIR, { recursive: true });
311
320
  mkdirSync(CONTEXTS_DIR, { recursive: true });
312
- mkdirSync(BROWSER_PROFILES_DIR, { recursive: true });
313
321
  mkdirSync(DM_WORKSPACE_DIR, { recursive: true });
314
322
  mkdirSync(SESSION_WORKSPACE_DIR, { recursive: true });
323
+ mkdirSync(BROWSER_DIR, { recursive: true });
324
+ mkdirSync(BROWSER_PROFILES_DIR, { recursive: true });
325
+ mkdirSync(BINARIES_DIR, { recursive: true });
326
+ mkdirSync(SECRETS_DIR, { recursive: true, mode: 448 });
315
327
  ACTIVE_QUERY_STALE_MS = 10 * 60 * 1000;
316
328
  AGENTS_PROMPTS_DIR = resolve(PROJECT_ROOT, "src/prompts/agents");
317
329
  RESOURCES_DIR = resolve(PROJECT_ROOT, "src/resources");
@@ -530,7 +542,12 @@ var init_shared = __esm(() => {
530
542
  init_config();
531
543
  init_logger();
532
544
  __dirname2 = dirname3(fileURLToPath2(import.meta.url));
533
- trustedWorkspaceRoots = [WORKSPACE_DIR, DM_WORKSPACE_DIR, TOPIC_WORKSPACE_DIR].map((root) => resolve3(root));
545
+ trustedWorkspaceRoots = [
546
+ WORKSPACE_DIR,
547
+ DM_WORKSPACE_DIR,
548
+ SESSION_WORKSPACE_DIR,
549
+ TOPIC_WORKSPACE_DIR
550
+ ].map((root) => resolve3(root));
534
551
  FIXTURES_DIR = join3(__dirname2, "..", "fixtures");
535
552
  UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
536
553
  });
@@ -1493,7 +1510,7 @@ function defaultWorkspaceDir() {
1493
1510
  return envPath("NEGOTIUM_WORKSPACE_DIR", join7(defaultStateDir(), "workspace"));
1494
1511
  }
1495
1512
  function defaultSessionAsksDir() {
1496
- const runDir = envPath("NEGOTIUM_RUN_DIR", join7(defaultStateDir(), "run"));
1513
+ const runDir = envPath("NEGOTIUM_RUN_DIR", join7(defaultStateDir(), "runtime"));
1497
1514
  return join7(runDir, "session-asks");
1498
1515
  }
1499
1516
  function defaultSessionsDatabasePath() {
@@ -1599,15 +1616,8 @@ import {
1599
1616
  writeFileSync as writeFileSync5
1600
1617
  } from "fs";
1601
1618
  import { dirname as dirname7, join as join8 } from "path";
1602
- function safeUserIdComponent(userId) {
1603
- const str = String(userId);
1604
- if (!str || /[/\\]|\.\./.test(str)) {
1605
- throw new Error(`conversations: refusing unsafe userId path component: ${str}`);
1606
- }
1607
- return str;
1608
- }
1609
- function conversationDir(userId) {
1610
- return join8(resolveStorageDataDir(), "conversations", safeUserIdComponent(userId));
1619
+ function conversationDir(_userId) {
1620
+ return join8(resolveStorageDataDir(), "conversations");
1611
1621
  }
1612
1622
  function topicFilename(topicName) {
1613
1623
  const t = sanitizeTopicName(topicName, true);
@@ -1845,7 +1855,7 @@ function writeRollout(options) {
1845
1855
  version: 1,
1846
1856
  cwd: options.cwd,
1847
1857
  createdAt: existingCreatedAt(path) ?? new Date().toISOString(),
1848
- sdkVersion: "0.1.53"
1858
+ sdkVersion: "0.1.54"
1849
1859
  }
1850
1860
  },
1851
1861
  ...messages
@@ -4199,9 +4209,9 @@ var init_transport_probe = __esm(() => {
4199
4209
  init_capability();
4200
4210
  });
4201
4211
 
4202
- // ../../packages/core/src/storage/vault-crypto.ts
4212
+ // ../../packages/core/src/storage/vault-crypto-core.ts
4203
4213
  import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes3 } from "crypto";
4204
- function encryptionKey(masterKey = VAULT_MASTER_KEY) {
4214
+ function encryptionKey(masterKey) {
4205
4215
  return createHash("sha256").update("otium-vault-value-v1\x00", "utf8").update(masterKey, "utf8").digest().subarray(0, KEY_BYTES);
4206
4216
  }
4207
4217
  function aad(userId, key) {
@@ -4210,7 +4220,7 @@ function aad(userId, key) {
4210
4220
  function isEncryptedVaultValue(value2) {
4211
4221
  return value2.startsWith(ENVELOPE_PREFIX);
4212
4222
  }
4213
- function encryptVaultValue(userId, key, value2, masterKey = VAULT_MASTER_KEY) {
4223
+ function encryptVaultValueWithKey(userId, key, value2, masterKey) {
4214
4224
  const iv = randomBytes3(IV_BYTES);
4215
4225
  const cipher = createCipheriv("aes-256-gcm", encryptionKey(masterKey), iv);
4216
4226
  cipher.setAAD(aad(userId, key));
@@ -4218,7 +4228,7 @@ function encryptVaultValue(userId, key, value2, masterKey = VAULT_MASTER_KEY) {
4218
4228
  const tag = cipher.getAuthTag();
4219
4229
  return `${ENVELOPE_PREFIX}${iv.toString("base64url")}.${ciphertext.toString("base64url")}.${tag.toString("base64url")}`;
4220
4230
  }
4221
- function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KEY) {
4231
+ function decryptVaultValueWithKey(userId, key, storedValue, masterKey) {
4222
4232
  if (!isEncryptedVaultValue(storedValue)) {
4223
4233
  return { value: storedValue, legacyPlaintext: true };
4224
4234
  }
@@ -4240,8 +4250,18 @@ function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KE
4240
4250
  return { value: plaintext.toString("utf8"), legacyPlaintext: false };
4241
4251
  }
4242
4252
  var ENVELOPE_PREFIX = "otium-vault:v1:", IV_BYTES = 12, KEY_BYTES = 32;
4253
+ var init_vault_crypto_core = () => {};
4254
+
4255
+ // ../../packages/core/src/storage/vault-crypto.ts
4256
+ function encryptVaultValue(userId, key, value2, masterKey = VAULT_MASTER_KEY) {
4257
+ return encryptVaultValueWithKey(userId, key, value2, masterKey);
4258
+ }
4259
+ function decryptVaultValue(userId, key, storedValue, masterKey = VAULT_MASTER_KEY) {
4260
+ return decryptVaultValueWithKey(userId, key, storedValue, masterKey);
4261
+ }
4243
4262
  var init_vault_crypto = __esm(() => {
4244
4263
  init_config();
4264
+ init_vault_crypto_core();
4245
4265
  });
4246
4266
 
4247
4267
  // ../../packages/core/src/storage/vault.ts
@@ -4281,8 +4301,9 @@ function initializeVaultDatabase(database) {
4281
4301
  }
4282
4302
  }
4283
4303
  function openVaultDatabase(dataDir) {
4284
- const path = join12(dataDir, "vault.db");
4285
- mkdirSync9(dataDir, { recursive: true });
4304
+ const vaultDir = join12(dataDir, "vault");
4305
+ const path = join12(vaultDir, "vault.db");
4306
+ mkdirSync9(vaultDir, { recursive: true, mode: 448 });
4286
4307
  const database = new Database(path, { create: true });
4287
4308
  chmodSync2(path, 384);
4288
4309
  initializeVaultDatabase(database);
@@ -4635,7 +4656,7 @@ function createBrowserProfile(ownerId, rawName) {
4635
4656
  const name = normalizeBrowserProfileName(rawName);
4636
4657
  if (name === DEFAULT_BROWSER_PROFILE)
4637
4658
  return name;
4638
- db.query("INSERT OR IGNORE INTO browser_profiles (owner_id, name, created_at) VALUES (?, ?, ?)").run(ownerId, name, new Date().toISOString());
4659
+ db.query("INSERT OR IGNORE INTO browser_profiles (owner_id, name, created_at) VALUES (?, ?, ?)").run("local", name, new Date().toISOString());
4639
4660
  return name;
4640
4661
  }
4641
4662
  function assignTopicBrowserProfile(opts) {
@@ -4675,7 +4696,6 @@ import {
4675
4696
  existsSync as existsSync11,
4676
4697
  mkdirSync as mkdirSync10,
4677
4698
  readFileSync as readFileSync9,
4678
- renameSync as renameSync5,
4679
4699
  rmSync,
4680
4700
  unlinkSync as unlinkSync10,
4681
4701
  writeFileSync as writeFileSync7
@@ -4691,7 +4711,7 @@ function defaultTopicBinding(userId, topic) {
4691
4711
  if (!topic)
4692
4712
  return managerHost.resolveNamedBinding(userId, "default");
4693
4713
  const ownerId = getBrowserProfileOwner(topic, userId);
4694
- const profile = migrateLegacyTopicProfile(ownerId, topic);
4714
+ const profile = getTopicBrowserProfile(topic);
4695
4715
  return managerHost.resolveNamedBinding(ownerId, profile);
4696
4716
  }
4697
4717
  function resolvePlaywrightProfileBinding(ownerId, rawProfile) {
@@ -4703,34 +4723,15 @@ function validateProfileBinding(binding) {
4703
4723
  }
4704
4724
  return Object.freeze({ ...binding });
4705
4725
  }
4706
- function defaultNamedBinding(ownerId, rawProfile) {
4726
+ function defaultNamedBinding(_ownerId, rawProfile) {
4707
4727
  const profile = normalizeBrowserProfileName(rawProfile);
4708
- const instanceKey = `profile:${encodeURIComponent(ownerId)}:${profile}`;
4728
+ const instanceKey = `profile:${profile}`;
4709
4729
  return {
4710
4730
  instanceKey,
4711
- ownerId,
4731
+ ownerId: "local",
4712
4732
  profile
4713
4733
  };
4714
4734
  }
4715
- function legacyBrowserProfileName(topic) {
4716
- return `legacy_${createHash2("sha256").update(topic).digest("hex").slice(0, 12)}`;
4717
- }
4718
- function migrateLegacyTopicProfile(ownerId, topic) {
4719
- const current2 = getTopicBrowserProfile(topic);
4720
- if (current2 !== "default" || !hasBrowserProfileTopic(topic))
4721
- return current2;
4722
- const legacyDir = resolve9(BROWSER_PROFILES_DIR, sanitizeTopicName(topic));
4723
- if (!existsSync11(legacyDir))
4724
- return current2;
4725
- const profile = legacyBrowserProfileName(topic);
4726
- const profileDir = defaultProfileDir(ownerId, profile);
4727
- mkdirSync10(dirname8(profileDir), { recursive: true });
4728
- if (!existsSync11(profileDir))
4729
- renameSync5(legacyDir, profileDir);
4730
- assignTopicBrowserProfile({ topicId: topic, actorUserId: ownerId, profile });
4731
- logger.info({ ownerId, topic, profile }, "Adopted legacy topic browser profile");
4732
- return profile;
4733
- }
4734
4735
  function defaultChildEnvironment(context) {
4735
4736
  const childEnvironment = {};
4736
4737
  for (const key of [
@@ -4761,6 +4762,10 @@ function defaultChildEnvironment(context) {
4761
4762
  return childEnvironment;
4762
4763
  }
4763
4764
  function parseInstanceKey(instanceKey) {
4765
+ const shared = /^profile:(.+)$/.exec(instanceKey);
4766
+ if (shared && !shared[1].includes(":")) {
4767
+ return { ownerId: "local", profile: normalizeBrowserProfileName(shared[1]) };
4768
+ }
4764
4769
  const match = /^profile:([^:]+):(.+)$/.exec(instanceKey);
4765
4770
  if (!match)
4766
4771
  return { ownerId: "legacy", profile: sanitizeTopicName(instanceKey) };
@@ -4903,12 +4908,8 @@ async function allocatePort() {
4903
4908
  function releasePort(port) {
4904
4909
  usedPorts.delete(port);
4905
4910
  }
4906
- function ownerDirectory(ownerId) {
4907
- const digest = createHash2("sha256").update(ownerId).digest("hex").slice(0, 16);
4908
- return `${sanitizeTopicName(ownerId).slice(0, 24)}_${digest}`;
4909
- }
4910
- function defaultProfileDir(ownerId, profile) {
4911
- return resolve9(BROWSER_PROFILES_DIR, "profiles", ownerDirectory(ownerId), profile);
4911
+ function defaultProfileDir(_ownerId, profile) {
4912
+ return resolve9(BROWSER_PROFILES_DIR, profile);
4912
4913
  }
4913
4914
  function resolveUserDataDir(instanceKey) {
4914
4915
  return managerHost.resolveInstanceDataDir(instanceKey);
@@ -5952,15 +5953,8 @@ RULES:
5952
5953
  - Keep the entire summary under 1500 words.`, CHARS_PER_TEXT_TOKEN = 3.5, CHARS_PER_CJK_TOKEN = 0.9;
5953
5954
 
5954
5955
  // ../../packages/core/src/storage/tasks.ts
5955
- import { existsSync as existsSync12, mkdirSync as mkdirSync11, readFileSync as readFileSync10, renameSync as renameSync6, statSync as statSync4, writeFileSync as writeFileSync8 } from "fs";
5956
+ import { existsSync as existsSync12, mkdirSync as mkdirSync11, readFileSync as readFileSync10, renameSync as renameSync5, statSync as statSync4, writeFileSync as writeFileSync8 } from "fs";
5956
5957
  import { dirname as dirname9, join as join15 } from "path";
5957
- function safeUserIdComponent2(userId) {
5958
- const str = String(userId);
5959
- if (!str || /[/\\]|\.\./.test(str)) {
5960
- throw new Error(`tasks: refusing unsafe userId path component: ${str}`);
5961
- }
5962
- return str;
5963
- }
5964
5958
  function safeTaskScopeKey(scopeKey) {
5965
5959
  const safe = sanitizeFileName(scopeKey);
5966
5960
  if (!safe || safe === "." || safe === "..") {
@@ -5972,7 +5966,7 @@ function taskScopeKey(opts) {
5972
5966
  return opts.topicId?.trim() || opts.session || "default";
5973
5967
  }
5974
5968
  function getTaskFilePath(userId, scopeKey) {
5975
- return join15(resolveStorageDataDir(), "tasks", safeUserIdComponent2(userId), `${safeTaskScopeKey(scopeKey)}.json`);
5969
+ return join15(resolveStorageDataDir(), "tasks", `${safeTaskScopeKey(scopeKey)}.json`);
5976
5970
  }
5977
5971
  function readTasks(userId, scopeKey) {
5978
5972
  const path = getTaskFilePath(userId, scopeKey);
@@ -5992,7 +5986,7 @@ function writeTasks(userId, scopeKey, tasks) {
5992
5986
  const payload = { version: 1, tasks };
5993
5987
  const tmp = `${path}.${process.pid}.tmp`;
5994
5988
  writeFileSync8(tmp, JSON.stringify(payload, null, 2), "utf-8");
5995
- renameSync6(tmp, path);
5989
+ renameSync5(tmp, path);
5996
5990
  }
5997
5991
  function taskFileMtimeNs(userId, scopeKey) {
5998
5992
  try {
@@ -6816,7 +6810,7 @@ function getMcpServersForQuery(opts) {
6816
6810
  if (!opts.topicId)
6817
6811
  throw new Error("getMcpServersForQuery: cron sessionType requires topicId");
6818
6812
  return getCronMcpServers({
6819
- userId: opts.userId || "default",
6813
+ userId: opts.userId || "local",
6820
6814
  session: opts.session || "cron",
6821
6815
  topicId: opts.topicId,
6822
6816
  queryId: opts.queryId,
@@ -6833,7 +6827,7 @@ function getMcpServersForQuery(opts) {
6833
6827
  }
6834
6828
  if (opts.sessionType === "dm" || opts.sessionType === "ephemeral") {
6835
6829
  return getDmMcpServers({
6836
- userId: opts.userId || "default",
6830
+ userId: opts.userId || "local",
6837
6831
  agent: opts.agent,
6838
6832
  playwrightPort: opts.playwrightPort,
6839
6833
  playwrightCapability: opts.playwrightCapability
@@ -6841,7 +6835,7 @@ function getMcpServersForQuery(opts) {
6841
6835
  }
6842
6836
  if (opts.sessionType === "manager") {
6843
6837
  return getManagerMcpServers({
6844
- userId: opts.userId || "default",
6838
+ userId: opts.userId || "local",
6845
6839
  session: opts.session,
6846
6840
  topicId: opts.topicId,
6847
6841
  queryId: opts.queryId,
@@ -6858,7 +6852,7 @@ function getMcpServersForQuery(opts) {
6858
6852
  });
6859
6853
  }
6860
6854
  return getForumMcpServers({
6861
- userId: opts.userId || "default",
6855
+ userId: opts.userId || "local",
6862
6856
  session: opts.session || "default",
6863
6857
  topicId: opts.topicId,
6864
6858
  subagentParentTopicId: opts.subagentParentTopicId,
@@ -7693,7 +7687,7 @@ var init_claude_provider = __esm(async () => {
7693
7687
  });
7694
7688
 
7695
7689
  // ../../packages/core/src/version.ts
7696
- var NEGOTIUM_VERSION = "0.1.49";
7690
+ var NEGOTIUM_VERSION = "0.2.1";
7697
7691
 
7698
7692
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
7699
7693
  import { spawn as spawn6 } from "child_process";
@@ -7704,7 +7698,7 @@ import {
7704
7698
  existsSync as existsSync14,
7705
7699
  mkdtempSync,
7706
7700
  readFileSync as readFileSync12,
7707
- renameSync as renameSync7,
7701
+ renameSync as renameSync6,
7708
7702
  rmSync as rmSync2,
7709
7703
  unlinkSync as unlinkSync11,
7710
7704
  writeFileSync as writeFileSync9
@@ -7752,7 +7746,7 @@ function writePrivateFileAtomic(path, contents) {
7752
7746
  const tempPath = `${path}.${process.pid}.${randomUUID8()}.tmp`;
7753
7747
  try {
7754
7748
  writeFileSync9(tempPath, contents, { encoding: "utf8", mode: 384 });
7755
- renameSync7(tempPath, path);
7749
+ renameSync6(tempPath, path);
7756
7750
  chmodSync4(path, 384);
7757
7751
  } finally {
7758
7752
  try {
@@ -10916,7 +10910,7 @@ var init_idle_archiver = __esm(async () => {
10916
10910
  });
10917
10911
 
10918
10912
  // ../../packages/core/src/agents/topic-cleanup.ts
10919
- import { mkdirSync as mkdirSync13, renameSync as renameSync8, unlinkSync as unlinkSync12, writeFileSync as writeFileSync11 } from "fs";
10913
+ import { mkdirSync as mkdirSync13, renameSync as renameSync7, unlinkSync as unlinkSync12, writeFileSync as writeFileSync11 } from "fs";
10920
10914
  import { dirname as dirname13 } from "path";
10921
10915
  function collectSessionIdsByAgent(entries, extraSessions = []) {
10922
10916
  const out = new Map;
@@ -10987,7 +10981,7 @@ function createTopicLogMaintenance(host) {
10987
10981
  writeFileSync11(tempPath, retained.length > 0 ? `${retained.map((entry) => JSON.stringify(entry)).join(`
10988
10982
  `)}
10989
10983
  ` : "", { flag: "wx" });
10990
- renameSync8(tempPath, path);
10984
+ renameSync7(tempPath, path);
10991
10985
  } catch (e) {
10992
10986
  try {
10993
10987
  unlinkSync12(tempPath);
@@ -11950,7 +11944,7 @@ var init_session_inbox_cleanup = __esm(() => {
11950
11944
  });
11951
11945
 
11952
11946
  // ../../packages/core/src/query/state.ts
11953
- import { mkdirSync as mkdirSync15, renameSync as renameSync9, unlinkSync as unlinkSync15, writeFileSync as writeFileSync13 } from "fs";
11947
+ import { mkdirSync as mkdirSync15, renameSync as renameSync8, unlinkSync as unlinkSync15, writeFileSync as writeFileSync13 } from "fs";
11954
11948
  import { basename as basename5, join as join25 } from "path";
11955
11949
  function createQueryStateStore(options) {
11956
11950
  const sanitize = options.sanitizeTopicId ?? sanitizeId;
@@ -11972,7 +11966,7 @@ function createQueryStateStore(options) {
11972
11966
  const target = queryStateFile(userId, topicId);
11973
11967
  const tmp = `${target}.${process.pid}.${Date.now()}.tmp`;
11974
11968
  writeFileSync13(tmp, JSON.stringify(state));
11975
- renameSync9(tmp, target);
11969
+ renameSync8(tmp, target);
11976
11970
  },
11977
11971
  clear(userId, topicId, legacyTopicName) {
11978
11972
  const paths = [
@@ -13154,7 +13148,7 @@ function promptWithAttachments(prompt, attachments) {
13154
13148
  return composeAttachmentPrompt(prompt, attachments.map(({ filename, path }) => attachmentPromptLine(filename, path)));
13155
13149
  }
13156
13150
  function ingestAttachment(args) {
13157
- const destDir = join27(workspaceCwdFor(args.topicId), "uploads");
13151
+ const destDir = join27(UPLOADS_DIR, args.topicId);
13158
13152
  mkdirSync17(destDir, { recursive: true });
13159
13153
  const safeName = safeAttachmentFilename(args.filename, "upload");
13160
13154
  const destPath = join27(destDir, `${Date.now()}-${randomUUID13().slice(0, 8)}-${safeName}`);
@@ -19338,4 +19332,4 @@ export {
19338
19332
  createAgentHealthMcpServer
19339
19333
  };
19340
19334
 
19341
- //# debugId=BC568829D61D883264756E2164756E21
19335
+ //# debugId=F5E2DADE8B532CB164756E2164756E21