@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,43 @@
1
+ export class KeyedMutationQueue {
2
+ pending = new Map();
3
+ async enqueue(key, work) {
4
+ const previous = this.pending.get(key) ?? Promise.resolve();
5
+ let releaseCurrent;
6
+ const current = new Promise((resolve) => {
7
+ releaseCurrent = resolve;
8
+ });
9
+ const stored = previous.catch(() => undefined).then(() => current);
10
+ this.pending.set(key, stored);
11
+ await previous.catch(() => undefined);
12
+ try {
13
+ return await work();
14
+ }
15
+ finally {
16
+ releaseCurrent();
17
+ if (this.pending.get(key) === stored) {
18
+ this.pending.delete(key);
19
+ }
20
+ }
21
+ }
22
+ pendingKeyCount() {
23
+ return this.pending.size;
24
+ }
25
+ }
26
+ export class WorkspaceToolMutationQueues {
27
+ toolQueue = new KeyedMutationQueue();
28
+ publishQueue = new KeyedMutationQueue();
29
+ panelPromotionQueue = new KeyedMutationQueue();
30
+ agentPersistentStartQueue = new KeyedMutationQueue();
31
+ enqueueTool(toolId, work) {
32
+ return this.toolQueue.enqueue(toolId, work);
33
+ }
34
+ enqueuePublish(publishKey, work) {
35
+ return this.publishQueue.enqueue(publishKey, work);
36
+ }
37
+ enqueuePanelPromotion(panelId, work) {
38
+ return this.panelPromotionQueue.enqueue(panelId, work);
39
+ }
40
+ enqueueAgentPersistentStart(agentId, work) {
41
+ return this.agentPersistentStartQueue.enqueue(agentId, work);
42
+ }
43
+ }
@@ -0,0 +1,460 @@
1
+ import { buildWorkspaceToolPanelActionParamKey, mapPanelLevelNodes, panelLevelNodeHasActionBar, } from '@bbigbang/protocol';
2
+ const TOOL_SNAPSHOT_RUNTIME_FIELD_LIMIT = 4;
3
+ const TOOL_RUNTIME_SUMMARY_MARKER = 'bigbang:tool-runtime-summary';
4
+ const TOOL_ACTION_PARAMETER_FORM_MARKER = 'bigbang:tool-action-parameter-form';
5
+ export function buildToolSnapshotPanelProjection(spec) {
6
+ const actions = spec.manifest.actions.map((action) => ({
7
+ id: action.actionId,
8
+ label: action.label,
9
+ ...(action.description ? { description: action.description } : {}),
10
+ ...(action.kind === 'stop' ? { variant: 'danger' } : {}),
11
+ }));
12
+ const sourceProps = spec.sourceProps ?? null;
13
+ const sourcePageSize = typeof sourceProps?.pageSize === 'number' && Number.isFinite(sourceProps.pageSize)
14
+ ? Math.min(50, Math.max(1, Math.trunc(sourceProps.pageSize)))
15
+ : null;
16
+ const props = {
17
+ title: spec.manifest.view.title ?? spec.manifest.name,
18
+ pageSize: sourceProps ? (sourcePageSize ?? 10) : 1,
19
+ fields: spec.manifest.view.fields,
20
+ mediaSlots: spec.manifest.view.mediaSlots ?? [],
21
+ template: spec.manifest.view.template,
22
+ };
23
+ const summary = buildToolSnapshotSummaryNode(spec.manifest.view.summary ?? null, sourceProps?.summary, spec.latestState, {
24
+ manifest: spec.manifest,
25
+ allowSharedExec: spec.allowSharedExec,
26
+ status: spec.status,
27
+ });
28
+ if (summary)
29
+ props.summary = summary;
30
+ const parameterForm = buildToolSnapshotParameterFormNode(spec.manifest.view.parameterForm ?? null, sourceProps?.parameterForm, spec.manifest, {
31
+ includeActionBar: true,
32
+ stripSourceInteractiveControls: Boolean(spec.sourcePanelId),
33
+ });
34
+ if (parameterForm)
35
+ props.parameterForm = parameterForm;
36
+ const latestStateRow = spec.latestState ? {
37
+ rowId: 'tool-state',
38
+ fields: spec.latestState.fields,
39
+ media: spec.latestState.media ?? {},
40
+ nodeId: spec.nodeId,
41
+ } : null;
42
+ const sourceRows = spec.sourceRows && spec.sourceRows.length > 0
43
+ ? spec.sourceRows
44
+ : spec.preservedRows ?? [];
45
+ const rows = sourceRows.length > 0
46
+ ? sourceRows
47
+ : latestStateRow
48
+ ? [latestStateRow]
49
+ : [];
50
+ const result = buildToolSnapshotPanelResult(spec.latestState, spec.status);
51
+ return {
52
+ props,
53
+ actions,
54
+ rows,
55
+ rowCount: rows.length,
56
+ result,
57
+ schemaFingerprint: buildToolSnapshotSchemaFingerprint(props),
58
+ };
59
+ }
60
+ export function buildToolSnapshotSchemaFingerprint(props) {
61
+ return stableStringify({
62
+ fields: props.fields ?? [],
63
+ mediaSlots: props.mediaSlots ?? [],
64
+ summary: props.summary ?? null,
65
+ template: props.template ?? null,
66
+ parameterForm: props.parameterForm ?? null,
67
+ });
68
+ }
69
+ export function deriveWorkspaceToolBusinessState(latestState) {
70
+ const value = latestState?.fields?.status;
71
+ if (typeof value === 'string' && value.trim().length > 0)
72
+ return value.trim();
73
+ if (typeof value === 'number' || typeof value === 'boolean')
74
+ return String(value);
75
+ return null;
76
+ }
77
+ export function deriveWorkspaceToolRuntimeState(params) {
78
+ if (params.activeTerminalId)
79
+ return 'running';
80
+ if (params.lastRunStatus === 'failed')
81
+ return 'failed';
82
+ if (params.lastRunStatus === 'completed')
83
+ return 'completed';
84
+ return 'idle';
85
+ }
86
+ export function workspaceToolRuntimeStateToPanelStatus(runtimeState) {
87
+ if (runtimeState === 'running')
88
+ return 'running';
89
+ if (runtimeState === 'failed')
90
+ return 'failed';
91
+ if (runtimeState === 'completed')
92
+ return 'completed';
93
+ return 'idle';
94
+ }
95
+ export function buildToolActionParameterFormSectionForActions(actions, options) {
96
+ const children = [];
97
+ for (const action of actions) {
98
+ for (const field of action.paramsSchema ?? []) {
99
+ const props = {
100
+ name: buildWorkspaceToolPanelActionParamKey(action.actionId, field.name),
101
+ label: field.label ? `${action.label} · ${field.label}` : `${action.label} · ${field.name}`,
102
+ __bigbangBuiltin: TOOL_ACTION_PARAMETER_FORM_MARKER,
103
+ };
104
+ if (field.placeholder)
105
+ props.placeholder = field.placeholder;
106
+ if (field.defaultValue !== undefined)
107
+ props.defaultValue = field.defaultValue;
108
+ if (field.required === true)
109
+ props.required = true;
110
+ if (field.min !== undefined)
111
+ props.min = field.min;
112
+ if (field.max !== undefined)
113
+ props.max = field.max;
114
+ if (field.accept !== undefined)
115
+ props.accept = field.accept;
116
+ if (field.multiple === true)
117
+ props.multiple = true;
118
+ if (field.maxBytes !== undefined)
119
+ props.maxBytes = field.maxBytes;
120
+ if (field.options?.length) {
121
+ props.options = field.options.map((option) => ({
122
+ label: option.label,
123
+ value: option.value,
124
+ }));
125
+ }
126
+ const input = field.input ?? 'text';
127
+ if (input === 'number') {
128
+ children.push({ type: 'NumberInput', props });
129
+ }
130
+ else if (input === 'checkbox') {
131
+ children.push({ type: 'Checkbox', props });
132
+ }
133
+ else if (input === 'select') {
134
+ children.push({ type: 'Select', props });
135
+ }
136
+ else if (input === 'multiselect') {
137
+ children.push({ type: 'MultiSelect', props });
138
+ }
139
+ else if (input === 'tags') {
140
+ children.push({ type: 'TagInput', props });
141
+ }
142
+ else if (input === 'date') {
143
+ children.push({ type: 'DatePicker', props });
144
+ }
145
+ else if (input === 'file') {
146
+ children.push({ type: 'FileUpload', props });
147
+ }
148
+ else if (input === 'textarea') {
149
+ children.push({ type: 'TextArea', props });
150
+ }
151
+ else {
152
+ children.push({ type: 'TextInput', props });
153
+ }
154
+ }
155
+ }
156
+ const actionBar = buildToolGeneratedActionBarNode(actions, options);
157
+ if (actionBar)
158
+ children.push(actionBar);
159
+ return children.length > 0
160
+ ? {
161
+ type: 'ParameterFormSection',
162
+ children,
163
+ }
164
+ : null;
165
+ }
166
+ function stableStringify(value) {
167
+ if (value === undefined)
168
+ return 'undefined';
169
+ if (value === null || typeof value !== 'object')
170
+ return JSON.stringify(value) ?? 'undefined';
171
+ if (Array.isArray(value))
172
+ return `[${value.map((item) => stableStringify(item)).join(',')}]`;
173
+ const entries = Object.entries(value)
174
+ .sort(([a], [b]) => a.localeCompare(b));
175
+ return `{${entries.map(([key, entryValue]) => `${JSON.stringify(key)}:${stableStringify(entryValue)}`).join(',')}}`;
176
+ }
177
+ function buildToolSnapshotPanelResult(latestState, status) {
178
+ if (!latestState)
179
+ return null;
180
+ const summary = formatToolSnapshotLatestStateSummary(latestState.fields);
181
+ return {
182
+ summary,
183
+ status: status ?? null,
184
+ latestState: {
185
+ fields: latestState.fields,
186
+ media: latestState.media ?? {},
187
+ },
188
+ };
189
+ }
190
+ function buildToolSnapshotSummaryNode(manifestSummary, sourceSummary, latestState, options) {
191
+ const baseSummary = stripToolSummaryNode(manifestSummary ?? sourceSummary);
192
+ const staticSummary = buildToolStaticSummaryNode(options.manifest, latestState, options);
193
+ const runtimeSummary = buildToolRuntimeSummaryNode(latestState);
194
+ const children = [baseSummary, staticSummary, runtimeSummary].filter((node) => node !== null);
195
+ if (children.length === 0)
196
+ return null;
197
+ if (children.length === 1)
198
+ return children[0] ?? null;
199
+ return {
200
+ type: 'Section',
201
+ children,
202
+ };
203
+ }
204
+ function buildToolStaticSummaryNode(manifest, latestState, options) {
205
+ const hasNotifyAgentActions = manifest.actions.some((action) => (action.mode ?? 'platform_exec') === 'notify_agent');
206
+ const children = [
207
+ buildToolStaticSummaryMetricCard('State', formatToolSnapshotBusinessState(latestState)),
208
+ buildToolStaticSummaryMetricCard('Runtime', formatToolSnapshotRuntimeStatus(options.status)),
209
+ buildToolStaticSummaryMetricCard('Shared execution', options.allowSharedExec ? 'Enabled' : 'Owner only'),
210
+ ];
211
+ if (hasNotifyAgentActions) {
212
+ children.push(buildToolStaticSummaryMetricCard('Notify-agent actions', 'Owner only'));
213
+ }
214
+ if (!latestState) {
215
+ children.push(buildToolStaticSummaryMetricCard('Runtime data', 'Pending'));
216
+ }
217
+ return buildCompactToolSummaryColumns(children);
218
+ }
219
+ function buildToolStaticSummaryMetricCard(label, value) {
220
+ return {
221
+ type: 'MetricCard',
222
+ props: {
223
+ label,
224
+ value,
225
+ __bigbangBuiltin: TOOL_RUNTIME_SUMMARY_MARKER,
226
+ },
227
+ };
228
+ }
229
+ function panelStatusToWorkspaceToolRuntimeState(status) {
230
+ if (status === 'running')
231
+ return 'running';
232
+ if (status === 'failed')
233
+ return 'failed';
234
+ if (status === 'completed')
235
+ return 'completed';
236
+ return 'idle';
237
+ }
238
+ function formatWorkspaceToolRuntimeStateLabel(runtimeState) {
239
+ if (runtimeState === 'running')
240
+ return 'Running';
241
+ if (runtimeState === 'failed')
242
+ return 'Failed';
243
+ if (runtimeState === 'completed')
244
+ return 'Completed';
245
+ return 'Idle';
246
+ }
247
+ function formatToolSnapshotBusinessState(latestState) {
248
+ return deriveWorkspaceToolBusinessState(latestState) ?? 'No runtime data yet';
249
+ }
250
+ function formatToolSnapshotRuntimeStatus(status) {
251
+ return formatWorkspaceToolRuntimeStateLabel(panelStatusToWorkspaceToolRuntimeState(status));
252
+ }
253
+ function buildToolSnapshotParameterFormNode(manifestParameterForm, sourceParameterForm, manifest, options) {
254
+ const baseParameterForm = manifestParameterForm
255
+ ? canonicalizeToolActionParameterFormNode(manifestParameterForm, manifest)
256
+ : stripToolActionParameterFormNode(sourceParameterForm, {
257
+ stripGeneratedActionBar: options?.includeActionBar !== false,
258
+ stripSourceInteractiveControls: options?.stripSourceInteractiveControls === true,
259
+ });
260
+ const generatedParameterForm = manifestParameterForm
261
+ ? (panelLevelNodeHasActionBar(manifestParameterForm)
262
+ ? null
263
+ : buildToolGeneratedActionBarNode(manifest.actions, options))
264
+ : buildToolActionParameterFormSectionForActions(manifest.actions, options);
265
+ if (baseParameterForm && generatedParameterForm) {
266
+ return {
267
+ type: 'Section',
268
+ children: [baseParameterForm, generatedParameterForm],
269
+ };
270
+ }
271
+ return baseParameterForm ?? generatedParameterForm;
272
+ }
273
+ function canonicalizeToolActionParameterFormNode(node, manifest) {
274
+ const fieldByKey = new Map();
275
+ for (const action of manifest.actions) {
276
+ for (const field of action.paramsSchema ?? []) {
277
+ fieldByKey.set(buildWorkspaceToolPanelActionParamKey(action.actionId, field.name), { action, field });
278
+ }
279
+ }
280
+ return mapPanelLevelNodes(node, (candidate) => {
281
+ const props = candidate.props;
282
+ if (!isPlainRecord(props))
283
+ return undefined;
284
+ const name = props.name;
285
+ if (typeof name !== 'string')
286
+ return undefined;
287
+ const binding = fieldByKey.get(name);
288
+ if (!binding)
289
+ return undefined;
290
+ const propsWithoutAuthoredContract = stripAuthoredToolParameterControlProps(props);
291
+ return {
292
+ ...candidate,
293
+ props: {
294
+ ...propsWithoutAuthoredContract,
295
+ ...buildCanonicalToolParameterControlProps(binding.action, binding.field),
296
+ },
297
+ };
298
+ }) ?? node;
299
+ }
300
+ function stripAuthoredToolParameterControlProps(props) {
301
+ const next = { ...props };
302
+ for (const key of ['label', 'placeholder', 'defaultValue', 'value', 'checked', 'required', 'min', 'max', 'accept', 'multiple', 'maxBytes', 'options']) {
303
+ delete next[key];
304
+ }
305
+ return next;
306
+ }
307
+ function buildCanonicalToolParameterControlProps(action, field) {
308
+ const props = {
309
+ label: field.label ? `${action.label} · ${field.label}` : `${action.label} · ${field.name}`,
310
+ };
311
+ if (field.placeholder)
312
+ props.placeholder = field.placeholder;
313
+ if (field.defaultValue !== undefined)
314
+ props.defaultValue = field.defaultValue;
315
+ if (field.required === true)
316
+ props.required = true;
317
+ if (field.min !== undefined)
318
+ props.min = field.min;
319
+ if (field.max !== undefined)
320
+ props.max = field.max;
321
+ if (field.accept !== undefined)
322
+ props.accept = field.accept;
323
+ if (field.multiple === true)
324
+ props.multiple = true;
325
+ if (field.maxBytes !== undefined)
326
+ props.maxBytes = field.maxBytes;
327
+ if (field.options?.length) {
328
+ props.options = field.options.map((option) => ({
329
+ label: option.label,
330
+ value: option.value,
331
+ }));
332
+ }
333
+ return props;
334
+ }
335
+ function buildToolGeneratedActionBarNode(actions, options) {
336
+ if (options?.includeActionBar === false || actions.length === 0)
337
+ return null;
338
+ return {
339
+ type: 'ActionBar',
340
+ actionIds: actions.map((action) => action.actionId),
341
+ title: 'Actions',
342
+ layout: 'wrap',
343
+ };
344
+ }
345
+ function buildToolRuntimeSummaryNode(latestState) {
346
+ if (!latestState)
347
+ return null;
348
+ const children = [
349
+ {
350
+ type: 'MetricCard',
351
+ props: {
352
+ label: 'Latest tool state',
353
+ source: { kind: 'panel_result', path: ['summary'] },
354
+ __bigbangBuiltin: TOOL_RUNTIME_SUMMARY_MARKER,
355
+ },
356
+ },
357
+ ];
358
+ const fieldEntries = Object.entries(latestState.fields)
359
+ .filter(([, value]) => (value === null
360
+ || typeof value === 'string'
361
+ || typeof value === 'number'
362
+ || typeof value === 'boolean'))
363
+ .slice(0, TOOL_SNAPSHOT_RUNTIME_FIELD_LIMIT);
364
+ for (const [field] of fieldEntries) {
365
+ children.push({
366
+ type: 'MetricCard',
367
+ props: {
368
+ label: field,
369
+ source: { kind: 'panel_result', path: ['latestState', 'fields', field] },
370
+ __bigbangBuiltin: TOOL_RUNTIME_SUMMARY_MARKER,
371
+ },
372
+ });
373
+ }
374
+ return buildCompactToolSummaryColumns(children);
375
+ }
376
+ function buildCompactToolSummaryColumns(children) {
377
+ if (children.length === 0)
378
+ return null;
379
+ return {
380
+ type: 'Columns',
381
+ columns: children.map((child) => ({ children: [child] })),
382
+ };
383
+ }
384
+ function stripToolSummaryNode(node) {
385
+ if (!isPlainRecord(node))
386
+ return null;
387
+ return stripPanelLevelNodes(node, (candidate) => (isToolRuntimeSummaryNode(candidate)
388
+ || isSourcePromotedToolInteractiveParameterNode(candidate)));
389
+ }
390
+ function stripToolActionParameterFormNode(node, options) {
391
+ if (!isPlainRecord(node))
392
+ return null;
393
+ return stripPanelLevelNodes(node, (candidate) => ((options?.stripSourceInteractiveControls === true
394
+ && isSourcePromotedToolInteractiveParameterNode(candidate))
395
+ || isToolActionParameterFormNode(candidate, options)));
396
+ }
397
+ function stripPanelLevelNodes(node, shouldStrip) {
398
+ return mapPanelLevelNodes(node, (candidate) => shouldStrip(candidate) ? null : undefined, {
399
+ pruneEmptyContainers: true,
400
+ pruneEmptyColumns: true,
401
+ collapseSingleChildContainers: true,
402
+ });
403
+ }
404
+ function isToolRuntimeSummaryNode(node) {
405
+ if (node.type === 'MetricCard') {
406
+ const props = node.props;
407
+ return isPlainRecord(props) && props.__bigbangBuiltin === TOOL_RUNTIME_SUMMARY_MARKER;
408
+ }
409
+ if (node.type === 'Section' && Array.isArray(node.children) && node.children.length > 0) {
410
+ return node.children.every((child) => isPlainRecord(child) && isToolRuntimeSummaryNode(child));
411
+ }
412
+ if (node.type === 'Columns' && Array.isArray(node.columns) && node.columns.length > 0) {
413
+ return node.columns.every((column) => (isPlainRecord(column)
414
+ && Array.isArray(column.children)
415
+ && column.children.length > 0
416
+ && column.children.every((child) => isPlainRecord(child) && isToolRuntimeSummaryNode(child))));
417
+ }
418
+ return false;
419
+ }
420
+ function isToolActionParameterFormNode(node, options) {
421
+ if (options?.stripGeneratedActionBar === true
422
+ && node.type === 'ActionBar'
423
+ && Array.isArray(node.actionIds)
424
+ && node.actionIds.every((actionId) => typeof actionId === 'string')
425
+ && (node.layout === undefined || node.layout === 'wrap')
426
+ && node.title === 'Actions') {
427
+ return true;
428
+ }
429
+ const props = node.props;
430
+ return isPlainRecord(props) && props.__bigbangBuiltin === TOOL_ACTION_PARAMETER_FORM_MARKER;
431
+ }
432
+ function isSourcePromotedToolInteractiveParameterNode(node) {
433
+ return node.type === 'ActionBar'
434
+ || node.type === 'TextInput'
435
+ || node.type === 'TextArea'
436
+ || node.type === 'NumberInput'
437
+ || node.type === 'Checkbox'
438
+ || node.type === 'Select'
439
+ || node.type === 'MultiSelect'
440
+ || node.type === 'TagInput'
441
+ || node.type === 'Slider'
442
+ || node.type === 'DatePicker'
443
+ || node.type === 'FileUpload'
444
+ || node.type === 'Button';
445
+ }
446
+ function formatToolSnapshotLatestStateSummary(fields) {
447
+ const entries = Object.entries(fields)
448
+ .filter(([, value]) => (value === null
449
+ || typeof value === 'string'
450
+ || typeof value === 'number'
451
+ || typeof value === 'boolean'))
452
+ .slice(0, TOOL_SNAPSHOT_RUNTIME_FIELD_LIMIT)
453
+ .map(([key, value]) => `${key}=${String(value)}`);
454
+ return entries.length > 0
455
+ ? `Latest tool state: ${entries.join(', ')}`
456
+ : 'Latest tool state updated.';
457
+ }
458
+ function isPlainRecord(value) {
459
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
460
+ }