negotium 0.2.17 → 0.2.19

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 (38) hide show
  1. package/dist/agent-helpers.js +41 -32
  2. package/dist/agent-helpers.js.map +10 -10
  3. package/dist/{chunk-5cpdbbeh.js → chunk-fc58cqry.js} +3 -1
  4. package/dist/{chunk-5cpdbbeh.js.map → chunk-fc58cqry.js.map} +3 -3
  5. package/dist/hosted-agent.js +4 -2
  6. package/dist/hosted-agent.js.map +4 -4
  7. package/dist/main.js +1377 -285
  8. package/dist/main.js.map +14 -13
  9. package/dist/mcp-factories.js +1497 -403
  10. package/dist/mcp-factories.js.map +14 -13
  11. package/dist/prompts.js +8 -8
  12. package/dist/prompts.js.map +3 -3
  13. package/dist/registry.js +3 -3
  14. package/dist/registry.js.map +2 -2
  15. package/dist/rollout.js +1 -1
  16. package/dist/runtime/src/agents/archiver.ts +1 -1
  17. package/dist/runtime/src/agents/idle-archiver.ts +3 -2
  18. package/dist/runtime/src/mcp/canonical-proxy-server.ts +31 -15
  19. package/dist/runtime/src/mcp/wiki-search-index.ts +359 -0
  20. package/dist/runtime/src/mcp/wiki-server.ts +1358 -155
  21. package/dist/runtime/src/platform/mcp-config.ts +2 -1
  22. package/dist/runtime/src/prompts/agents/wiki-archiver.md +73 -48
  23. package/dist/runtime/src/prompts/builders.ts +17 -34
  24. package/dist/runtime/src/runtime/turn-runner.ts +14 -17
  25. package/dist/runtime/src/storage/api-topics.ts +13 -4
  26. package/dist/runtime/src/topics/lifecycle.ts +3 -2
  27. package/dist/runtime/src/types/api.ts +6 -0
  28. package/dist/runtime/src/version.ts +1 -1
  29. package/dist/storage.js +12 -6
  30. package/dist/storage.js.map +3 -3
  31. package/dist/types/packages/core/src/agents/archiver.d.ts +1 -1
  32. package/dist/types/packages/core/src/mcp/wiki-search-index.d.ts +59 -0
  33. package/dist/types/packages/core/src/mcp/wiki-server.d.ts +4 -0
  34. package/dist/types/packages/core/src/prompts/builders.d.ts +2 -4
  35. package/dist/types/packages/core/src/storage/api-topics.d.ts +1 -0
  36. package/dist/types/packages/core/src/types/api.d.ts +6 -0
  37. package/dist/types/packages/core/src/version.d.ts +1 -1
  38. package/package.json +1 -1
@@ -1310,6 +1310,8 @@ var init_mcp_config = __esm(() => {
1310
1310
  return env ? buildStdioMcpServer(agent, CANONICAL_MCP_PROXY_SERVER, ["--surface=wiki"], env) : null;
1311
1311
  }
1312
1312
  const args = [`--user-id=${userId}`];
1313
+ if (topicId)
1314
+ args.push(`--current-topic-id=${topicId}`);
1313
1315
  const resolvedWikiTopicId = wikiTopicId ?? topicId ?? (session !== "dm" ? session : undefined);
1314
1316
  if (resolvedWikiTopicId)
1315
1317
  args.push(`--topic-id=${resolvedWikiTopicId}`);
@@ -2223,7 +2225,7 @@ var init_claude_registry = __esm(() => {
2223
2225
  });
2224
2226
 
2225
2227
  // ../../packages/core/src/version.ts
2226
- var NEGOTIUM_VERSION = "0.2.17";
2228
+ var NEGOTIUM_VERSION = "0.2.19";
2227
2229
 
2228
2230
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
2229
2231
  import { spawn as spawn2 } from "child_process";
@@ -6778,14 +6780,14 @@ function buildMemoryPromptSection(opts) {
6778
6780
  const parts = [`
6779
6781
 
6780
6782
  ## Memory`];
6781
- parts.push(`Memory directory: ${opts.wikiDir}/topic`);
6782
- parts.push(`Files: ${opts.hasFiles ? opts.briefFile : "(none)"}`);
6783
- if (opts.latestSummaryFile) {
6784
- parts.push(`Latest summary: ${opts.latestSummaryFile}`);
6785
- }
6786
- parts.push("", opts.isManager ? opts.hasFiles ? "Above is this workspace's memory-hub brief (accumulated across all archived topics). For past context or other topics, consult it first, then use the `wiki_query` MCP tool for deeper recall." : "If you need past context while handling delegated work, use the `wiki_query` MCP tool." : opts.hasFiles ? "The file above is this topic's wiki brief. Read it first for past context; use the `wiki_query` MCP tool for deeper recall." : opts.latestSummaryFile ? "There is no wiki brief file yet. For past context, read the Latest summary first; use the `wiki_query` MCP tool for deeper recall." : "There is no wiki brief file yet. Use the `wiki_query` MCP tool for past context.");
6787
- parts.push("", opts.isManager ? "When answering about past workspace decisions or other topics, weave in memory naturally, but confirm with `wiki_query` when unsure." : opts.hasFiles || opts.latestSummaryFile ? "On your first reply in the topic, read the wiki brief" + (opts.latestSummaryFile ? " and Latest summary" : "") + " and mention a one-line context recap so the user can quickly confirm it is on track." : "On your first reply in the topic, check prior conversation context if needed and mention it in one natural line.");
6788
- parts.push("", opts.hasFiles ? "If the user says your memory is wrong, find the file in the Memory directory with Read and fix it directly with Edit." : "If the user says your memory is wrong, check the relevant wiki brief and fix it directly when possible, or use `wiki_query` to find the entry and reconcile.");
6783
+ if (opts.isManager) {
6784
+ parts.push("Use `wiki_query` for past workspace decisions or cross-topic context, then `wiki_read` only for the relevant result.");
6785
+ } else if (opts.memoryKey) {
6786
+ parts.push(`This topic uses the canonical memory key \`${opts.memoryKey}\`. At the start of a new session, read it with \`wiki_read(kind: "topic", key: "${opts.memoryKey}")\`.`);
6787
+ } else {
6788
+ parts.push(`At the start of a new session, search topic memories with \`wiki_query(question: "${opts.topicTitle}", kind: "topic", limit: 5)\` and read the most relevant candidate with \`wiki_read\`.`, "If a candidate is clearly the same continuing topic/persona, read it with `adopt: true`; otherwise keep this topic's own name as its memory key. Do not merge weak or ambiguous matches.");
6789
+ }
6790
+ parts.push("Keep the lookup quiet. Mention prior context naturally in one short line only when it helps the user.", 'Use `wiki_query(kind: "article")` for reusable knowledge and `wiki_query(kind: "summary")` for historical session details.');
6789
6791
  if (opts.hasArchive) {
6790
6792
  parts.push("", "If you need the actual conversation from an earlier session, use the `wiki_last_conversation` MCP tool.");
6791
6793
  }
@@ -7439,6 +7441,7 @@ function initializeApiTopicsSchema() {
7439
7441
  last_message_at TEXT,
7440
7442
  parent_topic_id TEXT,
7441
7443
  memory_topic_id TEXT,
7444
+ memory_key TEXT,
7442
7445
  is_fork INTEGER NOT NULL DEFAULT 0 CHECK (is_fork IN (0,1)),
7443
7446
  is_subagent INTEGER NOT NULL DEFAULT 0 CHECK (is_subagent IN (0,1)),
7444
7447
  visibility TEXT NOT NULL DEFAULT 'visible' CHECK (visibility IN ('visible','hidden')),
@@ -7488,8 +7491,8 @@ function initializeApiTopicsSchema() {
7488
7491
  const legacyBaseEffort = row.base_effort ?? row.default_effort;
7489
7492
  db.query(`INSERT INTO api_topics_next
7490
7493
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
7491
- created_at,last_message_at,parent_topic_id,memory_topic_id,is_fork,is_subagent,visibility,access_mode,session_id)
7492
- 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, typeof row.memory_topic_id === "string" ? row.memory_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);
7494
+ created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,access_mode,session_id)
7495
+ 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, typeof row.memory_topic_id === "string" ? row.memory_topic_id : null, typeof row.memory_key === "string" ? row.memory_key : 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);
7493
7496
  }
7494
7497
  db.exec("DROP TABLE IF EXISTS topic_members");
7495
7498
  db.exec("DROP TABLE api_topics");
@@ -7558,6 +7561,9 @@ function initializeApiTopicsSchema() {
7558
7561
  if (!tableColumns2("api_topics").has("memory_topic_id")) {
7559
7562
  db.exec("ALTER TABLE api_topics ADD COLUMN memory_topic_id TEXT");
7560
7563
  }
7564
+ if (!tableColumns2("api_topics").has("memory_key")) {
7565
+ db.exec("ALTER TABLE api_topics ADD COLUMN memory_key TEXT");
7566
+ }
7561
7567
  db.exec(`
7562
7568
  UPDATE api_topics
7563
7569
  SET browser_profile_owner = (
@@ -7618,6 +7624,7 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
7618
7624
  lastMessageAt: r.last_message_at ?? new Date().toISOString(),
7619
7625
  parentTopicId: r.parent_topic_id ?? undefined,
7620
7626
  memoryTopicId: r.memory_topic_id ?? undefined,
7627
+ memoryKey: r.memory_key ?? undefined,
7621
7628
  isFork: r.is_fork !== 0,
7622
7629
  ...r.is_subagent !== 0 ? { isSubagent: true } : {},
7623
7630
  ...r.is_subagent !== 0 ? {
@@ -7689,9 +7696,9 @@ function upsertTopic(t) {
7689
7696
  db.transaction(() => {
7690
7697
  db.query(`INSERT INTO api_topics
7691
7698
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
7692
- created_at,last_message_at,parent_topic_id,memory_topic_id,is_fork,is_subagent,visibility,access_mode,
7699
+ created_at,last_message_at,parent_topic_id,memory_topic_id,memory_key,is_fork,is_subagent,visibility,access_mode,
7693
7700
  subagent_report_mode)
7694
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
7701
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
7695
7702
  ON CONFLICT(id) DO UPDATE SET
7696
7703
  title = excluded.title,
7697
7704
  kind = excluded.kind,
@@ -7704,11 +7711,12 @@ function upsertTopic(t) {
7704
7711
  last_message_at = excluded.last_message_at,
7705
7712
  parent_topic_id = excluded.parent_topic_id,
7706
7713
  memory_topic_id = excluded.memory_topic_id,
7714
+ memory_key = excluded.memory_key,
7707
7715
  is_fork = excluded.is_fork,
7708
7716
  is_subagent = excluded.is_subagent,
7709
7717
  visibility = excluded.visibility,
7710
7718
  access_mode = excluded.access_mode,
7711
- subagent_report_mode = excluded.subagent_report_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.memoryTopicId ?? null, t.isFork ? 1 : 0, t.isSubagent ? 1 : 0, normalizeTopicVisibility(t.visibility), normalizeTopicAccessMode(t.accessMode), t.subagentReportMode ?? "auto");
7719
+ subagent_report_mode = excluded.subagent_report_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.memoryTopicId ?? null, t.memoryKey ?? null, t.isFork ? 1 : 0, t.isSubagent ? 1 : 0, normalizeTopicVisibility(t.visibility), normalizeTopicAccessMode(t.accessMode), t.subagentReportMode ?? "auto");
7712
7720
  db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
7713
7721
  for (const participant of t.participants) {
7714
7722
  db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
@@ -9460,11 +9468,12 @@ function archiveActiveTopicForMemory(topicId, userId, options) {
9460
9468
  }, "topic-memory-archiver: raw snapshot preserved below exchange threshold");
9461
9469
  return "below-threshold";
9462
9470
  }
9463
- const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
9471
+ const memoryTopic = topic.memoryKey ? topic : getTopicMemoryOrigin(topicId) ?? topic;
9472
+ const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
9464
9473
  const launched = (options.launchArchiver ?? runArchiverTurn)({
9465
9474
  userId,
9466
9475
  topicId: memoryTopic.id,
9467
- topicTitle: memoryTopic.title,
9476
+ topicTitle: memoryTitle,
9468
9477
  archivePath: job.archivePath,
9469
9478
  ...options.rawArchivePaths ? { rawArchivePaths: options.rawArchivePaths } : {},
9470
9479
  messageCount: job.messageCount,
@@ -13976,11 +13985,12 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
13976
13985
  }
13977
13986
  if (archived && meetsMemoryArchiveExchangeThreshold(archived.exchangeCount, MIN_MEMORY_ARCHIVE_EXCHANGES, topic)) {
13978
13987
  try {
13979
- const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
13988
+ const memoryTopic = topic.memoryKey ? topic : getTopicMemoryOrigin(topicId) ?? topic;
13989
+ const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
13980
13990
  runArchiverTurn({
13981
13991
  userId,
13982
13992
  ...memoryTopic.id !== topicId && !deletingTopicIds.has(memoryTopic.id) ? { topicId: memoryTopic.id } : {},
13983
- topicTitle: memoryTopic.title,
13993
+ topicTitle: memoryTitle,
13984
13994
  archivePath: archived.path,
13985
13995
  ...rawArchives.length > 0 ? { rawArchivePaths: rawArchives } : {},
13986
13996
  messageCount: archived.messageCount
@@ -16412,25 +16422,24 @@ function startAiTurn(params) {
16412
16422
  const isManager = topicRecord?.kind === "manager";
16413
16423
  const isMentionOnlyChannel = topic.aiMode === "mention" && !isManager;
16414
16424
  let systemPrompt = isManager ? buildManagerSystemPrompt(systemPromptOpts) : isMentionOnlyChannel ? buildChannelSystemPrompt(systemPromptOpts) : buildTopicSystemPrompt(systemPromptOpts);
16415
- const memoryTopic = isMentionOnlyChannel || isManager ? topic : getTopicMemoryOrigin(topicId) ?? topic;
16425
+ const memoryTopic = isMentionOnlyChannel || isManager || topic.memoryKey ? topic : getTopicMemoryOrigin(topicId) ?? topic;
16426
+ const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
16416
16427
  if (!isMentionOnlyChannel) {
16428
+ let hasMemoryArchive = false;
16417
16429
  try {
16418
- const resolvedBrief = resolveTopicBrief(memoryTopic.id, memoryTopic.title);
16430
+ const resolvedBrief = resolveTopicBrief(memoryTopic.id, memoryTitle);
16419
16431
  const wikiDir = getSharedWikiDir();
16420
- const { briefFile, hasBriefFile, latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTopic.title);
16421
- if (resolvedBrief || hasBriefFile || latestSummaryFile) {
16422
- systemPrompt += buildMemoryPromptSection({
16423
- briefFile,
16424
- wikiDir,
16425
- hasFiles: hasBriefFile,
16426
- latestSummaryFile,
16427
- hasArchive: Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile),
16428
- isManager
16429
- });
16430
- }
16432
+ const { latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTitle);
16433
+ hasMemoryArchive = Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile);
16431
16434
  } catch (err2) {
16432
16435
  logger.warn({ topicId, err: err2 }, "ai: failed to inject topic brief");
16433
16436
  }
16437
+ systemPrompt += buildMemoryPromptSection({
16438
+ topicTitle: topic.title,
16439
+ ...memoryTopic.memoryKey ? { memoryKey: memoryTopic.memoryKey } : {},
16440
+ hasArchive: hasMemoryArchive,
16441
+ isManager
16442
+ });
16434
16443
  }
16435
16444
  const activeVisual = visualTools ? getActiveVisualForPrompt(topicId, userId) : null;
16436
16445
  if (activeVisual) {
@@ -18767,4 +18776,4 @@ export {
18767
18776
  DEFAULT_SELF_CONFIG_PRODUCT
18768
18777
  };
18769
18778
 
18770
- //# debugId=814F0B0C425F56EA64756E2164756E21
18779
+ //# debugId=3089657619E3681164756E2164756E21