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/storage.js CHANGED
@@ -228,6 +228,8 @@ if (isBun) {
228
228
  // ../../packages/core/src/storage/storage-host.ts
229
229
  var configuredHost = {};
230
230
  var fallbackDatabase = null;
231
+ var fallbackDatabasePath = null;
232
+ var storageHostFrames = [];
231
233
  var schemaInitializers = [];
232
234
  var initializedSchemas = new WeakMap;
233
235
  var initializingDatabases = new WeakSet;
@@ -252,7 +254,7 @@ function defaultSessionAsksDir() {
252
254
  return join(runDir, "session-asks");
253
255
  }
254
256
  function defaultSessionsDatabasePath() {
255
- return envPath("SESSIONS_DB_PATH", join(defaultDataDir(), "sessions.db"));
257
+ return envPath("SESSIONS_DB_PATH", join(resolveStorageDataDir(), "sessions.db"));
256
258
  }
257
259
  function initializeDatabase(database) {
258
260
  database.exec("PRAGMA journal_mode = WAL");
@@ -264,11 +266,14 @@ function initializeDatabase(database) {
264
266
  } catch {}
265
267
  }
266
268
  function defaultDatabase() {
267
- if (fallbackDatabase)
268
- return fallbackDatabase;
269
269
  const path = defaultSessionsDatabasePath();
270
+ if (fallbackDatabase && fallbackDatabasePath === path)
271
+ return fallbackDatabase;
272
+ if (fallbackDatabase)
273
+ fallbackDatabase.close();
270
274
  mkdirSync2(dirname2(path), { recursive: true });
271
275
  fallbackDatabase = new Database(path, { create: true });
276
+ fallbackDatabasePath = path;
272
277
  initializeDatabase(fallbackDatabase);
273
278
  return fallbackDatabase;
274
279
  }
@@ -288,27 +293,62 @@ function resolveStorageWorkspaceDir() {
288
293
  return configuredHost.workspaceDir ?? defaultWorkspaceDir();
289
294
  }
290
295
  function resolveStorageSharedWikiDir() {
291
- return join(resolveStorageWorkspaceDir(), "wiki");
296
+ return configuredHost.sharedWikiDir ?? join(resolveStorageWorkspaceDir(), "wiki");
292
297
  }
293
298
  function resolveStorageUsersLogDir() {
294
- return join(resolveStorageDataDir(), "users");
299
+ return configuredHost.usersLogDir ?? join(resolveStorageDataDir(), "users");
300
+ }
301
+ var STORAGE_PATH_KEYS = [
302
+ "dataDir",
303
+ "logDir",
304
+ "sessionAsksDir",
305
+ "workspaceDir",
306
+ "sharedWikiDir",
307
+ "usersLogDir"
308
+ ];
309
+ function normalizeStorageHostPatch(options) {
310
+ const patch = {};
311
+ if (options.database !== undefined)
312
+ patch.database = options.database;
313
+ for (const key of STORAGE_PATH_KEYS) {
314
+ const value = options[key];
315
+ if (value === undefined)
316
+ continue;
317
+ if (!value.trim())
318
+ throw new TypeError(`${key} must not be empty`);
319
+ patch[key] = resolve(value);
320
+ }
321
+ return Object.freeze(patch);
322
+ }
323
+ function refreshConfiguredHost() {
324
+ configuredHost = Object.freeze(Object.assign({}, ...storageHostFrames.filter((frame) => frame.active).map((frame) => frame.patch)));
295
325
  }
296
326
  function configureStorageHost(options) {
297
- const previous = configuredHost;
298
- configuredHost = Object.freeze({ ...previous, ...options });
299
- let restored = false;
327
+ const frame = { active: true, patch: normalizeStorageHostPatch(options) };
328
+ storageHostFrames.push(frame);
329
+ refreshConfiguredHost();
300
330
  return () => {
301
- if (restored)
331
+ if (!frame.active)
302
332
  return;
303
- restored = true;
304
- configuredHost = previous;
333
+ frame.active = false;
334
+ const index = storageHostFrames.indexOf(frame);
335
+ if (index >= 0)
336
+ storageHostFrames.splice(index, 1);
337
+ refreshConfiguredHost();
305
338
  };
306
339
  }
340
+ function resetStorageHost() {
341
+ for (const frame of storageHostFrames)
342
+ frame.active = false;
343
+ storageHostFrames.length = 0;
344
+ refreshConfiguredHost();
345
+ }
307
346
  function closeStorageDatabase() {
308
- if (configuredHost.database || !fallbackDatabase)
347
+ if (!fallbackDatabase)
309
348
  return;
310
349
  fallbackDatabase.close();
311
350
  fallbackDatabase = null;
351
+ fallbackDatabasePath = null;
312
352
  }
313
353
  function registerStorageSchemaInitializer(initialize, priority = 100) {
314
354
  schemaInitializers.push({ initialize, priority });
@@ -339,7 +379,7 @@ function ensureStorageSchemas(database = resolveStorageDatabase()) {
339
379
  initializingDatabases.delete(database);
340
380
  }
341
381
  }
342
- var storageDatabase = new Proxy({}, {
382
+ var internalStorageDatabase = new Proxy({}, {
343
383
  get(_target, property) {
344
384
  const database = resolveStorageDatabase();
345
385
  ensureStorageSchemas(database);
@@ -352,6 +392,7 @@ var storageDatabase = new Proxy({}, {
352
392
  return Reflect.set(database, property, value, database);
353
393
  }
354
394
  });
395
+ var storageDatabase = internalStorageDatabase;
355
396
 
356
397
  // ../../packages/core/src/storage/activity-log.ts
357
398
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
@@ -487,8 +528,13 @@ __export(exports_api_messages, {
487
528
  appendApiMessage: () => appendApiMessage,
488
529
  anonymizeApiMessages: () => anonymizeApiMessages
489
530
  });
531
+
532
+ // ../../packages/core/src/storage/forum-db.ts
533
+ var db = internalStorageDatabase;
534
+
535
+ // ../../packages/core/src/storage/api-messages.ts
490
536
  function initializeApiMessagesSchema() {
491
- storageDatabase.exec(`
537
+ db.exec(`
492
538
  CREATE TABLE IF NOT EXISTS api_messages (
493
539
  id TEXT PRIMARY KEY,
494
540
  topic_id TEXT NOT NULL,
@@ -512,34 +558,34 @@ function initializeApiMessagesSchema() {
512
558
  )
513
559
  `);
514
560
  try {
515
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN source_adapter TEXT");
561
+ db.exec("ALTER TABLE api_messages ADD COLUMN source_adapter TEXT");
516
562
  } catch {}
517
563
  try {
518
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0");
564
+ db.exec("ALTER TABLE api_messages ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0");
519
565
  } catch {}
520
566
  try {
521
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN edited_at TEXT");
567
+ db.exec("ALTER TABLE api_messages ADD COLUMN edited_at TEXT");
522
568
  } catch {}
523
569
  try {
524
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN reactions TEXT");
570
+ db.exec("ALTER TABLE api_messages ADD COLUMN reactions TEXT");
525
571
  } catch {}
526
572
  try {
527
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN kind TEXT");
573
+ db.exec("ALTER TABLE api_messages ADD COLUMN kind TEXT");
528
574
  } catch {}
529
575
  try {
530
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN ask_user_question TEXT");
576
+ db.exec("ALTER TABLE api_messages ADD COLUMN ask_user_question TEXT");
531
577
  } catch {}
532
578
  try {
533
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN mentions TEXT");
579
+ db.exec("ALTER TABLE api_messages ADD COLUMN mentions TEXT");
534
580
  } catch {}
535
581
  try {
536
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN thread_root_id TEXT");
582
+ db.exec("ALTER TABLE api_messages ADD COLUMN thread_root_id TEXT");
537
583
  } catch {}
538
584
  try {
539
- storageDatabase.exec("ALTER TABLE api_messages ADD COLUMN subagent_card TEXT");
585
+ db.exec("ALTER TABLE api_messages ADD COLUMN subagent_card TEXT");
540
586
  } catch {}
541
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_topic ON api_messages(topic_id)");
542
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_thread_root ON api_messages(thread_root_id)");
587
+ db.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_topic ON api_messages(topic_id)");
588
+ db.exec("CREATE INDEX IF NOT EXISTS idx_api_messages_thread_root ON api_messages(thread_root_id)");
543
589
  }
544
590
  registerStorageSchemaInitializer(initializeApiMessagesSchema, 30);
545
591
  var appendHooks = new Set;
@@ -598,14 +644,14 @@ function appendApiMessage(msg, options = {}) {
598
644
  const notify = options.notify ?? true;
599
645
  const updateTopicLastMessageAt = options.updateTopicLastMessageAt ?? true;
600
646
  let inserted = false;
601
- storageDatabase.transaction(() => {
602
- const result = storageDatabase.query(`INSERT INTO api_messages
647
+ db.transaction(() => {
648
+ const result = db.query(`INSERT INTO api_messages
603
649
  (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)
604
650
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
605
651
  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);
606
652
  inserted = Number(result.changes ?? 0) > 0;
607
653
  if (inserted && updateTopicLastMessageAt && !msg.deleted) {
608
- storageDatabase.query(`UPDATE api_topics
654
+ db.query(`UPDATE api_topics
609
655
  SET last_message_at = CASE
610
656
  WHEN last_message_at IS NULL OR last_message_at < ? THEN ?
611
657
  ELSE last_message_at
@@ -617,15 +663,15 @@ function appendApiMessage(msg, options = {}) {
617
663
  emitApiMessageAppended(msg);
618
664
  }
619
665
  function getApiMessage(topicId, messageId) {
620
- const row = storageDatabase.query("SELECT * FROM api_messages WHERE topic_id = ? AND id = ?").get(topicId, messageId);
666
+ const row = db.query("SELECT * FROM api_messages WHERE topic_id = ? AND id = ?").get(topicId, messageId);
621
667
  return row ? rowToDto(row) : null;
622
668
  }
623
669
  function topicHasAttachmentFileId(topicId, fileId) {
624
- const rows = storageDatabase.query("SELECT attachments FROM api_messages WHERE topic_id = ? AND deleted = 0 AND attachments IS NOT NULL").all(topicId);
670
+ const rows = db.query("SELECT attachments FROM api_messages WHERE topic_id = ? AND deleted = 0 AND attachments IS NOT NULL").all(topicId);
625
671
  return rows.some((row) => attachmentListHasFileId(row.attachments, fileId));
626
672
  }
627
673
  function updateApiMessageText(topicId, messageId, text, editedAt = new Date().toISOString()) {
628
- const res = storageDatabase.query(`UPDATE api_messages
674
+ const res = db.query(`UPDATE api_messages
629
675
  SET text = ?, edited_at = ?
630
676
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(text, editedAt, topicId, messageId);
631
677
  if (Number(res.changes ?? 0) === 0)
@@ -633,7 +679,7 @@ function updateApiMessageText(topicId, messageId, text, editedAt = new Date().to
633
679
  return getApiMessage(topicId, messageId);
634
680
  }
635
681
  function updateApiMessageUsage(topicId, messageId, usage) {
636
- const res = storageDatabase.query(`UPDATE api_messages
682
+ const res = db.query(`UPDATE api_messages
637
683
  SET usage = ?
638
684
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(JSON.stringify(usage), topicId, messageId);
639
685
  if (Number(res.changes ?? 0) === 0)
@@ -641,7 +687,7 @@ function updateApiMessageUsage(topicId, messageId, usage) {
641
687
  return getApiMessage(topicId, messageId);
642
688
  }
643
689
  function updateApiMessageAskUserQuestion(topicId, messageId, askUserQuestion, editedAt = new Date().toISOString()) {
644
- const res = storageDatabase.query(`UPDATE api_messages
690
+ const res = db.query(`UPDATE api_messages
645
691
  SET ask_user_question = ?, edited_at = ?
646
692
  WHERE topic_id = ? AND id = ? AND deleted = 0 AND kind = 'ask_user_question'`).run(JSON.stringify(askUserQuestion), editedAt, topicId, messageId);
647
693
  if (Number(res.changes ?? 0) === 0)
@@ -649,7 +695,7 @@ function updateApiMessageAskUserQuestion(topicId, messageId, askUserQuestion, ed
649
695
  return getApiMessage(topicId, messageId);
650
696
  }
651
697
  function updateApiMessageSubagentCard(topicId, messageId, subagentCard, editedAt = new Date().toISOString()) {
652
- const res = storageDatabase.query(`UPDATE api_messages
698
+ const res = db.query(`UPDATE api_messages
653
699
  SET subagent_card = ?, edited_at = ?
654
700
  WHERE topic_id = ? AND id = ? AND deleted = 0 AND kind = 'subagent'`).run(JSON.stringify(subagentCard), editedAt, topicId, messageId);
655
701
  if (Number(res.changes ?? 0) === 0)
@@ -657,11 +703,11 @@ function updateApiMessageSubagentCard(topicId, messageId, subagentCard, editedAt
657
703
  return getApiMessage(topicId, messageId);
658
704
  }
659
705
  function listApiMessagesByKind(kind) {
660
- const rows = storageDatabase.query("SELECT * FROM api_messages WHERE kind = ? AND deleted = 0").all(kind);
706
+ const rows = db.query("SELECT * FROM api_messages WHERE kind = ? AND deleted = 0").all(kind);
661
707
  return rows.map(rowToDto);
662
708
  }
663
709
  function setApiMessageReactions(topicId, messageId, reactions) {
664
- const res = storageDatabase.query(`UPDATE api_messages
710
+ const res = db.query(`UPDATE api_messages
665
711
  SET reactions = ?
666
712
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(reactions.length ? JSON.stringify(reactions) : null, topicId, messageId);
667
713
  if (Number(res.changes ?? 0) === 0)
@@ -669,7 +715,7 @@ function setApiMessageReactions(topicId, messageId, reactions) {
669
715
  return getApiMessage(topicId, messageId);
670
716
  }
671
717
  function softDeleteApiMessage(topicId, messageId) {
672
- const res = storageDatabase.query(`UPDATE api_messages
718
+ const res = db.query(`UPDATE api_messages
673
719
  SET deleted = 1, text = ''
674
720
  WHERE topic_id = ? AND id = ? AND deleted = 0`).run(topicId, messageId);
675
721
  if (Number(res.changes ?? 0) === 0)
@@ -680,14 +726,14 @@ function listApiMessages(topicId, options) {
680
726
  const limit = Math.max(1, Math.min(options?.limit ?? 50, 200));
681
727
  let anchorRowid = null;
682
728
  if (options?.cursor) {
683
- const cur = storageDatabase.query("SELECT rowid AS rowid FROM api_messages WHERE topic_id = ? AND id = ?").get(topicId, options.cursor);
729
+ const cur = db.query("SELECT rowid AS rowid FROM api_messages WHERE topic_id = ? AND id = ?").get(topicId, options.cursor);
684
730
  if (cur)
685
731
  anchorRowid = cur.rowid;
686
732
  }
687
- const rows = anchorRowid !== null ? storageDatabase.query(`SELECT *, rowid AS rowid FROM api_messages
733
+ const rows = anchorRowid !== null ? db.query(`SELECT *, rowid AS rowid FROM api_messages
688
734
  WHERE topic_id = ? AND deleted = 0 AND thread_root_id IS NULL AND rowid < ?
689
735
  ORDER BY rowid DESC
690
- LIMIT ?`).all(topicId, anchorRowid, limit + 1) : storageDatabase.query(`SELECT *, rowid AS rowid FROM api_messages
736
+ LIMIT ?`).all(topicId, anchorRowid, limit + 1) : db.query(`SELECT *, rowid AS rowid FROM api_messages
691
737
  WHERE topic_id = ? AND deleted = 0 AND thread_root_id IS NULL
692
738
  ORDER BY rowid DESC
693
739
  LIMIT ?`).all(topicId, limit + 1);
@@ -715,7 +761,7 @@ function getThreadSummaries(rootIds) {
715
761
  const ids = [...new Set(rootIds)].filter(Boolean);
716
762
  if (ids.length === 0)
717
763
  return out;
718
- const rows = storageDatabase.query(`SELECT thread_root_id AS rootId, COUNT(*) AS replyCount, MAX(created_at) AS lastReplyAt
764
+ const rows = db.query(`SELECT thread_root_id AS rootId, COUNT(*) AS replyCount, MAX(created_at) AS lastReplyAt
719
765
  FROM api_messages
720
766
  WHERE thread_root_id IN (${ids.map(() => "?").join(",")}) AND deleted = 0
721
767
  GROUP BY thread_root_id`).all(...ids);
@@ -726,14 +772,14 @@ function getThreadSummaries(rootIds) {
726
772
  }
727
773
  function listThreadMessages(topicId, rootId) {
728
774
  const root = getApiMessage(topicId, rootId);
729
- const rows = storageDatabase.query(`SELECT *, rowid AS rowid FROM api_messages
775
+ const rows = db.query(`SELECT *, rowid AS rowid FROM api_messages
730
776
  WHERE topic_id = ? AND thread_root_id = ? AND deleted = 0
731
777
  ORDER BY rowid ASC
732
778
  LIMIT 200`).all(topicId, rootId);
733
779
  return { root, replies: rows.map(rowToDto) };
734
780
  }
735
781
  function findRecentUserMessage(topicId, authorId, text, maxAgeMs) {
736
- const row = storageDatabase.query(`SELECT * FROM api_messages
782
+ const row = db.query(`SELECT * FROM api_messages
737
783
  WHERE topic_id = ? AND author_id = ? AND text = ?
738
784
  AND deleted = 0
739
785
  ORDER BY rowid DESC
@@ -750,7 +796,7 @@ function getLastMessagePreviews(topicIds) {
750
796
  if (uniqueTopicIds && uniqueTopicIds.length === 0)
751
797
  return new Map;
752
798
  const topicFilter = uniqueTopicIds ? `AND topic_id IN (${uniqueTopicIds.map(() => "?").join(",")})` : "";
753
- const rows = storageDatabase.query(`SELECT m.topic_id AS topic_id, m.text AS text
799
+ const rows = db.query(`SELECT m.topic_id AS topic_id, m.text AS text
754
800
  FROM api_messages m
755
801
  JOIN (
756
802
  SELECT topic_id, MAX(rowid) AS mx FROM api_messages
@@ -767,19 +813,19 @@ function getLastMessagePreviews(topicIds) {
767
813
  return out;
768
814
  }
769
815
  function deleteMessagesForTopic(topicId) {
770
- const res = storageDatabase.query("DELETE FROM api_messages WHERE topic_id = ?").run(topicId);
816
+ const res = db.query("DELETE FROM api_messages WHERE topic_id = ?").run(topicId);
771
817
  return Number(res.changes ?? 0);
772
818
  }
773
819
  function anonymizeApiMessages(userId) {
774
- storageDatabase.query("UPDATE api_messages SET author_id = 'deleted-user' WHERE author_id = ?").run(userId);
820
+ db.query("UPDATE api_messages SET author_id = 'deleted-user' WHERE author_id = ?").run(userId);
775
821
  }
776
822
  function listTopicIdsForAttachment(fileId) {
777
823
  const needle = `%"${fileId.replace(/[\\%_]/g, (char) => `\\${char}`)}"%`;
778
- const rows = storageDatabase.query("SELECT DISTINCT topic_id FROM api_messages WHERE attachments LIKE ? ESCAPE '\\'").all(needle);
824
+ const rows = db.query("SELECT DISTINCT topic_id FROM api_messages WHERE attachments LIKE ? ESCAPE '\\'").all(needle);
779
825
  return rows.map((row) => row.topic_id);
780
826
  }
781
827
  function copyMessagesForTopic(sourceTopicId, targetTopicId) {
782
- const rows = storageDatabase.query("SELECT * FROM api_messages WHERE topic_id = ? AND deleted = 0 ORDER BY rowid ASC").all(sourceTopicId);
828
+ const rows = db.query("SELECT * FROM api_messages WHERE topic_id = ? AND deleted = 0 ORDER BY rowid ASC").all(sourceTopicId);
783
829
  if (rows.length === 0)
784
830
  return 0;
785
831
  const idMap = new Map(rows.map((r) => [r.id, crypto.randomUUID()]));
@@ -800,10 +846,10 @@ function copyMessagesForTopic(sourceTopicId, targetTopicId) {
800
846
  return copied;
801
847
  }
802
848
  function getAllMessagesForTopic(topicId) {
803
- return storageDatabase.query("SELECT *, rowid AS rowid FROM api_messages WHERE topic_id = ? AND deleted = 0 ORDER BY rowid ASC").all(topicId);
849
+ return db.query("SELECT *, rowid AS rowid FROM api_messages WHERE topic_id = ? AND deleted = 0 ORDER BY rowid ASC").all(topicId);
804
850
  }
805
851
  function getMessagesForTopicAfterRowid(topicId, afterRowid) {
806
- 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);
852
+ 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);
807
853
  }
808
854
  // ../../packages/core/src/storage/api-topic-brief.ts
809
855
  var exports_api_topic_brief = {};
@@ -835,7 +881,7 @@ function rowToBrief(r) {
835
881
  };
836
882
  }
837
883
  function getTopicBrief(topicId) {
838
- 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);
884
+ 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);
839
885
  if (!row)
840
886
  return null;
841
887
  return rowToBrief(row);
@@ -852,7 +898,7 @@ function setTopicBrief(topicId, fields) {
852
898
  const briefMd = fields.briefMd !== undefined ? fields.briefMd : existing?.briefMd ?? "";
853
899
  const latestSummaryMd = fields.latestSummaryMd !== undefined ? fields.latestSummaryMd : existing?.latestSummaryMd ?? null;
854
900
  const summaryDate = fields.summaryDate !== undefined ? fields.summaryDate : existing?.summaryDate ?? null;
855
- storageDatabase.query(`INSERT INTO api_topic_brief
901
+ db.query(`INSERT INTO api_topic_brief
856
902
  (topic_id, brief_md, latest_summary_md, summary_date, updated_at)
857
903
  VALUES (?, ?, ?, ?, datetime('now'))
858
904
  ON CONFLICT(topic_id) DO UPDATE SET
@@ -863,10 +909,10 @@ function setTopicBrief(topicId, fields) {
863
909
  return getTopicBrief(topicId);
864
910
  }
865
911
  function deleteTopicBrief(topicId) {
866
- storageDatabase.query("DELETE FROM api_topic_brief WHERE topic_id = ?").run(topicId);
912
+ db.query("DELETE FROM api_topic_brief WHERE topic_id = ?").run(topicId);
867
913
  }
868
914
  function listTopicBriefs() {
869
- const rows = storageDatabase.query("SELECT topic_id, brief_md, latest_summary_md, summary_date, updated_at FROM api_topic_brief ORDER BY updated_at DESC").all();
915
+ const rows = db.query("SELECT topic_id, brief_md, latest_summary_md, summary_date, updated_at FROM api_topic_brief ORDER BY updated_at DESC").all();
870
916
  return rows.map(rowToBrief);
871
917
  }
872
918
  // ../../packages/core/src/storage/api-topic-config.ts
@@ -877,11 +923,11 @@ __export(exports_api_topic_config, {
877
923
  deleteApiTopicConfig: () => deleteApiTopicConfig
878
924
  });
879
925
  function tableColumns(table) {
880
- const rows = storageDatabase.query(`PRAGMA table_info(${table})`).all();
926
+ const rows = db.query(`PRAGMA table_info(${table})`).all();
881
927
  return new Set(rows.map((row) => row.name));
882
928
  }
883
929
  function createCanonicalConfigTable(name = "api_topic_config") {
884
- storageDatabase.exec(`
930
+ db.exec(`
885
931
  CREATE TABLE IF NOT EXISTS ${name} (
886
932
  topic_id TEXT PRIMARY KEY REFERENCES api_topics(id) ON DELETE CASCADE,
887
933
  model TEXT,
@@ -901,7 +947,7 @@ function initializeApiTopicConfigSchema() {
901
947
  const topicColumns = tableColumns("api_topics");
902
948
  const agentColumn = topicColumns.has("agent") ? "agent" : topicColumns.has("runtime_agent") ? "runtime_agent" : null;
903
949
  if (agentColumn && existingConfigColumns.has("agent")) {
904
- storageDatabase.exec(`UPDATE api_topics
950
+ db.exec(`UPDATE api_topics
905
951
  SET ${agentColumn} = (
906
952
  SELECT c.agent FROM api_topic_config c WHERE c.topic_id = api_topics.id
907
953
  )
@@ -911,15 +957,15 @@ function initializeApiTopicConfigSchema() {
911
957
  WHERE c.topic_id = api_topics.id AND c.agent IS NOT NULL
912
958
  )`);
913
959
  }
914
- const previousForeignKeys = storageDatabase.query("PRAGMA foreign_keys").get()?.foreign_keys;
915
- storageDatabase.exec("PRAGMA foreign_keys = OFF");
960
+ const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
961
+ db.exec("PRAGMA foreign_keys = OFF");
916
962
  try {
917
963
  const agentLockSource = existingConfigColumns.has("runtime_locked") ? "runtime_locked" : existingConfigColumns.has("agent_pinned") ? "agent_pinned" : "0";
918
964
  const modelLockSource = existingConfigColumns.has("model_locked") ? "model_locked" : existingConfigColumns.has("model_pinned") ? "model_pinned" : "0";
919
965
  const effortLockSource = existingConfigColumns.has("effort_locked") ? "effort_locked" : existingConfigColumns.has("effort_pinned") ? "effort_pinned" : "0";
920
- storageDatabase.transaction(() => {
966
+ db.transaction(() => {
921
967
  createCanonicalConfigTable("api_topic_config_next");
922
- storageDatabase.exec(`
968
+ db.exec(`
923
969
  INSERT INTO api_topic_config_next
924
970
  (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
925
971
  SELECT
@@ -933,11 +979,11 @@ function initializeApiTopicConfigSchema() {
933
979
  FROM api_topic_config
934
980
  WHERE EXISTS (SELECT 1 FROM api_topics t WHERE t.id = api_topic_config.topic_id)
935
981
  `);
936
- storageDatabase.exec("DROP TABLE api_topic_config");
937
- storageDatabase.exec("ALTER TABLE api_topic_config_next RENAME TO api_topic_config");
982
+ db.exec("DROP TABLE api_topic_config");
983
+ db.exec("ALTER TABLE api_topic_config_next RENAME TO api_topic_config");
938
984
  })();
939
985
  } finally {
940
- storageDatabase.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
986
+ db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
941
987
  }
942
988
  } else {
943
989
  createCanonicalConfigTable();
@@ -966,14 +1012,14 @@ function rowToConfig(r) {
966
1012
  return cfg;
967
1013
  }
968
1014
  function getApiTopicConfig(topicId) {
969
- 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);
1015
+ 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);
970
1016
  if (!row)
971
1017
  return;
972
1018
  const config = rowToConfig(row);
973
1019
  return Object.keys(config).length > 0 ? config : undefined;
974
1020
  }
975
1021
  function setApiTopicConfig(topicId, config) {
976
- storageDatabase.query(`INSERT INTO api_topic_config
1022
+ db.query(`INSERT INTO api_topic_config
977
1023
  (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
978
1024
  VALUES (?, ?, ?, ?, ?, ?, ?)
979
1025
  ON CONFLICT(topic_id) DO UPDATE SET
@@ -985,7 +1031,7 @@ function setApiTopicConfig(topicId, config) {
985
1031
  effort_locked = excluded.effort_locked`).run(topicId, config.model ?? null, config.effort ?? null, config.mcp ? JSON.stringify(config.mcp) : null, config.agentLocked ? 1 : 0, config.modelLocked ? 1 : 0, config.effortLocked ? 1 : 0);
986
1032
  }
987
1033
  function deleteApiTopicConfig(topicId) {
988
- storageDatabase.query("DELETE FROM api_topic_config WHERE topic_id = ?").run(topicId);
1034
+ db.query("DELETE FROM api_topic_config WHERE topic_id = ?").run(topicId);
989
1035
  }
990
1036
  // ../../packages/core/src/storage/api-topics.ts
991
1037
  var exports_api_topics = {};
@@ -1032,18 +1078,18 @@ var GENERAL_TOPIC_ID = "general";
1032
1078
  // ../../packages/core/src/storage/api-topics.ts
1033
1079
  var DEFAULT_AGENT_ROOM_AGENT = "maestro";
1034
1080
  function tableColumns2(table) {
1035
- const rows = storageDatabase.query(`PRAGMA table_info(${table})`).all();
1081
+ const rows = db.query(`PRAGMA table_info(${table})`).all();
1036
1082
  return new Set(rows.map((row) => row.name));
1037
1083
  }
1038
1084
  function setApiTopicAgent(topicId, agent, defaults) {
1039
1085
  if (!defaults) {
1040
- storageDatabase.query("UPDATE api_topics SET agent = ? WHERE id = ?").run(agent, topicId);
1086
+ db.query("UPDATE api_topics SET agent = ? WHERE id = ?").run(agent, topicId);
1041
1087
  return;
1042
1088
  }
1043
- storageDatabase.query("UPDATE api_topics SET agent = ?, base_model = ?, base_effort = ? WHERE id = ?").run(agent, defaults.model, defaults.effort ?? null, topicId);
1089
+ db.query("UPDATE api_topics SET agent = ?, base_model = ?, base_effort = ? WHERE id = ?").run(agent, defaults.model, defaults.effort ?? null, topicId);
1044
1090
  }
1045
1091
  function initializeApiTopicsSchema() {
1046
- storageDatabase.exec(`
1092
+ db.exec(`
1047
1093
  CREATE TABLE IF NOT EXISTS api_topics (
1048
1094
  id TEXT PRIMARY KEY,
1049
1095
  title TEXT NOT NULL,
@@ -1065,56 +1111,56 @@ function initializeApiTopicsSchema() {
1065
1111
  const needsCanonicalTopicRebuild = legacyTopicSchema || !initialTopicColumns.has("agent");
1066
1112
  if (legacyTopicSchema) {
1067
1113
  try {
1068
- storageDatabase.exec("ALTER TABLE api_topics RENAME COLUMN default_agent TO agent");
1114
+ db.exec("ALTER TABLE api_topics RENAME COLUMN default_agent TO agent");
1069
1115
  } catch {}
1070
1116
  try {
1071
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN ai_mention INTEGER NOT NULL DEFAULT 0");
1117
+ db.exec("ALTER TABLE api_topics ADD COLUMN ai_mention INTEGER NOT NULL DEFAULT 0");
1072
1118
  } catch {}
1073
1119
  try {
1074
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN parent_topic_id TEXT");
1120
+ db.exec("ALTER TABLE api_topics ADD COLUMN parent_topic_id TEXT");
1075
1121
  } catch {}
1076
1122
  try {
1077
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN is_fork INTEGER NOT NULL DEFAULT 0");
1123
+ db.exec("ALTER TABLE api_topics ADD COLUMN is_fork INTEGER NOT NULL DEFAULT 0");
1078
1124
  } catch {}
1079
1125
  try {
1080
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN is_subagent INTEGER NOT NULL DEFAULT 0");
1126
+ db.exec("ALTER TABLE api_topics ADD COLUMN is_subagent INTEGER NOT NULL DEFAULT 0");
1081
1127
  } catch {}
1082
1128
  try {
1083
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN session_id TEXT");
1129
+ db.exec("ALTER TABLE api_topics ADD COLUMN session_id TEXT");
1084
1130
  } catch {}
1085
1131
  try {
1086
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN kind TEXT NOT NULL DEFAULT 'channel'");
1132
+ db.exec("ALTER TABLE api_topics ADD COLUMN kind TEXT NOT NULL DEFAULT 'channel'");
1087
1133
  } catch {}
1088
1134
  try {
1089
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN ai_mode TEXT");
1135
+ db.exec("ALTER TABLE api_topics ADD COLUMN ai_mode TEXT");
1090
1136
  } catch {}
1091
- storageDatabase.exec(`
1137
+ db.exec(`
1092
1138
  CREATE TABLE IF NOT EXISTS api_schema_migrations (
1093
1139
  key TEXT PRIMARY KEY,
1094
1140
  applied_at TEXT NOT NULL
1095
1141
  )
1096
1142
  `);
1097
1143
  const ALWAYS_RESPOND_MIGRATION = "api_topics_ai_invited_default_always_respond_20260623";
1098
- const alwaysRespondMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(ALWAYS_RESPOND_MIGRATION);
1144
+ const alwaysRespondMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(ALWAYS_RESPOND_MIGRATION);
1099
1145
  if (!alwaysRespondMigration) {
1100
- storageDatabase.transaction(() => {
1101
- storageDatabase.query("UPDATE api_topics SET ai_mention = 0 WHERE agent IS NOT NULL").run();
1102
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(ALWAYS_RESPOND_MIGRATION, new Date().toISOString());
1146
+ db.transaction(() => {
1147
+ db.query("UPDATE api_topics SET ai_mention = 0 WHERE agent IS NOT NULL").run();
1148
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(ALWAYS_RESPOND_MIGRATION, new Date().toISOString());
1103
1149
  })();
1104
1150
  }
1105
1151
  const GENERAL_AGENT_KIND_MIGRATION = "api_topics_general_agent_kind_20260704";
1106
- const generalAgentKindMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_AGENT_KIND_MIGRATION);
1152
+ const generalAgentKindMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_AGENT_KIND_MIGRATION);
1107
1153
  if (!generalAgentKindMigration) {
1108
- storageDatabase.transaction(() => {
1109
- storageDatabase.query("UPDATE api_topics SET kind = 'agent', ai_mention = 0 WHERE id = ?").run(GENERAL_TOPIC_ID);
1110
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_AGENT_KIND_MIGRATION, new Date().toISOString());
1154
+ db.transaction(() => {
1155
+ db.query("UPDATE api_topics SET kind = 'agent', ai_mention = 0 WHERE id = ?").run(GENERAL_TOPIC_ID);
1156
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_AGENT_KIND_MIGRATION, new Date().toISOString());
1111
1157
  })();
1112
1158
  }
1113
1159
  const AI_MODE_MIGRATION = "api_topics_ai_mode_20260704";
1114
- const aiModeMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(AI_MODE_MIGRATION);
1160
+ const aiModeMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(AI_MODE_MIGRATION);
1115
1161
  if (!aiModeMigration) {
1116
- storageDatabase.transaction(() => {
1117
- storageDatabase.query(`UPDATE api_topics
1162
+ db.transaction(() => {
1163
+ db.query(`UPDATE api_topics
1118
1164
  SET
1119
1165
  kind = CASE
1120
1166
  WHEN id = ? THEN 'agent'
@@ -1130,20 +1176,20 @@ function initializeApiTopicsSchema() {
1130
1176
  WHEN ai_mention != 0 THEN 'mention'
1131
1177
  ELSE 'always'
1132
1178
  END`).run(GENERAL_TOPIC_ID, GENERAL_TOPIC_ID);
1133
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(AI_MODE_MIGRATION, new Date().toISOString());
1179
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(AI_MODE_MIGRATION, new Date().toISOString());
1134
1180
  })();
1135
1181
  }
1136
1182
  const GENERAL_MANAGER_KIND_MIGRATION = "api_topics_general_manager_kind_20260704";
1137
- const generalManagerKindMigration = storageDatabase.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_MANAGER_KIND_MIGRATION);
1183
+ const generalManagerKindMigration = db.query("SELECT key FROM api_schema_migrations WHERE key = ?").get(GENERAL_MANAGER_KIND_MIGRATION);
1138
1184
  if (!generalManagerKindMigration) {
1139
- storageDatabase.transaction(() => {
1140
- storageDatabase.query("UPDATE api_topics SET kind = 'manager', ai_mention = 0, ai_mode = 'always' WHERE id = ?").run(GENERAL_TOPIC_ID);
1141
- storageDatabase.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_MANAGER_KIND_MIGRATION, new Date().toISOString());
1185
+ db.transaction(() => {
1186
+ db.query("UPDATE api_topics SET kind = 'manager', ai_mention = 0, ai_mode = 'always' WHERE id = ?").run(GENERAL_TOPIC_ID);
1187
+ db.query("INSERT INTO api_schema_migrations (key, applied_at) VALUES (?, ?)").run(GENERAL_MANAGER_KIND_MIGRATION, new Date().toISOString());
1142
1188
  })();
1143
1189
  }
1144
1190
  }
1145
1191
  function createCanonicalTopicsTable(name) {
1146
- storageDatabase.exec(`
1192
+ db.exec(`
1147
1193
  CREATE TABLE IF NOT EXISTS ${name} (
1148
1194
  id TEXT PRIMARY KEY,
1149
1195
  title TEXT NOT NULL,
@@ -1172,7 +1218,7 @@ function initializeApiTopicsSchema() {
1172
1218
  `);
1173
1219
  }
1174
1220
  function createTopicMembersTable() {
1175
- storageDatabase.exec(`
1221
+ db.exec(`
1176
1222
  CREATE TABLE IF NOT EXISTS topic_members (
1177
1223
  topic_id TEXT NOT NULL REFERENCES api_topics(id) ON DELETE CASCADE,
1178
1224
  user_id TEXT NOT NULL,
@@ -1180,17 +1226,17 @@ function initializeApiTopicsSchema() {
1180
1226
  PRIMARY KEY (topic_id, user_id)
1181
1227
  )
1182
1228
  `);
1183
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_topic_members_user ON topic_members(user_id)");
1229
+ db.exec("CREATE INDEX IF NOT EXISTS idx_topic_members_user ON topic_members(user_id)");
1184
1230
  }
1185
1231
  if (needsCanonicalTopicRebuild) {
1186
- const legacyRows = storageDatabase.query("SELECT * FROM api_topics").all();
1187
- const existingMemberRows = tableColumns2("topic_members").has("topic_id") ? storageDatabase.query("SELECT topic_id, user_id, role FROM topic_members").all() : [];
1232
+ const legacyRows = db.query("SELECT * FROM api_topics").all();
1233
+ const existingMemberRows = tableColumns2("topic_members").has("topic_id") ? db.query("SELECT topic_id, user_id, role FROM topic_members").all() : [];
1188
1234
  const configColumns = tableColumns2("api_topic_config");
1189
- 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;
1190
- const previousForeignKeys = storageDatabase.query("PRAGMA foreign_keys").get()?.foreign_keys;
1191
- storageDatabase.exec("PRAGMA foreign_keys = OFF");
1235
+ 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;
1236
+ const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
1237
+ db.exec("PRAGMA foreign_keys = OFF");
1192
1238
  try {
1193
- storageDatabase.transaction(() => {
1239
+ db.transaction(() => {
1194
1240
  createCanonicalTopicsTable("api_topics_next");
1195
1241
  for (const row of legacyRows) {
1196
1242
  const selectedAgent = legacyAgentOverrides.get(String(row.id)) ?? row.agent ?? row.runtime_agent ?? row.default_agent ?? undefined;
@@ -1203,18 +1249,18 @@ function initializeApiTopicsSchema() {
1203
1249
  });
1204
1250
  const legacyBaseModel = row.base_model ?? row.default_model;
1205
1251
  const legacyBaseEffort = row.base_effort ?? row.default_effort;
1206
- storageDatabase.query(`INSERT INTO api_topics_next
1252
+ db.query(`INSERT INTO api_topics_next
1207
1253
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
1208
1254
  created_at,last_message_at,parent_topic_id,is_fork,is_subagent,visibility,access_mode,session_id)
1209
1255
  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);
1210
1256
  }
1211
- storageDatabase.exec("DROP TABLE IF EXISTS topic_members");
1212
- storageDatabase.exec("DROP TABLE api_topics");
1213
- storageDatabase.exec("ALTER TABLE api_topics_next RENAME TO api_topics");
1257
+ db.exec("DROP TABLE IF EXISTS topic_members");
1258
+ db.exec("DROP TABLE api_topics");
1259
+ db.exec("ALTER TABLE api_topics_next RENAME TO api_topics");
1214
1260
  createTopicMembersTable();
1215
1261
  if (existingMemberRows.length > 0) {
1216
1262
  for (const member of existingMemberRows) {
1217
- 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");
1263
+ 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");
1218
1264
  }
1219
1265
  } else {
1220
1266
  for (const row of legacyRows) {
@@ -1229,31 +1275,31 @@ function initializeApiTopicsSchema() {
1229
1275
  for (const participant of participants) {
1230
1276
  if (!participant?.userId)
1231
1277
  continue;
1232
- 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");
1278
+ 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");
1233
1279
  }
1234
1280
  }
1235
1281
  }
1236
1282
  })();
1237
1283
  } finally {
1238
- storageDatabase.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
1284
+ db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
1239
1285
  }
1240
1286
  } else {
1241
1287
  createCanonicalTopicsTable("api_topics");
1242
1288
  createTopicMembersTable();
1243
1289
  }
1244
1290
  if (!tableColumns2("api_topics").has("visibility")) {
1245
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
1291
+ db.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
1246
1292
  }
1247
1293
  if (!tableColumns2("api_topics").has("access_mode")) {
1248
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN access_mode TEXT NOT NULL DEFAULT 'private'");
1294
+ db.exec("ALTER TABLE api_topics ADD COLUMN access_mode TEXT NOT NULL DEFAULT 'private'");
1249
1295
  }
1250
1296
  if (!tableColumns2("api_topics").has("browser_profile")) {
1251
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
1297
+ db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
1252
1298
  }
1253
1299
  if (!tableColumns2("api_topics").has("browser_profile_owner")) {
1254
- storageDatabase.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
1300
+ db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
1255
1301
  }
1256
- storageDatabase.exec(`
1302
+ db.exec(`
1257
1303
  UPDATE api_topics
1258
1304
  SET browser_profile_owner = (
1259
1305
  SELECT m.user_id FROM topic_members m
@@ -1263,17 +1309,18 @@ function initializeApiTopicsSchema() {
1263
1309
  )
1264
1310
  WHERE browser_profile_owner IS NULL
1265
1311
  `);
1312
+ db.exec("CREATE INDEX IF NOT EXISTS idx_api_topics_last_message ON api_topics(last_message_at DESC)");
1266
1313
  }
1267
1314
  registerStorageSchemaInitializer(initializeApiTopicsSchema, 20);
1268
1315
  function shortSessionId(sessionId) {
1269
1316
  return sessionId ? sessionId.slice(0, 8) : null;
1270
1317
  }
1271
1318
  function getTopicParticipants(topicId) {
1272
- 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 }));
1319
+ 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 }));
1273
1320
  }
1274
1321
  function getAllTopicParticipants() {
1275
1322
  const grouped = new Map;
1276
- const rows = storageDatabase.query("SELECT topic_id, user_id, role FROM topic_members ORDER BY rowid").all();
1323
+ const rows = db.query("SELECT topic_id, user_id, role FROM topic_members ORDER BY rowid").all();
1277
1324
  for (const row of rows) {
1278
1325
  const participants = grouped.get(row.topic_id) ?? [];
1279
1326
  participants.push({ userId: row.user_id, role: row.role });
@@ -1387,8 +1434,8 @@ function upsertTopic(t) {
1387
1434
  aiMode: normalizeAiMode(t.aiMode),
1388
1435
  aiMention: t.aiMention
1389
1436
  });
1390
- storageDatabase.transaction(() => {
1391
- storageDatabase.query(`INSERT INTO api_topics
1437
+ db.transaction(() => {
1438
+ db.query(`INSERT INTO api_topics
1392
1439
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
1393
1440
  created_at,last_message_at,parent_topic_id,is_fork,is_subagent,visibility,access_mode)
1394
1441
  VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
@@ -1407,29 +1454,29 @@ function upsertTopic(t) {
1407
1454
  is_subagent = excluded.is_subagent,
1408
1455
  visibility = excluded.visibility,
1409
1456
  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));
1410
- storageDatabase.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
1457
+ db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
1411
1458
  for (const participant of t.participants) {
1412
- storageDatabase.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
1459
+ db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
1413
1460
  }
1414
1461
  const initialBrowserProfileOwner = t.participants.find((participant) => participant.role === "owner")?.userId;
1415
1462
  if (initialBrowserProfileOwner) {
1416
- storageDatabase.query(`UPDATE api_topics
1463
+ db.query(`UPDATE api_topics
1417
1464
  SET browser_profile_owner = COALESCE(browser_profile_owner, ?)
1418
1465
  WHERE id = ?`).run(initialBrowserProfileOwner, t.id);
1419
1466
  }
1420
1467
  })();
1421
1468
  }
1422
1469
  function listTopics() {
1423
- const rows = storageDatabase.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
1470
+ const rows = db.query("SELECT * FROM api_topics ORDER BY last_message_at DESC").all();
1424
1471
  const participants = getAllTopicParticipants();
1425
1472
  return rows.map((row) => rowToDto2(row, participants.get(row.id) ?? []));
1426
1473
  }
1427
1474
  function getTopic(id) {
1428
- const r = storageDatabase.query("SELECT * FROM api_topics WHERE id = ?").get(id);
1475
+ const r = db.query("SELECT * FROM api_topics WHERE id = ?").get(id);
1429
1476
  return r ? rowToDto2(r) : null;
1430
1477
  }
1431
1478
  function getManagerTopicForUser(userId) {
1432
- const row = storageDatabase.query(`SELECT t.* FROM api_topics t
1479
+ const row = db.query(`SELECT t.* FROM api_topics t
1433
1480
  JOIN topic_members m ON m.topic_id = t.id
1434
1481
  WHERE t.kind = 'manager'
1435
1482
  AND t.id != ?
@@ -1454,18 +1501,18 @@ function getTopicMemoryOrigin(id) {
1454
1501
  return current;
1455
1502
  }
1456
1503
  function getTopicByName(title) {
1457
- const r = storageDatabase.query("SELECT * FROM api_topics WHERE LOWER(title) = LOWER(?)").get(title);
1504
+ const r = db.query("SELECT * FROM api_topics WHERE LOWER(title) = LOWER(?)").get(title);
1458
1505
  return r ? rowToDto2(r) : null;
1459
1506
  }
1460
1507
  function getTopicByNameAndKind(title, kind) {
1461
- const r = storageDatabase.query("SELECT * FROM api_topics WHERE LOWER(title) = LOWER(?) AND kind = ?").get(title, kind);
1508
+ const r = db.query("SELECT * FROM api_topics WHERE LOWER(title) = LOWER(?) AND kind = ?").get(title, kind);
1462
1509
  return r ? rowToDto2(r) : null;
1463
1510
  }
1464
1511
  function findTopicTitleConflict(title, kind, opts = {}) {
1465
1512
  const wanted = normalizedTitle(title);
1466
1513
  const generalTitleRequested = wanted === normalizedTitle(GENERAL_TOPIC_ID);
1467
1514
  if (generalTitleRequested && opts.excludeTopicId !== GENERAL_TOPIC_ID) {
1468
- const general = storageDatabase.query("SELECT * FROM api_topics WHERE id = ?").get(GENERAL_TOPIC_ID);
1515
+ const general = db.query("SELECT * FROM api_topics WHERE id = ?").get(GENERAL_TOPIC_ID);
1469
1516
  if (general)
1470
1517
  return rowToDto2(general);
1471
1518
  }
@@ -1480,7 +1527,7 @@ function findTopicTitleConflict(title, kind, opts = {}) {
1480
1527
  params.push(opts.excludeTopicId);
1481
1528
  }
1482
1529
  sql += " LIMIT 1";
1483
- const row = storageDatabase.query(sql).get(...params);
1530
+ const row = db.query(sql).get(...params);
1484
1531
  return row ? rowToDto2(row) : null;
1485
1532
  }
1486
1533
  function getTopicByNameForUser(title, userId) {
@@ -1488,7 +1535,7 @@ function getTopicByNameForUser(title, userId) {
1488
1535
  const qualified = /^(agent|channel|manager):(.+)$/i.exec(trimmed);
1489
1536
  const requestedKind = qualified ? normalizeTopicKind(qualified[1]?.toLowerCase()) : null;
1490
1537
  const requestedTitle = qualified ? qualified[2].trim() : trimmed;
1491
- const rows = storageDatabase.query(`SELECT t.* FROM api_topics t
1538
+ const rows = db.query(`SELECT t.* FROM api_topics t
1492
1539
  WHERE LOWER(t.title) = LOWER(?)
1493
1540
  AND t.id != ?
1494
1541
  AND t.visibility != 'hidden'
@@ -1500,7 +1547,7 @@ function getTopicByNameForUser(title, userId) {
1500
1547
  }
1501
1548
  function setTopicSessionId(topicId, sessionId, context = {}) {
1502
1549
  const previous = getTopicSessionId(topicId);
1503
- const result = storageDatabase.query("UPDATE api_topics SET session_id = ? WHERE id = ?").run(sessionId, topicId);
1550
+ const result = db.query("UPDATE api_topics SET session_id = ? WHERE id = ?").run(sessionId, topicId);
1504
1551
  const changes = Number(result.changes ?? 0);
1505
1552
  const logContext = {
1506
1553
  topicId,
@@ -1520,7 +1567,7 @@ function setTopicSessionId(topicId, sessionId, context = {}) {
1520
1567
  }
1521
1568
  function clearTopicSessionId(topicId, reason = "unspecified") {
1522
1569
  const previous = getTopicSessionId(topicId);
1523
- const result = storageDatabase.query("UPDATE api_topics SET session_id = NULL WHERE id = ?").run(topicId);
1570
+ const result = db.query("UPDATE api_topics SET session_id = NULL WHERE id = ?").run(topicId);
1524
1571
  const changes = Number(result.changes ?? 0);
1525
1572
  const logContext = { topicId, previousSessionId: shortSessionId(previous), reason };
1526
1573
  if (changes === 0) {
@@ -1532,35 +1579,35 @@ function clearTopicSessionId(topicId, reason = "unspecified") {
1532
1579
  }
1533
1580
  }
1534
1581
  function getTopicSessionId(topicId) {
1535
- const r = storageDatabase.query("SELECT session_id FROM api_topics WHERE id = ?").get(topicId);
1582
+ const r = db.query("SELECT session_id FROM api_topics WHERE id = ?").get(topicId);
1536
1583
  return r?.session_id ?? null;
1537
1584
  }
1538
1585
  function deleteTopic(id, options = {}) {
1539
- const r = storageDatabase.query("SELECT id, kind FROM api_topics WHERE id = ?").get(id);
1586
+ const r = db.query("SELECT id, kind FROM api_topics WHERE id = ?").get(id);
1540
1587
  if (!r)
1541
1588
  return false;
1542
1589
  if (id === GENERAL_TOPIC_ID || r.kind === "manager" && !options.allowManager)
1543
1590
  return false;
1544
- storageDatabase.query("DELETE FROM api_topics WHERE id = ?").run(id);
1591
+ db.query("DELETE FROM api_topics WHERE id = ?").run(id);
1545
1592
  return true;
1546
1593
  }
1547
1594
  function reparentTopicChildren(deletedTopicId, replacementParentTopicId) {
1548
- const rows = storageDatabase.query("SELECT id FROM api_topics WHERE parent_topic_id = ?").all(deletedTopicId);
1595
+ const rows = db.query("SELECT id FROM api_topics WHERE parent_topic_id = ?").all(deletedTopicId);
1549
1596
  if (rows.length === 0)
1550
1597
  return [];
1551
- storageDatabase.query("UPDATE api_topics SET parent_topic_id = ? WHERE parent_topic_id = ?").run(replacementParentTopicId, deletedTopicId);
1598
+ db.query("UPDATE api_topics SET parent_topic_id = ? WHERE parent_topic_id = ?").run(replacementParentTopicId, deletedTopicId);
1552
1599
  return rows.map((row) => row.id);
1553
1600
  }
1554
1601
  function addParticipantToDB(topicId, userId, role) {
1555
- if (!storageDatabase.query("SELECT 1 FROM api_topics WHERE id = ?").get(topicId))
1602
+ if (!db.query("SELECT 1 FROM api_topics WHERE id = ?").get(topicId))
1556
1603
  return false;
1557
- storageDatabase.query("INSERT OR IGNORE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(topicId, userId, role);
1604
+ db.query("INSERT OR IGNORE INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(topicId, userId, role);
1558
1605
  return true;
1559
1606
  }
1560
1607
  function removeParticipantFromDB(topicId, userId) {
1561
- if (!storageDatabase.query("SELECT 1 FROM api_topics WHERE id = ?").get(topicId))
1608
+ if (!db.query("SELECT 1 FROM api_topics WHERE id = ?").get(topicId))
1562
1609
  return false;
1563
- storageDatabase.query("DELETE FROM topic_members WHERE topic_id = ? AND user_id = ?").run(topicId, userId);
1610
+ db.query("DELETE FROM topic_members WHERE topic_id = ? AND user_id = ?").run(topicId, userId);
1564
1611
  return true;
1565
1612
  }
1566
1613
  // ../../packages/core/src/storage/app-settings.ts
@@ -1778,7 +1825,7 @@ function errMsg(e, fallback) {
1778
1825
 
1779
1826
  // ../../packages/core/src/storage/forum/schema.ts
1780
1827
  function initializeForumSchema() {
1781
- storageDatabase.exec(`
1828
+ db.exec(`
1782
1829
  CREATE TABLE IF NOT EXISTS users (
1783
1830
  id TEXT PRIMARY KEY,
1784
1831
  dm_session_id TEXT,
@@ -1807,7 +1854,7 @@ function initializeForumSchema() {
1807
1854
  `);
1808
1855
  function tryMigrate(sql, expectedMsg) {
1809
1856
  try {
1810
- storageDatabase.exec(sql);
1857
+ db.exec(sql);
1811
1858
  } catch (e) {
1812
1859
  if (expectedMsg && errMsg(e).includes(expectedMsg))
1813
1860
  return;
@@ -1826,10 +1873,10 @@ function initializeForumSchema() {
1826
1873
  return String(value);
1827
1874
  }
1828
1875
  function columnExists(table, column) {
1829
- return storageDatabase.query(`PRAGMA table_info(${table})`).all().some((c) => c.name === column);
1876
+ return db.query(`PRAGMA table_info(${table})`).all().some((c) => c.name === column);
1830
1877
  }
1831
1878
  function tableSql(table) {
1832
- return storageDatabase.query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?").get(table)?.sql ?? null;
1879
+ return db.query("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?").get(table)?.sql ?? null;
1833
1880
  }
1834
1881
  function dropColumnIfExists(table, column) {
1835
1882
  if (columnExists(table, column)) {
@@ -1840,7 +1887,7 @@ function initializeForumSchema() {
1840
1887
  const sql = tableSql("topics");
1841
1888
  if (!sql)
1842
1889
  return false;
1843
- const cols = storageDatabase.query("PRAGMA table_info(topics)").all();
1890
+ const cols = db.query("PRAGMA table_info(topics)").all();
1844
1891
  const names = new Set(cols.map((c) => c.name));
1845
1892
  return names.has("forum_group_id") || names.has("system_prompt_extra") || names.has("model") || names.has("effort") || names.has("model_pinned") || names.has("effort_pinned") || names.has("memory_files") || names.has("memory_summary") || names.has("privacy_mode") || names.has("advisor_enabled") || names.has("agent_settings") || !/PRIMARY KEY \(\s*user_id\s*,\s*name\s*\)/i.test(sql);
1846
1893
  }
@@ -1854,11 +1901,11 @@ function initializeForumSchema() {
1854
1901
  function rebuildTopicsTableIfNeeded() {
1855
1902
  if (!topicTableNeedsRebuild())
1856
1903
  return;
1857
- const cols = storageDatabase.query("PRAGMA table_info(topics)").all();
1904
+ const cols = db.query("PRAGMA table_info(topics)").all();
1858
1905
  const has = new Set(cols.map((c) => c.name));
1859
1906
  const pick = (row, column, fallback = null) => has.has(column) ? row[column] ?? fallback : fallback;
1860
1907
  const descriptionFor = (row) => pick(row, "description", pick(row, "system_prompt_extra", null));
1861
- const rows = storageDatabase.query("SELECT rowid AS __rowid, * FROM topics").all().sort((a, b) => {
1908
+ const rows = db.query("SELECT rowid AS __rowid, * FROM topics").all().sort((a, b) => {
1862
1909
  const aCreated = String(pick(a, "created_at", ""));
1863
1910
  const bCreated = String(pick(b, "created_at", ""));
1864
1911
  const byDate = bCreated.localeCompare(aCreated);
@@ -1866,12 +1913,12 @@ function initializeForumSchema() {
1866
1913
  return byDate;
1867
1914
  return Number(b.__rowid ?? 0) - Number(a.__rowid ?? 0);
1868
1915
  });
1869
- const previousForeignKeys = storageDatabase.query("PRAGMA foreign_keys").get()?.foreign_keys;
1870
- storageDatabase.exec("PRAGMA foreign_keys = OFF");
1916
+ const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
1917
+ db.exec("PRAGMA foreign_keys = OFF");
1871
1918
  try {
1872
- storageDatabase.transaction(() => {
1873
- storageDatabase.exec("DROP TABLE IF EXISTS topics_new");
1874
- storageDatabase.exec(`
1919
+ db.transaction(() => {
1920
+ db.exec("DROP TABLE IF EXISTS topics_new");
1921
+ db.exec(`
1875
1922
  CREATE TABLE topics_new (
1876
1923
  user_id TEXT NOT NULL REFERENCES users(id),
1877
1924
  name TEXT NOT NULL,
@@ -1890,7 +1937,7 @@ function initializeForumSchema() {
1890
1937
  UNIQUE (user_id, message_thread_id)
1891
1938
  )
1892
1939
  `);
1893
- const insert = storageDatabase.query(`
1940
+ const insert = db.query(`
1894
1941
  INSERT OR IGNORE INTO topics_new
1895
1942
  (user_id, name, message_thread_id, session_id, created_at, description,
1896
1943
  fork_origin, agent, mcp_enabled, mcp_extra, last_shown_model,
@@ -1904,13 +1951,13 @@ function initializeForumSchema() {
1904
1951
  if (Number(result.changes ?? 0) > 0)
1905
1952
  inserted += 1;
1906
1953
  }
1907
- storageDatabase.exec("DROP TABLE topics");
1908
- storageDatabase.exec("ALTER TABLE topics_new RENAME TO topics");
1909
- storageDatabase.exec("CREATE INDEX IF NOT EXISTS idx_topics_lookup ON topics(user_id, message_thread_id)");
1954
+ db.exec("DROP TABLE topics");
1955
+ db.exec("ALTER TABLE topics_new RENAME TO topics");
1956
+ db.exec("CREATE INDEX IF NOT EXISTS idx_topics_lookup ON topics(user_id, message_thread_id)");
1910
1957
  logger.info({ migrated: inserted, skippedConflicts: rows.length - inserted }, "topics schema migrated to current user-scoped schema");
1911
1958
  })();
1912
1959
  } finally {
1913
- storageDatabase.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
1960
+ db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
1914
1961
  }
1915
1962
  }
1916
1963
  rebuildTopicsTableIfNeeded();
@@ -1974,14 +2021,14 @@ function flushSessionCache() {
1974
2021
 
1975
2022
  // ../../packages/core/src/storage/forum/agent-settings.ts
1976
2023
  function getTopicAgent(userId, topicName) {
1977
- const row = storageDatabase.query("SELECT agent FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2024
+ const row = db.query("SELECT agent FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
1978
2025
  const value = row?.agent;
1979
2026
  if (!isAgentKind(value))
1980
2027
  throw new Error(`Invalid agent in DB: ${value}`);
1981
2028
  return value;
1982
2029
  }
1983
2030
  function setTopicAgent(userId, topicName, agent) {
1984
- const result = storageDatabase.query("UPDATE topics SET agent = ? WHERE user_id = ? AND name = ?").run(agent, String(userId), topicName);
2031
+ const result = db.query("UPDATE topics SET agent = ? WHERE user_id = ? AND name = ?").run(agent, String(userId), topicName);
1985
2032
  return result.changes > 0;
1986
2033
  }
1987
2034
  // ../../packages/core/src/storage/forum/repository.ts
@@ -1997,10 +2044,10 @@ function defaultSessionAgent() {
1997
2044
  return "maestro";
1998
2045
  }
1999
2046
  function getUserConfig(userId) {
2000
- const user = storageDatabase.query("SELECT * FROM users WHERE id = ?").get(String(userId));
2047
+ const user = db.query("SELECT * FROM users WHERE id = ?").get(String(userId));
2001
2048
  if (!user)
2002
2049
  return null;
2003
- const topicRows = storageDatabase.query("SELECT * FROM topics WHERE user_id = ?").all(String(userId));
2050
+ const topicRows = db.query("SELECT * FROM topics WHERE user_id = ?").all(String(userId));
2004
2051
  const topics = {};
2005
2052
  for (const row of topicRows)
2006
2053
  topics[row.name] = rowToTopic(row);
@@ -2011,45 +2058,45 @@ function getUserConfig(userId) {
2011
2058
  };
2012
2059
  }
2013
2060
  function getTopicByName2(userId, name) {
2014
- const row = storageDatabase.query("SELECT * FROM topics WHERE user_id = ? AND name = ?").get(String(userId), name);
2061
+ const row = db.query("SELECT * FROM topics WHERE user_id = ? AND name = ?").get(String(userId), name);
2015
2062
  return row ? rowToTopic(row) : null;
2016
2063
  }
2017
2064
  function findUserByThread(threadId) {
2018
- const row = storageDatabase.query("SELECT * FROM topics WHERE message_thread_id = ?").get(threadId);
2065
+ const row = db.query("SELECT * FROM topics WHERE message_thread_id = ?").get(threadId);
2019
2066
  if (!row)
2020
2067
  return null;
2021
2068
  return { userId: Number(row.user_id), topic: rowToTopic(row) };
2022
2069
  }
2023
2070
  function getSessionForTopic(userId, topicName) {
2024
- const row = storageDatabase.query("SELECT session_id FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2071
+ const row = db.query("SELECT session_id FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2025
2072
  return row?.session_id || null;
2026
2073
  }
2027
2074
  function getTopicNames(userId) {
2028
- const rows = storageDatabase.query("SELECT name FROM topics WHERE user_id = ?").all(String(userId));
2075
+ const rows = db.query("SELECT name FROM topics WHERE user_id = ?").all(String(userId));
2029
2076
  return rows.map((r) => r.name);
2030
2077
  }
2031
2078
  function getAllTopics(userId) {
2032
- const rows = storageDatabase.query("SELECT * FROM topics WHERE user_id = ?").all(String(userId));
2079
+ const rows = db.query("SELECT * FROM topics WHERE user_id = ?").all(String(userId));
2033
2080
  return rows.map(rowToTopic);
2034
2081
  }
2035
2082
  function getAllUserIds() {
2036
- const rows = storageDatabase.query("SELECT id FROM users").all();
2083
+ const rows = db.query("SELECT id FROM users").all();
2037
2084
  return rows.map((r) => Number(r.id)).filter((n) => !Number.isNaN(n));
2038
2085
  }
2039
2086
  function getCommunicateThreadId(userId) {
2040
- const row = storageDatabase.query("SELECT communicate_thread_id FROM users WHERE id = ?").get(String(userId));
2087
+ const row = db.query("SELECT communicate_thread_id FROM users WHERE id = ?").get(String(userId));
2041
2088
  return row?.communicate_thread_id ?? null;
2042
2089
  }
2043
2090
  function getDmSessionId(userId) {
2044
- const row = storageDatabase.query("SELECT dm_session_id FROM users WHERE id = ?").get(String(userId));
2091
+ const row = db.query("SELECT dm_session_id FROM users WHERE id = ?").get(String(userId));
2045
2092
  return row?.dm_session_id ?? null;
2046
2093
  }
2047
2094
  function getTopicDescription(userId, topicName) {
2048
- const row = storageDatabase.query("SELECT description FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2095
+ const row = db.query("SELECT description FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2049
2096
  return row?.description || null;
2050
2097
  }
2051
2098
  function getTopicMcpConfig(userId, topicName) {
2052
- const row = storageDatabase.query("SELECT mcp_enabled, mcp_extra FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2099
+ const row = db.query("SELECT mcp_enabled, mcp_extra FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2053
2100
  let enabled = null;
2054
2101
  let extra = {};
2055
2102
  try {
@@ -2071,8 +2118,8 @@ function addTopic(userId, name, messageThreadId, sessionId, createdAt) {
2071
2118
  logger.warn({ name }, "addTopic: refusing reserved __ prefix");
2072
2119
  return false;
2073
2120
  }
2074
- storageDatabase.query("INSERT OR IGNORE INTO users (id) VALUES (?)").run(String(userId));
2075
- storageDatabase.query(`
2121
+ db.query("INSERT OR IGNORE INTO users (id) VALUES (?)").run(String(userId));
2122
+ db.query(`
2076
2123
  INSERT INTO topics (user_id, name, message_thread_id, session_id, created_at, agent)
2077
2124
  VALUES (?, ?, ?, ?, ?, ?)
2078
2125
  ON CONFLICT(user_id, name) DO UPDATE SET
@@ -2087,59 +2134,59 @@ function renameTopic(userId, oldName, newName) {
2087
2134
  return { ok: true };
2088
2135
  if (getTopicByName2(userId, newName))
2089
2136
  return { ok: false, reason: "name_taken" };
2090
- const result = storageDatabase.prepare("UPDATE topics SET name = ? WHERE user_id = ? AND name = ?").run(newName, String(userId), oldName);
2137
+ const result = db.prepare("UPDATE topics SET name = ? WHERE user_id = ? AND name = ?").run(newName, String(userId), oldName);
2091
2138
  if (result.changes === 0)
2092
2139
  return { ok: false, reason: "not_found" };
2093
2140
  return { ok: true };
2094
2141
  }
2095
2142
  function removeTopic(userId, name) {
2096
- storageDatabase.query("DELETE FROM topics WHERE user_id = ? AND name = ?").run(String(userId), name);
2143
+ db.query("DELETE FROM topics WHERE user_id = ? AND name = ?").run(String(userId), name);
2097
2144
  }
2098
2145
  function setSessionForTopic(userId, topicName, sessionId) {
2099
- storageDatabase.query("UPDATE topics SET session_id = ? WHERE user_id = ? AND name = ?").run(sessionId, String(userId), topicName);
2146
+ db.query("UPDATE topics SET session_id = ? WHERE user_id = ? AND name = ?").run(sessionId, String(userId), topicName);
2100
2147
  }
2101
2148
  function clearSessionForTopic(userId, topicName) {
2102
- storageDatabase.query("UPDATE topics SET session_id = NULL WHERE user_id = ? AND name = ?").run(String(userId), topicName);
2149
+ db.query("UPDATE topics SET session_id = NULL WHERE user_id = ? AND name = ?").run(String(userId), topicName);
2103
2150
  }
2104
2151
  function setDmSessionId(userId, sessionId) {
2105
- storageDatabase.query(`
2152
+ db.query(`
2106
2153
  INSERT INTO users (id, dm_session_id) VALUES (?, ?)
2107
2154
  ON CONFLICT(id) DO UPDATE SET dm_session_id = excluded.dm_session_id
2108
2155
  `).run(String(userId), sessionId);
2109
2156
  }
2110
2157
  function clearDmSessionId(userId) {
2111
- storageDatabase.query("UPDATE users SET dm_session_id = NULL WHERE id = ?").run(String(userId));
2158
+ db.query("UPDATE users SET dm_session_id = NULL WHERE id = ?").run(String(userId));
2112
2159
  }
2113
2160
  function setTopicDescription(userId, topicName, description) {
2114
- const result = storageDatabase.query("UPDATE topics SET description = ? WHERE user_id = ? AND name = ?").run(description, String(userId), topicName);
2161
+ const result = db.query("UPDATE topics SET description = ? WHERE user_id = ? AND name = ?").run(description, String(userId), topicName);
2115
2162
  return result.changes > 0;
2116
2163
  }
2117
2164
  function getLastShownConfig(userId, topicName) {
2118
- const row = storageDatabase.query("SELECT last_shown_agent, last_shown_model, last_shown_effort FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2165
+ const row = db.query("SELECT last_shown_agent, last_shown_model, last_shown_effort FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2119
2166
  if (!row)
2120
2167
  return null;
2121
2168
  const agent = row.last_shown_agent && isAgentKind(row.last_shown_agent) ? row.last_shown_agent : null;
2122
2169
  return { agent, model: row.last_shown_model, effort: row.last_shown_effort };
2123
2170
  }
2124
2171
  function setLastShownConfig(userId, topicName, agent, model, effort) {
2125
- const result = storageDatabase.query("UPDATE topics SET last_shown_agent = ?, last_shown_model = ?, last_shown_effort = ? WHERE user_id = ? AND name = ?").run(agent, model, effort ?? null, String(userId), topicName);
2172
+ const result = db.query("UPDATE topics SET last_shown_agent = ?, last_shown_model = ?, last_shown_effort = ? WHERE user_id = ? AND name = ?").run(agent, model, effort ?? null, String(userId), topicName);
2126
2173
  return result.changes > 0;
2127
2174
  }
2128
2175
  function setTopicForkOrigin(userId, topicName, origin) {
2129
- const result = storageDatabase.query("UPDATE topics SET fork_origin = ? WHERE user_id = ? AND name = ?").run(origin, String(userId), topicName);
2176
+ const result = db.query("UPDATE topics SET fork_origin = ? WHERE user_id = ? AND name = ?").run(origin, String(userId), topicName);
2130
2177
  return result.changes > 0;
2131
2178
  }
2132
2179
  function updateTopicThreadId(userId, topicName, newThreadId) {
2133
- const result = storageDatabase.query("UPDATE topics SET message_thread_id = ? WHERE user_id = ? AND name = ?").run(newThreadId, String(userId), topicName);
2180
+ const result = db.query("UPDATE topics SET message_thread_id = ? WHERE user_id = ? AND name = ?").run(newThreadId, String(userId), topicName);
2134
2181
  return result.changes > 0;
2135
2182
  }
2136
2183
  function setTopicMcpEnabled(userId, topicName, enabled) {
2137
2184
  const value = enabled !== null ? JSON.stringify(enabled) : null;
2138
- const result = storageDatabase.query("UPDATE topics SET mcp_enabled = ? WHERE user_id = ? AND name = ?").run(value, String(userId), topicName);
2185
+ const result = db.query("UPDATE topics SET mcp_enabled = ? WHERE user_id = ? AND name = ?").run(value, String(userId), topicName);
2139
2186
  return result.changes > 0;
2140
2187
  }
2141
2188
  function setTopicMcpExtra(userId, topicName, extra) {
2142
- const result = storageDatabase.query("UPDATE topics SET mcp_extra = ? WHERE user_id = ? AND name = ?").run(JSON.stringify(extra), String(userId), topicName);
2189
+ const result = db.query("UPDATE topics SET mcp_extra = ? WHERE user_id = ? AND name = ?").run(JSON.stringify(extra), String(userId), topicName);
2143
2190
  return result.changes > 0;
2144
2191
  }
2145
2192
  // ../../packages/core/src/storage/session-asks.ts
@@ -2170,7 +2217,7 @@ import { dirname as dirname5, join as join5 } from "path";
2170
2217
  var PENDING_ASK_TTL_MS = 15 * 60 * 1000;
2171
2218
  function pendingAskDir(userId) {
2172
2219
  const rawUserId = String(userId);
2173
- const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) ? rawUserId : `sha256-${createHash("sha256").update(rawUserId).digest("hex")}`;
2220
+ const safeUserId = /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash("sha256").update(rawUserId).digest("hex")}`;
2174
2221
  return join5(resolveStorageSessionAsksDir(), safeUserId);
2175
2222
  }
2176
2223
  var ASK_FILENAME_PREFIX = "v3-";
@@ -2231,6 +2278,12 @@ function readPendingAskFile(path, fallback) {
2231
2278
  const parsed = JSON.parse(raw);
2232
2279
  if (!parsed.requestId || !parsed.from || !parsed.to)
2233
2280
  return null;
2281
+ if (parsed.userId !== undefined && String(parsed.userId) !== String(fallback.userId))
2282
+ return null;
2283
+ if (fallback.from && parsed.from !== fallback.from)
2284
+ return null;
2285
+ if (fallback.to && parsed.to !== fallback.to)
2286
+ return null;
2234
2287
  const now = new Date().toISOString();
2235
2288
  return {
2236
2289
  userId: fallback.userId,
@@ -2498,6 +2551,10 @@ function describePendingAskState(state) {
2498
2551
  return "\uC751\uB2F5\uC744 \uC774 \uC138\uC158\uC5D0 \uC8FC\uC785 \uC911";
2499
2552
  }
2500
2553
  }
2554
+ // ../../packages/core/src/storage/storage-public-host.ts
2555
+ var configureStorageHost2 = configureStorageHost;
2556
+ var resetStorageHost2 = resetStorageHost;
2557
+ var db2 = storageDatabase;
2501
2558
  // ../../packages/core/src/storage/tasks.ts
2502
2559
  var exports_tasks = {};
2503
2560
  __export(exports_tasks, {
@@ -2666,7 +2723,7 @@ function emptyBucket() {
2666
2723
  }
2667
2724
  function tokenStatsFileId(userId) {
2668
2725
  const rawUserId = String(userId);
2669
- return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) ? rawUserId : `sha256-${createHash2("sha256").update(rawUserId).digest("hex")}`;
2726
+ return /^[A-Za-z0-9][A-Za-z0-9_.@-]{0,255}$/.test(rawUserId) && !rawUserId.includes("..") ? rawUserId : `sha256-${createHash2("sha256").update(rawUserId).digest("hex")}`;
2670
2727
  }
2671
2728
  function queriesPath(userId) {
2672
2729
  const fileId = tokenStatsFileId(userId);
@@ -2900,7 +2957,7 @@ registerStorageSchemaInitializer((database) => {
2900
2957
  `);
2901
2958
  }, 30);
2902
2959
  function getTopicArchiveState(topicId) {
2903
- const row = storageDatabase.query("SELECT * FROM api_topic_archive_state WHERE topic_id = ?").get(topicId);
2960
+ const row = db.query("SELECT * FROM api_topic_archive_state WHERE topic_id = ?").get(topicId);
2904
2961
  if (!row)
2905
2962
  return null;
2906
2963
  return {
@@ -2911,7 +2968,7 @@ function getTopicArchiveState(topicId) {
2911
2968
  };
2912
2969
  }
2913
2970
  function setTopicArchiveState(topicId, lastArchivedRowid, lastArchivePath) {
2914
- storageDatabase.query(`INSERT INTO api_topic_archive_state (topic_id, last_archived_rowid, last_archive_path, updated_at)
2971
+ db.query(`INSERT INTO api_topic_archive_state (topic_id, last_archived_rowid, last_archive_path, updated_at)
2915
2972
  VALUES (?, ?, ?, ?)
2916
2973
  ON CONFLICT(topic_id) DO UPDATE SET
2917
2974
  last_archived_rowid = excluded.last_archived_rowid,
@@ -2919,7 +2976,7 @@ function setTopicArchiveState(topicId, lastArchivedRowid, lastArchivePath) {
2919
2976
  updated_at = excluded.updated_at`).run(topicId, lastArchivedRowid, lastArchivePath ?? null, new Date().toISOString());
2920
2977
  }
2921
2978
  function deleteTopicArchiveState(topicId) {
2922
- return storageDatabase.query("DELETE FROM api_topic_archive_state WHERE topic_id = ?").run(topicId).changes > 0;
2979
+ return db.query("DELETE FROM api_topic_archive_state WHERE topic_id = ?").run(topicId).changes > 0;
2923
2980
  }
2924
2981
  // ../../packages/core/src/storage/topic-settings.ts
2925
2982
  var exports_topic_settings = {};
@@ -2937,13 +2994,13 @@ function toTopicAgentSwitchState(row) {
2937
2994
  };
2938
2995
  }
2939
2996
  function getTopicAgentSwitchState(userId, topicName) {
2940
- const row = storageDatabase.query("SELECT name, agent FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2997
+ const row = db.query("SELECT name, agent FROM topics WHERE user_id = ? AND name = ?").get(String(userId), topicName);
2941
2998
  return row ? toTopicAgentSwitchState(row) : null;
2942
2999
  }
2943
3000
  function setTopicAgentAndSession(opts) {
2944
3001
  const { userId, topicName, agent, sessionId } = opts;
2945
- storageDatabase.transaction(() => {
2946
- const r = storageDatabase.query("UPDATE topics SET agent = ?, session_id = ? WHERE user_id = ? AND name = ?").run(agent, sessionId, String(userId), topicName);
3002
+ db.transaction(() => {
3003
+ const r = db.query("UPDATE topics SET agent = ?, session_id = ? WHERE user_id = ? AND name = ?").run(agent, sessionId, String(userId), topicName);
2947
3004
  if (r.changes === 0) {
2948
3005
  throw new Error(`setTopicAgentAndSession: row missing for ${userId}/${topicName}`);
2949
3006
  }
@@ -2952,8 +3009,8 @@ function setTopicAgentAndSession(opts) {
2952
3009
  function setTopicAgentAndClearSession(opts) {
2953
3010
  const { userId, topicName, agent } = opts;
2954
3011
  let changed = false;
2955
- storageDatabase.transaction(() => {
2956
- const r = storageDatabase.query("UPDATE topics SET agent = ?, session_id = NULL WHERE user_id = ? AND name = ?").run(agent, String(userId), topicName);
3012
+ db.transaction(() => {
3013
+ const r = db.query("UPDATE topics SET agent = ?, session_id = NULL WHERE user_id = ? AND name = ?").run(agent, String(userId), topicName);
2957
3014
  changed = r.changes > 0;
2958
3015
  })();
2959
3016
  return changed;
@@ -3039,6 +3096,7 @@ export {
3039
3096
  exports_session_asks as sessionAsks,
3040
3097
  rotateOldLogs,
3041
3098
  resolveTopicBrief,
3099
+ resetStorageHost2 as resetStorageHost,
3042
3100
  replaceConversationStrict,
3043
3101
  reparentTopicChildren,
3044
3102
  renderTaskList,
@@ -3121,12 +3179,12 @@ export {
3121
3179
  deletePendingAsksForTopic,
3122
3180
  deleteMessagesForTopic,
3123
3181
  deleteApiTopicConfig,
3124
- storageDatabase as db,
3182
+ db2 as db,
3125
3183
  createTasks,
3126
3184
  createPendingAsk,
3127
3185
  copyMessagesForTopic,
3128
3186
  exports_conversations as conversations,
3129
- configureStorageHost,
3187
+ configureStorageHost2 as configureStorageHost,
3130
3188
  cloneConversationLog,
3131
3189
  clearTopicSessionId,
3132
3190
  clearSessionForTopic,
@@ -3153,4 +3211,4 @@ export {
3153
3211
  DEFAULT_AI_NAME
3154
3212
  };
3155
3213
 
3156
- //# debugId=11D9BB9680B7A81064756E2164756E21
3214
+ //# debugId=2E4BC25D01BF122564756E2164756E21