negotium 0.2.19 → 0.2.21

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 (56) hide show
  1. package/dist/agent-helpers.js +573 -593
  2. package/dist/agent-helpers.js.map +17 -17
  3. package/dist/background-bash.js +3 -2
  4. package/dist/background-bash.js.map +3 -3
  5. package/dist/browser-runtime.js +76 -36
  6. package/dist/browser-runtime.js.map +6 -6
  7. package/dist/canonical-mcp-bridge.js +1 -1
  8. package/dist/{chunk-fc58cqry.js → chunk-rhp26p2c.js} +171 -26
  9. package/dist/{chunk-fc58cqry.js.map → chunk-rhp26p2c.js.map} +6 -5
  10. package/dist/{chunk-r0xs3t81.js → chunk-s2gez3wg.js} +18 -3
  11. package/dist/{chunk-r0xs3t81.js.map → chunk-s2gez3wg.js.map} +2 -2
  12. package/dist/hosted-agent.js +185 -54
  13. package/dist/hosted-agent.js.map +7 -6
  14. package/dist/main.js +1209 -1114
  15. package/dist/main.js.map +25 -25
  16. package/dist/mcp-catalog.js.map +1 -1
  17. package/dist/mcp-factories.js +526 -540
  18. package/dist/mcp-factories.js.map +17 -17
  19. package/dist/outbox.js.map +1 -1
  20. package/dist/platform-runtime.js.map +1 -1
  21. package/dist/prompts.js +3 -2
  22. package/dist/prompts.js.map +3 -3
  23. package/dist/query-runtime.js +63 -26
  24. package/dist/query-runtime.js.map +4 -4
  25. package/dist/registry.js +4 -3
  26. package/dist/registry.js.map +3 -3
  27. package/dist/rollout.js +1 -1
  28. package/dist/runtime/src/agents/archiver.ts +3 -2
  29. package/dist/runtime/src/application/switch-topic-access-mode.ts +81 -8
  30. package/dist/runtime/src/bus.ts +19 -2
  31. package/dist/runtime/src/mcp/session-comm/runtime.ts +16 -0
  32. package/dist/runtime/src/platform/config.ts +13 -1
  33. package/dist/runtime/src/runtime/ask-callbacks.ts +19 -11
  34. package/dist/runtime/src/runtime/background-sessions.ts +9 -7
  35. package/dist/runtime/src/runtime/visual-store.ts +31 -23
  36. package/dist/runtime/src/storage/api-topics.ts +26 -0
  37. package/dist/runtime/src/storage/browser-profiles.ts +16 -8
  38. package/dist/runtime/src/storage/runtime-events.ts +30 -20
  39. package/dist/runtime/src/storage/runtime-gateway-submissions.ts +24 -16
  40. package/dist/runtime/src/storage/runtime-turn-requests.ts +9 -1
  41. package/dist/runtime/src/storage/self-schedules.ts +32 -24
  42. package/dist/runtime/src/storage/storage-host.ts +105 -43
  43. package/dist/runtime/src/storage/vault.ts +12 -3
  44. package/dist/runtime/src/version.ts +1 -1
  45. package/dist/runtime-helpers.js +63 -26
  46. package/dist/runtime-helpers.js.map +4 -4
  47. package/dist/sqlite.js +17 -1
  48. package/dist/sqlite.js.map +2 -2
  49. package/dist/storage.js +92 -46
  50. package/dist/storage.js.map +4 -4
  51. package/dist/types/packages/core/src/storage/api-topics.d.ts +15 -0
  52. package/dist/types/packages/core/src/storage/storage-host.d.ts +10 -0
  53. package/dist/types/packages/core/src/version.d.ts +1 -1
  54. package/dist/vault.js +156 -10
  55. package/dist/vault.js.map +6 -5
  56. package/package.json +1 -1
@@ -63,6 +63,21 @@ export declare function normalizeTopicState(input: {
63
63
  agent?: AgentKind;
64
64
  };
65
65
  export declare function upsertTopic(t: TopicDto): void;
66
+ /**
67
+ * Apply one access mode to a set of topics as a single all-or-nothing write.
68
+ *
69
+ * A partial write is not a cosmetic glitch here: a public parent left with
70
+ * private subagent children (or the reverse) is exactly the half-exposed state
71
+ * the access-mode cascade exists to prevent, so every row commits or none do.
72
+ *
73
+ * Deliberately a narrow UPDATE instead of a loop over {@link upsertTopic}.
74
+ * That helper opens its own transaction, and the node:sqlite shim in
75
+ * `sqlite.ts` emulates transactions with bare BEGIN/COMMIT rather than
76
+ * savepoints — nesting one inside an outer transaction would fail outright.
77
+ * It also rewrites participants and browser-profile ownership, none of which
78
+ * an access-mode change should touch.
79
+ */
80
+ export declare function setTopicAccessModes(topicIds: readonly string[], accessMode: TopicAccessMode): void;
66
81
  export declare function listTopics(): TopicDto[];
67
82
  export declare function getTopic(id: string): TopicDto | null;
68
83
  /** Return the private manager room owned by a user, excluding the retired shared General row. */
@@ -5,6 +5,16 @@ type InternalStorageDatabase = InstanceType<typeof Database>;
5
5
  type StorageSchemaInitializer = (database: InternalStorageDatabase) => void;
6
6
  export declare function initializeDatabase(database: InternalStorageDatabase): void;
7
7
  export declare function resolveStorageDatabase(): InternalStorageDatabase;
8
+ /**
9
+ * The host-injected connection, or null when Negotium owns its own store.
10
+ *
11
+ * Unlike {@link resolveStorageDatabase} this never opens anything. Callers that
12
+ * manage their own short-lived connections need to know whether a host store
13
+ * exists *before* deciding to open one by path: opening it anyway is how an
14
+ * embedded Negotium ends up writing half its state into the host's database and
15
+ * the other half into `~/.negotium`, with nothing reporting an error.
16
+ */
17
+ export declare function configuredStorageDatabase(): InternalStorageDatabase | null;
8
18
  export declare function resolveStorageDataDir(): string;
9
19
  export declare function resolveStorageLogDir(): string;
10
20
  export declare function resolveStorageSessionAsksDir(): string;
@@ -1 +1 @@
1
- export declare const NEGOTIUM_VERSION = "0.2.19";
1
+ export declare const NEGOTIUM_VERSION = "0.2.21";
package/dist/vault.js CHANGED
@@ -1,9 +1,25 @@
1
1
  // @bun
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
2
18
  var __require = import.meta.require;
3
19
 
4
20
  // ../../packages/core/src/storage/vault.ts
5
- import { chmodSync as chmodSync2, mkdirSync as mkdirSync2 } from "fs";
6
- import { join as join2 } from "path";
21
+ import { chmodSync as chmodSync2, mkdirSync as mkdirSync3 } from "fs";
22
+ import { join as join3 } from "path";
7
23
 
8
24
  // ../../packages/core/src/platform/config.ts
9
25
  import { execFileSync } from "child_process";
@@ -125,11 +141,12 @@ function versionAtLeast(actualVersion, minimumVersion) {
125
141
  }
126
142
  return true;
127
143
  }
144
+ var BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000;
128
145
  function browserRsMeetsMinimumVersion(candidate) {
129
146
  try {
130
147
  const output = execFileSync(candidate, ["--version"], {
131
148
  encoding: "utf8",
132
- timeout: 2000,
149
+ timeout: BROWSER_RS_VERSION_PROBE_TIMEOUT_MS,
133
150
  stdio: ["ignore", "pipe", "ignore"]
134
151
  }).trim();
135
152
  const match = output.match(/^browser-rs (\d+)\.(\d+)\.(\d+)$/);
@@ -340,6 +357,134 @@ if (isBun) {
340
357
  Database = NodeDatabase;
341
358
  }
342
359
 
360
+ // ../../packages/core/src/storage/storage-host.ts
361
+ import { mkdirSync as mkdirSync2 } from "fs";
362
+ import { homedir as homedir2 } from "os";
363
+ import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
364
+ var STORAGE_HOST_STATE = Symbol.for("negotium.storage-host.state.v1");
365
+ function storageState() {
366
+ const holder = globalThis;
367
+ const existing = holder[STORAGE_HOST_STATE];
368
+ if (existing)
369
+ return existing;
370
+ const created = {
371
+ configuredHost: {},
372
+ fallbackDatabase: null,
373
+ fallbackDatabasePath: null,
374
+ frames: [],
375
+ schemaInitializers: [],
376
+ initializedSchemas: new WeakMap,
377
+ initializingDatabases: new WeakSet
378
+ };
379
+ Object.defineProperty(holder, STORAGE_HOST_STATE, {
380
+ value: created,
381
+ enumerable: false,
382
+ writable: false,
383
+ configurable: false
384
+ });
385
+ return created;
386
+ }
387
+ function envPath(name, fallback) {
388
+ const value = process.env[name]?.trim();
389
+ return resolve2(value || fallback);
390
+ }
391
+ function defaultStateDir() {
392
+ return envPath("NEGOTIUM_STATE_DIR", join2(homedir2(), ".negotium"));
393
+ }
394
+ function defaultDataDir() {
395
+ return envPath("NEGOTIUM_DATA_DIR", join2(defaultStateDir(), "data"));
396
+ }
397
+ function defaultSessionsDatabasePath() {
398
+ return envPath("SESSIONS_DB_PATH", join2(resolveStorageDataDir(), "sessions.db"));
399
+ }
400
+ var SQLITE_INIT_RETRY_MS = 25;
401
+ var SQLITE_INIT_TIMEOUT_MS = 5000;
402
+ var SQLITE_INIT_SLEEP = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
403
+ function isSqliteBusy(error) {
404
+ const message = error instanceof Error ? error.message : String(error);
405
+ return /database is (?:locked|busy)|SQLITE_(?:BUSY|LOCKED)/i.test(message);
406
+ }
407
+ function execWithBusyRetry(database, sql, timeoutMs = SQLITE_INIT_TIMEOUT_MS) {
408
+ const deadline = Date.now() + timeoutMs;
409
+ while (true) {
410
+ try {
411
+ database.exec(sql);
412
+ return;
413
+ } catch (error) {
414
+ if (!isSqliteBusy(error) || Date.now() >= deadline)
415
+ throw error;
416
+ Atomics.wait(SQLITE_INIT_SLEEP, 0, 0, Math.min(SQLITE_INIT_RETRY_MS, deadline - Date.now()));
417
+ }
418
+ }
419
+ }
420
+ function initializeDatabase(database) {
421
+ database.exec("PRAGMA busy_timeout = 5000");
422
+ execWithBusyRetry(database, "PRAGMA journal_mode = WAL");
423
+ database.exec("PRAGMA foreign_keys = ON");
424
+ database.exec("PRAGMA wal_autocheckpoint = 1000");
425
+ try {
426
+ database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
427
+ } catch {}
428
+ }
429
+ function defaultDatabase() {
430
+ const path = defaultSessionsDatabasePath();
431
+ const state = storageState();
432
+ if (state.fallbackDatabase && state.fallbackDatabasePath === path)
433
+ return state.fallbackDatabase;
434
+ if (state.fallbackDatabase)
435
+ state.fallbackDatabase.close();
436
+ mkdirSync2(dirname2(path), { recursive: true });
437
+ state.fallbackDatabase = new Database(path, { create: true });
438
+ state.fallbackDatabasePath = path;
439
+ initializeDatabase(state.fallbackDatabase);
440
+ return state.fallbackDatabase;
441
+ }
442
+ function resolveStorageDatabase() {
443
+ return storageState().configuredHost.database ?? defaultDatabase();
444
+ }
445
+ function resolveStorageDataDir() {
446
+ return storageState().configuredHost.dataDir ?? defaultDataDir();
447
+ }
448
+ function ensureStorageSchemas(database = resolveStorageDatabase()) {
449
+ const state = storageState();
450
+ if (state.initializingDatabases.has(database))
451
+ return;
452
+ let initialized = state.initializedSchemas.get(database);
453
+ if (!initialized) {
454
+ initialized = new Set;
455
+ state.initializedSchemas.set(database, initialized);
456
+ }
457
+ state.initializingDatabases.add(database);
458
+ try {
459
+ for (const entry of state.schemaInitializers) {
460
+ if (initialized.has(entry.initialize))
461
+ continue;
462
+ initialized.add(entry.initialize);
463
+ try {
464
+ entry.initialize(database);
465
+ } catch (error) {
466
+ initialized.delete(entry.initialize);
467
+ throw error;
468
+ }
469
+ }
470
+ } finally {
471
+ state.initializingDatabases.delete(database);
472
+ }
473
+ }
474
+ var internalStorageDatabase = new Proxy({}, {
475
+ get(_target, property) {
476
+ const database = resolveStorageDatabase();
477
+ ensureStorageSchemas(database);
478
+ const value = Reflect.get(database, property, database);
479
+ return typeof value === "function" ? value.bind(database) : value;
480
+ },
481
+ set(_target, property, value) {
482
+ const database = resolveStorageDatabase();
483
+ ensureStorageSchemas(database);
484
+ return Reflect.set(database, property, value, database);
485
+ }
486
+ });
487
+
343
488
  // ../../packages/core/src/storage/vault-crypto-core.ts
344
489
  import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes2 } from "crypto";
345
490
  var ENVELOPE_PREFIX = "otium-vault:v1:";
@@ -429,17 +574,18 @@ function initializeVaultDatabase(database) {
429
574
  }
430
575
  }
431
576
  function openVaultDatabase(dataDir) {
432
- const vaultDir = join2(dataDir, "vault");
433
- const path = join2(vaultDir, "vault.db");
434
- mkdirSync2(vaultDir, { recursive: true, mode: 448 });
577
+ const vaultDir = join3(dataDir, "vault");
578
+ const path = join3(vaultDir, "vault.db");
579
+ mkdirSync3(vaultDir, { recursive: true, mode: 448 });
435
580
  const database = new Database(path, { create: true });
436
581
  chmodSync2(path, 384);
437
582
  initializeVaultDatabase(database);
438
583
  return database;
439
584
  }
440
585
  function activeVaultDatabase() {
441
- if (!vaultDb)
442
- vaultDb = openVaultDatabase(DATA_DIR);
586
+ if (!vaultDb) {
587
+ vaultDb = openVaultDatabase(resolveStorageDataDir());
588
+ }
443
589
  return vaultDb;
444
590
  }
445
591
  function configureVaultStorage(options) {
@@ -448,7 +594,7 @@ function configureVaultStorage(options) {
448
594
  }
449
595
  const previousDb = vaultDb;
450
596
  const previousMasterKey = vaultMasterKey;
451
- const configuredDb = options.database ?? openVaultDatabase(options.dataDir ?? DATA_DIR);
597
+ const configuredDb = options.database ?? openVaultDatabase(options.dataDir ?? resolveStorageDataDir());
452
598
  if (options.database)
453
599
  initializeVaultDatabase(configuredDb);
454
600
  vaultDb = configuredDb;
@@ -626,4 +772,4 @@ export {
626
772
  VAULT_DESCRIPTION_MAX_LENGTH
627
773
  };
628
774
 
629
- //# debugId=BC1F6A83A7692EAF64756E2164756E21
775
+ //# debugId=D5A79ADB789E4EA464756E2164756E21