@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,242 @@
1
+ export const EXACT_TARGET_HISTORY_SECTION_KINDS = new Set([
2
+ 'recent_messages',
3
+ 'history_cursor',
4
+ 'recent_summary',
5
+ 'unread_summary',
6
+ ]);
7
+ const PROMPT_CONTEXT_HEADER_KIND_MAP = new Map([
8
+ ['[Active project]', 'active_project'],
9
+ ['[Workspace memory reminder]', 'workspace_memory_reminder'],
10
+ ['[Source-surface handoff reminder]', 'source_handoff_reminder'],
11
+ ['[Reminder guidance]', 'reminder_guidance'],
12
+ ['[UI panel guidance]', 'ui_panel_guidance'],
13
+ ['[Workspace tool guidance]', 'workspace_tool_guidance'],
14
+ ['[Library document guidance]', 'library_document_guidance'],
15
+ ['[Library documents]', 'library_documents'],
16
+ ['[Thread root message]', 'thread_root_message'],
17
+ ['[Bound task for this DM thread]', 'bound_task_dm_thread'],
18
+ ['[Recent messages on this exact target]', 'recent_messages'],
19
+ ['[History cursor]', 'history_cursor'],
20
+ ['[Recent summary]', 'recent_summary'],
21
+ ['[Unread summary]', 'unread_summary'],
22
+ ['[Inbox]', 'activation_pointer'],
23
+ ['[Context from DM]', 'dm_context_snapshot'],
24
+ ['[Active DM task threads]', 'dm_active_task_threads'],
25
+ ['[Active DM task-thread hint]', 'dm_active_task_thread_hint'],
26
+ ['[Active participants on this target]', 'participants'],
27
+ ['[Bound task-message for this thread]', 'bound_task_thread'],
28
+ ['[Task-message board summary]', 'task_board_summary'],
29
+ ['[Task-message board hint]', 'task_board_hint'],
30
+ ['[System status messages on this surface]', 'surface_system_status'],
31
+ ['[Relevant context hint]', 'relevant_context_hint'],
32
+ ['[Handoff capsule]', 'handoff_capsule'],
33
+ ['[Shared collaboration capsule]', 'shared_collaboration_capsule'],
34
+ ['[Conversation rolling summary]', 'conversation_rolling_summary'],
35
+ ]);
36
+ const SAFE_SINGLE_SECTION_KINDS = new Set([
37
+ 'active_project',
38
+ 'workspace_memory_reminder',
39
+ 'source_handoff_reminder',
40
+ 'reminder_guidance',
41
+ 'ui_panel_guidance',
42
+ 'workspace_tool_guidance',
43
+ 'library_document_guidance',
44
+ 'library_documents',
45
+ 'surface_system_status',
46
+ 'relevant_context_hint',
47
+ 'activation_pointer',
48
+ 'handoff_capsule',
49
+ 'shared_collaboration_capsule',
50
+ 'conversation_rolling_summary',
51
+ 'continuity',
52
+ ]);
53
+ const LEADING_HEADER_SINGLE_SECTION_KINDS = new Set([
54
+ 'active_project',
55
+ 'workspace_memory_reminder',
56
+ 'source_handoff_reminder',
57
+ 'reminder_guidance',
58
+ 'ui_panel_guidance',
59
+ 'workspace_tool_guidance',
60
+ 'library_document_guidance',
61
+ 'library_documents',
62
+ 'thread_root_message',
63
+ 'bound_task_dm_thread',
64
+ 'dm_context_snapshot',
65
+ 'dm_active_task_threads',
66
+ 'dm_active_task_thread_hint',
67
+ 'participants',
68
+ 'bound_task_thread',
69
+ 'task_board_summary',
70
+ 'task_board_hint',
71
+ 'surface_system_status',
72
+ 'relevant_context_hint',
73
+ 'activation_pointer',
74
+ 'handoff_capsule',
75
+ 'shared_collaboration_capsule',
76
+ 'conversation_rolling_summary',
77
+ ]);
78
+ const EXACT_HISTORY_TEXT_FOLLOWUP_SECTION_KINDS = new Set([
79
+ 'history_cursor',
80
+ 'recent_summary',
81
+ 'unread_summary',
82
+ 'activation_pointer',
83
+ 'source_handoff_reminder',
84
+ 'reminder_guidance',
85
+ 'ui_panel_guidance',
86
+ 'workspace_tool_guidance',
87
+ 'library_document_guidance',
88
+ 'library_documents',
89
+ 'dm_context_snapshot',
90
+ 'dm_active_task_threads',
91
+ 'dm_active_task_thread_hint',
92
+ 'participants',
93
+ 'bound_task_thread',
94
+ 'bound_task_dm_thread',
95
+ 'task_board_summary',
96
+ 'task_board_hint',
97
+ 'surface_system_status',
98
+ ]);
99
+ export function createPromptContextSection(kind, text) {
100
+ const normalizedText = text?.trim();
101
+ if (!normalizedText)
102
+ return null;
103
+ return {
104
+ kind,
105
+ text: normalizedText,
106
+ };
107
+ }
108
+ export function renderPromptContextSections(sections) {
109
+ return (sections ?? [])
110
+ .map((section) => section.text.trim())
111
+ .filter(Boolean)
112
+ .join('\n\n');
113
+ }
114
+ export function inferSinglePromptContextSection(text, fallbackKind = 'other') {
115
+ const normalizedText = text?.trim();
116
+ if (!normalizedText)
117
+ return null;
118
+ const firstLine = normalizedText.split('\n', 1)[0]?.trim() ?? '';
119
+ const inferredKind = inferPromptContextHeaderKind(firstLine);
120
+ const kind = inferredKind && SAFE_SINGLE_SECTION_KINDS.has(inferredKind)
121
+ ? inferredKind
122
+ : fallbackKind;
123
+ return {
124
+ kind,
125
+ text: normalizedText,
126
+ };
127
+ }
128
+ export function inferLeadingPromptContextSection(text, fallbackKind = 'other') {
129
+ const normalizedText = text?.trim();
130
+ if (!normalizedText)
131
+ return null;
132
+ const firstLine = normalizedText.split('\n', 1)[0]?.trim() ?? '';
133
+ const inferredKind = inferPromptContextHeaderKind(firstLine);
134
+ let kind = fallbackKind;
135
+ if (inferredKind === 'continuity' || (inferredKind && LEADING_HEADER_SINGLE_SECTION_KINDS.has(inferredKind))) {
136
+ kind = inferredKind;
137
+ }
138
+ else if (inferredKind
139
+ && EXACT_TARGET_HISTORY_SECTION_KINDS.has(inferredKind)
140
+ && isPlatformExactTargetHistoryText(inferredKind, normalizedText)) {
141
+ kind = inferredKind;
142
+ }
143
+ return {
144
+ kind,
145
+ text: normalizedText,
146
+ };
147
+ }
148
+ export function inferPromptContextSections(text, fallbackKind = 'other') {
149
+ const normalizedText = text?.trim();
150
+ if (!normalizedText)
151
+ return [];
152
+ const lines = normalizedText.split('\n');
153
+ const blocks = [];
154
+ let current = [];
155
+ let previousLineWasBlank = false;
156
+ for (const line of lines) {
157
+ const trimmedLine = line.trim();
158
+ const nextKind = inferPromptContextHeaderKind(trimmedLine);
159
+ if (nextKind
160
+ && current.length > 0
161
+ && previousLineWasBlank
162
+ && shouldSplitPromptContextBlock(current, nextKind)) {
163
+ while (current.length > 0 && current.at(-1)?.trim() === '') {
164
+ current.pop();
165
+ }
166
+ blocks.push(current.join('\n').trim());
167
+ current = [line];
168
+ previousLineWasBlank = false;
169
+ continue;
170
+ }
171
+ current.push(line);
172
+ previousLineWasBlank = trimmedLine === '';
173
+ }
174
+ if (current.length > 0) {
175
+ blocks.push(current.join('\n').trim());
176
+ }
177
+ return blocks
178
+ .map((block) => inferLeadingPromptContextSection(block, fallbackKind))
179
+ .filter((section) => Boolean(section));
180
+ }
181
+ function inferPromptContextHeaderKind(line) {
182
+ return line.startsWith('Context (')
183
+ ? 'continuity'
184
+ : PROMPT_CONTEXT_HEADER_KIND_MAP.get(line);
185
+ }
186
+ function shouldSplitPromptContextBlock(currentLines, nextKind) {
187
+ const firstNonBlankLine = currentLines.find((line) => line.trim())?.trim() ?? '';
188
+ const currentKind = inferPromptContextHeaderKind(firstNonBlankLine);
189
+ if (currentKind && EXACT_TARGET_HISTORY_SECTION_KINDS.has(currentKind)) {
190
+ return EXACT_HISTORY_TEXT_FOLLOWUP_SECTION_KINDS.has(nextKind);
191
+ }
192
+ return true;
193
+ }
194
+ function isPlatformExactTargetHistoryText(kind, text) {
195
+ switch (kind) {
196
+ case 'recent_messages':
197
+ return /^\[Recent messages on this exact target\]\n/.test(text)
198
+ && /^target: \S+\s+seq: \d+$/m.test(text)
199
+ && /^time: .+\s+sender: @\S+/m.test(text)
200
+ && /^\[Message metadata\]$/m.test(text)
201
+ && /^\[Message body\]$/m.test(text);
202
+ case 'history_cursor':
203
+ return /^\[History cursor\]\noldest_visible_seq: \d+(?:\n|$)/.test(text);
204
+ case 'recent_summary':
205
+ return /^\[Recent summary\]\n\d+ (?:earlier )?recent messages? on this exact target (?:were not included above|were omitted above)\. Use (?:bigbang message read --channel "[^"]+" --(?:before|after|around) \d+|read_history\(channel="[^"]+", (?:before|after|around)=\d+\)) if you need them\.(?:\n|$)/.test(text);
206
+ case 'unread_summary':
207
+ return /^\[Unread summary\]\n\d+ older unread messages? on this exact target were not included above\. Use (?:bigbang message read --channel "[^"]+" --before \d+|read_history\(channel="[^"]+", before=\d+\)) if you need them\.(?:\n|$)/.test(text);
208
+ default:
209
+ return false;
210
+ }
211
+ }
212
+ export function isPromptContextSectionKind(value) {
213
+ return typeof value === 'string'
214
+ && (value === 'active_project'
215
+ || value === 'workspace_memory_reminder'
216
+ || value === 'source_handoff_reminder'
217
+ || value === 'reminder_guidance'
218
+ || value === 'ui_panel_guidance'
219
+ || value === 'library_document_guidance'
220
+ || value === 'library_documents'
221
+ || value === 'thread_root_message'
222
+ || value === 'bound_task_dm_thread'
223
+ || value === 'recent_messages'
224
+ || value === 'history_cursor'
225
+ || value === 'recent_summary'
226
+ || value === 'unread_summary'
227
+ || value === 'activation_pointer'
228
+ || value === 'dm_context_snapshot'
229
+ || value === 'dm_active_task_threads'
230
+ || value === 'dm_active_task_thread_hint'
231
+ || value === 'participants'
232
+ || value === 'bound_task_thread'
233
+ || value === 'task_board_summary'
234
+ || value === 'task_board_hint'
235
+ || value === 'surface_system_status'
236
+ || value === 'relevant_context_hint'
237
+ || value === 'handoff_capsule'
238
+ || value === 'shared_collaboration_capsule'
239
+ || value === 'conversation_rolling_summary'
240
+ || value === 'continuity'
241
+ || value === 'other');
242
+ }
@@ -0,0 +1,26 @@
1
+ const LOW_SIGNAL_STATUS_LINE_PATTERNS = [
2
+ /^\s*\[(?:plan|task)\]\s*$/i,
3
+ /^\s*\[(?:plan|task)\]\s*(?:plan|task)?\s*updated\s*$/i,
4
+ /^\s*\[(?:plan|task)\s+updated\]\s*$/i,
5
+ /^\s*(?:plan|task)\s+updated\s*$/i,
6
+ ];
7
+ function isLowSignalStatusLine(line) {
8
+ return LOW_SIGNAL_STATUS_LINE_PATTERNS.some((pattern) => pattern.test(line.trim()));
9
+ }
10
+ export function sanitizePromptHistoryContent(content, senderType) {
11
+ const trimmed = content.trim();
12
+ if (!trimmed)
13
+ return '';
14
+ if (senderType === 'user')
15
+ return trimmed;
16
+ const cleaned = trimmed
17
+ .split('\n')
18
+ .filter((line) => !isLowSignalStatusLine(line))
19
+ .join('\n')
20
+ .replace(/\n{3,}/g, '\n\n')
21
+ .trim();
22
+ return cleaned;
23
+ }
24
+ export function hasVisiblePromptHistoryContent(content, senderType) {
25
+ return sanitizePromptHistoryContent(content, senderType).length > 0;
26
+ }
@@ -0,0 +1,158 @@
1
+ const KNOWN_PROMPT_TEXT_SLASH_COMMAND_EXECUTION_KINDS = {
2
+ reminder: 'prompt_augment',
3
+ document: 'prompt_augment',
4
+ panel: 'prompt_augment',
5
+ 'panel:plan': 'prompt_augment',
6
+ tool: 'prompt_augment',
7
+ 'tool:plan': 'prompt_augment',
8
+ rewind: 'local_action',
9
+ };
10
+ export function normalizePromptSlashCommandName(value) {
11
+ const name = value?.trim().toLowerCase();
12
+ if (name === 'reminder'
13
+ || name === 'document'
14
+ || name === 'panel'
15
+ || name === 'panel:plan'
16
+ || name === 'tool'
17
+ || name === 'tool:plan'
18
+ || name === 'rewind') {
19
+ return name;
20
+ }
21
+ return null;
22
+ }
23
+ export function isPanelPromptSlashCommandName(value) {
24
+ const name = normalizePromptSlashCommandName(value);
25
+ return name === 'panel' || name === 'panel:plan';
26
+ }
27
+ export function isWorkspaceToolPromptSlashCommandName(value) {
28
+ const name = normalizePromptSlashCommandName(value);
29
+ return name === 'tool' || name === 'tool:plan';
30
+ }
31
+ export function isLayoutPlanPromptSlashCommandName(value) {
32
+ const name = normalizePromptSlashCommandName(value);
33
+ return name === 'panel:plan' || name === 'tool:plan';
34
+ }
35
+ export function normalizePromptSlashCommandInput(value) {
36
+ if (!value || typeof value !== 'object')
37
+ return null;
38
+ const input = value;
39
+ const name = normalizePromptSlashCommandName(typeof input.name === 'string' ? input.name : null);
40
+ const bodyText = typeof input.bodyText === 'string' ? input.bodyText.trim() : '';
41
+ if (name === 'reminder'
42
+ || name === 'document'
43
+ || name === 'panel'
44
+ || name === 'panel:plan'
45
+ || name === 'tool'
46
+ || name === 'tool:plan') {
47
+ return { name, bodyText };
48
+ }
49
+ return null;
50
+ }
51
+ export function parseKnownPromptSlashCommandFromText(text) {
52
+ const match = text.trim().match(/^\/([A-Za-z0-9:_-]+)(?:\s+([\s\S]*))?$/u);
53
+ const name = match?.[1]?.trim().toLowerCase();
54
+ if (!name)
55
+ return null;
56
+ const executionKind = KNOWN_PROMPT_TEXT_SLASH_COMMAND_EXECUTION_KINDS[name];
57
+ if (!executionKind)
58
+ return null;
59
+ return {
60
+ name,
61
+ bodyText: match?.[2]?.trim() ?? '',
62
+ executionKind,
63
+ };
64
+ }
65
+ export function toPromptAugmentSlashCommand(slashCommand) {
66
+ if (!slashCommand || slashCommand.executionKind !== 'prompt_augment')
67
+ return null;
68
+ return {
69
+ name: slashCommand.name,
70
+ bodyText: slashCommand.bodyText,
71
+ };
72
+ }
73
+ export function isPanelToggleCommand(slashCommand) {
74
+ if (!slashCommand || slashCommand.name !== 'panel')
75
+ return null;
76
+ const body = slashCommand.bodyText.trim().toLowerCase();
77
+ if (body === 'off')
78
+ return 'off';
79
+ if (body === 'on')
80
+ return 'on';
81
+ return null;
82
+ }
83
+ export function getPromptSlashCommandValidationError({ derivedSlashCommand, requestedSlashCommand, sendAsTask, isPrimaryPrivateChat, allowPanelTask, allowToolTask, allowToolPrompt, toolUnavailableError, }) {
84
+ if (requestedSlashCommand
85
+ && (!derivedSlashCommand
86
+ || derivedSlashCommand.executionKind !== 'prompt_augment'
87
+ || requestedSlashCommand.name !== derivedSlashCommand.name
88
+ || requestedSlashCommand.bodyText !== derivedSlashCommand.bodyText)) {
89
+ return {
90
+ statusCode: 400,
91
+ error: 'slashCommand payload must match the leading slash command text',
92
+ };
93
+ }
94
+ if (derivedSlashCommand?.executionKind === 'local_action') {
95
+ return {
96
+ statusCode: 409,
97
+ error: `/${derivedSlashCommand.name} is a local-only slash command and cannot be sent to the server`,
98
+ };
99
+ }
100
+ if (derivedSlashCommand?.name === 'reminder' && !derivedSlashCommand.bodyText) {
101
+ return {
102
+ statusCode: 400,
103
+ error: '/reminder requires reminder instructions after the command',
104
+ };
105
+ }
106
+ if (isPanelPromptSlashCommandName(derivedSlashCommand?.name) && !derivedSlashCommand?.bodyText) {
107
+ return {
108
+ statusCode: 400,
109
+ error: `/${derivedSlashCommand?.name ?? 'panel'} requires UI or panel instructions after the command`,
110
+ };
111
+ }
112
+ if (isWorkspaceToolPromptSlashCommandName(derivedSlashCommand?.name) && !derivedSlashCommand?.bodyText) {
113
+ return {
114
+ statusCode: 400,
115
+ error: `/${derivedSlashCommand?.name ?? 'tool'} requires workspace tool instructions after the command`,
116
+ };
117
+ }
118
+ if (derivedSlashCommand?.executionKind !== 'prompt_augment') {
119
+ return null;
120
+ }
121
+ if (isPanelPromptSlashCommandName(derivedSlashCommand.name)) {
122
+ if (!allowPanelTask && sendAsTask) {
123
+ return {
124
+ statusCode: 409,
125
+ error: 'Slash command requests cannot be sent as tasks',
126
+ };
127
+ }
128
+ return null;
129
+ }
130
+ if (isWorkspaceToolPromptSlashCommandName(derivedSlashCommand.name)) {
131
+ if (sendAsTask && !allowToolTask) {
132
+ return {
133
+ statusCode: 409,
134
+ error: 'Slash command requests cannot be sent as tasks',
135
+ };
136
+ }
137
+ if (allowToolPrompt === false) {
138
+ return {
139
+ statusCode: 409,
140
+ error: toolUnavailableError?.trim() || '/tool is not available on this surface',
141
+ };
142
+ }
143
+ return null;
144
+ }
145
+ if (sendAsTask) {
146
+ return {
147
+ statusCode: 409,
148
+ error: 'Slash command requests cannot be sent as tasks',
149
+ };
150
+ }
151
+ if (!isPrimaryPrivateChat) {
152
+ return {
153
+ statusCode: 409,
154
+ error: `/${derivedSlashCommand.name} is only available in a primary private chat`,
155
+ };
156
+ }
157
+ return null;
158
+ }