negotium 0.1.11 → 0.1.13

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 (165) hide show
  1. package/README.md +11 -2
  2. package/dist/canonical-mcp-bridge.js +2 -3
  3. package/dist/canonical-mcp-bridge.js.map +1 -1
  4. package/dist/{chunk-gz12qcf0.js → chunk-a9y2rwxf.js} +2 -2
  5. package/dist/{chunk-gz12qcf0.js.map → chunk-a9y2rwxf.js.map} +3 -3
  6. package/dist/{chunk-j0kjscb7.js → chunk-s2gez3wg.js} +20 -2
  7. package/dist/{chunk-j0kjscb7.js.map → chunk-s2gez3wg.js.map} +2 -2
  8. package/dist/cron.js +292 -256
  9. package/dist/cron.js.map +23 -22
  10. package/dist/hosted-agent.js +3012 -17
  11. package/dist/hosted-agent.js.map +30 -3
  12. package/dist/main.js +31323 -36
  13. package/dist/main.js.map +198 -3
  14. package/dist/prompts.js +12 -9
  15. package/dist/prompts.js.map +5 -5
  16. package/dist/registry.js +10 -6
  17. package/dist/registry.js.map +3 -3
  18. package/dist/rollout.js +1 -1
  19. package/dist/runtime/cron/store.ts +24 -1
  20. package/dist/runtime/src/application/submit-user-message.ts +3 -0
  21. package/dist/runtime/src/index.ts +7 -0
  22. package/dist/runtime/src/mcp/runtime-spec.ts +3 -0
  23. package/dist/runtime/src/mcp/session-comm/server.ts +1 -1
  24. package/dist/runtime/src/platform/config.ts +2 -2
  25. package/dist/runtime/src/platform/mcp-config.ts +13 -0
  26. package/dist/runtime/src/prompts/builders.ts +20 -6
  27. package/dist/runtime/src/query/active-rooms.ts +2 -0
  28. package/dist/runtime/src/runtime/delivery-ack.ts +112 -0
  29. package/dist/runtime/src/runtime/errors.ts +12 -12
  30. package/dist/runtime/src/runtime/turn-runner.ts +12 -0
  31. package/dist/runtime/src/storage/api-messages.ts +7 -5
  32. package/dist/runtime/src/storage/api-topics.ts +5 -2
  33. package/dist/runtime/src/storage/forum-db.ts +4 -1
  34. package/dist/runtime/src/storage/runtime-turn-requests.ts +1 -0
  35. package/dist/runtime/src/storage/session-asks.ts +13 -5
  36. package/dist/runtime/src/storage/storage-contract.ts +54 -0
  37. package/dist/runtime/src/storage/storage-host.ts +89 -36
  38. package/dist/runtime/src/storage/storage-public-host.ts +16 -0
  39. package/dist/runtime/src/storage/storage-public.ts +21 -5
  40. package/dist/runtime/src/storage/token-stats.ts +1 -1
  41. package/dist/runtime/src/types/api.ts +2 -0
  42. package/dist/runtime/src/types.ts +2 -0
  43. package/dist/runtime/src/version.ts +1 -1
  44. package/dist/runtime-helpers.js +29 -18
  45. package/dist/runtime-helpers.js.map +8 -7
  46. package/dist/storage.js +260 -202
  47. package/dist/storage.js.map +11 -9
  48. package/dist/types/packages/core/src/mcp/runtime-spec.d.ts +2 -0
  49. package/dist/types/packages/core/src/platform/mcp-config.d.ts +4 -0
  50. package/dist/types/packages/core/src/prompts/builders.d.ts +2 -0
  51. package/dist/types/packages/core/src/storage/api-messages.d.ts +6 -6
  52. package/dist/types/packages/core/src/storage/api-topics.d.ts +20 -2
  53. package/dist/types/packages/core/src/storage/forum-db.d.ts +2 -1
  54. package/dist/types/packages/core/src/storage/session-asks.d.ts +3 -2
  55. package/dist/types/packages/core/src/storage/storage-contract.d.ts +46 -0
  56. package/dist/types/packages/core/src/storage/storage-host.d.ts +12 -19
  57. package/dist/types/packages/core/src/storage/storage-public-host.d.ts +7 -0
  58. package/dist/types/packages/core/src/storage/storage-public.d.ts +4 -2
  59. package/dist/types/packages/core/src/types/api.d.ts +2 -0
  60. package/dist/types/packages/core/src/types.d.ts +2 -0
  61. package/dist/types/packages/core/src/version.d.ts +1 -1
  62. package/dist/types/packages/module-cron/src/store.d.ts +22 -2
  63. package/dist/vault.js +2 -2
  64. package/dist/vault.js.map +3 -3
  65. package/package.json +1 -1
  66. package/dist/chunk-01xcc856.js +0 -149
  67. package/dist/chunk-01xcc856.js.map +0 -10
  68. package/dist/chunk-1a6kv9vt.js +0 -118
  69. package/dist/chunk-1a6kv9vt.js.map +0 -10
  70. package/dist/chunk-1b62d730.js +0 -117
  71. package/dist/chunk-1b62d730.js.map +0 -10
  72. package/dist/chunk-1k7t7bnx.js +0 -97
  73. package/dist/chunk-1k7t7bnx.js.map +0 -10
  74. package/dist/chunk-28apmz4r.js +0 -431
  75. package/dist/chunk-28apmz4r.js.map +0 -11
  76. package/dist/chunk-2fvydfkx.js +0 -141
  77. package/dist/chunk-2fvydfkx.js.map +0 -10
  78. package/dist/chunk-41ygvg5k.js +0 -2387
  79. package/dist/chunk-41ygvg5k.js.map +0 -26
  80. package/dist/chunk-4q966ttx.js +0 -371
  81. package/dist/chunk-4q966ttx.js.map +0 -11
  82. package/dist/chunk-51rcsavw.js +0 -1712
  83. package/dist/chunk-51rcsavw.js.map +0 -18
  84. package/dist/chunk-59d0shyj.js +0 -103
  85. package/dist/chunk-59d0shyj.js.map +0 -10
  86. package/dist/chunk-5fzgvn79.js +0 -3536
  87. package/dist/chunk-5fzgvn79.js.map +0 -20
  88. package/dist/chunk-61px0717.js +0 -153
  89. package/dist/chunk-61px0717.js.map +0 -11
  90. package/dist/chunk-66y0hr8c.js +0 -2136
  91. package/dist/chunk-66y0hr8c.js.map +0 -29
  92. package/dist/chunk-69k45zg8.js +0 -250
  93. package/dist/chunk-69k45zg8.js.map +0 -11
  94. package/dist/chunk-6ah5farg.js +0 -130
  95. package/dist/chunk-6ah5farg.js.map +0 -10
  96. package/dist/chunk-6d4fmea5.js +0 -117
  97. package/dist/chunk-6d4fmea5.js.map +0 -12
  98. package/dist/chunk-8cahx7xc.js +0 -46
  99. package/dist/chunk-8cahx7xc.js.map +0 -10
  100. package/dist/chunk-8f20fk4n.js +0 -252
  101. package/dist/chunk-8f20fk4n.js.map +0 -10
  102. package/dist/chunk-91ckrvk8.js +0 -318
  103. package/dist/chunk-91ckrvk8.js.map +0 -10
  104. package/dist/chunk-93krf6ng.js +0 -3069
  105. package/dist/chunk-93krf6ng.js.map +0 -32
  106. package/dist/chunk-9qx1t77a.js +0 -214
  107. package/dist/chunk-9qx1t77a.js.map +0 -10
  108. package/dist/chunk-beqhdr9w.js +0 -589
  109. package/dist/chunk-beqhdr9w.js.map +0 -11
  110. package/dist/chunk-bftftsgq.js +0 -1637
  111. package/dist/chunk-bftftsgq.js.map +0 -15
  112. package/dist/chunk-c500xe9z.js +0 -33
  113. package/dist/chunk-c500xe9z.js.map +0 -10
  114. package/dist/chunk-cjsnkvq2.js +0 -23
  115. package/dist/chunk-cjsnkvq2.js.map +0 -10
  116. package/dist/chunk-cxa7yghg.js +0 -577
  117. package/dist/chunk-cxa7yghg.js.map +0 -14
  118. package/dist/chunk-edb07sjp.js +0 -567
  119. package/dist/chunk-edb07sjp.js.map +0 -14
  120. package/dist/chunk-f361dwba.js +0 -589
  121. package/dist/chunk-f361dwba.js.map +0 -11
  122. package/dist/chunk-f5xgprg1.js +0 -59
  123. package/dist/chunk-f5xgprg1.js.map +0 -10
  124. package/dist/chunk-ffefbd3r.js +0 -17
  125. package/dist/chunk-ffefbd3r.js.map +0 -10
  126. package/dist/chunk-fswhzdf5.js +0 -64
  127. package/dist/chunk-fswhzdf5.js.map +0 -10
  128. package/dist/chunk-g144wdrs.js +0 -2907
  129. package/dist/chunk-g144wdrs.js.map +0 -24
  130. package/dist/chunk-h980hb2n.js +0 -512
  131. package/dist/chunk-h980hb2n.js.map +0 -13
  132. package/dist/chunk-h9vbhhgr.js +0 -1337
  133. package/dist/chunk-h9vbhhgr.js.map +0 -16
  134. package/dist/chunk-hwy3n31w.js +0 -21
  135. package/dist/chunk-hwy3n31w.js.map +0 -9
  136. package/dist/chunk-jtrk0khr.js +0 -108
  137. package/dist/chunk-jtrk0khr.js.map +0 -10
  138. package/dist/chunk-jzz91jwh.js +0 -70
  139. package/dist/chunk-jzz91jwh.js.map +0 -10
  140. package/dist/chunk-m9e3tbr8.js +0 -708
  141. package/dist/chunk-m9e3tbr8.js.map +0 -14
  142. package/dist/chunk-mh5mexsf.js +0 -147
  143. package/dist/chunk-mh5mexsf.js.map +0 -11
  144. package/dist/chunk-npd8n03v.js +0 -2152
  145. package/dist/chunk-npd8n03v.js.map +0 -15
  146. package/dist/chunk-pg1azh6n.js +0 -2
  147. package/dist/chunk-pg1azh6n.js.map +0 -9
  148. package/dist/chunk-qwy57177.js +0 -237
  149. package/dist/chunk-qwy57177.js.map +0 -11
  150. package/dist/chunk-r31q21h5.js +0 -53
  151. package/dist/chunk-r31q21h5.js.map +0 -10
  152. package/dist/chunk-rbvctv1n.js +0 -366
  153. package/dist/chunk-rbvctv1n.js.map +0 -10
  154. package/dist/chunk-sa874j5c.js +0 -9
  155. package/dist/chunk-sa874j5c.js.map +0 -10
  156. package/dist/chunk-sctcs5zb.js +0 -281
  157. package/dist/chunk-sctcs5zb.js.map +0 -10
  158. package/dist/chunk-tsstrcfc.js +0 -122
  159. package/dist/chunk-tsstrcfc.js.map +0 -10
  160. package/dist/chunk-wk2qf31s.js +0 -58
  161. package/dist/chunk-wk2qf31s.js.map +0 -10
  162. package/dist/chunk-wx7ag4dd.js +0 -2936
  163. package/dist/chunk-wx7ag4dd.js.map +0 -20
  164. package/dist/chunk-znx1fpfd.js +0 -61
  165. package/dist/chunk-znx1fpfd.js.map +0 -10
package/dist/cron.js CHANGED
@@ -273,7 +273,7 @@ var init_config = __esm(() => {
273
273
  TESSERACT_BIN = envText("TESSERACT_BIN") ?? "tesseract";
274
274
  PDFTOTEXT_BIN = envText("PDFTOTEXT_BIN") ?? "pdftotext";
275
275
  _envMaxTellDepth = Number.parseInt(process.env.MAX_TELL_DEPTH ?? "", 10);
276
- MAX_TELL_DEPTH = Number.isInteger(_envMaxTellDepth) && _envMaxTellDepth > 0 ? _envMaxTellDepth : 3;
276
+ MAX_TELL_DEPTH = Number.isInteger(_envMaxTellDepth) && _envMaxTellDepth > 0 ? _envMaxTellDepth : 20;
277
277
  });
278
278
 
279
279
  // ../../packages/core/src/agents/auth-check.ts
@@ -1385,7 +1385,7 @@ function defaultSessionAsksDir() {
1385
1385
  return join6(runDir, "session-asks");
1386
1386
  }
1387
1387
  function defaultSessionsDatabasePath() {
1388
- return envPath("SESSIONS_DB_PATH", join6(defaultDataDir(), "sessions.db"));
1388
+ return envPath("SESSIONS_DB_PATH", join6(resolveStorageDataDir(), "sessions.db"));
1389
1389
  }
1390
1390
  function initializeDatabase(database) {
1391
1391
  database.exec("PRAGMA journal_mode = WAL");
@@ -1397,11 +1397,14 @@ function initializeDatabase(database) {
1397
1397
  } catch {}
1398
1398
  }
1399
1399
  function defaultDatabase() {
1400
- if (fallbackDatabase)
1401
- return fallbackDatabase;
1402
1400
  const path = defaultSessionsDatabasePath();
1401
+ if (fallbackDatabase && fallbackDatabasePath === path)
1402
+ return fallbackDatabase;
1403
+ if (fallbackDatabase)
1404
+ fallbackDatabase.close();
1403
1405
  mkdirSync5(dirname4(path), { recursive: true });
1404
1406
  fallbackDatabase = new Database(path, { create: true });
1407
+ fallbackDatabasePath = path;
1405
1408
  initializeDatabase(fallbackDatabase);
1406
1409
  return fallbackDatabase;
1407
1410
  }
@@ -1421,7 +1424,7 @@ function resolveStorageWorkspaceDir() {
1421
1424
  return configuredHost.workspaceDir ?? defaultWorkspaceDir();
1422
1425
  }
1423
1426
  function resolveStorageSharedWikiDir() {
1424
- return join6(resolveStorageWorkspaceDir(), "wiki");
1427
+ return configuredHost.sharedWikiDir ?? join6(resolveStorageWorkspaceDir(), "wiki");
1425
1428
  }
1426
1429
  function registerStorageSchemaInitializer(initialize, priority = 100) {
1427
1430
  schemaInitializers.push({ initialize, priority });
@@ -1452,14 +1455,14 @@ function ensureStorageSchemas(database = resolveStorageDatabase()) {
1452
1455
  initializingDatabases.delete(database);
1453
1456
  }
1454
1457
  }
1455
- var configuredHost, fallbackDatabase = null, schemaInitializers, initializedSchemas, initializingDatabases, storageDatabase;
1458
+ var configuredHost, fallbackDatabase = null, fallbackDatabasePath = null, schemaInitializers, initializedSchemas, initializingDatabases, internalStorageDatabase;
1456
1459
  var init_storage_host = __esm(async () => {
1457
1460
  await init_sqlite();
1458
1461
  configuredHost = {};
1459
1462
  schemaInitializers = [];
1460
1463
  initializedSchemas = new WeakMap;
1461
1464
  initializingDatabases = new WeakSet;
1462
- storageDatabase = new Proxy({}, {
1465
+ internalStorageDatabase = new Proxy({}, {
1463
1466
  get(_target, property) {
1464
1467
  const database = resolveStorageDatabase();
1465
1468
  ensureStorageSchemas(database);
@@ -2179,7 +2182,8 @@ function getManagerMcpServers(opts) {
2179
2182
  playwrightPort: opts.playwrightPort,
2180
2183
  playwrightCapability: opts.playwrightCapability,
2181
2184
  autoContinue: opts.autoContinue,
2182
- visualTools: opts.visualTools
2185
+ visualTools: opts.visualTools,
2186
+ fileDeliveryTools: opts.fileDeliveryTools
2183
2187
  });
2184
2188
  }
2185
2189
  function getForumMcpServers(opts) {
@@ -2202,6 +2206,7 @@ function getForumMcpServers(opts) {
2202
2206
  bgBashPort,
2203
2207
  autoContinue,
2204
2208
  visualTools,
2209
+ fileDeliveryTools,
2205
2210
  peerBridge
2206
2211
  } = opts;
2207
2212
  const filter = (name) => {
@@ -2227,6 +2232,7 @@ function getForumMcpServers(opts) {
2227
2232
  bgBashPort,
2228
2233
  autoContinue,
2229
2234
  visualTools,
2235
+ fileDeliveryTools,
2230
2236
  silent,
2231
2237
  peerBridge
2232
2238
  }, filter);
@@ -2246,7 +2252,8 @@ function getCronMcpServers(opts) {
2246
2252
  playwrightPort: opts.playwrightPort,
2247
2253
  playwrightCapability: opts.playwrightCapability,
2248
2254
  autoContinue: false,
2249
- visualTools: opts.visualTools
2255
+ visualTools: opts.visualTools,
2256
+ fileDeliveryTools: opts.fileDeliveryTools
2250
2257
  });
2251
2258
  }
2252
2259
  function getMcpServersForQuery(opts) {
@@ -2265,7 +2272,8 @@ function getMcpServersForQuery(opts) {
2265
2272
  currentUserPrompt: opts.prompt,
2266
2273
  playwrightPort: opts.playwrightPort,
2267
2274
  playwrightCapability: opts.playwrightCapability,
2268
- visualTools: opts.visualTools
2275
+ visualTools: opts.visualTools,
2276
+ fileDeliveryTools: opts.fileDeliveryTools
2269
2277
  });
2270
2278
  }
2271
2279
  if (opts.sessionType === "dm" || opts.sessionType === "ephemeral") {
@@ -2290,7 +2298,8 @@ function getMcpServersForQuery(opts) {
2290
2298
  playwrightPort: opts.playwrightPort,
2291
2299
  playwrightCapability: opts.playwrightCapability,
2292
2300
  autoContinue: opts.autoContinue,
2293
- visualTools: opts.visualTools
2301
+ visualTools: opts.visualTools,
2302
+ fileDeliveryTools: opts.fileDeliveryTools
2294
2303
  });
2295
2304
  }
2296
2305
  return getForumMcpServers({
@@ -2308,6 +2317,7 @@ function getMcpServersForQuery(opts) {
2308
2317
  bgBashPort: opts.bgBashPort,
2309
2318
  autoContinue: opts.autoContinue,
2310
2319
  visualTools: opts.visualTools,
2320
+ fileDeliveryTools: opts.fileDeliveryTools,
2311
2321
  depth: opts.depth,
2312
2322
  enabled: opts.mcpEnabled,
2313
2323
  extra: opts.mcpExtra,
@@ -2357,6 +2367,7 @@ var init_mcp_config = __esm(() => {
2357
2367
  currentUserPrompt,
2358
2368
  autoContinue,
2359
2369
  visualTools,
2370
+ fileDeliveryTools,
2360
2371
  peerBridge
2361
2372
  }) {
2362
2373
  if (!topicId || !agent)
@@ -2372,6 +2383,7 @@ var init_mcp_config = __esm(() => {
2372
2383
  currentUserPrompt,
2373
2384
  autoContinue,
2374
2385
  visualTools,
2386
+ fileDeliveryTools,
2375
2387
  peerBridge
2376
2388
  });
2377
2389
  }
@@ -3042,7 +3054,7 @@ var init_claude_provider = __esm(async () => {
3042
3054
  });
3043
3055
 
3044
3056
  // ../../packages/core/src/version.ts
3045
- var NEGOTIUM_VERSION = "0.1.11";
3057
+ var NEGOTIUM_VERSION = "0.1.13";
3046
3058
 
3047
3059
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
3048
3060
  import { spawn as spawn2 } from "child_process";
@@ -3973,8 +3985,10 @@ function errorResult(text) {
3973
3985
  }
3974
3986
 
3975
3987
  // ../../packages/core/src/storage/forum-db.ts
3988
+ var db;
3976
3989
  var init_forum_db = __esm(async () => {
3977
3990
  await init_storage_host();
3991
+ db = internalStorageDatabase;
3978
3992
  });
3979
3993
 
3980
3994
  // ../../packages/core/src/storage/runtime-events.ts
@@ -3995,19 +4009,19 @@ function rowToEvent(row) {
3995
4009
  }
3996
4010
  }
3997
4011
  function latestRuntimeEventSeq() {
3998
- const row = storageDatabase.query("SELECT MAX(seq) AS seq FROM runtime_events").get();
4012
+ const row = db.query("SELECT MAX(seq) AS seq FROM runtime_events").get();
3999
4013
  return Number(row?.seq ?? 0);
4000
4014
  }
4001
4015
  function appendRuntimeEvent(sourceId, event) {
4002
4016
  const createdAt = new Date().toISOString();
4003
- const result = storageDatabase.query(`INSERT INTO runtime_events
4017
+ const result = db.query(`INSERT INTO runtime_events
4004
4018
  (source_id, event_type, topic_id, payload_json, created_at)
4005
4019
  VALUES (?, ?, ?, ?, ?)`).run(sourceId, event.type, event.topicId, JSON.stringify(event.payload ?? null), createdAt);
4006
4020
  const seq = Number(result.lastInsertRowid);
4007
4021
  return { seq, sourceId, ...event, createdAt };
4008
4022
  }
4009
4023
  function listRuntimeEventsAfter(seq, limit = 500) {
4010
- const rows = storageDatabase.query(`SELECT seq, source_id, event_type, topic_id, payload_json, created_at
4024
+ const rows = db.query(`SELECT seq, source_id, event_type, topic_id, payload_json, created_at
4011
4025
  FROM runtime_events
4012
4026
  WHERE seq > ?
4013
4027
  ORDER BY seq ASC
@@ -4015,7 +4029,7 @@ function listRuntimeEventsAfter(seq, limit = 500) {
4015
4029
  return rows.map(rowToEvent).filter((event) => event !== null);
4016
4030
  }
4017
4031
  function listRecentRuntimeEventsForTopic(topicId, limit = 300) {
4018
- const rows = storageDatabase.query(`SELECT seq, source_id, event_type, topic_id, payload_json, created_at
4032
+ const rows = db.query(`SELECT seq, source_id, event_type, topic_id, payload_json, created_at
4019
4033
  FROM (
4020
4034
  SELECT seq, source_id, event_type, topic_id, payload_json, created_at
4021
4035
  FROM runtime_events
@@ -4037,7 +4051,7 @@ var init_runtime_events = __esm(async () => {
4037
4051
  "topic-updated",
4038
4052
  "topic-deleted"
4039
4053
  ];
4040
- storageDatabase.exec(`
4054
+ db.exec(`
4041
4055
  CREATE TABLE IF NOT EXISTS runtime_events (
4042
4056
  seq INTEGER PRIMARY KEY AUTOINCREMENT,
4043
4057
  source_id TEXT NOT NULL,
@@ -4056,7 +4070,7 @@ var init_runtime_events = __esm(async () => {
4056
4070
  created_at TEXT NOT NULL
4057
4071
  )
4058
4072
  `);
4059
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_runtime_events_topic_seq ON runtime_events(topic_id, seq)");
4073
+ db.exec("CREATE INDEX IF NOT EXISTS idx_runtime_events_topic_seq ON runtime_events(topic_id, seq)");
4060
4074
  types = new Set(RUNTIME_EVENT_TYPES);
4061
4075
  });
4062
4076
 
@@ -4226,7 +4240,7 @@ var init_bus = __esm(async () => {
4226
4240
 
4227
4241
  // ../../packages/core/src/storage/api-messages.ts
4228
4242
  function initializeApiMessagesSchema() {
4229
- storageDatabase.exec(`
4243
+ db.exec(`
4230
4244
  CREATE TABLE IF NOT EXISTS api_messages (
4231
4245
  id TEXT PRIMARY KEY,
4232
4246
  topic_id TEXT NOT NULL,
@@ -4250,34 +4264,34 @@ function initializeApiMessagesSchema() {
4250
4264
  )
4251
4265
  `);
4252
4266
  try {
4253
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN source_adapter TEXT");
4267
+ db.exec("ALTER TABLE api_messages ADD COLUMN source_adapter TEXT");
4254
4268
  } catch {}
4255
4269
  try {
4256
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0");
4270
+ db.exec("ALTER TABLE api_messages ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0");
4257
4271
  } catch {}
4258
4272
  try {
4259
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN edited_at TEXT");
4273
+ db.exec("ALTER TABLE api_messages ADD COLUMN edited_at TEXT");
4260
4274
  } catch {}
4261
4275
  try {
4262
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN reactions TEXT");
4276
+ db.exec("ALTER TABLE api_messages ADD COLUMN reactions TEXT");
4263
4277
  } catch {}
4264
4278
  try {
4265
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN kind TEXT");
4279
+ db.exec("ALTER TABLE api_messages ADD COLUMN kind TEXT");
4266
4280
  } catch {}
4267
4281
  try {
4268
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN ask_user_question TEXT");
4282
+ db.exec("ALTER TABLE api_messages ADD COLUMN ask_user_question TEXT");
4269
4283
  } catch {}
4270
4284
  try {
4271
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN mentions TEXT");
4285
+ db.exec("ALTER TABLE api_messages ADD COLUMN mentions TEXT");
4272
4286
  } catch {}
4273
4287
  try {
4274
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN thread_root_id TEXT");
4288
+ db.exec("ALTER TABLE api_messages ADD COLUMN thread_root_id TEXT");
4275
4289
  } catch {}
4276
4290
  try {
4277
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN subagent_card TEXT");
4291
+ db.exec("ALTER TABLE api_messages ADD COLUMN subagent_card TEXT");
4278
4292
  } catch {}
4279
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_topic ON api_messages(topic_id)");
4280
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_thread_root ON api_messages(thread_root_id)");
4293
+ db.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_topic ON api_messages(topic_id)");
4294
+ db.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_thread_root ON api_messages(thread_root_id)");
4281
4295
  }
4282
4296
  function emitApiMessageAppended(msg) {
4283
4297
  for (const hook of appendHooks) {
@@ -4328,14 +4342,14 @@ function appendApiMessage(msg, options = {}) {
4328
4342
  const notify = options.notify ?? true;
4329
4343
  const updateTopicLastMessageAt = options.updateTopicLastMessageAt ?? true;
4330
4344
  let inserted = false;
4331
- storageDatabase.transaction(() => {
4332
- const result = storageDatabase.query(`INSERT INTO api_messages
4345
+ db.transaction(() => {
4346
+ const result = db.query(`INSERT INTO api_messages
4333
4347
  (id, topic_id, parent_id, author_id, source_adapter, text, query_id, agent_type, model, attachments, usage, deleted, edited_at, reactions, kind, ask_user_question, subagent_card, mentions, thread_root_id, created_at)
4334
4348
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
4335
4349
  ON CONFLICT(id) DO NOTHING`).run(msg.id, msg.topicId, msg.parentId ?? null, msg.authorId, msg.sourceAdapter ?? null, msg.text, msg.queryId ?? null, msg.agentType ?? null, msg.model ?? null, msg.attachments ? JSON.stringify(msg.attachments) : null, msg.usage ? JSON.stringify(msg.usage) : null, msg.deleted ? 1 : 0, msg.editedAt ?? null, msg.reactions?.length ? JSON.stringify(msg.reactions) : null, msg.kind ?? null, msg.askUserQuestion ? JSON.stringify(msg.askUserQuestion) : null, msg.subagentCard ? JSON.stringify(msg.subagentCard) : null, msg.mentions?.length ? JSON.stringify(msg.mentions) : null, msg.threadRootId ?? null, msg.createdAt);
4336
4350
  inserted = Number(result.changes ?? 0) > 0;
4337
4351
  if (inserted && updateTopicLastMessageAt && !msg.deleted) {
4338
- storageDatabase.query(`UPDATE api_topics
4352
+ db.query(`UPDATE api_topics
4339
4353
  SET last_message_at = CASE
4340
4354
  WHEN last_message_at IS NULL OR last_message_at < ? THEN ?
4341
4355
  ELSE last_message_at
@@ -4347,15 +4361,15 @@ function appendApiMessage(msg, options = {}) {
4347
4361
  emitApiMessageAppended(msg);
4348
4362
  }
4349
4363
  function getApiMessage(topicId, messageId) {
4350
- const row = storageDatabase.query("SELECT * FROM api_messages WHERE topic_id = ? AND id = ?").get(topicId, messageId);
4364
+ const row = db.query("SELECT * FROM api_messages WHERE topic_id = ? AND id = ?").get(topicId, messageId);
4351
4365
  return row ? rowToDto(row) : null;
4352
4366
  }
4353
4367
  function topicHasAttachmentFileId(topicId, fileId) {
4354
- const rows = storageDatabase.query("SELECT attachments FROM api_messages WHERE topic_id = ? AND deleted = 0 AND attachments IS NOT NULL").all(topicId);
4368
+ const rows = db.query("SELECT attachments FROM api_messages WHERE topic_id = ? AND deleted = 0 AND attachments IS NOT NULL").all(topicId);
4355
4369
  return rows.some((row) => attachmentListHasFileId(row.attachments, fileId));
4356
4370
  }
4357
4371
  function updateApiMessageText(topicId, messageId, text, editedAt = new Date().toISOString()) {
4358
- const res = storageDatabase.query(`UPDATE api_messages
4372
+ const res = db.query(`UPDATE api_messages
4359
4373
  SET text = ?, edited_at = ?
4360
4374
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(text, editedAt, topicId, messageId);
4361
4375
  if (Number(res.changes ?? 0) === 0)
@@ -4363,7 +4377,7 @@ function updateApiMessageText(topicId, messageId, text, editedAt = new Date().to
4363
4377
  return getApiMessage(topicId, messageId);
4364
4378
  }
4365
4379
  function updateApiMessageUsage(topicId, messageId, usage) {
4366
- const res = storageDatabase.query(`UPDATE api_messages
4380
+ const res = db.query(`UPDATE api_messages
4367
4381
  SET usage = ?
4368
4382
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(JSON.stringify(usage), topicId, messageId);
4369
4383
  if (Number(res.changes ?? 0) === 0)
@@ -4371,7 +4385,7 @@ function updateApiMessageUsage(topicId, messageId, usage) {
4371
4385
  return getApiMessage(topicId, messageId);
4372
4386
  }
4373
4387
  function updateApiMessageAskUserQuestion(topicId, messageId, askUserQuestion, editedAt = new Date().toISOString()) {
4374
- const res = storageDatabase.query(`UPDATE api_messages
4388
+ const res = db.query(`UPDATE api_messages
4375
4389
  SET ask_user_question = ?, edited_at = ?
4376
4390
  WHERE topic_id = ? AND id = ? AND deleted = 0 AND kind = 'ask_user_question'`).run(JSON.stringify(askUserQuestion), editedAt, topicId, messageId);
4377
4391
  if (Number(res.changes ?? 0) === 0)
@@ -4379,7 +4393,7 @@ function updateApiMessageAskUserQuestion(topicId, messageId, askUserQuestion, ed
4379
4393
  return getApiMessage(topicId, messageId);
4380
4394
  }
4381
4395
  function updateApiMessageSubagentCard(topicId, messageId, subagentCard, editedAt = new Date().toISOString()) {
4382
- const res = storageDatabase.query(`UPDATE api_messages
4396
+ const res = db.query(`UPDATE api_messages
4383
4397
  SET subagent_card = ?, edited_at = ?
4384
4398
  WHERE topic_id = ? AND id = ? AND deleted = 0 AND kind = 'subagent'`).run(JSON.stringify(subagentCard), editedAt, topicId, messageId);
4385
4399
  if (Number(res.changes ?? 0) === 0)
@@ -4387,11 +4401,11 @@ function updateApiMessageSubagentCard(topicId, messageId, subagentCard, editedAt
4387
4401
  return getApiMessage(topicId, messageId);
4388
4402
  }
4389
4403
  function listApiMessagesByKind(kind) {
4390
- const rows = storageDatabase.query("SELECT * FROM api_messages WHERE kind = ? AND deleted = 0").all(kind);
4404
+ const rows = db.query("SELECT * FROM api_messages WHERE kind = ? AND deleted = 0").all(kind);
4391
4405
  return rows.map(rowToDto);
4392
4406
  }
4393
4407
  function softDeleteApiMessage(topicId, messageId) {
4394
- const res = storageDatabase.query(`UPDATE api_messages
4408
+ const res = db.query(`UPDATE api_messages
4395
4409
  SET deleted = 1, text = ''
4396
4410
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(topicId, messageId);
4397
4411
  if (Number(res.changes ?? 0) === 0)
@@ -4399,10 +4413,10 @@ function softDeleteApiMessage(topicId, messageId) {
4399
4413
  return getApiMessage(topicId, messageId);
4400
4414
  }
4401
4415
  function getAllMessagesForTopic(topicId) {
4402
- return storageDatabase.query("SELECT *, rowid AS rowid FROM api_messages WHERE topic_id = ? AND deleted = 0 ORDER BY rowid ASC").all(topicId);
4416
+ return db.query("SELECT *, rowid AS rowid FROM api_messages WHERE topic_id = ? AND deleted = 0 ORDER BY rowid ASC").all(topicId);
4403
4417
  }
4404
4418
  function getMessagesForTopicAfterRowid(topicId, afterRowid) {
4405
- return storageDatabase.query("SELECT *, rowid AS rowid FROM api_messages WHERE topic_id = ? AND rowid > ? AND deleted = 0 ORDER BY rowid ASC").all(topicId, afterRowid);
4419
+ return db.query("SELECT *, rowid AS rowid FROM api_messages WHERE topic_id = ? AND rowid > ? AND deleted = 0 ORDER BY rowid ASC").all(topicId, afterRowid);
4406
4420
  }
4407
4421
  var appendHooks;
4408
4422
  var init_api_messages = __esm(async () => {
@@ -4414,11 +4428,11 @@ var init_api_messages = __esm(async () => {
4414
4428
 
4415
4429
  // ../../packages/core/src/storage/api-topic-config.ts
4416
4430
  function tableColumns(table) {
4417
- const rows = storageDatabase.query(`PRAGMA table_info(${table})`).all();
4431
+ const rows = db.query(`PRAGMA table_info(${table})`).all();
4418
4432
  return new Set(rows.map((row) => row.name));
4419
4433
  }
4420
4434
  function createCanonicalConfigTable(name = "api_topic_config") {
4421
- storageDatabase.exec(`
4435
+ db.exec(`
4422
4436
  CREATE TABLE IF NOT EXISTS ${name} (
4423
4437
  topic_id TEXT PRIMARY KEY REFERENCES api_topics(id) ON DELETE CASCADE,
4424
4438
  model TEXT,
@@ -4438,7 +4452,7 @@ function initializeApiTopicConfigSchema() {
4438
4452
  const topicColumns = tableColumns("api_topics");
4439
4453
  const agentColumn = topicColumns.has("agent") ? "agent" : topicColumns.has("runtime_agent") ? "runtime_agent" : null;
4440
4454
  if (agentColumn && existingConfigColumns.has("agent")) {
4441
- storageDatabase.exec(`UPDATE api_topics
4455
+ db.exec(`UPDATE api_topics
4442
4456
  SET ${agentColumn} = (
4443
4457
  SELECT c.agent FROM api_topic_config c WHERE c.topic_id = api_topics.id
4444
4458
  )
@@ -4448,15 +4462,15 @@ function initializeApiTopicConfigSchema() {
4448
4462
  WHERE c.topic_id = api_topics.id AND c.agent IS NOT NULL
4449
4463
  )`);
4450
4464
  }
4451
- const previousForeignKeys = storageDatabase.query("PRAGMA foreign_keys").get()?.foreign_keys;
4452
- storageDatabase.exec("PRAGMA foreign_keys = OFF");
4465
+ const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
4466
+ db.exec("PRAGMA foreign_keys = OFF");
4453
4467
  try {
4454
4468
  const agentLockSource = existingConfigColumns.has("runtime_locked") ? "runtime_locked" : existingConfigColumns.has("agent_pinned") ? "agent_pinned" : "0";
4455
4469
  const modelLockSource = existingConfigColumns.has("model_locked") ? "model_locked" : existingConfigColumns.has("model_pinned") ? "model_pinned" : "0";
4456
4470
  const effortLockSource = existingConfigColumns.has("effort_locked") ? "effort_locked" : existingConfigColumns.has("effort_pinned") ? "effort_pinned" : "0";
4457
- storageDatabase.transaction(() => {
4471
+ db.transaction(() => {
4458
4472
  createCanonicalConfigTable("api_topic_config_next");
4459
- storageDatabase.exec(`
4473
+ db.exec(`
4460
4474
  INSERT INTO api_topic_config_next
4461
4475
  (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
4462
4476
  SELECT
@@ -4470,11 +4484,11 @@ function initializeApiTopicConfigSchema() {
4470
4484
  FROM api_topic_config
4471
4485
  WHERE EXISTS (SELECT 1 FROM api_topics t WHERE t.id = api_topic_config.topic_id)
4472
4486
  `);
4473
- storageDatabase.exec("DROP TABLE api_topic_config");
4474
- storageDatabase.exec("ALTER TABLE api_topic_config_next RENAME TO api_topic_config");
4487
+ db.exec("DROP TABLE api_topic_config");
4488
+ db.exec("ALTER TABLE api_topic_config_next RENAME TO api_topic_config");
4475
4489
  })();
4476
4490
  } finally {
4477
- storageDatabase.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
4491
+ db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
4478
4492
  }
4479
4493
  } else {
4480
4494
  createCanonicalConfigTable();
@@ -4502,14 +4516,14 @@ function rowToConfig(r) {
4502
4516
  return cfg;
4503
4517
  }
4504
4518
  function getApiTopicConfig(topicId) {
4505
- const row = storageDatabase.query("SELECT topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked FROM api_topic_config WHERE topic_id = ?").get(topicId);
4519
+ const row = db.query("SELECT topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked FROM api_topic_config WHERE topic_id = ?").get(topicId);
4506
4520
  if (!row)
4507
4521
  return;
4508
4522
  const config = rowToConfig(row);
4509
4523
  return Object.keys(config).length > 0 ? config : undefined;
4510
4524
  }
4511
4525
  function setApiTopicConfig(topicId, config) {
4512
- storageDatabase.query(`INSERT INTO api_topic_config
4526
+ db.query(`INSERT INTO api_topic_config
4513
4527
  (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
4514
4528
  VALUES (?, ?, ?, ?, ?, ?, ?)
4515
4529
  ON CONFLICT(topic_id) DO UPDATE SET
@@ -4538,11 +4552,11 @@ var init_constants = __esm(() => {
4538
4552
 
4539
4553
  // ../../packages/core/src/storage/api-topics.ts
4540
4554
  function tableColumns2(table) {
4541
- const rows = storageDatabase.query(`PRAGMA table_info(${table})`).all();
4555
+ const rows = db.query(`PRAGMA table_info(${table})`).all();
4542
4556
  return new Set(rows.map((row) => row.name));
4543
4557
  }
4544
4558
  function initializeApiTopicsSchema() {
4545
- storageDatabase.exec(`
4559
+ db.exec(`
4546
4560
  CREATE TABLE IF NOT EXISTS api_topics (
4547
4561
  id TEXT PRIMARY KEY,
4548
4562
  title TEXT NOT NULL,
@@ -4564,56 +4578,56 @@ function initializeApiTopicsSchema() {
4564
4578
  const needsCanonicalTopicRebuild = legacyTopicSchema || !initialTopicColumns.has("agent");
4565
4579
  if (legacyTopicSchema) {
4566
4580
  try {
4567
- storageDatabase.exec("ALTER TABLE api_topics RENAME COLUMN default_agent TO agent");
4581
+ db.exec("ALTER TABLE api_topics RENAME COLUMN default_agent TO agent");
4568
4582
  } catch {}
4569
4583
  try {
4570
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN ai_mention INTEGER NOT NULL DEFAULT 0");
4584
+ db.exec("ALTER TABLE api_topics ADD COLUMN ai_mention INTEGER NOT NULL DEFAULT 0");
4571
4585
  } catch {}
4572
4586
  try {
4573
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN parent_topic_id TEXT");
4587
+ db.exec("ALTER TABLE api_topics ADD COLUMN parent_topic_id TEXT");
4574
4588
  } catch {}
4575
4589
  try {
4576
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN is_fork INTEGER NOT NULL DEFAULT 0");
4590
+ db.exec("ALTER TABLE api_topics ADD COLUMN is_fork INTEGER NOT NULL DEFAULT 0");
4577
4591
  } catch {}
4578
4592
  try {
4579
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN is_subagent INTEGER NOT NULL DEFAULT 0");
4593
+ db.exec("ALTER TABLE api_topics ADD COLUMN is_subagent INTEGER NOT NULL DEFAULT 0");
4580
4594
  } catch {}
4581
4595
  try {
4582
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN session_id TEXT");
4596
+ db.exec("ALTER TABLE api_topics ADD COLUMN session_id TEXT");
4583
4597
  } catch {}
4584
4598
  try {
4585
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN kind TEXT NOT NULL DEFAULT 'channel'");
4599
+ db.exec("ALTER TABLE api_topics ADD COLUMN kind TEXT NOT NULL DEFAULT 'channel'");
4586
4600
  } catch {}
4587
4601
  try {
4588
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN ai_mode TEXT");
4602
+ db.exec("ALTER TABLE api_topics ADD COLUMN ai_mode TEXT");
4589
4603
  } catch {}
4590
- storageDatabase.exec(`
4604
+ db.exec(`
4591
4605
  CREATE TABLE IF NOT EXISTS api_schema_migrations (
4592
4606
  key TEXT PRIMARY KEY,
4593
4607
  applied_at TEXT NOT NULL
4594
4608
  )
4595
4609
  `);
4596
4610
  const ALWAYS_RESPOND_MIGRATION = "api_topics_ai_invited_default_always_respond_20260623";
4597
- const alwaysRespondMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(ALWAYS_RESPOND_MIGRATION);
4611
+ const alwaysRespondMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(ALWAYS_RESPOND_MIGRATION);
4598
4612
  if (!alwaysRespondMigration) {
4599
- storageDatabase.transaction(() => {
4600
- storageDatabase.query("UPDATE api_topics SET ai_mention = 0 WHERE agent IS NOT NULL").run();
4601
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(ALWAYS_RESPOND_MIGRATION, new Date().toISOString());
4613
+ db.transaction(() => {
4614
+ db.query("UPDATE api_topics SET ai_mention = 0 WHERE agent IS NOT NULL").run();
4615
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(ALWAYS_RESPOND_MIGRATION, new Date().toISOString());
4602
4616
  })();
4603
4617
  }
4604
4618
  const GENERAL_AGENT_KIND_MIGRATION = "api_topics_general_agent_kind_20260704";
4605
- const generalAgentKindMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_AGENT_KIND_MIGRATION);
4619
+ const generalAgentKindMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_AGENT_KIND_MIGRATION);
4606
4620
  if (!generalAgentKindMigration) {
4607
- storageDatabase.transaction(() => {
4608
- storageDatabase.query("UPDATE api_topics SET kind = 'agent', ai_mention = 0 WHERE id = ?").run(GENERAL_TOPIC_ID);
4609
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_AGENT_KIND_MIGRATION, new Date().toISOString());
4621
+ db.transaction(() => {
4622
+ db.query("UPDATE api_topics SET kind = 'agent', ai_mention = 0 WHERE id = ?").run(GENERAL_TOPIC_ID);
4623
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_AGENT_KIND_MIGRATION, new Date().toISOString());
4610
4624
  })();
4611
4625
  }
4612
4626
  const AI_MODE_MIGRATION = "api_topics_ai_mode_20260704";
4613
- const aiModeMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(AI_MODE_MIGRATION);
4627
+ const aiModeMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(AI_MODE_MIGRATION);
4614
4628
  if (!aiModeMigration) {
4615
- storageDatabase.transaction(() => {
4616
- storageDatabase.query(`UPDATE api_topics
4629
+ db.transaction(() => {
4630
+ db.query(`UPDATE api_topics
4617
4631
  SET
4618
4632
  kind = CASE
4619
4633
  WHEN id = ? THEN 'agent'
@@ -4629,20 +4643,20 @@ function initializeApiTopicsSchema() {
4629
4643
  WHEN ai_mention != 0 THEN 'mention'
4630
4644
  ELSE 'always'
4631
4645
  END`).run(GENERAL_TOPIC_ID, GENERAL_TOPIC_ID);
4632
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(AI_MODE_MIGRATION, new Date().toISOString());
4646
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(AI_MODE_MIGRATION, new Date().toISOString());
4633
4647
  })();
4634
4648
  }
4635
4649
  const GENERAL_MANAGER_KIND_MIGRATION = "api_topics_general_manager_kind_20260704";
4636
- const generalManagerKindMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_MANAGER_KIND_MIGRATION);
4650
+ const generalManagerKindMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_MANAGER_KIND_MIGRATION);
4637
4651
  if (!generalManagerKindMigration) {
4638
- storageDatabase.transaction(() => {
4639
- storageDatabase.query("UPDATE api_topics SET kind = 'manager', ai_mention = 0, ai_mode = 'always' WHERE id = ?").run(GENERAL_TOPIC_ID);
4640
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_MANAGER_KIND_MIGRATION, new Date().toISOString());
4652
+ db.transaction(() => {
4653
+ db.query("UPDATE api_topics SET kind = 'manager', ai_mention = 0, ai_mode = 'always' WHERE id = ?").run(GENERAL_TOPIC_ID);
4654
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_MANAGER_KIND_MIGRATION, new Date().toISOString());
4641
4655
  })();
4642
4656
  }
4643
4657
  }
4644
4658
  function createCanonicalTopicsTable(name) {
4645
- storageDatabase.exec(`
4659
+ db.exec(`
4646
4660
  CREATE TABLE IF NOT EXISTS ${name} (
4647
4661
  id TEXT PRIMARY KEY,
4648
4662
  title TEXT NOT NULL,
@@ -4671,7 +4685,7 @@ function initializeApiTopicsSchema() {
4671
4685
  `);
4672
4686
  }
4673
4687
  function createTopicMembersTable() {
4674
- storageDatabase.exec(`
4688
+ db.exec(`
4675
4689
  CREATE TABLE IF NOT EXISTS topic_members (
4676
4690
  topic_id TEXT NOT NULL REFERENCES api_topics(id) ON DELETE CASCADE,
4677
4691
  user_id TEXT NOT NULL,
@@ -4679,17 +4693,17 @@ function initializeApiTopicsSchema() {
4679
4693
  PRIMARY KEY (topic_id, user_id)
4680
4694
  )
4681
4695
  `);
4682
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_topic_members_user ON topic_members(user_id)");
4696
+ db.exec("CREATE INDEX IF NOT EXISTS idx_topic_members_user ON topic_members(user_id)");
4683
4697
  }
4684
4698
  if (needsCanonicalTopicRebuild) {
4685
- const legacyRows = storageDatabase.query("SELECT * FROM api_topics").all();
4686
- const existingMemberRows = tableColumns2("topic_members").has("topic_id") ? storageDatabase.query("SELECT topic_id, user_id, role FROM topic_members").all() : [];
4699
+ const legacyRows = db.query("SELECT * FROM api_topics").all();
4700
+ const existingMemberRows = tableColumns2("topic_members").has("topic_id") ? db.query("SELECT topic_id, user_id, role FROM topic_members").all() : [];
4687
4701
  const configColumns = tableColumns2("api_topic_config");
4688
- const legacyAgentOverrides = configColumns.has("agent") ? new Map(storageDatabase.query("SELECT topic_id, agent FROM api_topic_config WHERE agent IS NOT NULL").all().map((row) => [row.topic_id, row.agent])) : new Map;
4689
- const previousForeignKeys = storageDatabase.query("PRAGMA foreign_keys").get()?.foreign_keys;
4690
- storageDatabase.exec("PRAGMA foreign_keys = OFF");
4702
+ const legacyAgentOverrides = configColumns.has("agent") ? new Map(db.query("SELECT topic_id, agent FROM api_topic_config WHERE agent IS NOT NULL").all().map((row) => [row.topic_id, row.agent])) : new Map;
4703
+ const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
4704
+ db.exec("PRAGMA foreign_keys = OFF");
4691
4705
  try {
4692
- storageDatabase.transaction(() => {
4706
+ db.transaction(() => {
4693
4707
  createCanonicalTopicsTable("api_topics_next");
4694
4708
  for (const row of legacyRows) {
4695
4709
  const selectedAgent = legacyAgentOverrides.get(String(row.id)) ?? row.agent ?? row.runtime_agent ?? row.default_agent ?? undefined;
@@ -4702,18 +4716,18 @@ function initializeApiTopicsSchema() {
4702
4716
  });
4703
4717
  const legacyBaseModel = row.base_model ?? row.default_model;
4704
4718
  const legacyBaseEffort = row.base_effort ?? row.default_effort;
4705
- storageDatabase.query(`INSERT INTO api_topics_next
4719
+ db.query(`INSERT INTO api_topics_next
4706
4720
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
4707
4721
  created_at,last_message_at,parent_topic_id,is_fork,is_subagent,visibility,access_mode,session_id)
4708
4722
  VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(String(row.id), String(row.title), normalized.kind, typeof row.description === "string" ? row.description : null, normalized.agent ?? null, typeof legacyBaseModel === "string" ? legacyBaseModel : null, typeof legacyBaseEffort === "string" ? legacyBaseEffort : null, normalized.aiMode, String(row.created_at), typeof row.last_message_at === "string" ? row.last_message_at : null, typeof row.parent_topic_id === "string" ? row.parent_topic_id : null, Number(row.is_fork ?? 0) !== 0 ? 1 : 0, Number(row.is_subagent ?? 0) !== 0 ? 1 : 0, row.visibility === "hidden" ? "hidden" : "visible", row.access_mode === "shared" ? "shared" : "private", typeof row.session_id === "string" ? row.session_id : null);
4709
4723
  }
4710
- storageDatabase.exec("DROP TABLE IF EXISTS topic_members");
4711
- storageDatabase.exec("DROP TABLE api_topics");
4712
- storageDatabase.exec("ALTER TABLE api_topics_next RENAME TO api_topics");
4724
+ db.exec("DROP TABLE IF EXISTS topic_members");
4725
+ db.exec("DROP TABLE api_topics");
4726
+ db.exec("ALTER TABLE api_topics_next RENAME TO api_topics");
4713
4727
  createTopicMembersTable();
4714
4728
  if (existingMemberRows.length > 0) {
4715
4729
  for (const member of existingMemberRows) {
4716
- storageDatabase.query("INSERT OR REPLACE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(member.topic_id, member.user_id, member.role === "owner" ? "owner" : "member");
4730
+ db.query("INSERT OR REPLACE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(member.topic_id, member.user_id, member.role === "owner" ? "owner" : "member");
4717
4731
  }
4718
4732
  } else {
4719
4733
  for (const row of legacyRows) {
@@ -4728,31 +4742,31 @@ function initializeApiTopicsSchema() {
4728
4742
  for (const participant of participants) {
4729
4743
  if (!participant?.userId)
4730
4744
  continue;
4731
- storageDatabase.query("INSERT OR REPLACE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(String(row.id), participant.userId, participant.role === "owner" ? "owner" : "member");
4745
+ db.query("INSERT OR REPLACE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(String(row.id), participant.userId, participant.role === "owner" ? "owner" : "member");
4732
4746
  }
4733
4747
  }
4734
4748
  }
4735
4749
  })();
4736
4750
  } finally {
4737
- storageDatabase.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
4751
+ db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
4738
4752
  }
4739
4753
  } else {
4740
4754
  createCanonicalTopicsTable("api_topics");
4741
4755
  createTopicMembersTable();
4742
4756
  }
4743
4757
  if (!tableColumns2("api_topics").has("visibility")) {
4744
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
4758
+ db.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
4745
4759
  }
4746
4760
  if (!tableColumns2("api_topics").has("access_mode")) {
4747
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN access_mode TEXT NOT NULL DEFAULT 'private'");
4761
+ db.exec("ALTER TABLE api_topics ADD COLUMN access_mode TEXT NOT NULL DEFAULT 'private'");
4748
4762
  }
4749
4763
  if (!tableColumns2("api_topics").has("browser_profile")) {
4750
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
4764
+ db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
4751
4765
  }
4752
4766
  if (!tableColumns2("api_topics").has("browser_profile_owner")) {
4753
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
4767
+ db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
4754
4768
  }
4755
- storageDatabase.exec(`
4769
+ db.exec(`
4756
4770
  UPDATE api_topics
4757
4771
  SET browser_profile_owner = (
4758
4772
  SELECT m.user_id FROM topic_members m
@@ -4762,16 +4776,17 @@ function initializeApiTopicsSchema() {
4762
4776
  )
4763
4777
  WHERE browser_profile_owner IS NULL
4764
4778
  `);
4779
+ db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_last_message ON api_topics(last_message_at DESC)");
4765
4780
  }
4766
4781
  function shortSessionId(sessionId) {
4767
4782
  return sessionId ? sessionId.slice(0, 8) : null;
4768
4783
  }
4769
4784
  function getTopicParticipants(topicId) {
4770
- return storageDatabase.query("SELECT user_id, role FROM topic_members WHERE topic_id = ? ORDER BY rowid").all(topicId).map((row) => ({ userId: row.user_id, role: row.role }));
4785
+ return db.query("SELECT user_id, role FROM topic_members WHERE topic_id = ? ORDER BY rowid").all(topicId).map((row) => ({ userId: row.user_id, role: row.role }));
4771
4786
  }
4772
4787
  function getAllTopicParticipants() {
4773
4788
  const grouped = new Map;
4774
- const rows = storageDatabase.query("SELECT topic_id, user_id, role FROM topic_members ORDER BY rowid").all();
4789
+ const rows = db.query("SELECT topic_id, user_id, role FROM topic_members ORDER BY rowid").all();
4775
4790
  for (const row of rows) {
4776
4791
  const participants = grouped.get(row.topic_id) ?? [];
4777
4792
  participants.push({ userId: row.user_id, role: row.role });
@@ -4853,8 +4868,8 @@ function upsertTopic(t) {
4853
4868
  aiMode: normalizeAiMode(t.aiMode),
4854
4869
  aiMention: t.aiMention
4855
4870
  });
4856
- storageDatabase.transaction(() => {
4857
- storageDatabase.query(`INSERT INTO api_topics
4871
+ db.transaction(() => {
4872
+ db.query(`INSERT INTO api_topics
4858
4873
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
4859
4874
  created_at,last_message_at,parent_topic_id,is_fork,is_subagent,visibility,access_mode)
4860
4875
  VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
@@ -4873,29 +4888,29 @@ function upsertTopic(t) {
4873
4888
  is_subagent = excluded.is_subagent,
4874
4889
  visibility = excluded.visibility,
4875
4890
  access_mode = excluded.access_mode`).run(t.id, t.title, normalized.kind, t.description ?? null, normalized.agent ?? null, t.defaultModel ?? null, t.defaultEffort ?? null, normalized.aiMode, t.createdAt, t.lastMessageAt ?? null, t.parentTopicId ?? null, t.isFork ? 1 : 0, t.isSubagent ? 1 : 0, normalizeTopicVisibility(t.visibility), normalizeTopicAccessMode(t.accessMode));
4876
- storageDatabase.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
4891
+ db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
4877
4892
  for (const participant of t.participants) {
4878
- storageDatabase.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
4893
+ db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
4879
4894
  }
4880
4895
  const initialBrowserProfileOwner = t.participants.find((participant) => participant.role === "owner")?.userId;
4881
4896
  if (initialBrowserProfileOwner) {
4882
- storageDatabase.query(`UPDATE api_topics
4897
+ db.query(`UPDATE api_topics
4883
4898
  SET browser_profile_owner = COALESCE(browser_profile_owner, ?)
4884
4899
  WHERE id = ?`).run(initialBrowserProfileOwner, t.id);
4885
4900
  }
4886
4901
  })();
4887
4902
  }
4888
4903
  function listTopics() {
4889
- const rows = storageDatabase.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
4904
+ const rows = db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
4890
4905
  const participants = getAllTopicParticipants();
4891
4906
  return rows.map((row) => rowToDto2(row, participants.get(row.id) ?? []));
4892
4907
  }
4893
4908
  function getTopic(id) {
4894
- const r = storageDatabase.query("SELECT * FROM api_topics WHERE id = ?").get(id);
4909
+ const r = db.query("SELECT * FROM api_topics WHERE id = ?").get(id);
4895
4910
  return r ? rowToDto2(r) : null;
4896
4911
  }
4897
4912
  function getManagerTopicForUser(userId) {
4898
- const row = storageDatabase.query(`SELECT t.* FROM api_topics t
4913
+ const row = db.query(`SELECT t.* FROM api_topics t
4899
4914
  JOIN topic_members m ON m.topic_id = t.id
4900
4915
  WHERE t.kind = 'manager'
4901
4916
  AND t.id != ?
@@ -4921,7 +4936,7 @@ function getTopicMemoryOrigin(id) {
4921
4936
  }
4922
4937
  function setTopicSessionId(topicId, sessionId, context = {}) {
4923
4938
  const previous = getTopicSessionId(topicId);
4924
- const result = storageDatabase.query("UPDATE api_topics SET session_id = ? WHERE id = ?").run(sessionId, topicId);
4939
+ const result = db.query("UPDATE api_topics SET session_id = ? WHERE id = ?").run(sessionId, topicId);
4925
4940
  const changes = Number(result.changes ?? 0);
4926
4941
  const logContext = {
4927
4942
  topicId,
@@ -4941,7 +4956,7 @@ function setTopicSessionId(topicId, sessionId, context = {}) {
4941
4956
  }
4942
4957
  function clearTopicSessionId(topicId, reason = "unspecified") {
4943
4958
  const previous = getTopicSessionId(topicId);
4944
- const result = storageDatabase.query("UPDATE api_topics SET session_id = NULL WHERE id = ?").run(topicId);
4959
+ const result = db.query("UPDATE api_topics SET session_id = NULL WHERE id = ?").run(topicId);
4945
4960
  const changes = Number(result.changes ?? 0);
4946
4961
  const logContext = { topicId, previousSessionId: shortSessionId(previous), reason };
4947
4962
  if (changes === 0) {
@@ -4953,7 +4968,7 @@ function clearTopicSessionId(topicId, reason = "unspecified") {
4953
4968
  }
4954
4969
  }
4955
4970
  function getTopicSessionId(topicId) {
4956
- const r = storageDatabase.query("SELECT session_id FROM api_topics WHERE id = ?").get(topicId);
4971
+ const r = db.query("SELECT session_id FROM api_topics WHERE id = ?").get(topicId);
4957
4972
  return r?.session_id ?? null;
4958
4973
  }
4959
4974
  var DEFAULT_AGENT_ROOM_AGENT = "maestro";
@@ -5121,7 +5136,7 @@ function rowToState(row, now = Date.now()) {
5121
5136
  };
5122
5137
  }
5123
5138
  function getRuntimeTopicState(topicId, now = Date.now()) {
5124
- const row = storageDatabase.query("SELECT * FROM runtime_topic_state WHERE topic_id = ?").get(topicId);
5139
+ const row = db.query("SELECT * FROM runtime_topic_state WHERE topic_id = ?").get(topicId);
5125
5140
  return row ? rowToState(row, now) : { topicId, epoch: 0, maintenance: false };
5126
5141
  }
5127
5142
  function getRuntimeTopicEpoch(topicId) {
@@ -5133,7 +5148,7 @@ function isRuntimeTopicMaintenance(topicId, now = Date.now()) {
5133
5148
  var TOPIC_MAINTENANCE_STALE_MS = 30000;
5134
5149
  var init_runtime_topic_state = __esm(async () => {
5135
5150
  await init_forum_db();
5136
- storageDatabase.exec(`
5151
+ db.exec(`
5137
5152
  CREATE TABLE IF NOT EXISTS runtime_topic_state (
5138
5153
  topic_id TEXT PRIMARY KEY,
5139
5154
  epoch INTEGER NOT NULL DEFAULT 0,
@@ -5160,18 +5175,18 @@ function rowToLease(row) {
5160
5175
  };
5161
5176
  }
5162
5177
  function getRuntimeTurnLease(topicId, now = Date.now()) {
5163
- const row = storageDatabase.query("SELECT * FROM runtime_turn_leases WHERE topic_id = ?").get(topicId);
5178
+ const row = db.query("SELECT * FROM runtime_turn_leases WHERE topic_id = ?").get(topicId);
5164
5179
  if (!row)
5165
5180
  return null;
5166
5181
  const lease = rowToLease(row);
5167
5182
  return now - lease.heartbeatAt <= TURN_LEASE_STALE_MS ? lease : null;
5168
5183
  }
5169
5184
  function listRuntimeTurnLeases(now = Date.now()) {
5170
- return storageDatabase.query("SELECT * FROM runtime_turn_leases ORDER BY started_at ASC").all().map(rowToLease).filter((lease) => now - lease.heartbeatAt <= TURN_LEASE_STALE_MS);
5185
+ return db.query("SELECT * FROM runtime_turn_leases ORDER BY started_at ASC").all().map(rowToLease).filter((lease) => now - lease.heartbeatAt <= TURN_LEASE_STALE_MS);
5171
5186
  }
5172
5187
  function claimRuntimeTurnLease(input, now = Date.now()) {
5173
5188
  const ownerId = input.ownerId ?? RUNTIME_INSTANCE_ID;
5174
- const result = storageDatabase.query(`INSERT INTO runtime_turn_leases
5189
+ const result = db.query(`INSERT INTO runtime_turn_leases
5175
5190
  (topic_id, query_id, owner_id, origin, started_at, heartbeat_at, abort_requested, abort_reason)
5176
5191
  SELECT ?, ?, ?, ?, ?, ?, 0, NULL
5177
5192
  WHERE NOT EXISTS (
@@ -5195,12 +5210,12 @@ function claimRuntimeTurnLease(input, now = Date.now()) {
5195
5210
  return Number(result.changes ?? 0) > 0;
5196
5211
  }
5197
5212
  function heartbeatRuntimeTurnLease(topicId, queryId, ownerId = RUNTIME_INSTANCE_ID, now = Date.now()) {
5198
- const updated = storageDatabase.query(`UPDATE runtime_turn_leases
5213
+ const updated = db.query(`UPDATE runtime_turn_leases
5199
5214
  SET heartbeat_at = ?
5200
5215
  WHERE topic_id = ? AND query_id = ? AND owner_id = ?`).run(now, topicId, queryId, ownerId);
5201
5216
  if (Number(updated.changes ?? 0) === 0)
5202
5217
  return { owned: false, abortRequested: false };
5203
- const row = storageDatabase.query(`SELECT abort_requested, abort_reason
5218
+ const row = db.query(`SELECT abort_requested, abort_reason
5204
5219
  FROM runtime_turn_leases
5205
5220
  WHERE topic_id = ? AND query_id = ? AND owner_id = ?`).get(topicId, queryId, ownerId);
5206
5221
  const abortReason = row?.abort_reason === "internal" || row?.abort_reason === "external" ? row.abort_reason : undefined;
@@ -5211,7 +5226,7 @@ function heartbeatRuntimeTurnLease(topicId, queryId, ownerId = RUNTIME_INSTANCE_
5211
5226
  };
5212
5227
  }
5213
5228
  function requestRuntimeTurnAbort(topicId, reason) {
5214
- const result = storageDatabase.query(`UPDATE runtime_turn_leases
5229
+ const result = db.query(`UPDATE runtime_turn_leases
5215
5230
  SET abort_requested = 1,
5216
5231
  abort_reason = CASE
5217
5232
  WHEN abort_reason = 'external' THEN abort_reason
@@ -5221,7 +5236,7 @@ function requestRuntimeTurnAbort(topicId, reason) {
5221
5236
  return Number(result.changes ?? 0) > 0;
5222
5237
  }
5223
5238
  function releaseRuntimeTurnLease(topicId, queryId, ownerId = RUNTIME_INSTANCE_ID) {
5224
- const result = storageDatabase.query(`DELETE FROM runtime_turn_leases
5239
+ const result = db.query(`DELETE FROM runtime_turn_leases
5225
5240
  WHERE topic_id = ? AND query_id = ? AND owner_id = ?`).run(topicId, queryId, ownerId);
5226
5241
  return Number(result.changes ?? 0) > 0;
5227
5242
  }
@@ -5230,7 +5245,7 @@ var init_runtime_leases = __esm(async () => {
5230
5245
  await init_forum_db();
5231
5246
  await init_runtime_topic_state();
5232
5247
  RUNTIME_INSTANCE_ID = `${process.pid}-${randomUUID3()}`;
5233
- storageDatabase.exec(`
5248
+ db.exec(`
5234
5249
  CREATE TABLE IF NOT EXISTS runtime_turn_leases (
5235
5250
  topic_id TEXT PRIMARY KEY,
5236
5251
  query_id TEXT NOT NULL UNIQUE,
@@ -5242,7 +5257,7 @@ var init_runtime_leases = __esm(async () => {
5242
5257
  abort_reason TEXT CHECK (abort_reason IS NULL OR abort_reason IN ('internal', 'external'))
5243
5258
  )
5244
5259
  `);
5245
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_runtime_turn_leases_heartbeat ON runtime_turn_leases(heartbeat_at)");
5260
+ db.exec("CREATE INDEX IF NOT EXISTS idx_runtime_turn_leases_heartbeat ON runtime_turn_leases(heartbeat_at)");
5246
5261
  });
5247
5262
 
5248
5263
  // ../../packages/core/src/storage/self-schedules.ts
@@ -5250,7 +5265,7 @@ var init_self_schedules = __esm(async () => {
5250
5265
  await init_forum_db();
5251
5266
  await init_runtime_leases();
5252
5267
  await init_runtime_topic_state();
5253
- storageDatabase.exec(`
5268
+ db.exec(`
5254
5269
  CREATE TABLE IF NOT EXISTS runtime_self_schedules (
5255
5270
  id TEXT PRIMARY KEY,
5256
5271
  topic_id TEXT NOT NULL,
@@ -5265,12 +5280,12 @@ var init_self_schedules = __esm(async () => {
5265
5280
  running_query_id TEXT
5266
5281
  )
5267
5282
  `);
5268
- storageDatabase.exec(`
5283
+ db.exec(`
5269
5284
  CREATE UNIQUE INDEX IF NOT EXISTS idx_runtime_self_schedules_one_pending
5270
5285
  ON runtime_self_schedules(topic_id)
5271
5286
  WHERE status = 'pending'
5272
5287
  `);
5273
- storageDatabase.exec(`
5288
+ db.exec(`
5274
5289
  CREATE INDEX IF NOT EXISTS idx_runtime_self_schedules_due
5275
5290
  ON runtime_self_schedules(status, deliver_at)
5276
5291
  `);
@@ -5288,23 +5303,23 @@ function normalizeBrowserProfileName(name) {
5288
5303
  return value;
5289
5304
  }
5290
5305
  function getBrowserProfileOwner(topicId, fallbackUserId) {
5291
- return storageDatabase.query("SELECT browser_profile_owner FROM api_topics WHERE id = ?").get(topicId)?.browser_profile_owner ?? fallbackUserId;
5306
+ return db.query("SELECT browser_profile_owner FROM api_topics WHERE id = ?").get(topicId)?.browser_profile_owner ?? fallbackUserId;
5292
5307
  }
5293
5308
  function isTopicBrowserProfileOwner(topicId, userId) {
5294
5309
  return getBrowserProfileOwner(topicId, "") === userId;
5295
5310
  }
5296
5311
  function getTopicBrowserProfile(topicId) {
5297
- const value = storageDatabase.query("SELECT browser_profile FROM api_topics WHERE id = ?").get(topicId)?.browser_profile;
5312
+ const value = db.query("SELECT browser_profile FROM api_topics WHERE id = ?").get(topicId)?.browser_profile;
5298
5313
  return value || DEFAULT_BROWSER_PROFILE;
5299
5314
  }
5300
5315
  function hasBrowserProfileTopic(topicId) {
5301
- return Boolean(storageDatabase.query("SELECT id FROM api_topics WHERE id = ?").get(topicId));
5316
+ return Boolean(db.query("SELECT id FROM api_topics WHERE id = ?").get(topicId));
5302
5317
  }
5303
5318
  function createBrowserProfile(ownerId, rawName) {
5304
5319
  const name = normalizeBrowserProfileName(rawName);
5305
5320
  if (name === DEFAULT_BROWSER_PROFILE)
5306
5321
  return name;
5307
- storageDatabase.query("INSERT OR IGNORE INTO browser_profiles (owner_id, name, created_at) VALUES (?, ?, ?)").run(ownerId, name, new Date().toISOString());
5322
+ db.query("INSERT OR IGNORE INTO browser_profiles (owner_id, name, created_at) VALUES (?, ?, ?)").run(ownerId, name, new Date().toISOString());
5308
5323
  return name;
5309
5324
  }
5310
5325
  function assignTopicBrowserProfile(opts) {
@@ -5318,7 +5333,7 @@ function assignTopicBrowserProfile(opts) {
5318
5333
  if (profile !== DEFAULT_BROWSER_PROFILE)
5319
5334
  createBrowserProfile(actualOwner, profile);
5320
5335
  const previous = getTopicBrowserProfile(opts.topicId);
5321
- const result = storageDatabase.query("UPDATE api_topics SET browser_profile = ? WHERE id = ?").run(profile, opts.topicId);
5336
+ const result = db.query("UPDATE api_topics SET browser_profile = ? WHERE id = ?").run(profile, opts.topicId);
5322
5337
  if (Number(result.changes ?? 0) !== 1)
5323
5338
  throw new Error(`Topic "${opts.topicId}" not found.`);
5324
5339
  return { previous, profile };
@@ -5326,7 +5341,7 @@ function assignTopicBrowserProfile(opts) {
5326
5341
  var DEFAULT_BROWSER_PROFILE = "default";
5327
5342
  var init_browser_profiles = __esm(async () => {
5328
5343
  await init_forum_db();
5329
- storageDatabase.exec(`
5344
+ db.exec(`
5330
5345
  CREATE TABLE IF NOT EXISTS browser_profiles (
5331
5346
  owner_id TEXT NOT NULL,
5332
5347
  name TEXT NOT NULL,
@@ -6304,7 +6319,7 @@ function enqueueRuntimeUserTurnRequest(input) {
6304
6319
  const requestId = input.requestId ?? randomUUID5();
6305
6320
  const now = Date.now();
6306
6321
  const topicEpoch = input.topicEpoch ?? getRuntimeTopicEpoch(input.topicId);
6307
- storageDatabase.query(`INSERT INTO runtime_user_turn_requests
6322
+ db.query(`INSERT INTO runtime_user_turn_requests
6308
6323
  (topic_id, request_id, user_id, prompt, attachments_json,
6309
6324
  allow_auto_continue, execution_json, topic_epoch, created_at,
6310
6325
  status, claimed_by, claimed_at, running_query_id)
@@ -6325,8 +6340,8 @@ function enqueueRuntimeUserTurnRequest(input) {
6325
6340
  return requestId;
6326
6341
  }
6327
6342
  function claimNextRuntimeUserTurnRequest(ownerId, now = Date.now()) {
6328
- return storageDatabase.transaction(() => {
6329
- const row = storageDatabase.query(`SELECT r.*
6343
+ return db.transaction(() => {
6344
+ const row = db.query(`SELECT r.*
6330
6345
  FROM runtime_user_turn_requests r
6331
6346
  LEFT JOIN runtime_turn_leases l ON l.topic_id = r.topic_id
6332
6347
  LEFT JOIN runtime_topic_state s ON s.topic_id = r.topic_id
@@ -6341,7 +6356,7 @@ function claimNextRuntimeUserTurnRequest(ownerId, now = Date.now()) {
6341
6356
  LIMIT 1`).get(now - TURN_LEASE_STALE_MS, now - TOPIC_MAINTENANCE_STALE_MS, now - REQUEST_CLAIM_STALE_MS, now - REQUEST_CLAIM_STALE_MS);
6342
6357
  if (!row)
6343
6358
  return null;
6344
- const updated = storageDatabase.query(`UPDATE runtime_user_turn_requests
6359
+ const updated = db.query(`UPDATE runtime_user_turn_requests
6345
6360
  SET claimed_by = ?, claimed_at = ?
6346
6361
  WHERE topic_id = ? AND request_id = ?
6347
6362
  AND (
@@ -6354,23 +6369,23 @@ function claimNextRuntimeUserTurnRequest(ownerId, now = Date.now()) {
6354
6369
  }).immediate();
6355
6370
  }
6356
6371
  function markRuntimeUserTurnRunning(topicId, requestId, ownerId, queryId) {
6357
- const result = storageDatabase.query(`UPDATE runtime_user_turn_requests
6372
+ const result = db.query(`UPDATE runtime_user_turn_requests
6358
6373
  SET status = 'running', running_query_id = ?, claimed_at = ?
6359
6374
  WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(queryId, Date.now(), topicId, requestId, ownerId);
6360
6375
  return Number(result.changes ?? 0) > 0;
6361
6376
  }
6362
6377
  function releaseRuntimeUserTurnClaim(topicId, requestId, ownerId) {
6363
- const result = storageDatabase.query(`UPDATE runtime_user_turn_requests
6378
+ const result = db.query(`UPDATE runtime_user_turn_requests
6364
6379
  SET status = 'pending', claimed_by = NULL, claimed_at = NULL, running_query_id = NULL
6365
6380
  WHERE topic_id = ? AND request_id = ? AND claimed_by = ?`).run(topicId, requestId, ownerId);
6366
6381
  return Number(result.changes ?? 0) > 0;
6367
6382
  }
6368
6383
  function completeRuntimeUserTurnRequest(topicId, requestId) {
6369
- const result = storageDatabase.query("DELETE FROM runtime_user_turn_requests WHERE topic_id = ? AND request_id = ?").run(topicId, requestId);
6384
+ const result = db.query("DELETE FROM runtime_user_turn_requests WHERE topic_id = ? AND request_id = ?").run(topicId, requestId);
6370
6385
  return Number(result.changes ?? 0) > 0;
6371
6386
  }
6372
6387
  function getRuntimeUserTurnRequest(topicId) {
6373
- const row = storageDatabase.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ?").get(topicId);
6388
+ const row = db.query("SELECT * FROM runtime_user_turn_requests WHERE topic_id = ?").get(topicId);
6374
6389
  return row ? rowToRequest(row) : null;
6375
6390
  }
6376
6391
  var REQUEST_CLAIM_STALE_MS;
@@ -6379,7 +6394,7 @@ var init_runtime_turn_requests = __esm(async () => {
6379
6394
  await init_runtime_leases();
6380
6395
  await init_runtime_topic_state();
6381
6396
  REQUEST_CLAIM_STALE_MS = TURN_LEASE_STALE_MS;
6382
- storageDatabase.exec(`
6397
+ db.exec(`
6383
6398
  CREATE TABLE IF NOT EXISTS runtime_user_turn_requests (
6384
6399
  topic_id TEXT PRIMARY KEY,
6385
6400
  request_id TEXT NOT NULL UNIQUE,
@@ -6397,12 +6412,12 @@ var init_runtime_turn_requests = __esm(async () => {
6397
6412
  )
6398
6413
  `);
6399
6414
  try {
6400
- storageDatabase.exec("ALTER TABLE runtime_user_turn_requests ADD COLUMN execution_json TEXT");
6415
+ db.exec("ALTER TABLE runtime_user_turn_requests ADD COLUMN execution_json TEXT");
6401
6416
  } catch {}
6402
6417
  try {
6403
- storageDatabase.exec("ALTER TABLE runtime_user_turn_requests ADD COLUMN topic_epoch INTEGER NOT NULL DEFAULT 0");
6418
+ db.exec("ALTER TABLE runtime_user_turn_requests ADD COLUMN topic_epoch INTEGER NOT NULL DEFAULT 0");
6404
6419
  } catch {}
6405
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_runtime_user_turn_requests_ready ON runtime_user_turn_requests(status, created_at)");
6420
+ db.exec("CREATE INDEX IF NOT EXISTS idx_runtime_user_turn_requests_ready ON runtime_user_turn_requests(status, created_at)");
6406
6421
  });
6407
6422
 
6408
6423
  // ../../packages/core/src/prompts/builders.ts
@@ -6483,7 +6498,7 @@ function loadAgentPrompt(filename) {
6483
6498
  prompt: match[2].trim()
6484
6499
  };
6485
6500
  }
6486
- function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualTools = false) {
6501
+ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualTools = false, fileDeliveryTools = false) {
6487
6502
  const runtimeNamespace = "mcp__runtime";
6488
6503
  const taskNamespace = "mcp__task";
6489
6504
  const visualToolLine = agentKind === "codex" ? `To display charts, tables, or interactive HTML results to the user, call the \`show_html\` function in the \`${runtimeNamespace}\` namespace with { html: "<complete HTML string>", title?: "optional title" }.` : `To display charts, tables, or interactive HTML results to the user, call the MCP tool "${runtimeNamespace}__show_html" with { html: "<complete HTML string>", title?: "optional title" }.`;
@@ -6510,6 +6525,12 @@ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualToo
6510
6525
  'Do not call a bare "show_html"; use the exposed visuals MCP tool. A successful call means the card was shown in the user chat.',
6511
6526
  "Visual HTML runs in a sandbox. Use inline CSS/JS only; local buttons, tabs, filters, forms with preventDefault, canvas, and SVG interactions are supported. External navigation, scripts, network fetches, form posts, popups, and parent-window access are blocked."
6512
6527
  ] : [];
6528
+ const fileDeliverySection = fileDeliveryTools ? [
6529
+ "",
6530
+ "## File Delivery",
6531
+ `To send a file to the user, save it under your working directory and call the ${sendFileTool} with { file_path: "<absolute path>" }.`,
6532
+ "It appears as a downloadable attachment in the chat and returns success. Never claim file delivery is unavailable after a successful call."
6533
+ ] : [];
6513
6534
  const shared = [
6514
6535
  "",
6515
6536
  "",
@@ -6524,10 +6545,7 @@ function buildRuntimeToolSection(agentKind, canSpawnSubagents = false, visualToo
6524
6545
  taskToolLine,
6525
6546
  "Use this shared task store for plans, task progress, and checklist updates. It is visible across claude/codex/maestro turns and drives the live task panel.",
6526
6547
  nativeTaskPolicyLine,
6527
- "",
6528
- "## File Delivery",
6529
- `To send a file to the user, save it under your working directory and call the ${sendFileTool} with { file_path: "<absolute path>" }.`,
6530
- "It appears as a downloadable attachment in the chat and returns success. Never claim file delivery is unavailable after a successful call.",
6548
+ ...fileDeliverySection,
6531
6549
  "",
6532
6550
  "## Session Communication",
6533
6551
  "The session-comm MCP server is the only cross-topic messaging surface. Its canonical tools are `list_sessions`, `peek_session`, `tell_session`, `ask_session`, and `abort_session`.",
@@ -6574,7 +6592,7 @@ function buildTopicSystemPrompt(opts) {
6574
6592
  TOPIC_TITLE: opts.topicTitle,
6575
6593
  WORKSPACE_CWD: opts.workspaceCwd,
6576
6594
  UPLOADS_DIR: uploadsDir
6577
- }) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools);
6595
+ }) + buildRuntimeToolSection(opts.agentKind, opts.canSpawnSubagents, opts.visualTools, opts.fileDeliveryTools);
6578
6596
  if (opts.description?.trim()) {
6579
6597
  prompt += `
6580
6598
 
@@ -6590,7 +6608,7 @@ function buildChannelSystemPrompt(opts) {
6590
6608
  TOPIC_TITLE: opts.topicTitle,
6591
6609
  WORKSPACE_CWD: opts.workspaceCwd,
6592
6610
  UPLOADS_DIR: uploadsDir
6593
- }) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools);
6611
+ }) + buildRuntimeToolSection(opts.agentKind, false, opts.visualTools, opts.fileDeliveryTools);
6594
6612
  }
6595
6613
  function buildManagerSystemPrompt(opts) {
6596
6614
  return `${buildTopicSystemPrompt(opts)}
@@ -6657,7 +6675,7 @@ function rowToBrief(r) {
6657
6675
  };
6658
6676
  }
6659
6677
  function getTopicBrief(topicId) {
6660
- const row = storageDatabase.query("SELECT topic_id, brief_md, latest_summary_md, summary_date, updated_at FROM api_topic_brief WHERE topic_id = ?").get(topicId);
6678
+ const row = db.query("SELECT topic_id, brief_md, latest_summary_md, summary_date, updated_at FROM api_topic_brief WHERE topic_id = ?").get(topicId);
6661
6679
  if (!row)
6662
6680
  return null;
6663
6681
  return rowToBrief(row);
@@ -6674,7 +6692,7 @@ function setTopicBrief(topicId, fields) {
6674
6692
  const briefMd = fields.briefMd !== undefined ? fields.briefMd : existing?.briefMd ?? "";
6675
6693
  const latestSummaryMd = fields.latestSummaryMd !== undefined ? fields.latestSummaryMd : existing?.latestSummaryMd ?? null;
6676
6694
  const summaryDate = fields.summaryDate !== undefined ? fields.summaryDate : existing?.summaryDate ?? null;
6677
- storageDatabase.query(`INSERT INTO api_topic_brief
6695
+ db.query(`INSERT INTO api_topic_brief
6678
6696
  (topic_id, brief_md, latest_summary_md, summary_date, updated_at)
6679
6697
  VALUES (?, ?, ?, ?, datetime('now'))
6680
6698
  ON CONFLICT(topic_id) DO UPDATE SET
@@ -7063,7 +7081,7 @@ var init_topic_archive = __esm(async () => {
7063
7081
 
7064
7082
  // ../../packages/core/src/storage/topic-archive-state.ts
7065
7083
  function getTopicArchiveState(topicId) {
7066
- const row = storageDatabase.query("SELECT * FROM api_topic_archive_state WHERE topic_id = ?").get(topicId);
7084
+ const row = db.query("SELECT * FROM api_topic_archive_state WHERE topic_id = ?").get(topicId);
7067
7085
  if (!row)
7068
7086
  return null;
7069
7087
  return {
@@ -7074,7 +7092,7 @@ function getTopicArchiveState(topicId) {
7074
7092
  };
7075
7093
  }
7076
7094
  function setTopicArchiveState(topicId, lastArchivedRowid, lastArchivePath) {
7077
- storageDatabase.query(`INSERT INTO api_topic_archive_state (topic_id, last_archived_rowid, last_archive_path, updated_at)
7095
+ db.query(`INSERT INTO api_topic_archive_state (topic_id, last_archived_rowid, last_archive_path, updated_at)
7078
7096
  VALUES (?, ?, ?, ?)
7079
7097
  ON CONFLICT(topic_id) DO UPDATE SET
7080
7098
  last_archived_rowid = excluded.last_archived_rowid,
@@ -7958,11 +7976,11 @@ function stringifyError(err) {
7958
7976
  function authRecoveryHint(agent) {
7959
7977
  switch (agent) {
7960
7978
  case "claude":
7961
- return "Claude Code \uB85C\uADF8\uC778\uC744 \uAC31\uC2E0\uD574\uC8FC\uC138\uC694";
7979
+ return "Please refresh your Claude Code login";
7962
7980
  case "codex":
7963
- return "`codex login` \uC73C\uB85C \uB2E4\uC2DC \uB85C\uADF8\uC778\uD574\uC8FC\uC138\uC694 (~/.codex/auth.json)";
7981
+ return "Please log in again with `codex login` (~/.codex/auth.json)";
7964
7982
  case "maestro":
7965
- return "DEEPSEEK_API_KEY \uD658\uACBD\uBCC0\uC218\uB97C \uD655\uC778\uD574\uC8FC\uC138\uC694";
7983
+ return "Please check the DEEPSEEK_API_KEY environment variable";
7966
7984
  }
7967
7985
  }
7968
7986
  function classifyAgentError(err, agent) {
@@ -7970,25 +7988,25 @@ function classifyAgentError(err, agent) {
7970
7988
  const hint = authRecoveryHint(agent);
7971
7989
  const ctor = typeof err === "object" && err !== null ? err.constructor?.name : undefined;
7972
7990
  if (ctor === "AuthenticationError")
7973
- return `${name} \uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. ${hint}. (401)`;
7991
+ return `${name} authentication expired. ${hint}. (401)`;
7974
7992
  if (ctor === "RateLimitError")
7975
- return `${name} \uC694\uCCAD \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694. (429)`;
7993
+ return `${name} request limit exceeded. Please try again in a moment. (429)`;
7976
7994
  if (ctor === "InternalServerError") {
7977
7995
  const status = err.status;
7978
- return status === 529 ? `${name} \uC11C\uBC84\uAC00 \uACFC\uBD80\uD558 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694. (529)` : `${name} \uC11C\uBC84 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694. (500)`;
7996
+ return status === 529 ? `${name} server is overloaded. Please try again in a moment. (529)` : `${name} server error occurred. Please try again in a moment. (500)`;
7979
7997
  }
7980
7998
  const s = stringifyError(err);
7981
7999
  if (/401|authentication.error|invalid.*api.key|not logged|ANTHROPIC_API_KEY|DEEPSEEK_API_KEY/i.test(s)) {
7982
- return `${name} \uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. ${hint}. (401)`;
8000
+ return `${name} authentication expired. ${hint}. (401)`;
7983
8001
  }
7984
8002
  if (/429|rate.limit/i.test(s))
7985
- return `${name} \uC694\uCCAD \uD55C\uB3C4\uB97C \uCD08\uACFC\uD588\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694. (429)`;
8003
+ return `${name} request limit exceeded. Please try again in a moment. (429)`;
7986
8004
  if (/529|overloaded/i.test(s))
7987
- return `${name} \uC11C\uBC84\uAC00 \uACFC\uBD80\uD558 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694. (529)`;
8005
+ return `${name} server is overloaded. Please try again in a moment. (529)`;
7988
8006
  if (/500|internal.server/i.test(s))
7989
- return `${name} \uC11C\uBC84 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694. (500)`;
8007
+ return `${name} server error occurred. Please try again in a moment. (500)`;
7990
8008
  const snippet = s.length > 200 ? `${s.slice(0, 200)}...` : s;
7991
- return `${name} \uC624\uB958: ${snippet}`;
8009
+ return `${name} error: ${snippet}`;
7992
8010
  }
7993
8011
  function isSessionExpiredError(message) {
7994
8012
  return message.includes(SESSION_EXPIRED_MSG) || /session was recorded with model .+ but is resuming with/i.test(message) || /session.*not found|session.*expired|unknown conversation/i.test(message);
@@ -8152,13 +8170,13 @@ function normalizeVisualKind(value) {
8152
8170
  return VISUAL_KINDS.includes(value) ? value : "html";
8153
8171
  }
8154
8172
  function insertVisual(input) {
8155
- const result = storageDatabase.query(`INSERT INTO api_topic_visuals
8173
+ const result = db.query(`INSERT INTO api_topic_visuals
8156
8174
  (topic_id, html, title, created_at, kind, source, file_id, mime_type, media_token)
8157
8175
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
8158
8176
  RETURNING id`).get(input.topicId, input.html, input.title, Date.now(), input.kind ?? "html", input.source ?? null, input.fileId ?? null, input.mimeType ?? null, input.mediaToken ?? null);
8159
8177
  if (!result)
8160
8178
  throw new Error("Failed to insert visual");
8161
- storageDatabase.query(`DELETE FROM api_topic_visual_views
8179
+ db.query(`DELETE FROM api_topic_visual_views
8162
8180
  WHERE visual_id IN (
8163
8181
  SELECT id FROM api_topic_visuals
8164
8182
  WHERE topic_id = ? AND id NOT IN (
@@ -8166,7 +8184,7 @@ function insertVisual(input) {
8166
8184
  ORDER BY created_at DESC LIMIT ?
8167
8185
  )
8168
8186
  )`).run(input.topicId, input.topicId, MAX_HISTORY);
8169
- storageDatabase.query(`DELETE FROM api_topic_visuals
8187
+ db.query(`DELETE FROM api_topic_visuals
8170
8188
  WHERE topic_id = ? AND id NOT IN (
8171
8189
  SELECT id FROM api_topic_visuals WHERE topic_id = ?
8172
8190
  ORDER BY created_at DESC LIMIT ?
@@ -8174,22 +8192,22 @@ function insertVisual(input) {
8174
8192
  return result.id;
8175
8193
  }
8176
8194
  function listVisuals(topicId) {
8177
- return storageDatabase.query("SELECT id, title, created_at, kind, mime_type FROM api_topic_visuals WHERE topic_id = ? ORDER BY created_at DESC").all(topicId).map((row) => ({ ...row, kind: normalizeVisualKind(row.kind) }));
8195
+ return db.query("SELECT id, title, created_at, kind, mime_type FROM api_topic_visuals WHERE topic_id = ? ORDER BY created_at DESC").all(topicId).map((row) => ({ ...row, kind: normalizeVisualKind(row.kind) }));
8178
8196
  }
8179
8197
  function getVisualById(id) {
8180
- const row = storageDatabase.query("SELECT * FROM api_topic_visuals WHERE id = ?").get(id);
8198
+ const row = db.query("SELECT * FROM api_topic_visuals WHERE id = ?").get(id);
8181
8199
  return row ? { ...row, kind: normalizeVisualKind(row.kind) } : null;
8182
8200
  }
8183
8201
  function topicHasVisualFileId(topicId, fileId) {
8184
- const row = storageDatabase.query("SELECT id FROM api_topic_visuals WHERE topic_id = ? AND file_id = ? LIMIT 1").get(topicId, fileId);
8202
+ const row = db.query("SELECT id FROM api_topic_visuals WHERE topic_id = ? AND file_id = ? LIMIT 1").get(topicId, fileId);
8185
8203
  return Boolean(row);
8186
8204
  }
8187
8205
  function getUserActiveVisualId(topicId, userId) {
8188
- const row = storageDatabase.query("SELECT visual_id FROM api_topic_visual_views WHERE topic_id = ? AND user_id = ?").get(topicId, userId);
8206
+ const row = db.query("SELECT visual_id FROM api_topic_visual_views WHERE topic_id = ? AND user_id = ?").get(topicId, userId);
8189
8207
  return row?.visual_id ?? null;
8190
8208
  }
8191
8209
  function setUserActiveVisualId(topicId, userId, visualId) {
8192
- storageDatabase.query(`INSERT INTO api_topic_visual_views (topic_id, user_id, visual_id) VALUES (?, ?, ?)
8210
+ db.query(`INSERT INTO api_topic_visual_views (topic_id, user_id, visual_id) VALUES (?, ?, ?)
8193
8211
  ON CONFLICT(topic_id, user_id) DO UPDATE SET visual_id = excluded.visual_id`).run(topicId, userId, visualId);
8194
8212
  }
8195
8213
  function withVisualBaseStyle(html) {
@@ -8313,7 +8331,7 @@ if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",
8313
8331
  </script>`;
8314
8332
  var init_visual_store = __esm(async () => {
8315
8333
  await init_forum_db();
8316
- storageDatabase.exec(`
8334
+ db.exec(`
8317
8335
  CREATE TABLE IF NOT EXISTS api_topic_visuals (
8318
8336
  id INTEGER PRIMARY KEY AUTOINCREMENT,
8319
8337
  topic_id TEXT NOT NULL,
@@ -8344,7 +8362,7 @@ var init_visual_store = __esm(async () => {
8344
8362
  "ALTER TABLE api_topic_visuals ADD COLUMN media_token TEXT"
8345
8363
  ]) {
8346
8364
  try {
8347
- storageDatabase.exec(statement);
8365
+ db.exec(statement);
8348
8366
  } catch {}
8349
8367
  }
8350
8368
  VISUAL_KINDS = ["html", "mermaid", "image", "video"];
@@ -8644,7 +8662,7 @@ import { mkdirSync as mkdirSync14 } from "fs";
8644
8662
  import { join as join20 } from "path";
8645
8663
  function tokenStatsFileId(userId) {
8646
8664
  const rawUserId = String(userId);
8647
- return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) ? rawUserId : `sha256-${createHash3("sha256").update(rawUserId).digest("hex")}`;
8665
+ return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash3("sha256").update(rawUserId).digest("hex")}`;
8648
8666
  }
8649
8667
  function queriesPath(userId) {
8650
8668
  const fileId = tokenStatsFileId(userId);
@@ -8789,7 +8807,7 @@ import {
8789
8807
  import { dirname as dirname11, join as join21 } from "path";
8790
8808
  function pendingAskDir(userId) {
8791
8809
  const rawUserId = String(userId);
8792
- const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) ? rawUserId : `sha256-${createHash4("sha256").update(rawUserId).digest("hex")}`;
8810
+ const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash4("sha256").update(rawUserId).digest("hex")}`;
8793
8811
  return join21(resolveStorageSessionAsksDir(), safeUserId);
8794
8812
  }
8795
8813
  function encodeAskKey(key) {
@@ -8848,6 +8866,12 @@ function readPendingAskFile(path, fallback) {
8848
8866
  const parsed = JSON.parse(raw);
8849
8867
  if (!parsed.requestId || !parsed.from || !parsed.to)
8850
8868
  return null;
8869
+ if (parsed.userId !== undefined && String(parsed.userId) !== String(fallback.userId))
8870
+ return null;
8871
+ if (fallback.from && parsed.from !== fallback.from)
8872
+ return null;
8873
+ if (fallback.to && parsed.to !== fallback.to)
8874
+ return null;
8851
8875
  const now = new Date().toISOString();
8852
8876
  return {
8853
8877
  userId: fallback.userId,
@@ -9133,7 +9157,7 @@ __export(exports_ask_callbacks, {
9133
9157
  function registerAskCallback(entry) {
9134
9158
  pendingAsks2.set(entry.targetQueryId, entry);
9135
9159
  if (entry.remoteReply) {
9136
- storageDatabase.query(`INSERT INTO remote_ask_callbacks
9160
+ db.query(`INSERT INTO remote_ask_callbacks
9137
9161
  (target_query_id, request_id, node_name, node_cell_id, topic_id, user_id, created_at)
9138
9162
  VALUES (?, ?, ?, ?, ?, ?, ?)
9139
9163
  ON CONFLICT(target_query_id) DO UPDATE SET
@@ -9153,7 +9177,7 @@ function resolveAskCallback(queryId) {
9153
9177
  entry.timedOut = true;
9154
9178
  }
9155
9179
  pendingAsks2.delete(queryId);
9156
- storageDatabase.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(queryId);
9180
+ db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(queryId);
9157
9181
  return entry;
9158
9182
  }
9159
9183
  function purgeStaleAsks(now = Date.now()) {
@@ -9161,7 +9185,7 @@ function purgeStaleAsks(now = Date.now()) {
9161
9185
  if (now - entry.createdAt > MAX_ASK_AGE_MS)
9162
9186
  pendingAsks2.delete(id);
9163
9187
  }
9164
- storageDatabase.query("DELETE FROM remote_ask_callbacks WHERE created_at < ?").run(now - MAX_ASK_AGE_MS);
9188
+ db.query("DELETE FROM remote_ask_callbacks WHERE created_at < ?").run(now - MAX_ASK_AGE_MS);
9165
9189
  }
9166
9190
  function cancelAskCallbacksForTopic(topicId) {
9167
9191
  let cancelled = 0;
@@ -9169,13 +9193,13 @@ function cancelAskCallbacksForTopic(topicId) {
9169
9193
  if (entry.callerTopicId !== topicId)
9170
9194
  continue;
9171
9195
  pendingAsks2.delete(queryId);
9172
- storageDatabase.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(queryId);
9196
+ db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(queryId);
9173
9197
  cancelled++;
9174
9198
  }
9175
9199
  return cancelled;
9176
9200
  }
9177
9201
  async function failInterruptedRemoteAskCallbacks() {
9178
- const rows = storageDatabase.query(`SELECT target_query_id, request_id, node_name, node_cell_id, topic_id, user_id
9202
+ const rows = db.query(`SELECT target_query_id, request_id, node_name, node_cell_id, topic_id, user_id
9179
9203
  FROM remote_ask_callbacks
9180
9204
  ORDER BY created_at ASC`).all();
9181
9205
  let failed = 0;
@@ -9189,7 +9213,7 @@ async function failInterruptedRemoteAskCallbacks() {
9189
9213
  }, "peer", "The remote worker restarted before this ask completed. Please retry the request.", "error");
9190
9214
  if (!delivered)
9191
9215
  continue;
9192
- storageDatabase.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
9216
+ db.query("DELETE FROM remote_ask_callbacks WHERE target_query_id = ?").run(row.target_query_id);
9193
9217
  failed++;
9194
9218
  }
9195
9219
  return failed;
@@ -9198,7 +9222,7 @@ var pendingAsks2, MAX_ASK_AGE_MS;
9198
9222
  var init_ask_callbacks = __esm(async () => {
9199
9223
  await init_forum_db();
9200
9224
  await init_session_asks();
9201
- storageDatabase.exec(`
9225
+ db.exec(`
9202
9226
  CREATE TABLE IF NOT EXISTS remote_ask_callbacks (
9203
9227
  target_query_id TEXT PRIMARY KEY,
9204
9228
  request_id TEXT NOT NULL,
@@ -9859,6 +9883,7 @@ function redispatchInject(inject) {
9859
9883
  sessionName: inject.sessionName,
9860
9884
  sessionType: inject.sessionType,
9861
9885
  visualTools: inject.visualTools,
9886
+ fileDeliveryTools: inject.fileDeliveryTools,
9862
9887
  onSessionId: inject.onSessionId,
9863
9888
  onSessionReset: inject.onSessionReset,
9864
9889
  bridgeSessionFromHistory: inject.bridgeSessionFromHistory,
@@ -10040,6 +10065,7 @@ function serializableUserTurnExecution(params) {
10040
10065
  sessionName: params.sessionName,
10041
10066
  sessionType: params.sessionType,
10042
10067
  visualTools: params.visualTools,
10068
+ fileDeliveryTools: params.fileDeliveryTools,
10043
10069
  bridgeSessionFromHistory: params.bridgeSessionFromHistory,
10044
10070
  peerBridge: params.peerBridge,
10045
10071
  from: params.from
@@ -10119,6 +10145,7 @@ async function drainOneDurableUserTurn() {
10119
10145
  sessionName: execution?.sessionName,
10120
10146
  sessionType: execution?.sessionType,
10121
10147
  visualTools: execution?.visualTools,
10148
+ fileDeliveryTools: execution?.fileDeliveryTools,
10122
10149
  bridgeSessionFromHistory: execution?.bridgeSessionFromHistory,
10123
10150
  peerBridge: execution?.peerBridge,
10124
10151
  from: execution?.from,
@@ -10204,6 +10231,7 @@ function startAiTurn(params) {
10204
10231
  const sessionName = params.sessionName ?? topic.title;
10205
10232
  const sessionType = params.sessionType;
10206
10233
  const visualTools = params.visualTools === true;
10234
+ const fileDeliveryTools = params.fileDeliveryTools === true;
10207
10235
  const onSessionId = params.onSessionId;
10208
10236
  const onSessionReset = params.onSessionReset;
10209
10237
  const bridgeSessionFromHistory = params.bridgeSessionFromHistory === true;
@@ -10252,6 +10280,7 @@ function startAiTurn(params) {
10252
10280
  sessionName,
10253
10281
  sessionType,
10254
10282
  visualTools,
10283
+ fileDeliveryTools,
10255
10284
  onSessionId,
10256
10285
  onSessionReset,
10257
10286
  bridgeSessionFromHistory,
@@ -10359,6 +10388,7 @@ function startAiTurn(params) {
10359
10388
  sessionName,
10360
10389
  sessionType,
10361
10390
  visualTools,
10391
+ fileDeliveryTools,
10362
10392
  onSessionId,
10363
10393
  onSessionReset,
10364
10394
  bridgeSessionFromHistory,
@@ -10460,7 +10490,8 @@ function startAiTurn(params) {
10460
10490
  agentKind,
10461
10491
  description: topic.description,
10462
10492
  canSpawnSubagents: peerBridge?.canSpawnSubagents ?? (topicRecord?.kind === "agent" && !topicRecord.isSubagent),
10463
- visualTools
10493
+ visualTools,
10494
+ fileDeliveryTools
10464
10495
  };
10465
10496
  const isManager = topicRecord?.kind === "manager";
10466
10497
  const isMentionOnlyChannel = topic.aiMode === "mention" && !isManager;
@@ -10610,6 +10641,7 @@ ${playwrightNote}`;
10610
10641
  wikiTopicId: memoryTopic.id,
10611
10642
  autoContinue: allowAutoContinue && !silent,
10612
10643
  visualTools,
10644
+ fileDeliveryTools,
10613
10645
  peerBridge
10614
10646
  });
10615
10647
  } finally {
@@ -10674,6 +10706,7 @@ ${playwrightNote}`;
10674
10706
  sessionName,
10675
10707
  sessionType,
10676
10708
  visualTools,
10709
+ fileDeliveryTools,
10677
10710
  onSessionId,
10678
10711
  onSessionReset,
10679
10712
  bridgeSessionFromHistory,
@@ -10800,6 +10833,7 @@ function triggerTopicAiTurn(topicId, userId, prompt, agentType, opts) {
10800
10833
  sessionName: opts?.sessionName,
10801
10834
  sessionType: opts?.sessionType,
10802
10835
  visualTools: opts?.visualTools,
10836
+ fileDeliveryTools: opts?.fileDeliveryTools,
10803
10837
  onSessionId: opts?.onSessionId,
10804
10838
  onSessionReset: opts?.onSessionReset,
10805
10839
  bridgeSessionFromHistory: opts?.bridgeSessionFromHistory,
@@ -11418,7 +11452,7 @@ init_logger();
11418
11452
  // ../../packages/core/src/storage/runtime-process-leases.ts
11419
11453
  await init_forum_db();
11420
11454
  await init_runtime_leases();
11421
- storageDatabase.exec(`
11455
+ db.exec(`
11422
11456
  CREATE TABLE IF NOT EXISTS runtime_process_leases (
11423
11457
  role TEXT PRIMARY KEY,
11424
11458
  owner_id TEXT NOT NULL UNIQUE,
@@ -11427,7 +11461,7 @@ storageDatabase.exec(`
11427
11461
  heartbeat_at INTEGER NOT NULL
11428
11462
  )
11429
11463
  `);
11430
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_runtime_process_leases_heartbeat ON runtime_process_leases(heartbeat_at)");
11464
+ db.exec("CREATE INDEX IF NOT EXISTS idx_runtime_process_leases_heartbeat ON runtime_process_leases(heartbeat_at)");
11431
11465
 
11432
11466
  // ../../packages/core/src/index.ts
11433
11467
  await init_manager();
@@ -11484,6 +11518,8 @@ function backgroundSessionProgress(topicId, queryId) {
11484
11518
  }
11485
11519
  return { status, steps: steps.slice(-MAX_STEPS) };
11486
11520
  }
11521
+ // ../../packages/core/src/runtime/delivery-ack.ts
11522
+ await init_bus();
11487
11523
 
11488
11524
  // ../../packages/core/src/index.ts
11489
11525
  init_file_hooks();
@@ -11839,24 +11875,24 @@ async function runCronPromptScript(options) {
11839
11875
 
11840
11876
  // ../../packages/module-cron/src/store.ts
11841
11877
  var schemaReady = false;
11842
- var db = storageDatabase;
11878
+ var db2 = db;
11843
11879
  function configureCronDatabase(database) {
11844
- const previous = db;
11845
- db = database;
11880
+ const previous = db2;
11881
+ db2 = database;
11846
11882
  schemaReady = false;
11847
11883
  let disposed = false;
11848
11884
  return () => {
11849
11885
  if (disposed)
11850
11886
  return;
11851
11887
  disposed = true;
11852
- db = previous;
11888
+ db2 = previous;
11853
11889
  schemaReady = false;
11854
11890
  };
11855
11891
  }
11856
11892
  function ensureCronSchema() {
11857
11893
  if (schemaReady)
11858
11894
  return;
11859
- db.exec(`
11895
+ db2.exec(`
11860
11896
  CREATE TABLE IF NOT EXISTS negotium_cron_jobs (
11861
11897
  id TEXT PRIMARY KEY,
11862
11898
  name TEXT NOT NULL,
@@ -11925,28 +11961,28 @@ function ensureCronSchema() {
11925
11961
  updated_at TEXT NOT NULL
11926
11962
  );
11927
11963
  `);
11928
- const jobColumns = new Set(db.query("PRAGMA table_info(negotium_cron_jobs)").all().map((column) => column.name));
11964
+ const jobColumns = new Set(db2.query("PRAGMA table_info(negotium_cron_jobs)").all().map((column) => column.name));
11929
11965
  if (!jobColumns.has("script")) {
11930
- db.exec("ALTER TABLE negotium_cron_jobs ADD COLUMN script TEXT");
11966
+ db2.exec("ALTER TABLE negotium_cron_jobs ADD COLUMN script TEXT");
11931
11967
  }
11932
11968
  if (!jobColumns.has("summary")) {
11933
- db.exec("ALTER TABLE negotium_cron_jobs ADD COLUMN summary TEXT");
11969
+ db2.exec("ALTER TABLE negotium_cron_jobs ADD COLUMN summary TEXT");
11934
11970
  }
11935
- const runColumns = new Set(db.query("PRAGMA table_info(negotium_cron_runs)").all().map((column) => column.name));
11971
+ const runColumns = new Set(db2.query("PRAGMA table_info(negotium_cron_runs)").all().map((column) => column.name));
11936
11972
  if (!runColumns.has("exit_code")) {
11937
- db.exec("ALTER TABLE negotium_cron_runs ADD COLUMN exit_code INTEGER");
11973
+ db2.exec("ALTER TABLE negotium_cron_runs ADD COLUMN exit_code INTEGER");
11938
11974
  }
11939
11975
  if (!runColumns.has("topic_id")) {
11940
- db.exec("ALTER TABLE negotium_cron_runs ADD COLUMN topic_id TEXT");
11976
+ db2.exec("ALTER TABLE negotium_cron_runs ADD COLUMN topic_id TEXT");
11941
11977
  }
11942
- const legacySessions = db.query(`SELECT j.topic_id, COALESCE(j.agent, t.agent) AS agent,
11978
+ const legacySessions = db2.query(`SELECT j.topic_id, COALESCE(j.agent, t.agent) AS agent,
11943
11979
  j.owner_user_id, j.session_id, j.created_at, j.updated_at
11944
11980
  FROM negotium_cron_jobs j
11945
11981
  LEFT JOIN api_topics t ON t.id = j.topic_id
11946
11982
  WHERE j.session_id IS NOT NULL AND COALESCE(j.agent, t.agent) IS NOT NULL
11947
11983
  ORDER BY j.updated_at ASC`).all();
11948
11984
  for (const legacy of legacySessions) {
11949
- db.query(`INSERT INTO negotium_cron_topic_sessions
11985
+ db2.query(`INSERT INTO negotium_cron_topic_sessions
11950
11986
  (topic_id,agent,owner_user_id,session_id,created_at,updated_at)
11951
11987
  VALUES (?,?,?,?,?,?)
11952
11988
  ON CONFLICT(topic_id,agent) DO UPDATE SET
@@ -11955,13 +11991,13 @@ function ensureCronSchema() {
11955
11991
  updated_at = excluded.updated_at`).run(legacy.topic_id, legacy.agent, legacy.owner_user_id, legacy.session_id, legacy.created_at, legacy.updated_at);
11956
11992
  }
11957
11993
  if (legacySessions.length > 0) {
11958
- db.query("UPDATE negotium_cron_jobs SET session_id = NULL WHERE session_id IS NOT NULL").run();
11994
+ db2.query("UPDATE negotium_cron_jobs SET session_id = NULL WHERE session_id IS NOT NULL").run();
11959
11995
  }
11960
11996
  schemaReady = true;
11961
11997
  }
11962
11998
  function toJob(row) {
11963
- const topicAgent = row.agent ? row.agent : db.query("SELECT agent FROM api_topics WHERE id = ?").get(row.topic_id)?.agent;
11964
- const topicSession = topicAgent ? db.query("SELECT session_id FROM negotium_cron_topic_sessions WHERE topic_id = ? AND agent = ?").get(row.topic_id, topicAgent) : undefined;
11999
+ const topicAgent = row.agent ? row.agent : db2.query("SELECT agent FROM api_topics WHERE id = ?").get(row.topic_id)?.agent;
12000
+ const topicSession = topicAgent ? db2.query("SELECT session_id FROM negotium_cron_topic_sessions WHERE topic_id = ? AND agent = ?").get(row.topic_id, topicAgent) : undefined;
11965
12001
  return {
11966
12002
  id: row.id,
11967
12003
  name: row.name,
@@ -12031,7 +12067,7 @@ function createCronJob(input) {
12031
12067
  if (!valid.ok)
12032
12068
  throw new Error(valid.error);
12033
12069
  }
12034
- const otherOwner = db.query(`SELECT owner_user_id
12070
+ const otherOwner = db2.query(`SELECT owner_user_id
12035
12071
  FROM negotium_cron_jobs
12036
12072
  WHERE topic_id = ? AND owner_user_id <> ?
12037
12073
  LIMIT 1`).get(input.topicId, input.ownerUserId);
@@ -12062,36 +12098,36 @@ function createCronJob(input) {
12062
12098
  createdAt: nowIso,
12063
12099
  updatedAt: nowIso
12064
12100
  };
12065
- db.query(`INSERT INTO negotium_cron_jobs
12101
+ db2.query(`INSERT INTO negotium_cron_jobs
12066
12102
  (id,name,owner_user_id,topic_id,prompt,script,summary,schedule,timezone,enabled,agent,model,effort,session_id,next_run_at,created_at,updated_at)
12067
12103
  VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(job.id, job.name, job.ownerUserId, job.topicId, job.prompt ?? "", job.script ?? null, job.summary ?? null, job.schedule, job.timezone ?? null, 1, job.agent ?? null, job.model ?? null, job.effort ?? null, null, job.nextRunAt, job.createdAt, job.updatedAt);
12068
12104
  return job;
12069
12105
  }
12070
12106
  function listCronJobs(ownerUserId) {
12071
12107
  ensureCronSchema();
12072
- const rows = ownerUserId ? db.query("SELECT * FROM negotium_cron_jobs WHERE owner_user_id = ? ORDER BY created_at DESC").all(ownerUserId) : db.query("SELECT * FROM negotium_cron_jobs ORDER BY created_at DESC").all();
12108
+ const rows = ownerUserId ? db2.query("SELECT * FROM negotium_cron_jobs WHERE owner_user_id = ? ORDER BY created_at DESC").all(ownerUserId) : db2.query("SELECT * FROM negotium_cron_jobs ORDER BY created_at DESC").all();
12073
12109
  return rows.map(toJob);
12074
12110
  }
12075
12111
  function listEnabledCronJobs() {
12076
12112
  ensureCronSchema();
12077
- return db.query("SELECT * FROM negotium_cron_jobs WHERE enabled = 1 ORDER BY created_at DESC").all().map(toJob);
12113
+ return db2.query("SELECT * FROM negotium_cron_jobs WHERE enabled = 1 ORDER BY created_at DESC").all().map(toJob);
12078
12114
  }
12079
12115
  function listCronJobsForTopic(topicId) {
12080
12116
  ensureCronSchema();
12081
- return db.query("SELECT * FROM negotium_cron_jobs WHERE topic_id = ? ORDER BY created_at DESC").all(topicId).map(toJob);
12117
+ return db2.query("SELECT * FROM negotium_cron_jobs WHERE topic_id = ? ORDER BY created_at DESC").all(topicId).map(toJob);
12082
12118
  }
12083
12119
  function listCronJobsForTopicOwner(topicId, ownerUserId) {
12084
12120
  ensureCronSchema();
12085
- return db.query("SELECT * FROM negotium_cron_jobs WHERE topic_id = ? AND owner_user_id = ? ORDER BY created_at DESC").all(topicId, ownerUserId).map(toJob);
12121
+ return db2.query("SELECT * FROM negotium_cron_jobs WHERE topic_id = ? AND owner_user_id = ? ORDER BY created_at DESC").all(topicId, ownerUserId).map(toJob);
12086
12122
  }
12087
12123
  function getCronJob(id) {
12088
12124
  ensureCronSchema();
12089
- const row = db.query("SELECT * FROM negotium_cron_jobs WHERE id = ?").get(id);
12125
+ const row = db2.query("SELECT * FROM negotium_cron_jobs WHERE id = ?").get(id);
12090
12126
  return row ? toJob(row) : null;
12091
12127
  }
12092
12128
  function getCronJobByOwnerAndName(ownerUserId, name) {
12093
12129
  ensureCronSchema();
12094
- const row = db.query("SELECT * FROM negotium_cron_jobs WHERE owner_user_id = ? AND name = ?").get(ownerUserId, name);
12130
+ const row = db2.query("SELECT * FROM negotium_cron_jobs WHERE owner_user_id = ? AND name = ?").get(ownerUserId, name);
12095
12131
  return row ? toJob(row) : null;
12096
12132
  }
12097
12133
  function cronJobPatchChangesContext(job, patch) {
@@ -12125,7 +12161,7 @@ function updateCronJob(id, patch, now = new Date) {
12125
12161
  if (rawTimezone && !nextTimezone)
12126
12162
  throw new Error(`invalid timezone: ${rawTimezone}`);
12127
12163
  const nextTopicId = patch.topicId?.trim() || job.topicId;
12128
- const otherOwner = db.query(`SELECT owner_user_id FROM negotium_cron_jobs
12164
+ const otherOwner = db2.query(`SELECT owner_user_id FROM negotium_cron_jobs
12129
12165
  WHERE topic_id = ? AND owner_user_id <> ? AND id <> ? LIMIT 1`).get(nextTopicId, job.ownerUserId, id);
12130
12166
  if (otherOwner) {
12131
12167
  throw new Error(`topic cron context is already owned by ${otherOwner.owner_user_id}; ` + "all cron jobs in one topic must share one owner");
@@ -12136,13 +12172,13 @@ function updateCronJob(id, patch, now = new Date) {
12136
12172
  const timestamp = now.toISOString();
12137
12173
  const sessionSensitiveChanged = cronJobPatchChangesContext(job, patch);
12138
12174
  if (sessionSensitiveChanged) {
12139
- const active = db.query("SELECT 1 FROM negotium_cron_runs WHERE job_id = ? AND status IN ('pending','running') LIMIT 1").get(id);
12175
+ const active = db2.query("SELECT 1 FROM negotium_cron_runs WHERE job_id = ? AND status IN ('pending','running') LIMIT 1").get(id);
12140
12176
  if (active) {
12141
12177
  throw new Error("cannot change Cron context while a run is active; cancel it first");
12142
12178
  }
12143
12179
  }
12144
- db.transaction(() => {
12145
- db.query(`UPDATE negotium_cron_jobs SET
12180
+ db2.transaction(() => {
12181
+ db2.query(`UPDATE negotium_cron_jobs SET
12146
12182
  name = ?, topic_id = ?, prompt = ?, script = ?, summary = ?, schedule = ?, timezone = ?,
12147
12183
  enabled = ?, agent = ?, model = ?, effort = ?, next_run_at = ?, updated_at = ?
12148
12184
  WHERE id = ?`).run(nextName, nextTopicId, nextPrompt ?? "", nextScript ?? null, patch.summary !== undefined ? patch.summary?.trim() || null : job.summary ?? null, nextSchedule, nextTimezone ?? null, enabled ? 1 : 0, patch.agent !== undefined ? patch.agent : job.agent ?? null, patch.model !== undefined ? patch.model?.trim() || null : job.model ?? null, patch.effort !== undefined ? patch.effort : job.effort ?? null, nextRunAt, timestamp, id);
@@ -12151,7 +12187,7 @@ function updateCronJob(id, patch, now = new Date) {
12151
12187
  }
12152
12188
  function updateCronJobSummaryIfPromptMatches(id, expectedPrompt, summary) {
12153
12189
  ensureCronSchema();
12154
- const result = db.query("UPDATE negotium_cron_jobs SET summary = ? WHERE id = ? AND prompt = ?").run(summary.trim(), id, expectedPrompt.trim());
12190
+ const result = db2.query("UPDATE negotium_cron_jobs SET summary = ? WHERE id = ? AND prompt = ?").run(summary.trim(), id, expectedPrompt.trim());
12155
12191
  return Number(result.changes) > 0;
12156
12192
  }
12157
12193
  function setCronJobEnabled(id, enabled, now = new Date) {
@@ -12160,14 +12196,14 @@ function setCronJobEnabled(id, enabled, now = new Date) {
12160
12196
  if (!job)
12161
12197
  return null;
12162
12198
  const nextRunAt = enabled ? computeNextCronRun(job.schedule, now, job.timezone).toISOString() : job.nextRunAt;
12163
- db.query("UPDATE negotium_cron_jobs SET enabled = ?, next_run_at = ?, updated_at = ? WHERE id = ?").run(enabled ? 1 : 0, nextRunAt, now.toISOString(), id);
12199
+ db2.query("UPDATE negotium_cron_jobs SET enabled = ?, next_run_at = ?, updated_at = ? WHERE id = ?").run(enabled ? 1 : 0, nextRunAt, now.toISOString(), id);
12164
12200
  return getCronJob(id);
12165
12201
  }
12166
12202
  function setCronJobSessionId(id, sessionId) {
12167
12203
  const job = getCronJob(id);
12168
12204
  if (!job)
12169
12205
  return;
12170
- const topic = db.query("SELECT agent FROM api_topics WHERE id = ?").get(job.topicId);
12206
+ const topic = db2.query("SELECT agent FROM api_topics WHERE id = ?").get(job.topicId);
12171
12207
  const agent = job.agent ?? topic?.agent;
12172
12208
  if (!agent)
12173
12209
  return;
@@ -12178,17 +12214,17 @@ function setCronJobSessionId(id, sessionId) {
12178
12214
  }
12179
12215
  function getCronTopicSession(topicId, agent) {
12180
12216
  ensureCronSchema();
12181
- const row = db.query("SELECT * FROM negotium_cron_topic_sessions WHERE topic_id = ? AND agent = ?").get(topicId, agent);
12217
+ const row = db2.query("SELECT * FROM negotium_cron_topic_sessions WHERE topic_id = ? AND agent = ?").get(topicId, agent);
12182
12218
  return row ? toTopicSession(row) : null;
12183
12219
  }
12184
12220
  function listCronTopicSessions(topicId) {
12185
12221
  ensureCronSchema();
12186
- return db.query("SELECT * FROM negotium_cron_topic_sessions WHERE topic_id = ? ORDER BY agent").all(topicId).map(toTopicSession);
12222
+ return db2.query("SELECT * FROM negotium_cron_topic_sessions WHERE topic_id = ? ORDER BY agent").all(topicId).map(toTopicSession);
12187
12223
  }
12188
12224
  function setCronTopicSession(topicId, agent, ownerUserId, sessionId, now = new Date) {
12189
12225
  ensureCronSchema();
12190
12226
  const timestamp = now.toISOString();
12191
- db.query(`INSERT INTO negotium_cron_topic_sessions
12227
+ db2.query(`INSERT INTO negotium_cron_topic_sessions
12192
12228
  (topic_id,agent,owner_user_id,session_id,created_at,updated_at)
12193
12229
  VALUES (?,?,?,?,?,?)
12194
12230
  ON CONFLICT(topic_id,agent) DO UPDATE SET
@@ -12200,8 +12236,8 @@ function setCronTopicSession(topicId, agent, ownerUserId, sessionId, now = new D
12200
12236
  function setCronTopicSessionIfJobUpdatedAt(jobId, expectedJobUpdatedAt, topicId, agent, ownerUserId, sessionId, now = new Date) {
12201
12237
  ensureCronSchema();
12202
12238
  let updated = false;
12203
- db.transaction(() => {
12204
- const current3 = db.query("SELECT topic_id, updated_at FROM negotium_cron_jobs WHERE id = ?").get(jobId);
12239
+ db2.transaction(() => {
12240
+ const current3 = db2.query("SELECT topic_id, updated_at FROM negotium_cron_jobs WHERE id = ?").get(jobId);
12205
12241
  if (!current3 || current3.topic_id !== topicId || current3.updated_at !== expectedJobUpdatedAt)
12206
12242
  return;
12207
12243
  setCronTopicSession(topicId, agent, ownerUserId, sessionId, now);
@@ -12211,23 +12247,23 @@ function setCronTopicSessionIfJobUpdatedAt(jobId, expectedJobUpdatedAt, topicId,
12211
12247
  }
12212
12248
  function clearCronTopicSession(topicId, agent) {
12213
12249
  ensureCronSchema();
12214
- const result = db.query("DELETE FROM negotium_cron_topic_sessions WHERE topic_id = ? AND agent = ?").run(topicId, agent);
12250
+ const result = db2.query("DELETE FROM negotium_cron_topic_sessions WHERE topic_id = ? AND agent = ?").run(topicId, agent);
12215
12251
  return Number(result.changes) > 0;
12216
12252
  }
12217
12253
  function resetCronTopicSessions(topicId) {
12218
12254
  ensureCronSchema();
12219
12255
  const sessions = listCronTopicSessions(topicId);
12220
- db.query("DELETE FROM negotium_cron_topic_sessions WHERE topic_id = ?").run(topicId);
12256
+ db2.query("DELETE FROM negotium_cron_topic_sessions WHERE topic_id = ?").run(topicId);
12221
12257
  return sessions;
12222
12258
  }
12223
12259
  function getCronTopicContext(topicId) {
12224
12260
  ensureCronSchema();
12225
- const row = db.query("SELECT * FROM negotium_cron_topic_context WHERE topic_id = ?").get(topicId);
12261
+ const row = db2.query("SELECT * FROM negotium_cron_topic_context WHERE topic_id = ?").get(topicId);
12226
12262
  return row ? toTopicContext(row) : null;
12227
12263
  }
12228
12264
  function incrementCronTopicSuccess(topicId, now) {
12229
12265
  const timestamp = now.toISOString();
12230
- db.query(`INSERT INTO negotium_cron_topic_context
12266
+ db2.query(`INSERT INTO negotium_cron_topic_context
12231
12267
  (topic_id,successful_runs_since_rotation,last_rotated_at,updated_at)
12232
12268
  VALUES (?,1,NULL,?)
12233
12269
  ON CONFLICT(topic_id) DO UPDATE SET
@@ -12238,7 +12274,7 @@ function incrementCronTopicSuccess(topicId, now) {
12238
12274
  function markCronTopicContextRotated(topicId, now = new Date) {
12239
12275
  ensureCronSchema();
12240
12276
  const timestamp = now.toISOString();
12241
- db.query(`INSERT INTO negotium_cron_topic_context
12277
+ db2.query(`INSERT INTO negotium_cron_topic_context
12242
12278
  (topic_id,successful_runs_since_rotation,last_rotated_at,updated_at)
12243
12279
  VALUES (?,0,?,?)
12244
12280
  ON CONFLICT(topic_id) DO UPDATE SET
@@ -12248,41 +12284,41 @@ function markCronTopicContextRotated(topicId, now = new Date) {
12248
12284
  }
12249
12285
  function resetCronTopicContextState(topicId) {
12250
12286
  ensureCronSchema();
12251
- const result = db.query("DELETE FROM negotium_cron_topic_context WHERE topic_id = ?").run(topicId);
12287
+ const result = db2.query("DELETE FROM negotium_cron_topic_context WHERE topic_id = ?").run(topicId);
12252
12288
  return Number(result.changes) > 0;
12253
12289
  }
12254
12290
  function listOrphanedCronTopicSessions() {
12255
12291
  ensureCronSchema();
12256
- return db.query(`SELECT s.* FROM negotium_cron_topic_sessions s
12292
+ return db2.query(`SELECT s.* FROM negotium_cron_topic_sessions s
12257
12293
  LEFT JOIN api_topics t ON t.id = s.topic_id
12258
12294
  WHERE t.id IS NULL
12259
12295
  ORDER BY s.topic_id, s.agent`).all().map(toTopicSession);
12260
12296
  }
12261
12297
  function deleteCronJob(id) {
12262
12298
  ensureCronSchema();
12263
- const result = db.query("DELETE FROM negotium_cron_jobs WHERE id = ?").run(id);
12299
+ const result = db2.query("DELETE FROM negotium_cron_jobs WHERE id = ?").run(id);
12264
12300
  return Number(result.changes) > 0;
12265
12301
  }
12266
12302
  function requestCronRun(jobId, now = new Date) {
12267
12303
  ensureCronSchema();
12268
12304
  const id = randomUUID10();
12269
- db.query("INSERT INTO negotium_cron_requests (id,job_id,requested_at) VALUES (?,?,?)").run(id, jobId, now.toISOString());
12305
+ db2.query("INSERT INTO negotium_cron_requests (id,job_id,requested_at) VALUES (?,?,?)").run(id, jobId, now.toISOString());
12270
12306
  return id;
12271
12307
  }
12272
12308
  function requestCronCancel(jobId, now = new Date) {
12273
12309
  ensureCronSchema();
12274
12310
  const id = randomUUID10();
12275
- db.query("INSERT INTO negotium_cron_cancellations (id,job_id,requested_at) VALUES (?,?,?)").run(id, jobId, now.toISOString());
12311
+ db2.query("INSERT INTO negotium_cron_cancellations (id,job_id,requested_at) VALUES (?,?,?)").run(id, jobId, now.toISOString());
12276
12312
  return id;
12277
12313
  }
12278
12314
  function claimCronCancellations(limit = 100) {
12279
12315
  ensureCronSchema();
12280
12316
  const jobIds = [];
12281
- db.transaction(() => {
12282
- const rows = db.query(`SELECT id, job_id FROM negotium_cron_cancellations
12317
+ db2.transaction(() => {
12318
+ const rows = db2.query(`SELECT id, job_id FROM negotium_cron_cancellations
12283
12319
  ORDER BY requested_at LIMIT ?`).all(limit);
12284
12320
  for (const row of rows) {
12285
- db.query("DELETE FROM negotium_cron_cancellations WHERE id = ?").run(row.id);
12321
+ db2.query("DELETE FROM negotium_cron_cancellations WHERE id = ?").run(row.id);
12286
12322
  if (!jobIds.includes(row.job_id))
12287
12323
  jobIds.push(row.job_id);
12288
12324
  }
@@ -12297,18 +12333,18 @@ function insertRun(jobId, topicId, source, scheduledAt) {
12297
12333
  scheduledAt,
12298
12334
  status: "pending"
12299
12335
  };
12300
- db.query("INSERT INTO negotium_cron_runs (id,job_id,topic_id,source,scheduled_at,status) VALUES (?,?,?,?,?,?)").run(run.id, run.jobId, topicId, run.source, run.scheduledAt, run.status);
12336
+ db2.query("INSERT INTO negotium_cron_runs (id,job_id,topic_id,source,scheduled_at,status) VALUES (?,?,?,?,?,?)").run(run.id, run.jobId, topicId, run.source, run.scheduledAt, run.status);
12301
12337
  return run;
12302
12338
  }
12303
12339
  function claimCronRuns(now = new Date, limit = 20) {
12304
12340
  ensureCronSchema();
12305
12341
  const claimed = [];
12306
- db.transaction(() => {
12307
- const requests = db.query(`SELECT r.id AS request_id, r.requested_at, j.*
12342
+ db2.transaction(() => {
12343
+ const requests = db2.query(`SELECT r.id AS request_id, r.requested_at, j.*
12308
12344
  FROM negotium_cron_requests r JOIN negotium_cron_jobs j ON j.id = r.job_id
12309
12345
  ORDER BY r.requested_at LIMIT ?`).all(limit);
12310
12346
  for (const row of requests) {
12311
- db.query("DELETE FROM negotium_cron_requests WHERE id = ?").run(row.request_id);
12347
+ db2.query("DELETE FROM negotium_cron_requests WHERE id = ?").run(row.request_id);
12312
12348
  claimed.push({
12313
12349
  job: toJob(row),
12314
12350
  run: insertRun(row.id, row.topic_id, "manual", row.requested_at)
@@ -12317,13 +12353,13 @@ function claimCronRuns(now = new Date, limit = 20) {
12317
12353
  const remaining = Math.max(0, limit - claimed.length);
12318
12354
  if (remaining === 0)
12319
12355
  return;
12320
- const due = db.query(`SELECT * FROM negotium_cron_jobs
12356
+ const due = db2.query(`SELECT * FROM negotium_cron_jobs
12321
12357
  WHERE enabled = 1 AND next_run_at <= ? ORDER BY next_run_at LIMIT ?`).all(now.toISOString(), remaining);
12322
12358
  for (const row of due) {
12323
12359
  const job = toJob(row);
12324
12360
  const run = insertRun(job.id, job.topicId, "schedule", job.nextRunAt);
12325
12361
  const nextRunAt = computeNextCronRun(job.schedule, now, job.timezone).toISOString();
12326
- db.query("UPDATE negotium_cron_jobs SET next_run_at = ? WHERE id = ?").run(nextRunAt, job.id);
12362
+ db2.query("UPDATE negotium_cron_jobs SET next_run_at = ? WHERE id = ?").run(nextRunAt, job.id);
12327
12363
  claimed.push({ job: { ...job, nextRunAt }, run });
12328
12364
  }
12329
12365
  })();
@@ -12331,13 +12367,13 @@ function claimCronRuns(now = new Date, limit = 20) {
12331
12367
  }
12332
12368
  function markCronRunStarted(runId, queryId, now = new Date) {
12333
12369
  ensureCronSchema();
12334
- db.query(`UPDATE negotium_cron_runs
12370
+ db2.query(`UPDATE negotium_cron_runs
12335
12371
  SET status = 'running', query_id = ?, started_at = COALESCE(started_at, ?)
12336
12372
  WHERE id = ?`).run(queryId, now.toISOString(), runId);
12337
12373
  }
12338
12374
  function finishCronRun(runId, result, now = new Date) {
12339
12375
  ensureCronSchema();
12340
- const row = db.query(`SELECT r.started_at, r.status, COALESCE(r.topic_id, j.topic_id) AS topic_id
12376
+ const row = db2.query(`SELECT r.started_at, r.status, COALESCE(r.topic_id, j.topic_id) AS topic_id
12341
12377
  FROM negotium_cron_runs r
12342
12378
  JOIN negotium_cron_jobs j ON j.id = r.job_id
12343
12379
  WHERE r.id = ?`).get(runId);
@@ -12345,9 +12381,9 @@ function finishCronRun(runId, result, now = new Date) {
12345
12381
  return null;
12346
12382
  const durationMs = row?.started_at ? Math.max(0, now.getTime() - Date.parse(row.started_at)) : null;
12347
12383
  let successfulRunsSinceRotation = null;
12348
- db.transaction(() => {
12384
+ db2.transaction(() => {
12349
12385
  const exitCode = result.exitCode ?? { succeeded: 0, skipped: 0, failed: 1, aborted: 130, interrupted: 137 }[result.status];
12350
- const updated = db.query(`UPDATE negotium_cron_runs
12386
+ const updated = db2.query(`UPDATE negotium_cron_runs
12351
12387
  SET status = ?, finished_at = ?, duration_ms = ?, output_preview = ?, error = ?, exit_code = ?
12352
12388
  WHERE id = ? AND status IN ('pending','running')`).run(result.status, now.toISOString(), durationMs, result.outputPreview?.slice(0, 500) ?? null, result.error ?? null, exitCode, runId);
12353
12389
  if (Number(updated.changes) > 0 && result.status === "succeeded") {
@@ -12358,19 +12394,19 @@ function finishCronRun(runId, result, now = new Date) {
12358
12394
  }
12359
12395
  function listCronRuns(jobId, limit = 20) {
12360
12396
  ensureCronSchema();
12361
- return db.query("SELECT * FROM negotium_cron_runs WHERE job_id = ? ORDER BY scheduled_at DESC LIMIT ?").all(jobId, limit).map(toRun);
12397
+ return db2.query("SELECT * FROM negotium_cron_runs WHERE job_id = ? ORDER BY scheduled_at DESC LIMIT ?").all(jobId, limit).map(toRun);
12362
12398
  }
12363
12399
  function getLastCronRun(jobId) {
12364
12400
  return listCronRuns(jobId, 1)[0] ?? null;
12365
12401
  }
12366
12402
  function countCronRuns(jobId) {
12367
12403
  ensureCronSchema();
12368
- const row = db.query("SELECT COUNT(*) AS count FROM negotium_cron_runs WHERE job_id = ?").get(jobId);
12404
+ const row = db2.query("SELECT COUNT(*) AS count FROM negotium_cron_runs WHERE job_id = ?").get(jobId);
12369
12405
  return row?.count ?? 0;
12370
12406
  }
12371
12407
  function recoverPendingCronRuns(limit = 100) {
12372
12408
  ensureCronSchema();
12373
- const rows = db.query(`SELECT r.id AS run_id, r.job_id AS run_job_id, r.source AS run_source,
12409
+ const rows = db2.query(`SELECT r.id AS run_id, r.job_id AS run_job_id, r.source AS run_source,
12374
12410
  r.scheduled_at AS run_scheduled_at, r.started_at AS run_started_at,
12375
12411
  r.finished_at AS run_finished_at, r.status AS run_status,
12376
12412
  r.query_id AS run_query_id, r.duration_ms AS run_duration_ms,
@@ -12404,7 +12440,7 @@ function recoverPendingCronRuns(limit = 100) {
12404
12440
  }
12405
12441
  function finalizeOrphanedCronRuns(now = new Date) {
12406
12442
  ensureCronSchema();
12407
- const result = db.query(`UPDATE negotium_cron_runs
12443
+ const result = db2.query(`UPDATE negotium_cron_runs
12408
12444
  SET status = 'interrupted', finished_at = ?, exit_code = 137,
12409
12445
  error = 'node restarted after dispatch; final outcome is unknown'
12410
12446
  WHERE status = 'running'`).run(now.toISOString());
@@ -13181,4 +13217,4 @@ export {
13181
13217
  CRON_CONTEXT_RETAIN_TURNS
13182
13218
  };
13183
13219
 
13184
- //# debugId=2F24B8722CE00CDA64756E2164756E21
13220
+ //# debugId=4523810F2A196B5864756E2164756E21