negotium 0.6.6 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/agent-helpers.js +168 -152
  2. package/dist/agent-helpers.js.map +11 -11
  3. package/dist/{chunk-pxnv3gh2.js → chunk-f124y9d0.js} +2 -2
  4. package/dist/{chunk-pxnv3gh2.js.map → chunk-f124y9d0.js.map} +2 -2
  5. package/dist/hosted-agent.js +2 -2
  6. package/dist/hosted-agent.js.map +2 -2
  7. package/dist/main.js +40 -16
  8. package/dist/main.js.map +12 -12
  9. package/dist/mcp-factories.js +29 -13
  10. package/dist/mcp-factories.js.map +9 -9
  11. package/dist/registry.js +1 -1
  12. package/dist/runtime/src/agents/archiver.ts +25 -7
  13. package/dist/runtime/src/agents/idle-archiver.ts +1 -0
  14. package/dist/runtime/src/application/topic-service.ts +5 -1
  15. package/dist/runtime/src/runtime/turn-event-stream.ts +2 -1
  16. package/dist/runtime/src/runtime/turn-runner.ts +8 -1
  17. package/dist/runtime/src/runtime-gateway.ts +6 -2
  18. package/dist/runtime/src/topics/lifecycle.ts +4 -1
  19. package/dist/runtime/src/topics/session.ts +15 -9
  20. package/dist/runtime/src/version.ts +1 -1
  21. package/dist/runtime-gateway.js +7 -6
  22. package/dist/runtime-gateway.js.map +3 -3
  23. package/dist/types/packages/core/src/agents/archiver.d.ts +3 -1
  24. package/dist/types/packages/core/src/runtime/turn-event-stream.d.ts +1 -0
  25. package/dist/types/packages/core/src/runtime/turn-runner.d.ts +1 -0
  26. package/dist/types/packages/core/src/runtime-gateway.d.ts +2 -2
  27. package/dist/types/packages/core/src/topics/lifecycle.d.ts +2 -0
  28. package/dist/types/packages/core/src/topics/session.d.ts +2 -0
  29. package/dist/types/packages/core/src/version.d.ts +1 -1
  30. package/package.json +1 -1
@@ -2980,7 +2980,7 @@ var init_codex = __esm(async () => {
2980
2980
  });
2981
2981
 
2982
2982
  // ../../packages/core/src/version.ts
2983
- var NEGOTIUM_VERSION = "0.6.6";
2983
+ var NEGOTIUM_VERSION = "0.6.7";
2984
2984
 
2985
2985
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
2986
2986
  import { spawn as spawn2 } from "child_process";
@@ -7463,132 +7463,6 @@ var init_api_topic_brief = __esm(async () => {
7463
7463
  }, 30);
7464
7464
  });
7465
7465
 
7466
- // ../../packages/core/src/storage/wiki.ts
7467
- import { basename as basename2, dirname as dirname11, join as join15 } from "path";
7468
- function getSharedWikiDir(workspaceDir = resolveStorageWorkspaceDir()) {
7469
- return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join15(workspaceDir, "wiki");
7470
- }
7471
- var init_wiki = __esm(async () => {
7472
- await init_storage_host();
7473
- });
7474
-
7475
- // ../../packages/core/src/storage/api-topic-config.ts
7476
- function tableColumns(table) {
7477
- const rows = db.query(`PRAGMA table_info(${table})`).all();
7478
- return new Set(rows.map((row) => row.name));
7479
- }
7480
- function createCanonicalConfigTable(name = "api_topic_config") {
7481
- db.exec(`
7482
- CREATE TABLE IF NOT EXISTS ${name} (
7483
- topic_id TEXT PRIMARY KEY REFERENCES api_topics(id) ON DELETE CASCADE,
7484
- model TEXT,
7485
- effort TEXT CHECK (effort IS NULL OR effort IN ('low','medium','high','xhigh','max')),
7486
- mcp TEXT,
7487
- agent_locked INTEGER NOT NULL DEFAULT 0 CHECK (agent_locked IN (0,1)),
7488
- model_locked INTEGER NOT NULL DEFAULT 0 CHECK (model_locked IN (0,1)),
7489
- effort_locked INTEGER NOT NULL DEFAULT 0 CHECK (effort_locked IN (0,1))
7490
- )
7491
- `);
7492
- }
7493
- function initializeApiTopicConfigSchema() {
7494
- const existingConfigColumns = tableColumns("api_topic_config");
7495
- if (existingConfigColumns.size === 0) {
7496
- createCanonicalConfigTable();
7497
- } else if (existingConfigColumns.has("agent") || existingConfigColumns.has("agent_pinned") || existingConfigColumns.has("runtime_locked") || existingConfigColumns.has("model_pinned") || existingConfigColumns.has("effort_pinned") || existingConfigColumns.has("last_shown_agent")) {
7498
- const topicColumns = tableColumns("api_topics");
7499
- const agentColumn = topicColumns.has("agent") ? "agent" : topicColumns.has("runtime_agent") ? "runtime_agent" : null;
7500
- if (agentColumn && existingConfigColumns.has("agent")) {
7501
- db.exec(`UPDATE api_topics
7502
- SET ${agentColumn} = (
7503
- SELECT c.agent FROM api_topic_config c WHERE c.topic_id = api_topics.id
7504
- )
7505
- WHERE ${agentColumn} IS NULL
7506
- AND EXISTS (
7507
- SELECT 1 FROM api_topic_config c
7508
- WHERE c.topic_id = api_topics.id AND c.agent IS NOT NULL
7509
- )`);
7510
- }
7511
- const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
7512
- db.exec("PRAGMA foreign_keys = OFF");
7513
- try {
7514
- const agentLockSource = existingConfigColumns.has("runtime_locked") ? "runtime_locked" : existingConfigColumns.has("agent_pinned") ? "agent_pinned" : "0";
7515
- const modelLockSource = existingConfigColumns.has("model_locked") ? "model_locked" : existingConfigColumns.has("model_pinned") ? "model_pinned" : "0";
7516
- const effortLockSource = existingConfigColumns.has("effort_locked") ? "effort_locked" : existingConfigColumns.has("effort_pinned") ? "effort_pinned" : "0";
7517
- db.transaction(() => {
7518
- createCanonicalConfigTable("api_topic_config_next");
7519
- db.exec(`
7520
- INSERT INTO api_topic_config_next
7521
- (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
7522
- SELECT
7523
- topic_id,
7524
- model,
7525
- effort,
7526
- mcp,
7527
- COALESCE(${agentLockSource}, 0),
7528
- COALESCE(${modelLockSource}, 0),
7529
- COALESCE(${effortLockSource}, 0)
7530
- FROM api_topic_config
7531
- WHERE EXISTS (SELECT 1 FROM api_topics t WHERE t.id = api_topic_config.topic_id)
7532
- `);
7533
- db.exec("DROP TABLE api_topic_config");
7534
- db.exec("ALTER TABLE api_topic_config_next RENAME TO api_topic_config");
7535
- })();
7536
- } finally {
7537
- db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
7538
- }
7539
- } else {
7540
- createCanonicalConfigTable();
7541
- }
7542
- }
7543
- function rowToConfig(r) {
7544
- const cfg = {};
7545
- if (r.model)
7546
- cfg.model = r.model;
7547
- if (r.effort)
7548
- cfg.effort = r.effort;
7549
- if (r.mcp) {
7550
- try {
7551
- const parsed = JSON.parse(r.mcp);
7552
- if (Array.isArray(parsed))
7553
- cfg.mcp = parsed;
7554
- } catch {}
7555
- }
7556
- if (r.agent_locked)
7557
- cfg.agentLocked = true;
7558
- if (r.model_locked)
7559
- cfg.modelLocked = true;
7560
- if (r.effort_locked)
7561
- cfg.effortLocked = true;
7562
- return cfg;
7563
- }
7564
- function getApiTopicConfig(topicId) {
7565
- 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);
7566
- if (!row)
7567
- return;
7568
- const config = rowToConfig(row);
7569
- return Object.keys(config).length > 0 ? config : undefined;
7570
- }
7571
- function setApiTopicConfig(topicId, config) {
7572
- db.query(`INSERT INTO api_topic_config
7573
- (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
7574
- VALUES (?, ?, ?, ?, ?, ?, ?)
7575
- ON CONFLICT(topic_id) DO UPDATE SET
7576
- model = excluded.model,
7577
- effort = excluded.effort,
7578
- mcp = excluded.mcp,
7579
- agent_locked = excluded.agent_locked,
7580
- model_locked = excluded.model_locked,
7581
- 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);
7582
- }
7583
- function deleteApiTopicConfig(topicId) {
7584
- db.query("DELETE FROM api_topic_config WHERE topic_id = ?").run(topicId);
7585
- }
7586
- var init_api_topic_config = __esm(async () => {
7587
- await init_forum_db();
7588
- await init_storage_host();
7589
- registerStorageSchemaInitializer(initializeApiTopicConfigSchema, 40);
7590
- });
7591
-
7592
7466
  // ../../packages/core/src/storage/api-topics.ts
7593
7467
  function defaultTopicSurface() {
7594
7468
  return normalizeTopicSurface(process.env.NEGOTIUM_DEFAULT_SURFACE);
@@ -7605,7 +7479,7 @@ function normalizeSurfaceScope(value) {
7605
7479
  function defaultSurfaceScope() {
7606
7480
  return activeSurfaceScope ?? normalizeSurfaceScope(process.env.NEGOTIUM_SURFACE_SCOPE);
7607
7481
  }
7608
- function tableColumns2(table) {
7482
+ function tableColumns(table) {
7609
7483
  const rows = db.query(`PRAGMA table_info(${table})`).all();
7610
7484
  return new Set(rows.map((row) => row.name));
7611
7485
  }
@@ -7634,7 +7508,7 @@ function initializeApiTopicsSchema() {
7634
7508
  ai_mode TEXT
7635
7509
  )
7636
7510
  `);
7637
- const initialTopicColumns = tableColumns2("api_topics");
7511
+ const initialTopicColumns = tableColumns("api_topics");
7638
7512
  const legacyTopicSchema = !initialTopicColumns.has("response_policy");
7639
7513
  const needsCanonicalTopicRebuild = legacyTopicSchema || !initialTopicColumns.has("agent");
7640
7514
  if (legacyTopicSchema) {
@@ -7761,8 +7635,8 @@ function initializeApiTopicsSchema() {
7761
7635
  }
7762
7636
  if (needsCanonicalTopicRebuild) {
7763
7637
  const legacyRows = db.query("SELECT * FROM api_topics").all();
7764
- const existingMemberRows = tableColumns2("topic_members").has("topic_id") ? db.query("SELECT topic_id, user_id, role FROM topic_members").all() : [];
7765
- const configColumns = tableColumns2("api_topic_config");
7638
+ const existingMemberRows = tableColumns("topic_members").has("topic_id") ? db.query("SELECT topic_id, user_id, role FROM topic_members").all() : [];
7639
+ const configColumns = tableColumns("api_topic_config");
7766
7640
  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;
7767
7641
  const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
7768
7642
  db.exec("PRAGMA foreign_keys = OFF");
@@ -7834,35 +7708,35 @@ function initializeApiTopicsSchema() {
7834
7708
  OR granted_by_topic_id NOT IN (SELECT id FROM api_topics)
7835
7709
  `);
7836
7710
  db.exec("DELETE FROM topic_members WHERE topic_id NOT IN (SELECT id FROM api_topics)");
7837
- if (!tableColumns2("api_topics").has("visibility")) {
7711
+ if (!tableColumns("api_topics").has("visibility")) {
7838
7712
  db.exec("ALTER TABLE api_topics ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible'");
7839
7713
  }
7840
- if (!tableColumns2("api_topics").has("surface")) {
7714
+ if (!tableColumns("api_topics").has("surface")) {
7841
7715
  db.exec("ALTER TABLE api_topics ADD COLUMN surface TEXT NOT NULL DEFAULT 'terminal'");
7842
7716
  }
7843
- if (!tableColumns2("api_topics").has("surface_scope")) {
7717
+ if (!tableColumns("api_topics").has("surface_scope")) {
7844
7718
  db.exec("ALTER TABLE api_topics ADD COLUMN surface_scope TEXT");
7845
7719
  }
7846
- if (tableColumns2("api_topics").has("access_mode")) {
7720
+ if (tableColumns("api_topics").has("access_mode")) {
7847
7721
  try {
7848
7722
  db.exec("ALTER TABLE api_topics DROP COLUMN access_mode");
7849
7723
  } catch (err) {
7850
7724
  logger.warn({ err }, "api_topics: could not drop the retired access_mode column");
7851
7725
  }
7852
7726
  }
7853
- if (!tableColumns2("api_topics").has("browser_profile")) {
7727
+ if (!tableColumns("api_topics").has("browser_profile")) {
7854
7728
  db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile TEXT NOT NULL DEFAULT 'default'");
7855
7729
  }
7856
- if (!tableColumns2("api_topics").has("browser_profile_owner")) {
7730
+ if (!tableColumns("api_topics").has("browser_profile_owner")) {
7857
7731
  db.exec("ALTER TABLE api_topics ADD COLUMN browser_profile_owner TEXT");
7858
7732
  }
7859
- if (!tableColumns2("api_topics").has("subagent_report_mode")) {
7733
+ if (!tableColumns("api_topics").has("subagent_report_mode")) {
7860
7734
  db.exec("ALTER TABLE api_topics ADD COLUMN subagent_report_mode TEXT NOT NULL DEFAULT 'auto'");
7861
7735
  }
7862
- if (!tableColumns2("api_topics").has("memory_topic_id")) {
7736
+ if (!tableColumns("api_topics").has("memory_topic_id")) {
7863
7737
  db.exec("ALTER TABLE api_topics ADD COLUMN memory_topic_id TEXT");
7864
7738
  }
7865
- if (!tableColumns2("api_topics").has("memory_key")) {
7739
+ if (!tableColumns("api_topics").has("memory_key")) {
7866
7740
  db.exec("ALTER TABLE api_topics ADD COLUMN memory_key TEXT");
7867
7741
  }
7868
7742
  db.exec(`
@@ -8238,6 +8112,132 @@ var init_api_topics = __esm(async () => {
8238
8112
  registerStorageSchemaInitializer(initializeApiTopicsSchema, 20);
8239
8113
  });
8240
8114
 
8115
+ // ../../packages/core/src/storage/wiki.ts
8116
+ import { basename as basename2, dirname as dirname11, join as join15 } from "path";
8117
+ function getSharedWikiDir(workspaceDir = resolveStorageWorkspaceDir()) {
8118
+ return workspaceDir === resolveStorageWorkspaceDir() ? resolveStorageSharedWikiDir() : join15(workspaceDir, "wiki");
8119
+ }
8120
+ var init_wiki = __esm(async () => {
8121
+ await init_storage_host();
8122
+ });
8123
+
8124
+ // ../../packages/core/src/storage/api-topic-config.ts
8125
+ function tableColumns2(table) {
8126
+ const rows = db.query(`PRAGMA table_info(${table})`).all();
8127
+ return new Set(rows.map((row) => row.name));
8128
+ }
8129
+ function createCanonicalConfigTable(name = "api_topic_config") {
8130
+ db.exec(`
8131
+ CREATE TABLE IF NOT EXISTS ${name} (
8132
+ topic_id TEXT PRIMARY KEY REFERENCES api_topics(id) ON DELETE CASCADE,
8133
+ model TEXT,
8134
+ effort TEXT CHECK (effort IS NULL OR effort IN ('low','medium','high','xhigh','max')),
8135
+ mcp TEXT,
8136
+ agent_locked INTEGER NOT NULL DEFAULT 0 CHECK (agent_locked IN (0,1)),
8137
+ model_locked INTEGER NOT NULL DEFAULT 0 CHECK (model_locked IN (0,1)),
8138
+ effort_locked INTEGER NOT NULL DEFAULT 0 CHECK (effort_locked IN (0,1))
8139
+ )
8140
+ `);
8141
+ }
8142
+ function initializeApiTopicConfigSchema() {
8143
+ const existingConfigColumns = tableColumns2("api_topic_config");
8144
+ if (existingConfigColumns.size === 0) {
8145
+ createCanonicalConfigTable();
8146
+ } else if (existingConfigColumns.has("agent") || existingConfigColumns.has("agent_pinned") || existingConfigColumns.has("runtime_locked") || existingConfigColumns.has("model_pinned") || existingConfigColumns.has("effort_pinned") || existingConfigColumns.has("last_shown_agent")) {
8147
+ const topicColumns = tableColumns2("api_topics");
8148
+ const agentColumn = topicColumns.has("agent") ? "agent" : topicColumns.has("runtime_agent") ? "runtime_agent" : null;
8149
+ if (agentColumn && existingConfigColumns.has("agent")) {
8150
+ db.exec(`UPDATE api_topics
8151
+ SET ${agentColumn} = (
8152
+ SELECT c.agent FROM api_topic_config c WHERE c.topic_id = api_topics.id
8153
+ )
8154
+ WHERE ${agentColumn} IS NULL
8155
+ AND EXISTS (
8156
+ SELECT 1 FROM api_topic_config c
8157
+ WHERE c.topic_id = api_topics.id AND c.agent IS NOT NULL
8158
+ )`);
8159
+ }
8160
+ const previousForeignKeys = db.query("PRAGMA foreign_keys").get()?.foreign_keys;
8161
+ db.exec("PRAGMA foreign_keys = OFF");
8162
+ try {
8163
+ const agentLockSource = existingConfigColumns.has("runtime_locked") ? "runtime_locked" : existingConfigColumns.has("agent_pinned") ? "agent_pinned" : "0";
8164
+ const modelLockSource = existingConfigColumns.has("model_locked") ? "model_locked" : existingConfigColumns.has("model_pinned") ? "model_pinned" : "0";
8165
+ const effortLockSource = existingConfigColumns.has("effort_locked") ? "effort_locked" : existingConfigColumns.has("effort_pinned") ? "effort_pinned" : "0";
8166
+ db.transaction(() => {
8167
+ createCanonicalConfigTable("api_topic_config_next");
8168
+ db.exec(`
8169
+ INSERT INTO api_topic_config_next
8170
+ (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
8171
+ SELECT
8172
+ topic_id,
8173
+ model,
8174
+ effort,
8175
+ mcp,
8176
+ COALESCE(${agentLockSource}, 0),
8177
+ COALESCE(${modelLockSource}, 0),
8178
+ COALESCE(${effortLockSource}, 0)
8179
+ FROM api_topic_config
8180
+ WHERE EXISTS (SELECT 1 FROM api_topics t WHERE t.id = api_topic_config.topic_id)
8181
+ `);
8182
+ db.exec("DROP TABLE api_topic_config");
8183
+ db.exec("ALTER TABLE api_topic_config_next RENAME TO api_topic_config");
8184
+ })();
8185
+ } finally {
8186
+ db.exec(`PRAGMA foreign_keys = ${previousForeignKeys ? "ON" : "OFF"}`);
8187
+ }
8188
+ } else {
8189
+ createCanonicalConfigTable();
8190
+ }
8191
+ }
8192
+ function rowToConfig(r) {
8193
+ const cfg = {};
8194
+ if (r.model)
8195
+ cfg.model = r.model;
8196
+ if (r.effort)
8197
+ cfg.effort = r.effort;
8198
+ if (r.mcp) {
8199
+ try {
8200
+ const parsed = JSON.parse(r.mcp);
8201
+ if (Array.isArray(parsed))
8202
+ cfg.mcp = parsed;
8203
+ } catch {}
8204
+ }
8205
+ if (r.agent_locked)
8206
+ cfg.agentLocked = true;
8207
+ if (r.model_locked)
8208
+ cfg.modelLocked = true;
8209
+ if (r.effort_locked)
8210
+ cfg.effortLocked = true;
8211
+ return cfg;
8212
+ }
8213
+ function getApiTopicConfig(topicId) {
8214
+ 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);
8215
+ if (!row)
8216
+ return;
8217
+ const config = rowToConfig(row);
8218
+ return Object.keys(config).length > 0 ? config : undefined;
8219
+ }
8220
+ function setApiTopicConfig(topicId, config) {
8221
+ db.query(`INSERT INTO api_topic_config
8222
+ (topic_id, model, effort, mcp, agent_locked, model_locked, effort_locked)
8223
+ VALUES (?, ?, ?, ?, ?, ?, ?)
8224
+ ON CONFLICT(topic_id) DO UPDATE SET
8225
+ model = excluded.model,
8226
+ effort = excluded.effort,
8227
+ mcp = excluded.mcp,
8228
+ agent_locked = excluded.agent_locked,
8229
+ model_locked = excluded.model_locked,
8230
+ 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);
8231
+ }
8232
+ function deleteApiTopicConfig(topicId) {
8233
+ db.query("DELETE FROM api_topic_config WHERE topic_id = ?").run(topicId);
8234
+ }
8235
+ var init_api_topic_config = __esm(async () => {
8236
+ await init_forum_db();
8237
+ await init_storage_host();
8238
+ registerStorageSchemaInitializer(initializeApiTopicConfigSchema, 40);
8239
+ });
8240
+
8241
8241
  // ../../packages/core/src/topics/personal-general.ts
8242
8242
  import { randomUUID as randomUUID5 } from "crypto";
8243
8243
  function ensurePersonalGeneral(userId, surface, opts = {}) {
@@ -8352,6 +8352,7 @@ function createArchiverRuntime(host) {
8352
8352
  const runTurn = (params) => {
8353
8353
  const {
8354
8354
  userId,
8355
+ sourceTopicId,
8355
8356
  topicId,
8356
8357
  topicTitle,
8357
8358
  archivePath,
@@ -8359,6 +8360,7 @@ function createArchiverRuntime(host) {
8359
8360
  messageCount,
8360
8361
  mode = "deleted-topic"
8361
8362
  } = params;
8363
+ const generalTopicId = host.storage.getGeneralTopicId(userId, sourceTopicId);
8362
8364
  let definition;
8363
8365
  try {
8364
8366
  definition = getAgentDefinition();
@@ -8517,7 +8519,7 @@ function createArchiverRuntime(host) {
8517
8519
  }
8518
8520
  }
8519
8521
  const text = finalText.trimEnd();
8520
- finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, mode, topicId, ok && text ? { text, agent, model, usage } : undefined);
8522
+ finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, mode, topicId, generalTopicId, ok && text ? { text, agent, model, usage } : undefined);
8521
8523
  });
8522
8524
  topicQueues.set(safeTopic, work);
8523
8525
  work.finally(() => {
@@ -8563,14 +8565,14 @@ function findSummaryFile(storage, topicTitle, date, sinceMs, topicId) {
8563
8565
  }
8564
8566
  return best?.path ?? null;
8565
8567
  }
8566
- function finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, mode, topicId, generalReply) {
8567
- const generalTopicId = host.storage.getGeneralTopicId(userId);
8568
+ function finalizeGeneralMemory(host, userId, topicTitle, messageCount, startMs, ok, mode, topicId, generalTopicId, generalReply) {
8569
+ const resolvedGeneralTopicId = generalTopicId ?? host.storage.getGeneralTopicId(userId, topicId);
8568
8570
  const date = host.config.now().toISOString().slice(0, 10);
8569
8571
  try {
8570
8572
  const summaryPath = ok ? findSummaryFile(host.storage, topicTitle, date, startMs, topicId) : null;
8571
8573
  const summaryMd = summaryPath ? host.storage.readTextFile(summaryPath) : "";
8572
8574
  const oneLine = summaryMd && distillOneLine(summaryMd) || `Archived ${messageCount} messages`;
8573
- const prev = host.storage.getTopicBrief(generalTopicId);
8575
+ const prev = host.storage.getTopicBrief(resolvedGeneralTopicId);
8574
8576
  const prevEntries = (prev?.briefMd ?? "").split(`
8575
8577
  `).map((l) => l.trim()).filter((l) => l.startsWith("- "));
8576
8578
  const newEntry = `- **${topicTitle}** (${date}): ${oneLine}`;
@@ -8585,7 +8587,7 @@ Recent memory digest distilled from archived topics (deletions and idle/session-
8585
8587
  ## Recent Archives
8586
8588
  ${rolled.join(`
8587
8589
  `)}`;
8588
- host.storage.setTopicBrief(generalTopicId, {
8590
+ host.storage.setTopicBrief(resolvedGeneralTopicId, {
8589
8591
  briefMd,
8590
8592
  ...summaryMd ? { latestSummaryMd: summaryMd, summaryDate: date } : {}
8591
8593
  });
@@ -8604,13 +8606,13 @@ ${rolled.join(`
8604
8606
  } : { authorId: "system" };
8605
8607
  const msg = {
8606
8608
  id: host.config.createId(),
8607
- topicId: generalTopicId,
8609
+ topicId: resolvedGeneralTopicId,
8608
8610
  text,
8609
8611
  ...replyMeta,
8610
8612
  createdAt: host.config.now().toISOString()
8611
8613
  };
8612
8614
  host.messaging.appendMessage(msg);
8613
- host.messaging.broadcastMessage(generalTopicId, msg);
8615
+ host.messaging.broadcastMessage(resolvedGeneralTopicId, msg);
8614
8616
  } catch (err) {
8615
8617
  host.config.warn({ err, topicTitle }, "archiver: failed to post #General notification");
8616
8618
  }
@@ -8629,6 +8631,7 @@ var init_archiver = __esm(async () => {
8629
8631
  init_background_session_policy();
8630
8632
  await init_api_messages();
8631
8633
  await init_api_topic_brief();
8634
+ await init_api_topics();
8632
8635
  await init_wiki();
8633
8636
  init_wiki_summary_names();
8634
8637
  await init_personal_general();
@@ -8640,7 +8643,12 @@ var init_archiver = __esm(async () => {
8640
8643
  readTextFile: (path) => readFileSync13(path, "utf-8"),
8641
8644
  fileSize: (path) => statSync6(path).size,
8642
8645
  fileModifiedAt: (path) => statSync6(path).mtimeMs,
8643
- getGeneralTopicId: (userId) => ensurePersonalGeneral(userId).id,
8646
+ getGeneralTopicId: (userId, sourceTopicId) => {
8647
+ const source = sourceTopicId ? getTopic(sourceTopicId) : null;
8648
+ return source ? ensurePersonalGeneral(userId, source.surface, {
8649
+ surfaceScope: source.surfaceScope ?? null
8650
+ }).id : ensurePersonalGeneral(userId).id;
8651
+ },
8644
8652
  getTopicBrief,
8645
8653
  setTopicBrief: (topicId, fields) => {
8646
8654
  setTopicBrief(topicId, fields);
@@ -9828,6 +9836,7 @@ function archiveActiveTopicForMemory(topicId, userId, options) {
9828
9836
  const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
9829
9837
  const launched = (options.launchArchiver ?? runArchiverTurn)({
9830
9838
  userId,
9839
+ sourceTopicId: topic.id,
9831
9840
  topicId: memoryTopic.id,
9832
9841
  topicTitle: memoryTitle,
9833
9842
  archivePath: job.archivePath,
@@ -14502,7 +14511,8 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
14502
14511
  const memoryTopic = topic.memoryKey ? topic : getTopicMemoryOrigin(topicId) ?? topic;
14503
14512
  const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
14504
14513
  runArchiverTurn({
14505
- userId,
14514
+ userId: options.memoryUserId ?? userId,
14515
+ sourceTopicId: topicId,
14506
14516
  ...memoryTopic.id !== topicId && !deletingTopicIds.has(memoryTopic.id) ? { topicId: memoryTopic.id } : {},
14507
14517
  topicTitle: memoryTitle,
14508
14518
  archivePath: archived.path,
@@ -15756,7 +15766,7 @@ ${JSON.stringify(event.input ?? {})}`);
15756
15766
  }
15757
15767
  }
15758
15768
  if (!silent) {
15759
- scheduleIdleArchiveForTopic(topicId, userId);
15769
+ scheduleIdleArchiveForTopic(topicId, execution?.actorUserId ?? userId);
15760
15770
  hub.broadcastDone(topicId, queryId, event.usage ? {
15761
15771
  input: event.usage.inputTokens,
15762
15772
  output: event.usage.outputTokens,
@@ -17127,7 +17137,13 @@ function startAiTurn(params) {
17127
17137
  WsHub.get().broadcastTyping(topicId, "ai");
17128
17138
  WsHub.get().broadcastAiActive(topicId, queryId);
17129
17139
  }
17130
- streamAgentEvents(topicId, topic.title, queryId, events, control, agentKind, resolvedModel, resolvedEffort, userId, !sessionRetried, onSessionId, { silent, peerBridge, sourceNode, ...threadRootId ? { threadRootId } : {} }).then(async (streamOutcome) => {
17140
+ streamAgentEvents(topicId, topic.title, queryId, events, control, agentKind, resolvedModel, resolvedEffort, userId, !sessionRetried, onSessionId, {
17141
+ silent,
17142
+ actorUserId: params.actorUserId,
17143
+ peerBridge,
17144
+ sourceNode,
17145
+ ...threadRootId ? { threadRootId } : {}
17146
+ }).then(async (streamOutcome) => {
17131
17147
  let outcome = streamOutcome;
17132
17148
  if (outcome.kind === "session-expired") {
17133
17149
  const retry = resolveSessionRetry({
@@ -19299,4 +19315,4 @@ export {
19299
19315
  DEFAULT_SELF_CONFIG_PRODUCT
19300
19316
  };
19301
19317
 
19302
- //# debugId=FE024E0414DA725F64756E2164756E21
19318
+ //# debugId=E2BEA0E09AFF549864756E2164756E21