negotium 0.2.16 → 0.2.18

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 (47) hide show
  1. package/dist/agent-helpers.js +83 -38
  2. package/dist/agent-helpers.js.map +13 -13
  3. package/dist/background-bash.js.map +1 -1
  4. package/dist/browser-runtime.js.map +1 -1
  5. package/dist/{chunk-5cpdbbeh.js → chunk-fc58cqry.js} +3 -1
  6. package/dist/{chunk-5cpdbbeh.js.map → chunk-fc58cqry.js.map} +4 -4
  7. package/dist/hosted-agent.js +5 -2
  8. package/dist/hosted-agent.js.map +6 -6
  9. package/dist/main.js +1228 -486
  10. package/dist/main.js.map +23 -22
  11. package/dist/mcp-factories.js +701 -97
  12. package/dist/mcp-factories.js.map +14 -14
  13. package/dist/prompts.js +8 -8
  14. package/dist/prompts.js.map +4 -4
  15. package/dist/query-runtime.js.map +1 -1
  16. package/dist/registry.js +3 -3
  17. package/dist/registry.js.map +2 -2
  18. package/dist/rollout.js +1 -1
  19. package/dist/runtime/src/agents/compaction-support.ts +1 -1
  20. package/dist/runtime/src/agents/idle-archiver.ts +3 -2
  21. package/dist/runtime/src/agents/maestro-provider.ts +3 -0
  22. package/dist/runtime/src/index.ts +1 -0
  23. package/dist/runtime/src/mcp/canonical-proxy-server.ts +18 -1
  24. package/dist/runtime/src/mcp/wiki-server.ts +801 -59
  25. package/dist/runtime/src/platform/mcp-config.ts +1 -0
  26. package/dist/runtime/src/prompts/agents/wiki-archiver.md +16 -6
  27. package/dist/runtime/src/prompts/builders.ts +17 -34
  28. package/dist/runtime/src/runtime/turn-event-stream.ts +26 -0
  29. package/dist/runtime/src/runtime/turn-runner.ts +34 -26
  30. package/dist/runtime/src/storage/api-topics.ts +13 -4
  31. package/dist/runtime/src/topics/lifecycle.ts +3 -2
  32. package/dist/runtime/src/types/api.ts +6 -0
  33. package/dist/runtime/src/types.ts +6 -0
  34. package/dist/runtime/src/version.ts +1 -1
  35. package/dist/runtime-helpers.js.map +1 -1
  36. package/dist/storage.js +12 -6
  37. package/dist/storage.js.map +4 -4
  38. package/dist/types/packages/core/src/agents/compaction-support.d.ts +1 -0
  39. package/dist/types/packages/core/src/mcp/wiki-server.d.ts +4 -0
  40. package/dist/types/packages/core/src/prompts/builders.d.ts +2 -4
  41. package/dist/types/packages/core/src/runtime/turn-runner.d.ts +4 -0
  42. package/dist/types/packages/core/src/storage/api-topics.d.ts +1 -0
  43. package/dist/types/packages/core/src/types/api.d.ts +6 -0
  44. package/dist/types/packages/core/src/types.d.ts +6 -0
  45. package/dist/types/packages/core/src/version.d.ts +1 -1
  46. package/dist/vault.js.map +1 -1
  47. package/package.json +2 -2
@@ -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.16";
2228
+ var NEGOTIUM_VERSION = "0.2.18";
2227
2229
 
2228
2230
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
2229
2231
  import { spawn as spawn2 } from "child_process";
@@ -5834,6 +5836,7 @@ function maestroProvider(opts) {
5834
5836
  ...opts,
5835
5837
  enableToolSearch: !opts.toolPolicy && opts.enableToolSearch !== false,
5836
5838
  toolResultTruncation: buildMaestroToolResultTruncation(opts),
5839
+ ephemeralSystemPrompt: opts.ephemeralSystemPrompt,
5837
5840
  apiKeyOverrides: resolveMaestroApiKeyOverrides(userId),
5838
5841
  agent: "maestro",
5839
5842
  disallowedTools: buildMaestroDisallowedTools(callerDisallowedTools, opts.toolPolicy),
@@ -6777,14 +6780,14 @@ function buildMemoryPromptSection(opts) {
6777
6780
  const parts = [`
6778
6781
 
6779
6782
  ## Memory`];
6780
- parts.push(`Memory directory: ${opts.wikiDir}/topic`);
6781
- parts.push(`Files: ${opts.hasFiles ? opts.briefFile : "(none)"}`);
6782
- if (opts.latestSummaryFile) {
6783
- parts.push(`Latest summary: ${opts.latestSummaryFile}`);
6784
- }
6785
- 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.");
6786
- 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.");
6787
- 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.');
6788
6791
  if (opts.hasArchive) {
6789
6792
  parts.push("", "If you need the actual conversation from an earlier session, use the `wiki_last_conversation` MCP tool.");
6790
6793
  }
@@ -7438,6 +7441,7 @@ function initializeApiTopicsSchema() {
7438
7441
  last_message_at TEXT,
7439
7442
  parent_topic_id TEXT,
7440
7443
  memory_topic_id TEXT,
7444
+ memory_key TEXT,
7441
7445
  is_fork INTEGER NOT NULL DEFAULT 0 CHECK (is_fork IN (0,1)),
7442
7446
  is_subagent INTEGER NOT NULL DEFAULT 0 CHECK (is_subagent IN (0,1)),
7443
7447
  visibility TEXT NOT NULL DEFAULT 'visible' CHECK (visibility IN ('visible','hidden')),
@@ -7487,8 +7491,8 @@ function initializeApiTopicsSchema() {
7487
7491
  const legacyBaseEffort = row.base_effort ?? row.default_effort;
7488
7492
  db.query(`INSERT INTO api_topics_next
7489
7493
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
7490
- created_at,last_message_at,parent_topic_id,memory_topic_id,is_fork,is_subagent,visibility,access_mode,session_id)
7491
- 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);
7492
7496
  }
7493
7497
  db.exec("DROP TABLE IF EXISTS topic_members");
7494
7498
  db.exec("DROP TABLE api_topics");
@@ -7557,6 +7561,9 @@ function initializeApiTopicsSchema() {
7557
7561
  if (!tableColumns2("api_topics").has("memory_topic_id")) {
7558
7562
  db.exec("ALTER TABLE api_topics ADD COLUMN memory_topic_id TEXT");
7559
7563
  }
7564
+ if (!tableColumns2("api_topics").has("memory_key")) {
7565
+ db.exec("ALTER TABLE api_topics ADD COLUMN memory_key TEXT");
7566
+ }
7560
7567
  db.exec(`
7561
7568
  UPDATE api_topics
7562
7569
  SET browser_profile_owner = (
@@ -7617,6 +7624,7 @@ function rowToDto2(r, participants = getTopicParticipants(r.id), tellTargets) {
7617
7624
  lastMessageAt: r.last_message_at ?? new Date().toISOString(),
7618
7625
  parentTopicId: r.parent_topic_id ?? undefined,
7619
7626
  memoryTopicId: r.memory_topic_id ?? undefined,
7627
+ memoryKey: r.memory_key ?? undefined,
7620
7628
  isFork: r.is_fork !== 0,
7621
7629
  ...r.is_subagent !== 0 ? { isSubagent: true } : {},
7622
7630
  ...r.is_subagent !== 0 ? {
@@ -7688,9 +7696,9 @@ function upsertTopic(t) {
7688
7696
  db.transaction(() => {
7689
7697
  db.query(`INSERT INTO api_topics
7690
7698
  (id,title,kind,description,agent,base_model,base_effort,response_policy,
7691
- 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,
7692
7700
  subagent_report_mode)
7693
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
7701
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
7694
7702
  ON CONFLICT(id) DO UPDATE SET
7695
7703
  title = excluded.title,
7696
7704
  kind = excluded.kind,
@@ -7703,11 +7711,12 @@ function upsertTopic(t) {
7703
7711
  last_message_at = excluded.last_message_at,
7704
7712
  parent_topic_id = excluded.parent_topic_id,
7705
7713
  memory_topic_id = excluded.memory_topic_id,
7714
+ memory_key = excluded.memory_key,
7706
7715
  is_fork = excluded.is_fork,
7707
7716
  is_subagent = excluded.is_subagent,
7708
7717
  visibility = excluded.visibility,
7709
7718
  access_mode = excluded.access_mode,
7710
- 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");
7711
7720
  db.query("DELETE FROM topic_members WHERE topic_id = ?").run(t.id);
7712
7721
  for (const participant of t.participants) {
7713
7722
  db.query("INSERT INTO topic_members (topic_id,user_id,role) VALUES (?,?,?)").run(t.id, participant.userId, participant.role);
@@ -9459,11 +9468,12 @@ function archiveActiveTopicForMemory(topicId, userId, options) {
9459
9468
  }, "topic-memory-archiver: raw snapshot preserved below exchange threshold");
9460
9469
  return "below-threshold";
9461
9470
  }
9462
- const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
9471
+ const memoryTopic = topic.memoryKey ? topic : getTopicMemoryOrigin(topicId) ?? topic;
9472
+ const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
9463
9473
  const launched = (options.launchArchiver ?? runArchiverTurn)({
9464
9474
  userId,
9465
9475
  topicId: memoryTopic.id,
9466
- topicTitle: memoryTopic.title,
9476
+ topicTitle: memoryTitle,
9467
9477
  archivePath: job.archivePath,
9468
9478
  ...options.rawArchivePaths ? { rawArchivePaths: options.rawArchivePaths } : {},
9469
9479
  messageCount: job.messageCount,
@@ -13975,11 +13985,12 @@ async function deleteTopicCascadeImpl(topic, userId, options, deletingAncestorId
13975
13985
  }
13976
13986
  if (archived && meetsMemoryArchiveExchangeThreshold(archived.exchangeCount, MIN_MEMORY_ARCHIVE_EXCHANGES, topic)) {
13977
13987
  try {
13978
- const memoryTopic = getTopicMemoryOrigin(topicId) ?? topic;
13988
+ const memoryTopic = topic.memoryKey ? topic : getTopicMemoryOrigin(topicId) ?? topic;
13989
+ const memoryTitle = memoryTopic.memoryKey?.trim() || memoryTopic.title;
13979
13990
  runArchiverTurn({
13980
13991
  userId,
13981
13992
  ...memoryTopic.id !== topicId && !deletingTopicIds.has(memoryTopic.id) ? { topicId: memoryTopic.id } : {},
13982
- topicTitle: memoryTopic.title,
13993
+ topicTitle: memoryTitle,
13983
13994
  archivePath: archived.path,
13984
13995
  ...rawArchives.length > 0 ? { rawArchivePaths: rawArchives } : {},
13985
13996
  messageCount: archived.messageCount
@@ -14856,6 +14867,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
14856
14867
  let pendingSawDelta = false;
14857
14868
  let accumulatedText = "";
14858
14869
  let pendingText = "";
14870
+ let assistantContextTokens = 0;
14871
+ let toolContextTokens = 0;
14872
+ let lastContextProgressAt = 0;
14859
14873
  let lastVisibleMessageId = null;
14860
14874
  const visibleMessageIds = [];
14861
14875
  let lastTaskPanelText = null;
@@ -14874,6 +14888,20 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
14874
14888
  model
14875
14889
  });
14876
14890
  };
14891
+ const broadcastContextProgress = (force = false) => {
14892
+ if (silent)
14893
+ return;
14894
+ const now = Date.now();
14895
+ if (!force && lastContextProgressAt > 0 && now - lastContextProgressAt < 250)
14896
+ return;
14897
+ lastContextProgressAt = now;
14898
+ hub.broadcastAiStatus(topicId, {
14899
+ kind: "context_progress",
14900
+ queryId,
14901
+ assistantTokens: assistantContextTokens,
14902
+ toolTokens: toolContextTokens
14903
+ });
14904
+ };
14877
14905
  const nextSyntheticToolUseId = () => `tool-${queryId}-${++syntheticToolCounter}`;
14878
14906
  const bindToolUseId = (providerToolUseId, fallback) => {
14879
14907
  const providerId = normalizeToolUseId(providerToolUseId);
@@ -14983,6 +15011,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
14983
15011
  const incoming = event.content;
14984
15012
  accumulatedText += incoming;
14985
15013
  pendingText += incoming;
15014
+ assistantContextTokens = estimateTextTokens(accumulatedText);
15015
+ broadcastContextProgress();
14986
15016
  break;
14987
15017
  }
14988
15018
  case "text":
@@ -14990,10 +15020,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
14990
15020
  const incoming = event.content;
14991
15021
  accumulatedText += incoming;
14992
15022
  pendingText += incoming;
15023
+ assistantContextTokens = estimateTextTokens(accumulatedText);
15024
+ broadcastContextProgress();
14993
15025
  }
14994
15026
  break;
14995
15027
  case "tool_use":
14996
15028
  emitPendingAssistantMessage();
15029
+ toolContextTokens += estimateTextTokens(`${event.name}
15030
+ ${JSON.stringify(event.input ?? {})}`);
15031
+ broadcastContextProgress(true);
14997
15032
  if (isVisualsShowHtmlTool(event.name)) {
14998
15033
  const input = event.input;
14999
15034
  if (typeof input.html !== "string" || input.html.trim().length === 0) {
@@ -15147,6 +15182,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
15147
15182
  }
15148
15183
  break;
15149
15184
  case "tool_result":
15185
+ toolContextTokens += estimateTextTokens(event.content);
15186
+ broadcastContextProgress(true);
15150
15187
  if (isVisualToolResultHandled(event.toolUseId))
15151
15188
  break;
15152
15189
  if (!silent) {
@@ -15532,6 +15569,7 @@ __export(exports_turn_runner, {
15532
15569
  channelTranscriptSpeaker: () => channelTranscriptSpeaker,
15533
15570
  canonicalModelId: () => canonicalModelId,
15534
15571
  buildVideoHtml: () => buildVideoHtml,
15572
+ buildTurnReminderQuery: () => buildTurnReminderQuery,
15535
15573
  buildMermaidHtml: () => buildMermaidHtml,
15536
15574
  buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
15537
15575
  buildImageHtml: () => buildImageHtml,
@@ -15557,6 +15595,18 @@ function withDefaultPlaywright(configuredMcp, isManager) {
15557
15595
  enabled.add("background-bash");
15558
15596
  return [...enabled];
15559
15597
  }
15598
+ function buildTurnReminderQuery(agent, prompt, reminders) {
15599
+ const reminderPrompt = reminders.join(`
15600
+
15601
+ `);
15602
+ if (!reminderPrompt)
15603
+ return { prompt };
15604
+ if (agent === "maestro")
15605
+ return { prompt, ephemeralSystemPrompt: reminderPrompt };
15606
+ return { prompt: `${prompt}
15607
+
15608
+ ${reminderPrompt}` };
15609
+ }
15560
15610
  function appendSystemMessage(topicId, text2) {
15561
15611
  const message = {
15562
15612
  id: randomUUID16(),
@@ -16372,25 +16422,24 @@ function startAiTurn(params) {
16372
16422
  const isManager = topicRecord?.kind === "manager";
16373
16423
  const isMentionOnlyChannel = topic.aiMode === "mention" && !isManager;
16374
16424
  let systemPrompt = isManager ? buildManagerSystemPrompt(systemPromptOpts) : isMentionOnlyChannel ? buildChannelSystemPrompt(systemPromptOpts) : buildTopicSystemPrompt(systemPromptOpts);
16375
- 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;
16376
16427
  if (!isMentionOnlyChannel) {
16428
+ let hasMemoryArchive = false;
16377
16429
  try {
16378
- const resolvedBrief = resolveTopicBrief(memoryTopic.id, memoryTopic.title);
16430
+ const resolvedBrief = resolveTopicBrief(memoryTopic.id, memoryTitle);
16379
16431
  const wikiDir = getSharedWikiDir();
16380
- const { briefFile, hasBriefFile, latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTopic.title);
16381
- if (resolvedBrief || hasBriefFile || latestSummaryFile) {
16382
- systemPrompt += buildMemoryPromptSection({
16383
- briefFile,
16384
- wikiDir,
16385
- hasFiles: hasBriefFile,
16386
- latestSummaryFile,
16387
- hasArchive: Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile),
16388
- isManager
16389
- });
16390
- }
16432
+ const { latestSummaryFile } = resolveWikiMemoryMirror(wikiDir, memoryTopic.id, memoryTitle);
16433
+ hasMemoryArchive = Boolean(resolvedBrief?.brief.latestSummaryMd || latestSummaryFile);
16391
16434
  } catch (err2) {
16392
16435
  logger.warn({ topicId, err: err2 }, "ai: failed to inject topic brief");
16393
16436
  }
16437
+ systemPrompt += buildMemoryPromptSection({
16438
+ topicTitle: topic.title,
16439
+ ...memoryTopic.memoryKey ? { memoryKey: memoryTopic.memoryKey } : {},
16440
+ hasArchive: hasMemoryArchive,
16441
+ isManager
16442
+ });
16394
16443
  }
16395
16444
  const activeVisual = visualTools ? getActiveVisualForPrompt(topicId, userId) : null;
16396
16445
  if (activeVisual) {
@@ -16504,15 +16553,11 @@ function startAiTurn(params) {
16504
16553
  if (consumePlaywrightUnavailable(userId, topic.title)) {
16505
16554
  turnReminders.push("<system-reminder>Playwright browser tools are UNAVAILABLE this turn. The `mcp__playwright__*` tools have been removed from this turn's catalog because the long-lived browser MCP could not be prepared. Do not attempt to call browser tools. If browser interaction is required, ask the user to retry shortly or use a non-browser alternative.</system-reminder>");
16506
16555
  }
16507
- const effectivePrompt = turnReminders.length > 0 ? `${agentPrompt}
16508
-
16509
- ${turnReminders.join(`
16510
-
16511
- `)}` : agentPrompt;
16556
+ const reminderQuery = buildTurnReminderQuery(agentKind, agentPrompt, turnReminders);
16512
16557
  try {
16513
16558
  yield* runAgent({
16514
16559
  agent: agentKind,
16515
- prompt: effectivePrompt,
16560
+ ...reminderQuery,
16516
16561
  attachments: promptAttachments,
16517
16562
  cwd: workspaceCwd,
16518
16563
  systemPrompt,
@@ -18731,4 +18776,4 @@ export {
18731
18776
  DEFAULT_SELF_CONFIG_PRODUCT
18732
18777
  };
18733
18778
 
18734
- //# debugId=969112A1E458C75264756E2164756E21
18779
+ //# debugId=407E1CBFBD75364B64756E2164756E21