@bbigbang/core 0.1.0

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 (175) hide show
  1. package/dist/config.js +380 -0
  2. package/dist/execution/executionDispatcher.js +3810 -0
  3. package/dist/main.js +90 -0
  4. package/dist/nodeEventHistory.js +206 -0
  5. package/dist/scheduler/dreamLogic.js +50 -0
  6. package/dist/scheduler/dreamScheduler.js +65 -0
  7. package/dist/services/agentFileAccessService.js +1913 -0
  8. package/dist/services/agentRuntimeCleanupBroker.js +62 -0
  9. package/dist/services/agentSkillsBroker.js +118 -0
  10. package/dist/services/agentSkillsService.js +83 -0
  11. package/dist/services/agentWorkspaceBroker.js +937 -0
  12. package/dist/services/agentWorkspaceService.js +70 -0
  13. package/dist/services/appVersion.js +14 -0
  14. package/dist/services/auth.js +586 -0
  15. package/dist/services/claudeControlBroker.js +154 -0
  16. package/dist/services/claudeTranscriptBroker.js +100 -0
  17. package/dist/services/claudeTranscriptService.js +359 -0
  18. package/dist/services/codexAppServerBroker.js +155 -0
  19. package/dist/services/codexTranscriptBroker.js +98 -0
  20. package/dist/services/codexTranscriptService.js +961 -0
  21. package/dist/services/droidMissionBroker.js +124 -0
  22. package/dist/services/droidMissionImporter.js +630 -0
  23. package/dist/services/droidModelOptions.js +165 -0
  24. package/dist/services/hubServerRegistrationService.js +268 -0
  25. package/dist/services/libraryManifest.js +43 -0
  26. package/dist/services/libraryScaffold.js +26 -0
  27. package/dist/services/libraryService.js +2263 -0
  28. package/dist/services/memoryService.js +386 -0
  29. package/dist/services/missionEvidence.js +377 -0
  30. package/dist/services/missionService.js +2361 -0
  31. package/dist/services/missionTrace.js +158 -0
  32. package/dist/services/nativeMissionBriefParser.js +120 -0
  33. package/dist/services/nativeMissionOrchestrator.js +2045 -0
  34. package/dist/services/nativeMissionReportGenerator.js +227 -0
  35. package/dist/services/nativeMissionValidationRunner.js +452 -0
  36. package/dist/services/nativeMissionWorkerBroker.js +190 -0
  37. package/dist/services/nodeRegistry.js +34 -0
  38. package/dist/services/nodeStateReconciler.js +97 -0
  39. package/dist/services/panelMediaScanner.js +119 -0
  40. package/dist/services/persistentRuntimeJsonlClient.js +153 -0
  41. package/dist/services/platformAgentPolicy.js +180 -0
  42. package/dist/services/platformAgentService.js +2041 -0
  43. package/dist/services/projectAccessResolver.js +93 -0
  44. package/dist/services/projectService.js +392 -0
  45. package/dist/services/resourceSpaceService.js +140 -0
  46. package/dist/services/scenarioRuntimeService.js +1130 -0
  47. package/dist/services/suggestedPlannerService.js +868 -0
  48. package/dist/services/workbenchGitBroker.js +161 -0
  49. package/dist/services/workbenchGitService.js +69 -0
  50. package/dist/services/workbenchInspectBroker.js +65 -0
  51. package/dist/services/workbenchNodePathService.js +79 -0
  52. package/dist/services/workbenchRegistryService.js +240 -0
  53. package/dist/services/workbenchRootService.js +181 -0
  54. package/dist/services/workbenchTerminalBroker.js +378 -0
  55. package/dist/services/workspaceRunOwnership.js +60 -0
  56. package/dist/services/workspaceScaffold.js +105 -0
  57. package/dist/services/workspaceSessionRuntimeService.js +576 -0
  58. package/dist/services/workspaceSessionService.js +245 -0
  59. package/dist/services/workspaceToolActionRunner.js +1582 -0
  60. package/dist/services/workspaceToolErrors.js +10 -0
  61. package/dist/services/workspaceToolExecutionUtils.js +895 -0
  62. package/dist/services/workspaceToolLatestStateProjector.js +91 -0
  63. package/dist/services/workspaceToolManifest.js +572 -0
  64. package/dist/services/workspaceToolMutationQueue.js +43 -0
  65. package/dist/services/workspaceToolPanelProjection.js +460 -0
  66. package/dist/services/workspaceToolPromotion.js +255 -0
  67. package/dist/services/workspaceToolPromotionState.js +224 -0
  68. package/dist/services/workspaceToolPublishDiagnostics.js +189 -0
  69. package/dist/services/workspaceToolPublishIdentityResolver.js +146 -0
  70. package/dist/services/workspaceToolReadModel.js +378 -0
  71. package/dist/services/workspaceToolRunLedger.js +239 -0
  72. package/dist/services/workspaceToolService.js +3067 -0
  73. package/dist/services/workspaceToolSnapshotPanelSync.js +293 -0
  74. package/dist/services/workspaceToolTerminalLifecycle.js +283 -0
  75. package/dist/services/workspaceToolTypes.js +1 -0
  76. package/dist/services/workspaceToolUploadMaterializer.js +228 -0
  77. package/dist/web/actionCardRoutes.js +129 -0
  78. package/dist/web/actionCards.js +469 -0
  79. package/dist/web/activationContext.js +684 -0
  80. package/dist/web/agentChannelGuards.js +48 -0
  81. package/dist/web/agentMentionCooldowns.js +32 -0
  82. package/dist/web/agentReminders.js +1668 -0
  83. package/dist/web/agentRuntimePresence.js +197 -0
  84. package/dist/web/agentSelfState.js +494 -0
  85. package/dist/web/agentTaskLinks.js +26 -0
  86. package/dist/web/agentVisibility.js +79 -0
  87. package/dist/web/assets.js +95 -0
  88. package/dist/web/channelActivationPrompt.js +395 -0
  89. package/dist/web/channelMemoryNotes.js +127 -0
  90. package/dist/web/channelMentions.js +10 -0
  91. package/dist/web/channelMessageSequences.js +19 -0
  92. package/dist/web/channelSubscriptions.js +26 -0
  93. package/dist/web/clearedTaskRoots.js +10 -0
  94. package/dist/web/collaborationPromptGuidance.js +36 -0
  95. package/dist/web/collaborationSurfaceState.js +140 -0
  96. package/dist/web/contextBundleRanking.js +154 -0
  97. package/dist/web/contextBundleResolver.js +488 -0
  98. package/dist/web/conversationBuiltinSkillRoots.js +50 -0
  99. package/dist/web/conversationControls.js +232 -0
  100. package/dist/web/conversationHandoffs.js +612 -0
  101. package/dist/web/conversationManager.js +2511 -0
  102. package/dist/web/conversationSummaries.js +876 -0
  103. package/dist/web/conversationSurfaceKinds.js +17 -0
  104. package/dist/web/conversationTargets.js +173 -0
  105. package/dist/web/directActivationPrompt.js +122 -0
  106. package/dist/web/directReplyTargets.js +69 -0
  107. package/dist/web/directThreadResolver.js +129 -0
  108. package/dist/web/dmTaskHandoffPrompt.js +120 -0
  109. package/dist/web/dmTaskThreadStatusProjection.js +229 -0
  110. package/dist/web/ftsQuery.js +33 -0
  111. package/dist/web/internalAgentRouter.js +11341 -0
  112. package/dist/web/libraryCuratorScheduler.js +58 -0
  113. package/dist/web/libraryDocumentPromptGuidance.js +8 -0
  114. package/dist/web/messageCheckpoints.js +19 -0
  115. package/dist/web/nodeWsHandler.js +2495 -0
  116. package/dist/web/notificationRounds.js +1061 -0
  117. package/dist/web/panelActionMessages.js +108 -0
  118. package/dist/web/panelActivationPrompt.js +18 -0
  119. package/dist/web/panelAudit.js +273 -0
  120. package/dist/web/panelLifecycle.js +222 -0
  121. package/dist/web/panelMediaPolicy.js +43 -0
  122. package/dist/web/panelPathPolicy.js +63 -0
  123. package/dist/web/panelPreviews.js +175 -0
  124. package/dist/web/panelQueryHandles.js +2749 -0
  125. package/dist/web/panelRoutes.js +2147 -0
  126. package/dist/web/panels.js +904 -0
  127. package/dist/web/peerInboxAggregates.js +1247 -0
  128. package/dist/web/planApprovalState.js +92 -0
  129. package/dist/web/platformAgentScheduler.js +66 -0
  130. package/dist/web/proactiveOpportunities.js +452 -0
  131. package/dist/web/promptContextSections.js +242 -0
  132. package/dist/web/promptHistorySanitizer.js +26 -0
  133. package/dist/web/promptSlashCommands.js +158 -0
  134. package/dist/web/rollingConversationSummary.js +453 -0
  135. package/dist/web/routeHelpers.js +11 -0
  136. package/dist/web/routes/handoff.js +288 -0
  137. package/dist/web/routes/history.js +345 -0
  138. package/dist/web/routes/memory.js +258 -0
  139. package/dist/web/routes/selfState.js +171 -0
  140. package/dist/web/routes/workspace.js +154 -0
  141. package/dist/web/runSurfaceWatermarks.js +431 -0
  142. package/dist/web/runtimeCapabilities.js +48 -0
  143. package/dist/web/sameAgentHandoffs.js +494 -0
  144. package/dist/web/server.js +15567 -0
  145. package/dist/web/sharedCollaborationCapsules.js +163 -0
  146. package/dist/web/soloSessionRelay.js +42 -0
  147. package/dist/web/soloWsHandler.js +138 -0
  148. package/dist/web/suggestedPlannerScheduler.js +56 -0
  149. package/dist/web/surfaceActivationPolicy.js +108 -0
  150. package/dist/web/surfaceCollaborators.js +61 -0
  151. package/dist/web/surfaceSystemStatus.js +263 -0
  152. package/dist/web/targetParticipants.js +77 -0
  153. package/dist/web/taskEvents.js +49 -0
  154. package/dist/web/taskLifecycleMessages.js +165 -0
  155. package/dist/web/taskLoops.js +732 -0
  156. package/dist/web/taskMemoryNotes.js +224 -0
  157. package/dist/web/taskNumbers.js +16 -0
  158. package/dist/web/taskOwnerGuards.js +49 -0
  159. package/dist/web/taskParticipantResolver.js +42 -0
  160. package/dist/web/taskParticipants.js +97 -0
  161. package/dist/web/taskSourceDetails.js +20 -0
  162. package/dist/web/taskStateViews.js +210 -0
  163. package/dist/web/taskStatusTransitions.js +9 -0
  164. package/dist/web/taskThreadFollowups.js +599 -0
  165. package/dist/web/taskThreadRuntimeClosure.js +685 -0
  166. package/dist/web/taskUpdateDelivery.js +104 -0
  167. package/dist/web/threadReplyContentHeuristics.js +30 -0
  168. package/dist/web/threadRoots.js +61 -0
  169. package/dist/web/threadTaskBindings.js +365 -0
  170. package/dist/web/uiPanelPromptGuidance.js +27 -0
  171. package/dist/web/workspaceMemoryHints.js +143 -0
  172. package/dist/web/workspaceToolPromptGuidance.js +30 -0
  173. package/dist/web/wsHandler.js +397 -0
  174. package/dist/web/wsSink.js +116 -0
  175. package/package.json +54 -0
@@ -0,0 +1,684 @@
1
+ import { buildThreadShortId } from '@bbigbang/protocol';
2
+ import { getUnifiedSurfaceUnreadCheckpoint, listUnifiedRecentSurfaceParticipants, } from './collaborationSurfaceState.js';
3
+ import { getBoundTaskForThread, listThreadCollaborationParticipants } from './threadTaskBindings.js';
4
+ import { findThreadRootMessageId } from './threadRoots.js';
5
+ import { isClearedTaskRootTarget } from './clearedTaskRoots.js';
6
+ import { hasVisiblePromptHistoryContent } from './promptHistorySanitizer.js';
7
+ import { buildChannelActivationContextSections, } from './channelActivationPrompt.js';
8
+ import { buildDirectActivationContextSections, } from './directActivationPrompt.js';
9
+ import { historyLimitForSurfaceActivationTier, resolveChannelSurfaceActivationPolicy, resolveDirectSurfaceActivationPolicy, } from './surfaceActivationPolicy.js';
10
+ import { buildDefaultChannelMemoryHints, buildDefaultDirectMemoryHints, buildWorkspaceMemoryReminder, getCurrentISOWeek, shouldIncludeDmContextSnapshot, shouldIncludeOpenTaskBoardSummary, } from './workspaceMemoryHints.js';
11
+ import { createPromptContextSection, renderPromptContextSections, } from './promptContextSections.js';
12
+ import { buildSourceSurfaceHandoffReminderSection } from './conversationHandoffs.js';
13
+ import { buildSurfaceSystemStatusSection } from './surfaceSystemStatus.js';
14
+ import { TASK_LIFECYCLE_SOURCE } from './taskLifecycleMessages.js';
15
+ import { PANEL_ACTION_SOURCE } from './panelActionMessages.js';
16
+ const DEFAULT_DM_TASK_THREAD_CONTEXT_MESSAGE_LIMIT = 4;
17
+ const DM_THREAD_CONTEXT_SNAPSHOT_LIMIT = 6;
18
+ function ensureDmThreadContextSnapshotTable(db) {
19
+ db.exec(`
20
+ CREATE TABLE IF NOT EXISTS dm_thread_context_snapshots (
21
+ channel_id TEXT NOT NULL,
22
+ thread_root_id TEXT NOT NULL,
23
+ trigger_message_id TEXT,
24
+ snapshot_json TEXT NOT NULL,
25
+ created_at INTEGER NOT NULL,
26
+ PRIMARY KEY (channel_id, thread_root_id)
27
+ );
28
+ `);
29
+ }
30
+ function loadActivationMessageById(db, channelId, messageId) {
31
+ const row = db.prepare(`SELECT message_id as messageId, seq, target, sender_name as senderName, sender_type as senderType,
32
+ content, created_at as createdAt, attachment_ids as attachmentIds, message_source as messageSource,
33
+ deleted_at as deletedAt
34
+ FROM channel_messages
35
+ WHERE channel_id = ? AND message_id = ?
36
+ LIMIT 1`).get(channelId, messageId);
37
+ if (!row)
38
+ return undefined;
39
+ if (isClearedTaskRootTarget(row.target))
40
+ return undefined;
41
+ return hydrateActivationContextMessage(row);
42
+ }
43
+ function loadThreadRootMessage(db, channelId, threadRootId, rootMessageId) {
44
+ if (rootMessageId) {
45
+ const exact = loadActivationMessageById(db, channelId, rootMessageId);
46
+ if (exact)
47
+ return exact;
48
+ }
49
+ const matchedMessageId = findThreadRootMessageId(db, channelId, threadRootId);
50
+ return matchedMessageId
51
+ ? loadActivationMessageById(db, channelId, matchedMessageId)
52
+ : undefined;
53
+ }
54
+ function parseDmThreadContextSnapshot(raw) {
55
+ try {
56
+ const parsed = JSON.parse(raw);
57
+ if (!Array.isArray(parsed))
58
+ return [];
59
+ return parsed
60
+ .filter((value) => (!!value
61
+ && typeof value === 'object'
62
+ && (() => {
63
+ const message = value;
64
+ return typeof message.messageId === 'string'
65
+ && typeof message.seq === 'number'
66
+ && typeof message.target === 'string'
67
+ && typeof message.senderName === 'string'
68
+ && typeof message.senderType === 'string'
69
+ && typeof message.content === 'string'
70
+ && typeof message.createdAt === 'number'
71
+ && (message.messageSource == null
72
+ || typeof message.messageSource === 'string')
73
+ && (message.attachmentIds == null
74
+ || (Array.isArray(message.attachmentIds)
75
+ && message.attachmentIds.every((attachmentId) => typeof attachmentId === 'string')));
76
+ })()))
77
+ .filter(isPromptHistoryMessage)
78
+ .sort((a, b) => a.seq - b.seq);
79
+ }
80
+ catch {
81
+ return [];
82
+ }
83
+ }
84
+ function parseAttachmentIds(raw) {
85
+ if (!raw)
86
+ return undefined;
87
+ try {
88
+ const parsed = JSON.parse(raw);
89
+ if (!Array.isArray(parsed))
90
+ return undefined;
91
+ const attachmentIds = parsed.filter((value) => typeof value === 'string');
92
+ return attachmentIds.length > 0 ? attachmentIds : undefined;
93
+ }
94
+ catch {
95
+ return undefined;
96
+ }
97
+ }
98
+ function dmThreadSnapshotReferencesDeletedMessage(db, params) {
99
+ const messageIds = Array.from(new Set([
100
+ params.triggerMessageId,
101
+ ...params.messages.map((message) => message.messageId),
102
+ ].filter((value) => typeof value === 'string' && value.trim().length > 0)));
103
+ if (messageIds.length === 0)
104
+ return false;
105
+ const placeholders = messageIds.map(() => '?').join(', ');
106
+ const row = db.prepare(`SELECT 1
107
+ FROM channel_messages
108
+ WHERE channel_id = ?
109
+ AND message_id IN (${placeholders})
110
+ AND deleted_at IS NOT NULL
111
+ LIMIT 1`).get(params.channelId, ...messageIds);
112
+ return Boolean(row);
113
+ }
114
+ function hydrateActivationContextMessage(row) {
115
+ const attachmentIds = row.deletedAt == null ? parseAttachmentIds(row.attachmentIds) : undefined;
116
+ return {
117
+ messageId: row.messageId,
118
+ seq: row.seq,
119
+ target: row.target,
120
+ senderName: row.senderName,
121
+ senderType: row.senderType,
122
+ content: row.content,
123
+ createdAt: row.createdAt,
124
+ messageSource: row.messageSource ?? null,
125
+ ...(attachmentIds ? { attachmentIds } : {}),
126
+ };
127
+ }
128
+ function isPromptHistoryMessage(message) {
129
+ const source = message.messageSource ?? null;
130
+ return source !== TASK_LIFECYCLE_SOURCE && source !== PANEL_ACTION_SOURCE;
131
+ }
132
+ export function getDmThreadContextSnapshot(db, params) {
133
+ ensureDmThreadContextSnapshotTable(db);
134
+ const row = db.prepare(`SELECT trigger_message_id as triggerMessageId, snapshot_json as snapshotJson
135
+ FROM dm_thread_context_snapshots
136
+ WHERE channel_id = ? AND thread_root_id = ?
137
+ LIMIT 1`).get(params.channelId, params.threadRootId);
138
+ if (!row)
139
+ return undefined;
140
+ const messages = parseDmThreadContextSnapshot(row.snapshotJson);
141
+ if (dmThreadSnapshotReferencesDeletedMessage(db, {
142
+ channelId: params.channelId,
143
+ triggerMessageId: row.triggerMessageId,
144
+ messages,
145
+ })) {
146
+ db.prepare(`DELETE FROM dm_thread_context_snapshots
147
+ WHERE channel_id = ? AND thread_root_id = ?`).run(params.channelId, params.threadRootId);
148
+ return undefined;
149
+ }
150
+ return {
151
+ triggerMessageId: row.triggerMessageId,
152
+ messages,
153
+ };
154
+ }
155
+ export function ensureDmThreadContextSnapshot(db, params) {
156
+ ensureDmThreadContextSnapshotTable(db);
157
+ const existing = getDmThreadContextSnapshot(db, {
158
+ channelId: params.channelId,
159
+ threadRootId: params.threadRootId,
160
+ });
161
+ if (existing)
162
+ return existing;
163
+ const rootMessage = loadThreadRootMessage(db, params.channelId, params.threadRootId, params.rootMessageId);
164
+ if (!rootMessage)
165
+ return undefined;
166
+ const recentLimit = Math.max(1, params.recentLimit ?? DM_THREAD_CONTEXT_SNAPSHOT_LIMIT);
167
+ const recentMessages = db.prepare(`SELECT message_id as messageId, seq, target, sender_name as senderName, sender_type as senderType,
168
+ content, created_at as createdAt, attachment_ids as attachmentIds, message_source as messageSource,
169
+ deleted_at as deletedAt
170
+ FROM channel_messages
171
+ WHERE channel_id = ?
172
+ AND target = ?
173
+ AND thread_root_id IS NULL
174
+ AND seq < ?
175
+ AND COALESCE(message_source, '') NOT IN (?, ?)
176
+ ORDER BY seq DESC
177
+ LIMIT ?`).all(params.channelId, params.directTarget, rootMessage.seq, TASK_LIFECYCLE_SOURCE, PANEL_ACTION_SOURCE, recentLimit)
178
+ .map(hydrateActivationContextMessage)
179
+ .reverse();
180
+ const latestUserMessage = db.prepare(`SELECT message_id as messageId, seq, target, sender_name as senderName, sender_type as senderType,
181
+ content, created_at as createdAt, attachment_ids as attachmentIds, message_source as messageSource,
182
+ deleted_at as deletedAt
183
+ FROM channel_messages
184
+ WHERE channel_id = ?
185
+ AND target = ?
186
+ AND thread_root_id IS NULL
187
+ AND sender_type = 'user'
188
+ AND seq < ?
189
+ ORDER BY seq DESC
190
+ LIMIT 1`).get(params.channelId, params.directTarget, rootMessage.seq);
191
+ const fallbackTriggerMessageRow = latestUserMessage ?? db.prepare(`SELECT message_id as messageId, seq, target, sender_name as senderName, sender_type as senderType,
192
+ content, created_at as createdAt, attachment_ids as attachmentIds, message_source as messageSource,
193
+ deleted_at as deletedAt
194
+ FROM channel_messages
195
+ WHERE channel_id = ?
196
+ AND target = ?
197
+ AND thread_root_id IS NULL
198
+ AND seq < ?
199
+ AND COALESCE(message_source, '') NOT IN (?, ?)
200
+ ORDER BY seq DESC
201
+ LIMIT 1`).get(params.channelId, params.directTarget, rootMessage.seq, TASK_LIFECYCLE_SOURCE, PANEL_ACTION_SOURCE);
202
+ const fallbackTriggerMessage = fallbackTriggerMessageRow
203
+ ? hydrateActivationContextMessage(fallbackTriggerMessageRow)
204
+ : undefined;
205
+ const triggerMessageId = rootMessage.senderType === 'user' && rootMessage.target === params.directTarget
206
+ ? rootMessage.messageId
207
+ : fallbackTriggerMessage?.messageId ?? null;
208
+ const messageMap = new Map(recentMessages.map((message) => [message.messageId, message]));
209
+ if (triggerMessageId && triggerMessageId !== rootMessage.messageId && !messageMap.has(triggerMessageId)) {
210
+ const triggerMessage = loadActivationMessageById(db, params.channelId, triggerMessageId);
211
+ if (triggerMessage && triggerMessage.target === params.directTarget) {
212
+ messageMap.set(triggerMessage.messageId, triggerMessage);
213
+ }
214
+ }
215
+ const snapshot = {
216
+ triggerMessageId,
217
+ messages: [...messageMap.values()].sort((a, b) => a.seq - b.seq),
218
+ };
219
+ db.prepare(`INSERT INTO dm_thread_context_snapshots(channel_id, thread_root_id, trigger_message_id, snapshot_json, created_at)
220
+ VALUES(?, ?, ?, ?, ?)
221
+ ON CONFLICT(channel_id, thread_root_id) DO UPDATE SET
222
+ trigger_message_id = excluded.trigger_message_id,
223
+ snapshot_json = excluded.snapshot_json`).run(params.channelId, params.threadRootId, snapshot.triggerMessageId, JSON.stringify(snapshot.messages), Date.now());
224
+ return snapshot;
225
+ }
226
+ export function buildTargetActivationContext(db, params) {
227
+ const recentLimit = Math.max(1, params.recentLimit ?? 8);
228
+ const normalizedThreadRootId = params.threadRootId ?? null;
229
+ const openTasksMode = params.openTasksMode ?? 'full';
230
+ const includeDmContextSnapshot = params.includeDmContextSnapshot ?? true;
231
+ const dmActiveTaskThreadsMode = params.dmActiveTaskThreadsMode ?? 'full';
232
+ const checkpoint = Math.max(0, Math.floor(params.unreadCheckpointSeq ?? getUnifiedSurfaceUnreadCheckpoint(db, {
233
+ agentId: params.agentId,
234
+ channelId: params.channelId,
235
+ threadRootId: normalizedThreadRootId,
236
+ })));
237
+ const isDirectThreadTarget = normalizedThreadRootId !== null && params.replyTarget.startsWith('dm:@');
238
+ const threadClause = normalizedThreadRootId == null
239
+ ? 'thread_root_id IS NULL'
240
+ : isDirectThreadTarget
241
+ ? '(thread_root_id = ? OR thread_root_id IS NULL)'
242
+ : 'thread_root_id = ?';
243
+ const threadArgs = normalizedThreadRootId == null ? [] : [normalizedThreadRootId];
244
+ const recentUnreadClause = params.constrainRecentMessagesToUnread ? 'AND seq > ?' : '';
245
+ const recentUnreadArgs = params.constrainRecentMessagesToUnread ? [checkpoint] : [];
246
+ const recentSenderClause = params.excludeRecentMessageSenderId ? 'AND sender_id != ?' : '';
247
+ const recentSenderArgs = params.excludeRecentMessageSenderId ? [params.excludeRecentMessageSenderId] : [];
248
+ const recentMessages = db.prepare(`SELECT message_id as messageId, seq, target, sender_name as senderName, sender_type as senderType,
249
+ content, created_at as createdAt, attachment_ids as attachmentIds, message_source as messageSource,
250
+ deleted_at as deletedAt
251
+ FROM channel_messages
252
+ WHERE channel_id = ? AND target = ? AND ${threadClause} AND seq < ?
253
+ ${recentUnreadClause}
254
+ ${recentSenderClause}
255
+ AND COALESCE(message_source, '') NOT IN (?, ?)
256
+ ORDER BY seq DESC
257
+ LIMIT ?`).all(params.channelId, params.replyTarget, ...threadArgs, params.triggerSeq, ...recentUnreadArgs, ...recentSenderArgs, TASK_LIFECYCLE_SOURCE, PANEL_ACTION_SOURCE, recentLimit)
258
+ .map(hydrateActivationContextMessage)
259
+ .reverse()
260
+ .filter((message) => hasVisiblePromptHistoryContent(message.content, message.senderType));
261
+ const recentWindowStartSeq = recentMessages.length > 0
262
+ ? recentMessages[0].seq
263
+ : undefined;
264
+ const unreadUpperBound = recentWindowStartSeq ?? params.triggerSeq;
265
+ const unreadRow = db.prepare(`SELECT COUNT(*) as count
266
+ FROM channel_messages
267
+ WHERE channel_id = ?
268
+ AND target = ?
269
+ AND ${threadClause}
270
+ AND seq > ?
271
+ AND seq < ?
272
+ AND COALESCE(message_source, '') NOT IN (?, ?)
273
+ AND sender_id != ?`).get(params.channelId, params.replyTarget, ...threadArgs, checkpoint, unreadUpperBound, TASK_LIFECYCLE_SOURCE, PANEL_ACTION_SOURCE, params.agentId);
274
+ const rootMessage = normalizedThreadRootId
275
+ ? (() => {
276
+ const matchedMessageId = findThreadRootMessageId(db, params.channelId, normalizedThreadRootId);
277
+ return matchedMessageId
278
+ ? loadActivationMessageById(db, params.channelId, matchedMessageId)
279
+ : undefined;
280
+ })()
281
+ : undefined;
282
+ const directTarget = normalizedThreadRootId && params.replyTarget.startsWith('dm:@')
283
+ ? params.replyTarget.replace(/:[^:]+$/, '')
284
+ : null;
285
+ const dmContextSnapshot = includeDmContextSnapshot && normalizedThreadRootId && directTarget
286
+ ? ensureDmThreadContextSnapshot(db, {
287
+ channelId: params.channelId,
288
+ directTarget,
289
+ threadRootId: normalizedThreadRootId,
290
+ rootMessageId: rootMessage?.messageId,
291
+ })
292
+ : undefined;
293
+ const recentParticipants = listUnifiedRecentSurfaceParticipants(db, {
294
+ channelId: params.channelId,
295
+ threadRootId: normalizedThreadRootId,
296
+ });
297
+ const boundTaskRow = getBoundTaskForThread(db, {
298
+ channelId: params.channelId,
299
+ threadRootId: normalizedThreadRootId,
300
+ });
301
+ const boundTask = boundTaskRow
302
+ ? {
303
+ taskId: boundTaskRow.taskId,
304
+ taskNumber: boundTaskRow.taskNumber,
305
+ title: boundTaskRow.title,
306
+ description: boundTaskRow.description ?? null,
307
+ status: boundTaskRow.status,
308
+ claimedByName: boundTaskRow.assigneeName,
309
+ }
310
+ : undefined;
311
+ const participants = normalizedThreadRootId
312
+ ? listThreadCollaborationParticipants(db, {
313
+ channelId: params.channelId,
314
+ threadRootId: normalizedThreadRootId,
315
+ })
316
+ : recentParticipants;
317
+ let openTaskCount = 0;
318
+ let openTasks = [];
319
+ if (!boundTask && openTasksMode !== 'off') {
320
+ if (openTasksMode === 'full') {
321
+ openTasks = db.prepare(`SELECT task_number as taskNumber,
322
+ title,
323
+ status,
324
+ claimed_by_name as claimedByName
325
+ FROM tasks
326
+ WHERE channel_id = ? AND status != 'done'
327
+ ORDER BY
328
+ CASE status
329
+ WHEN 'in_progress' THEN 0
330
+ WHEN 'in_review' THEN 1
331
+ WHEN 'todo' THEN 2
332
+ ELSE 3
333
+ END ASC,
334
+ task_number ASC
335
+ LIMIT 5`).all(params.channelId);
336
+ openTaskCount = openTasks.length;
337
+ }
338
+ else {
339
+ openTaskCount = db.prepare(`SELECT COUNT(*) as count
340
+ FROM tasks
341
+ WHERE channel_id = ? AND status != 'done'`).get(params.channelId).count;
342
+ }
343
+ }
344
+ let dmActiveTaskThreadCount = 0;
345
+ let dmActiveTaskThreads = [];
346
+ if (normalizedThreadRootId === null && params.replyTarget.startsWith('dm:@') && dmActiveTaskThreadsMode !== 'off') {
347
+ if (dmActiveTaskThreadsMode === 'full') {
348
+ dmActiveTaskThreads = db.prepare(`SELECT t.agent_task_ref as agentTaskRef,
349
+ t.task_number as taskNumber,
350
+ t.title,
351
+ t.status,
352
+ t.claimed_by_name as claimedByName,
353
+ t.message_id as messageId
354
+ FROM tasks t
355
+ LEFT JOIN channel_messages cm ON cm.message_id = t.message_id
356
+ WHERE t.channel_id = ?
357
+ AND COALESCE(t.dm_target, cm.target) = ?
358
+ AND t.message_id IS NOT NULL
359
+ AND t.status IN ('todo', 'in_progress', 'in_review')
360
+ ORDER BY t.updated_at DESC, t.task_number DESC`).all(params.channelId, params.replyTarget).map((task) => ({
361
+ agentTaskRef: task.agentTaskRef,
362
+ taskNumber: task.taskNumber,
363
+ title: task.title,
364
+ status: task.status,
365
+ claimedByName: task.claimedByName,
366
+ threadTarget: `${params.replyTarget}:${buildThreadShortId(task.messageId)}`,
367
+ }));
368
+ dmActiveTaskThreadCount = dmActiveTaskThreads.length;
369
+ }
370
+ else {
371
+ dmActiveTaskThreadCount = db.prepare(`SELECT COUNT(*) as count
372
+ FROM tasks t
373
+ LEFT JOIN channel_messages cm ON cm.message_id = t.message_id
374
+ WHERE t.channel_id = ?
375
+ AND COALESCE(t.dm_target, cm.target) = ?
376
+ AND t.message_id IS NOT NULL
377
+ AND t.status IN ('todo', 'in_progress', 'in_review')`).get(params.channelId, params.replyTarget).count;
378
+ }
379
+ }
380
+ return {
381
+ replyTarget: params.replyTarget,
382
+ recentMessages,
383
+ olderUnreadCount: unreadRow.count,
384
+ ...(recentWindowStartSeq ? { recentWindowStartSeq } : {}),
385
+ unreadCount: unreadRow.count,
386
+ ...(recentWindowStartSeq ? { oldestVisibleSeq: recentWindowStartSeq } : {}),
387
+ participants,
388
+ ...(boundTask ? { boundTask } : {}),
389
+ openTaskCount,
390
+ openTasks,
391
+ ...(rootMessage ? { rootMessage } : {}),
392
+ ...(dmContextSnapshot ? { dmContextSnapshot } : {}),
393
+ dmActiveTaskThreadCount,
394
+ ...(dmActiveTaskThreads.length > 0 ? { dmActiveTaskThreads } : {}),
395
+ };
396
+ }
397
+ export function buildDirectSurfaceActivationEnvelope(db, params) {
398
+ const boundDmThreadTask = params.threadRootId && params.replyTarget.startsWith('dm:@')
399
+ ? getBoundTaskForThread(db, {
400
+ channelId: params.channelId,
401
+ threadRootId: params.threadRootId,
402
+ })
403
+ : undefined;
404
+ const includeDmSnapshot = params.includeDmContextSnapshot ?? (boundDmThreadTask
405
+ ? true
406
+ : shouldIncludeDmContextSnapshot({
407
+ target: params.replyTarget,
408
+ includeRecoverySnapshot: params.includeRecoverySnapshot,
409
+ }));
410
+ const promptIncludeDmSnapshot = params.promptIncludeDmContextSnapshot ?? (params.includeDmContextSnapshot ?? (boundDmThreadTask ? true : includeDmSnapshot));
411
+ const seedPolicy = resolveDirectSurfaceActivationPolicy({
412
+ target: params.replyTarget,
413
+ includeDmActiveTaskThreads: params.includeDmActiveTaskThreads,
414
+ includeDmContextSnapshot: includeDmSnapshot,
415
+ promptIncludeDmContextSnapshot: promptIncludeDmSnapshot,
416
+ strongSignalFlags: {
417
+ ...params.strongSignalFlags,
418
+ handoff_recovery_bootstrap: params.includeRecoverySnapshot ?? params.strongSignalFlags?.handoff_recovery_bootstrap,
419
+ },
420
+ });
421
+ const activationContext = buildTargetActivationContext(db, {
422
+ agentId: params.agentId,
423
+ channelId: params.channelId,
424
+ replyTarget: params.replyTarget,
425
+ triggerSeq: params.triggerSeq,
426
+ threadRootId: params.threadRootId ?? null,
427
+ unreadCheckpointSeq: params.unreadCheckpointSeq,
428
+ constrainRecentMessagesToUnread: params.constrainRecentMessagesToUnread,
429
+ excludeRecentMessageSenderId: params.excludeRecentMessageSenderId,
430
+ openTasksMode: 'off',
431
+ includeDmContextSnapshot: includeDmSnapshot,
432
+ dmActiveTaskThreadsMode: params.dmActiveTaskThreadsMode ?? seedPolicy.dmTaskThreadPresence.activationMode,
433
+ });
434
+ const applyMessageContentOverrides = (message) => {
435
+ if (!message)
436
+ return message;
437
+ const nextContent = params.messageContentOverrides?.[message.messageId];
438
+ if (typeof nextContent !== 'string' || nextContent === message.content) {
439
+ return message;
440
+ }
441
+ return {
442
+ ...message,
443
+ content: nextContent,
444
+ };
445
+ };
446
+ const applySnapshotContentOverrides = (snapshot) => {
447
+ if (!snapshot)
448
+ return snapshot;
449
+ const nextMessages = snapshot.messages.map((message) => applyMessageContentOverrides(message) ?? message);
450
+ const changed = nextMessages.some((message, index) => message !== snapshot.messages[index]);
451
+ if (!changed)
452
+ return snapshot;
453
+ return {
454
+ ...snapshot,
455
+ messages: nextMessages,
456
+ };
457
+ };
458
+ const normalizedActivationContext = {
459
+ ...activationContext,
460
+ recentMessages: activationContext.recentMessages.map((message) => applyMessageContentOverrides(message) ?? message),
461
+ rootMessage: applyMessageContentOverrides(activationContext.rootMessage),
462
+ dmContextSnapshot: applySnapshotContentOverrides(activationContext.dmContextSnapshot),
463
+ };
464
+ const policy = resolveDirectSurfaceActivationPolicy({
465
+ target: params.replyTarget,
466
+ includeDmActiveTaskThreads: params.includeDmActiveTaskThreads,
467
+ includeDmContextSnapshot: includeDmSnapshot,
468
+ promptIncludeDmContextSnapshot: promptIncludeDmSnapshot,
469
+ strongSignalFlags: {
470
+ ...params.strongSignalFlags,
471
+ handoff_recovery_bootstrap: params.includeRecoverySnapshot ?? params.strongSignalFlags?.handoff_recovery_bootstrap,
472
+ active_dm_task_thread_linkage: normalizedActivationContext.dmActiveTaskThreadCount > 0,
473
+ bound_task_match: Boolean(normalizedActivationContext.boundTask) || params.strongSignalFlags?.bound_task_match,
474
+ task_thread: Boolean(normalizedActivationContext.boundTask && params.threadRootId) || params.strongSignalFlags?.task_thread,
475
+ },
476
+ });
477
+ const today = params.today ?? getCurrentISOWeek();
478
+ const memoryHints = buildDefaultDirectMemoryHints({
479
+ threadRootId: params.threadRootId ?? null,
480
+ forceTaskNotes: params.forceTaskNotes,
481
+ forceWorkLog: params.forceWorkLog,
482
+ currentWeek: today.week,
483
+ });
484
+ const promptDmActiveTaskThreadsMode = params.promptDmActiveTaskThreadsMode ?? policy.dmTaskThreadPresence.renderMode;
485
+ const promptIncludeRootMessage = params.promptIncludeRootMessage ?? !Boolean(boundDmThreadTask);
486
+ const promptIncludeBoundTaskBrief = params.promptIncludeBoundTaskBrief ?? true;
487
+ const dmContextSnapshotLimit = boundDmThreadTask ? DEFAULT_DM_TASK_THREAD_CONTEXT_MESSAGE_LIMIT : undefined;
488
+ const shouldRenderFullRecentWindow = params.threadRootId == null && params.replyTarget.startsWith('dm:@');
489
+ const fullRecentWindowLimit = shouldRenderFullRecentWindow ? normalizedActivationContext.recentMessages.length : undefined;
490
+ const surfaceSystemStatusSection = buildSurfaceSystemStatusSection(db, {
491
+ channelId: params.channelId,
492
+ replyTarget: params.replyTarget,
493
+ threadRootId: params.threadRootId ?? null,
494
+ boundTaskId: normalizedActivationContext.boundTask?.taskId,
495
+ });
496
+ const sourceHandoffReminderSection = buildSourceSurfaceHandoffReminderSection(db, {
497
+ agentId: params.agentId,
498
+ channelId: params.channelId,
499
+ replyTarget: params.replyTarget,
500
+ threadRootId: params.threadRootId ?? null,
501
+ });
502
+ const activationContextSections = [
503
+ ...(sourceHandoffReminderSection ? [sourceHandoffReminderSection] : []),
504
+ ...(surfaceSystemStatusSection ? [surfaceSystemStatusSection] : []),
505
+ ...buildDirectActivationContextSections({
506
+ target: params.replyTarget,
507
+ recentMessages: normalizedActivationContext.recentMessages,
508
+ olderUnreadCount: normalizedActivationContext.olderUnreadCount,
509
+ recentWindowStartSeq: normalizedActivationContext.recentWindowStartSeq,
510
+ rootMessage: normalizedActivationContext.rootMessage,
511
+ boundTask: normalizedActivationContext.boundTask,
512
+ dmContextSnapshot: normalizedActivationContext.dmContextSnapshot,
513
+ dmActiveTaskThreads: normalizedActivationContext.dmActiveTaskThreads,
514
+ dmActiveTaskThreadCount: normalizedActivationContext.dmActiveTaskThreadCount,
515
+ }, {
516
+ includeDmContextSnapshot: promptIncludeDmSnapshot,
517
+ historyLimit: params.activationHistoryLimit ?? fullRecentWindowLimit ?? historyLimitForSurfaceActivationTier(policy.activationTier),
518
+ dmActiveTaskThreadsMode: promptDmActiveTaskThreadsMode,
519
+ includeRootMessage: promptIncludeRootMessage,
520
+ includeBoundTaskBrief: promptIncludeBoundTaskBrief,
521
+ ...(dmContextSnapshotLimit ? { dmContextSnapshotLimit } : {}),
522
+ }),
523
+ ];
524
+ const activationContextText = renderPromptContextSections(activationContextSections) || undefined;
525
+ const resumeContextSections = [
526
+ createPromptContextSection('workspace_memory_reminder', `[Workspace memory reminder]
527
+ ${buildWorkspaceMemoryReminder(memoryHints, today)}`),
528
+ sourceHandoffReminderSection,
529
+ surfaceSystemStatusSection,
530
+ ...buildDirectActivationContextSections({
531
+ target: params.replyTarget,
532
+ recentMessages: normalizedActivationContext.recentMessages,
533
+ olderUnreadCount: normalizedActivationContext.olderUnreadCount,
534
+ recentWindowStartSeq: normalizedActivationContext.recentWindowStartSeq,
535
+ rootMessage: normalizedActivationContext.rootMessage,
536
+ boundTask: normalizedActivationContext.boundTask,
537
+ dmContextSnapshot: promptIncludeDmSnapshot ? normalizedActivationContext.dmContextSnapshot : undefined,
538
+ dmActiveTaskThreads: normalizedActivationContext.dmActiveTaskThreads,
539
+ dmActiveTaskThreadCount: normalizedActivationContext.dmActiveTaskThreadCount,
540
+ }, {
541
+ includeDmContextSnapshot: promptIncludeDmSnapshot,
542
+ historyLimit: params.resumeHistoryLimit ?? fullRecentWindowLimit ?? historyLimitForSurfaceActivationTier(policy.resumeTier),
543
+ dmActiveTaskThreadsMode: promptDmActiveTaskThreadsMode,
544
+ includeRootMessage: promptIncludeRootMessage,
545
+ includeBoundTaskBrief: promptIncludeBoundTaskBrief,
546
+ ...(dmContextSnapshotLimit ? { dmContextSnapshotLimit } : {}),
547
+ }),
548
+ ].filter((section) => Boolean(section));
549
+ const resumeContextText = renderPromptContextSections(resumeContextSections) || undefined;
550
+ return {
551
+ today,
552
+ activationContext: normalizedActivationContext,
553
+ activationContextText,
554
+ activationContextSections: activationContextSections.length > 0 ? activationContextSections : undefined,
555
+ resumeContextText,
556
+ resumeContextSections: resumeContextSections.length > 0 ? resumeContextSections : undefined,
557
+ replayOverlapRecentMessages: normalizedActivationContext.recentMessages,
558
+ policy,
559
+ };
560
+ }
561
+ export function buildChannelSurfaceActivationEnvelope(db, params) {
562
+ const seedPolicy = resolveChannelSurfaceActivationPolicy({
563
+ target: params.replyTarget,
564
+ reason: params.reason,
565
+ includeOpenTasks: params.includeOpenTasks,
566
+ strongSignalFlags: params.strongSignalFlags,
567
+ });
568
+ // Thread-reply activations need enough local timeline for collaboration
569
+ // follow-ups; unread-only delivery can otherwise hide already-acked agent dialogue.
570
+ const shouldPreserveThreadRecentHistory = Boolean(params.constrainRecentMessagesToUnread
571
+ && params.reason === 'thread_reply'
572
+ && params.threadRootId);
573
+ const activationContext = buildTargetActivationContext(db, {
574
+ agentId: params.agentId,
575
+ channelId: params.channelId,
576
+ replyTarget: params.replyTarget,
577
+ triggerSeq: params.triggerSeq,
578
+ threadRootId: params.threadRootId ?? null,
579
+ recentLimit: params.recentLimit,
580
+ unreadCheckpointSeq: params.unreadCheckpointSeq,
581
+ constrainRecentMessagesToUnread: shouldPreserveThreadRecentHistory
582
+ ? false
583
+ : params.constrainRecentMessagesToUnread,
584
+ excludeRecentMessageSenderId: params.excludeRecentMessageSenderId,
585
+ openTasksMode: params.openTasksMode ?? seedPolicy.taskBoardPresence.activationMode,
586
+ });
587
+ const previewPolicy = resolveChannelSurfaceActivationPolicy({
588
+ target: params.replyTarget,
589
+ reason: params.reason,
590
+ hasBoundTask: Boolean(activationContext.boundTask),
591
+ participantsCount: activationContext.participants.length,
592
+ strongSignalFlags: params.strongSignalFlags,
593
+ });
594
+ const includeParticipants = params.includeParticipants ?? previewPolicy.includeParticipantsByDefault;
595
+ const includeOpenTasks = params.includeOpenTasks ?? (previewPolicy.includeOpenTasksByDefault || shouldIncludeOpenTaskBoardSummary({
596
+ target: params.replyTarget,
597
+ hasBoundTask: Boolean(activationContext.boundTask),
598
+ }));
599
+ const policy = resolveChannelSurfaceActivationPolicy({
600
+ target: params.replyTarget,
601
+ reason: params.reason,
602
+ hasBoundTask: Boolean(activationContext.boundTask),
603
+ includeOpenTasks,
604
+ participantsCount: activationContext.participants.length,
605
+ strongSignalFlags: params.strongSignalFlags,
606
+ });
607
+ const today = params.today ?? getCurrentISOWeek();
608
+ const memoryHints = buildDefaultChannelMemoryHints({
609
+ channelName: params.channelName,
610
+ hasBoundTask: Boolean(activationContext.boundTask),
611
+ forceTaskNotes: params.forceTaskNotes,
612
+ forceWorkLog: params.forceWorkLog,
613
+ currentWeek: today.week,
614
+ });
615
+ const openTaskMode = params.openTaskMode ?? policy.taskBoardPresence.renderMode;
616
+ const surfaceSystemStatusSection = buildSurfaceSystemStatusSection(db, {
617
+ channelId: params.channelId,
618
+ replyTarget: params.replyTarget,
619
+ threadRootId: params.threadRootId ?? null,
620
+ boundTaskId: activationContext.boundTask?.taskId,
621
+ });
622
+ const sourceHandoffReminderSection = buildSourceSurfaceHandoffReminderSection(db, {
623
+ agentId: params.agentId,
624
+ channelId: params.channelId,
625
+ replyTarget: params.replyTarget,
626
+ threadRootId: params.threadRootId ?? null,
627
+ });
628
+ const activationContextSections = [
629
+ ...(sourceHandoffReminderSection ? [sourceHandoffReminderSection] : []),
630
+ ...(surfaceSystemStatusSection ? [surfaceSystemStatusSection] : []),
631
+ ...buildChannelActivationContextSections({
632
+ target: params.replyTarget,
633
+ recentMessages: activationContext.recentMessages,
634
+ rootMessage: activationContext.rootMessage,
635
+ olderUnreadCount: activationContext.olderUnreadCount,
636
+ recentWindowStartSeq: activationContext.recentWindowStartSeq,
637
+ participants: activationContext.participants,
638
+ boundTask: activationContext.boundTask,
639
+ openTasks: activationContext.openTasks,
640
+ openTaskCount: activationContext.openTaskCount,
641
+ }, {
642
+ includeParticipants,
643
+ includeOpenTasks,
644
+ maxOpenTasks: 3,
645
+ historyLimit: params.activationHistoryLimit ?? historyLimitForSurfaceActivationTier(policy.activationTier),
646
+ openTaskMode,
647
+ }),
648
+ ];
649
+ const activationContextText = renderPromptContextSections(activationContextSections) || undefined;
650
+ const resumeContextSections = [
651
+ createPromptContextSection('workspace_memory_reminder', `[Workspace memory reminder]
652
+ ${buildWorkspaceMemoryReminder(memoryHints, today)}`),
653
+ sourceHandoffReminderSection,
654
+ surfaceSystemStatusSection,
655
+ ...buildChannelActivationContextSections({
656
+ target: params.replyTarget,
657
+ recentMessages: activationContext.recentMessages,
658
+ rootMessage: activationContext.rootMessage,
659
+ olderUnreadCount: activationContext.olderUnreadCount,
660
+ recentWindowStartSeq: activationContext.recentWindowStartSeq,
661
+ participants: activationContext.participants,
662
+ boundTask: activationContext.boundTask,
663
+ openTasks: activationContext.openTasks,
664
+ openTaskCount: activationContext.openTaskCount,
665
+ }, {
666
+ includeParticipants,
667
+ includeOpenTasks,
668
+ maxOpenTasks: 3,
669
+ historyLimit: params.resumeHistoryLimit ?? historyLimitForSurfaceActivationTier(policy.resumeTier),
670
+ openTaskMode,
671
+ }),
672
+ ].filter((section) => Boolean(section));
673
+ const resumeContextText = renderPromptContextSections(resumeContextSections) || undefined;
674
+ return {
675
+ today,
676
+ activationContext,
677
+ activationContextText,
678
+ activationContextSections: activationContextSections.length > 0 ? activationContextSections : undefined,
679
+ resumeContextText,
680
+ resumeContextSections: resumeContextSections.length > 0 ? resumeContextSections : undefined,
681
+ replayOverlapRecentMessages: activationContext.recentMessages,
682
+ policy,
683
+ };
684
+ }