@burdenoff/microfe-bigconsole 2026.624.1 → 2026.625.1

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 (186) hide show
  1. package/dist/bigconsole/BigConsoleRoutes.js +94 -94
  2. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  3. package/dist/bigconsole/assistant/assistantApi.js +215 -0
  4. package/dist/bigconsole/assistant/assistantApi.js.map +1 -0
  5. package/dist/bigconsole/assistant/createSandboxAssistantTransport.js +119 -0
  6. package/dist/bigconsole/assistant/createSandboxAssistantTransport.js.map +1 -0
  7. package/dist/bigconsole/assistant/index.js +2 -0
  8. package/dist/bigconsole/assistant/pageContext.js +51 -0
  9. package/dist/bigconsole/assistant/pageContext.js.map +1 -0
  10. package/dist/bigconsole/components/DrilldownModal.js +4 -4
  11. package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
  12. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +48 -48
  13. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +1 -1
  14. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  15. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +54 -54
  16. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  17. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +1 -1
  18. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  19. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +33 -33
  20. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +205 -205
  21. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  22. package/dist/bigconsole/components/dashboard/WidgetPalette.js +38 -38
  23. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +1 -1
  24. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  25. package/dist/bigconsole/components/datasink/DataSinkCard.js +4 -4
  26. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  27. package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +2 -2
  28. package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
  29. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +2 -2
  30. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  31. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +2 -2
  32. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  33. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +34 -34
  34. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
  35. package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +31 -31
  36. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +121 -121
  37. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  38. package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +1 -1
  39. package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
  40. package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +3 -3
  41. package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
  42. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +2 -2
  43. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  44. package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +2 -2
  45. package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
  46. package/dist/bigconsole/components/parser/DataSinkSelector.js +3 -3
  47. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  48. package/dist/bigconsole/components/parser/ExportParserDialog.js +31 -31
  49. package/dist/bigconsole/components/parser/ImportParserDialog.js +186 -186
  50. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  51. package/dist/bigconsole/components/parser/ParserCard.js +5 -5
  52. package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
  53. package/dist/bigconsole/components/parser/ParserSelector.js +6 -6
  54. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  55. package/dist/bigconsole/components/parser/ParserStatusBadge.js +1 -1
  56. package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
  57. package/dist/bigconsole/components/parser/ParserTypeBadge.js +1 -1
  58. package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
  59. package/dist/bigconsole/components/pipeline/PipelineCard.js +2 -2
  60. package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
  61. package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +1 -1
  62. package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
  63. package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +1 -1
  64. package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
  65. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +79 -79
  66. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  67. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +11 -11
  68. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  69. package/dist/bigconsole/components/widgets/PropertiesPanel.js +322 -322
  70. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  71. package/dist/bigconsole/components/widgets/WidgetConfigDialog.js +234 -234
  72. package/dist/bigconsole/components/widgets/WidgetConfigDialog.js.map +1 -1
  73. package/dist/bigconsole/components/widgets/WidgetHeader.js +4 -4
  74. package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
  75. package/dist/bigconsole/components/widgets/WidgetMenu.js +3 -3
  76. package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
  77. package/dist/bigconsole/components/widgets/WidgetTypeSelector.js +23 -23
  78. package/dist/bigconsole/components/widgets/WidgetWrapper.js +1 -1
  79. package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
  80. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +1 -1
  81. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  82. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +2 -2
  83. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  84. package/dist/bigconsole/components/widgets/custom/CustomWidget.js +5 -5
  85. package/dist/bigconsole/components/widgets/custom/CustomWidget.js.map +1 -1
  86. package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +1 -1
  87. package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
  88. package/dist/bigconsole/components/widgets/gauge/LinearGauge.js +1 -1
  89. package/dist/bigconsole/components/widgets/gauge/LinearGauge.js.map +1 -1
  90. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +2 -2
  91. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  92. package/dist/bigconsole/components/widgets/kpi/KPIWidget.js +2 -2
  93. package/dist/bigconsole/components/widgets/kpi/KPIWidget.js.map +1 -1
  94. package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +2 -2
  95. package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
  96. package/dist/bigconsole/components/widgets/list/ListItem.js +3 -3
  97. package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
  98. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +3 -3
  99. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
  100. package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js +1 -1
  101. package/dist/bigconsole/components/widgets/metric-card/ComparisonBadge.js.map +1 -1
  102. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js +2 -2
  103. package/dist/bigconsole/components/widgets/metric-card/MetricCardWidget.js.map +1 -1
  104. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +12 -12
  105. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  106. package/dist/bigconsole/components/widgets/progress/ProgressBar.js +2 -2
  107. package/dist/bigconsole/components/widgets/progress/ProgressBar.js.map +1 -1
  108. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +1 -1
  109. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  110. package/dist/bigconsole/components/widgets/progress/ProgressWidget.js +1 -1
  111. package/dist/bigconsole/components/widgets/progress/ProgressWidget.js.map +1 -1
  112. package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +2 -2
  113. package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
  114. package/dist/bigconsole/components/widgets/states/EmptyState.js +1 -1
  115. package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
  116. package/dist/bigconsole/components/widgets/table/TableCell.js +1 -1
  117. package/dist/bigconsole/components/widgets/table/TableCell.js.map +1 -1
  118. package/dist/bigconsole/components/widgets/table/TableConfig.js +1 -1
  119. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  120. package/dist/bigconsole/components/widgets/table/TableHeader.js +2 -2
  121. package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
  122. package/dist/bigconsole/components/widgets/table/TablePagination.js +4 -4
  123. package/dist/bigconsole/components/widgets/table/TablePagination.js.map +1 -1
  124. package/dist/bigconsole/components/widgets/table/TableWidget.js +5 -5
  125. package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
  126. package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
  127. package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
  128. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
  129. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
  130. package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
  131. package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
  132. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +3 -3
  133. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  134. package/dist/bigconsole/components/workflow/WorkflowCard.js +2 -2
  135. package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
  136. package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +1 -1
  137. package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
  138. package/dist/bigconsole/index.js +3 -0
  139. package/dist/bigconsole/pages/DashboardBuilderPage.js +76 -76
  140. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  141. package/dist/bigconsole/pages/DashboardViewPage.js +169 -190
  142. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  143. package/dist/bigconsole/pages/DashboardsPage.js +268 -312
  144. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  145. package/dist/bigconsole/pages/DataParsersPage.js +148 -194
  146. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  147. package/dist/bigconsole/pages/DataSinkBuilderPage.js +254 -248
  148. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  149. package/dist/bigconsole/pages/DataSinkViewPage.js +256 -231
  150. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  151. package/dist/bigconsole/pages/DataSinksPage.js +173 -219
  152. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  153. package/dist/bigconsole/pages/HomePage.js +125 -141
  154. package/dist/bigconsole/pages/HomePage.js.map +1 -1
  155. package/dist/bigconsole/pages/InsightsPage.js +159 -184
  156. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  157. package/dist/bigconsole/pages/ParserBuilderPage.js +404 -396
  158. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  159. package/dist/bigconsole/pages/ParserViewPage.js +221 -202
  160. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  161. package/dist/bigconsole/pages/PipelineBuilderPage.js +216 -210
  162. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  163. package/dist/bigconsole/pages/PipelineViewPage.js +213 -190
  164. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  165. package/dist/bigconsole/pages/PipelinesPage.js +107 -150
  166. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  167. package/dist/bigconsole/pages/SettingsPage.js +184 -171
  168. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  169. package/dist/bigconsole/pages/WidgetDemoPage.js +71 -83
  170. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  171. package/dist/bigconsole/pages/WorkflowViewPage.js +235 -221
  172. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  173. package/dist/bigconsole/pages/WorkflowsPage.js +106 -149
  174. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  175. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +12 -12
  176. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
  177. package/dist/bigconsole/renderers/adapters/BigConsoleRenderer.js +2 -2
  178. package/dist/bigconsole/renderers/adapters/BigConsoleRenderer.js.map +1 -1
  179. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +5 -5
  180. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
  181. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +2 -2
  182. package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
  183. package/dist/generated/wspace-operations.js +87 -36
  184. package/dist/generated/wspace-operations.js.map +1 -1
  185. package/dist/index.js +3 -1
  186. package/package.json +6 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assistantApi.js","names":[],"sources":["../../../src/bigconsole/assistant/assistantApi.ts"],"sourcesContent":["/**\n * AI Assistant API service for BigConsole.\n *\n * All requests go through the wspace-public-gateway (GraphQL Federation):\n * Frontend → wspace-public-gateway → wspace-sandbox-svc → ai-assistant (sandbox)\n *\n * This is a faithful port of microfe-vibecontrols' `services/assistantApi.ts`,\n * adapted for BigConsole: the only product-specific difference is\n * `AI_ASSISTANT_PRODUCT=bigconsole` in the sandbox container env (drives the\n * agent's per-product docs fetch + system prompt).\n */\n\nimport { print, type DocumentNode } from 'graphql';\nimport type { AssistantMode, AssistantRawMessage, AssistantSandboxAuthContext } from './types';\nimport type { PageContext } from './pageContext';\nimport {\n CreateSandboxDocument,\n GetSandboxDocument,\n GetActiveSandboxesDocument,\n ProxySandboxRequestDocument,\n ExtendSandboxTtlDocument,\n} from '../../generated/wspace-operations';\n\n// ── Image registry ─────────────────────────────────────────────────\n\nconst ACR_REGISTRY = 'burdenoffregistry.azurecr.io';\nconst GENERAL_IMAGE_TAG = import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha-proxy-auth-v1';\nconst VIBE_PLUGINS_IMAGE_TAG = import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha-proxy-auth-v1';\nconst API_CALLS_IMAGE_TAG = import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha-delegated-auth-v11';\nconst ASSISTANT_API_AUTH_STRATEGY = 'sandbox-app-client-headers-v1';\n\nfunction getImageTagForMode(mode: AssistantMode): string {\n switch (mode) {\n case 'general':\n return GENERAL_IMAGE_TAG;\n case 'vibe-plugins':\n return VIBE_PLUGINS_IMAGE_TAG;\n // The combined default mode runs in the api-calls image (it can make calls).\n case 'assistant':\n case 'api-calls':\n return API_CALLS_IMAGE_TAG;\n }\n}\n\nfunction getImageForMode(mode: AssistantMode): string {\n // `assistant` reuses the api-calls image — one image, mode selected at runtime\n // via AI_ASSISTANT_MODE. So the image segment is api-calls for both.\n const imageMode = mode === 'assistant' ? 'api-calls' : mode;\n return `${ACR_REGISTRY}/wspace/ai-assistant-${imageMode}:${getImageTagForMode(mode)}`;\n}\n\nfunction getResourcesForMode(mode: AssistantMode): {\n cpuRequest: string;\n cpuLimit: string;\n memoryRequest: string;\n memoryLimit: string;\n} {\n switch (mode) {\n case 'general':\n return {\n cpuRequest: '100m',\n cpuLimit: '500m',\n memoryRequest: '256Mi',\n memoryLimit: '1Gi',\n };\n case 'vibe-plugins':\n case 'assistant':\n case 'api-calls':\n return {\n cpuRequest: '150m',\n cpuLimit: '750m',\n memoryRequest: '384Mi',\n memoryLimit: '1536Mi',\n };\n }\n}\n\nfunction resolveSandboxAssistantMode(sandbox: {\n metadata: Record<string, unknown> | null;\n name?: string | null;\n}): AssistantMode | null {\n const metadataMode = sandbox.metadata?.assistantMode;\n if (\n metadataMode === 'assistant' ||\n metadataMode === 'general' ||\n metadataMode === 'api-calls' ||\n metadataMode === 'vibe-plugins'\n ) {\n return metadataMode;\n }\n\n const name = sandbox.name ?? '';\n if (name.startsWith('ai-assistant-vibe-plugins-')) return 'vibe-plugins';\n if (name.startsWith('ai-assistant-api-calls-')) return 'api-calls';\n if (name.startsWith('ai-assistant-general-')) return 'general';\n if (name.startsWith('ai-assistant-assistant-')) return 'assistant';\n return null;\n}\n\n// ── Types ───────────────────────────────────────────────────────────\n\ninterface GraphQLResponse<TData> {\n data?: TData;\n errors?: Array<{ message: string }>;\n}\n\ninterface ProxyResponse {\n proxySandboxRequest: {\n status: number;\n body: Record<string, unknown>;\n };\n}\n\nfunction getGatewayRequestContext(\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): { headers?: Record<string, string> } | undefined {\n const headers: Record<string, string> = {};\n\n if (authContext?.accessToken) {\n headers.authorization = `Bearer ${authContext.accessToken}`;\n }\n\n if (authContext?.workspaceToken) {\n headers['x-workspace-authorization'] = `Bearer ${authContext.workspaceToken}`;\n }\n\n if (workspaceId) {\n headers['x-workspace-id'] = workspaceId;\n }\n\n if (authContext?.userId) {\n headers['x-actor-id'] = authContext.userId;\n headers['x-actor-type'] = 'user';\n }\n\n if (authContext?.organizationId) {\n headers['x-org-id'] = authContext.organizationId;\n }\n\n return Object.keys(headers).length > 0 ? { headers } : undefined;\n}\n\nfunction buildSandboxContextInput(\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): Record<string, unknown> {\n return {\n workspaceId,\n ...(authContext?.organizationId\n ? {\n custom: {\n organizationId: authContext.organizationId,\n },\n }\n : {}),\n };\n}\n\nasync function executeSandboxGraphQL<TData>(params: {\n document: DocumentNode;\n variables: Record<string, unknown>;\n workspaceId: string;\n authContext?: AssistantSandboxAuthContext;\n}): Promise<TData> {\n const response = await fetch('/workspaces/graphql', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(getGatewayRequestContext(params.workspaceId, params.authContext)?.headers ?? {}),\n },\n body: JSON.stringify({\n query: print(params.document),\n variables: params.variables,\n }),\n });\n\n const result = (await response.json().catch(() => null)) as GraphQLResponse<TData> | null;\n\n if (!response.ok) {\n const messages = result?.errors?.map((error: { message: string }) => error.message).join(', ');\n const httpError = new Error(messages || `Sandbox GraphQL HTTP ${response.status}`) as Error & {\n statusCode?: number;\n result?: unknown;\n };\n httpError.statusCode = response.status;\n httpError.result = result ?? undefined;\n throw httpError;\n }\n\n if (!result) {\n throw new Error('Sandbox GraphQL returned empty response');\n }\n\n if (result.errors?.length) {\n throw new Error(result.errors.map((error: { message: string }) => error.message).join(', '));\n }\n\n if (!result.data) {\n throw new Error('Sandbox GraphQL returned no data');\n }\n\n return result.data;\n}\n\n// ── Find existing sandbox for a mode ───────────────────────────────\n\nexport async function findExistingSandbox(\n workspaceId: string,\n mode: AssistantMode,\n authContext?: AssistantSandboxAuthContext\n): Promise<string | null> {\n const data = await executeSandboxGraphQL<{\n getActiveSandboxes: Array<{\n id: string;\n name: string;\n status: string;\n metadata: Record<string, unknown> | null;\n template: string;\n createdBy: string;\n }>;\n }>({\n document: GetActiveSandboxesDocument,\n variables: { context: buildSandboxContextInput(workspaceId, authContext) },\n workspaceId,\n authContext,\n });\n const sandboxes = data.getActiveSandboxes ?? [];\n\n return (\n sandboxes.find(\n (s) =>\n (s.status === 'RUNNING' || s.status === 'PROVISIONING' || s.status === 'PENDING') &&\n s.template === 'AI_BUILDER' &&\n resolveSandboxAssistantMode(s) === mode &&\n (!authContext?.userId || s.createdBy === authContext.userId) &&\n s.metadata?.authStrategy === ASSISTANT_API_AUTH_STRATEGY &&\n s.metadata?.imageTag === getImageTagForMode(mode)\n )?.id ?? null\n );\n}\n\n// ── Sandbox lifecycle ──────────────────────────────────────────────\n\nexport async function createAssistantSandbox(\n mode: AssistantMode,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<string> {\n const resources = getResourcesForMode(mode);\n const env = [\n { name: 'AI_ASSISTANT_MODE', value: mode },\n { name: 'HOSTNAME', value: '0.0.0.0' },\n { name: 'WORKSPACE_ID', value: workspaceId },\n // Product the user is in — drives the agent's dynamic per-product docs fetch\n // (the docs repo is `<product>-docs`) and personalizes its system prompt.\n // This package is the BigConsole MFE, so the product is bigconsole.\n { name: 'AI_ASSISTANT_PRODUCT', value: 'bigconsole' },\n ];\n\n const data = await executeSandboxGraphQL<{ createSandbox: { id: string } }>({\n document: CreateSandboxDocument,\n variables: {\n input: {\n name: `ai-assistant-${mode}-${Date.now()}`,\n description: `AI Assistant sandbox (${mode} mode)`,\n template: 'AI_BUILDER',\n mode: 'DEPLOYMENT',\n containers: [\n {\n name: 'ai-assistant',\n image: getImageForMode(mode),\n // The agent (start-assistant.sh) binds :8080; the sandbox svc proxies\n // to this declared containerPort, so it MUST be 8080.\n ports: [{ containerPort: 8080, name: 'http' }],\n env,\n },\n ],\n resources: {\n cpuRequest: resources.cpuRequest,\n cpuLimit: resources.cpuLimit,\n memoryRequest: resources.memoryRequest,\n memoryLimit: resources.memoryLimit,\n },\n ttlSeconds: 600,\n metadata: {\n assistantMode: mode,\n assistantOwnerUserId: authContext?.userId ?? null,\n assistantOrganizationId: authContext?.organizationId ?? null,\n authStrategy: ASSISTANT_API_AUTH_STRATEGY,\n imageTag: getImageTagForMode(mode),\n },\n context: buildSandboxContextInput(workspaceId, authContext),\n },\n },\n workspaceId,\n authContext,\n });\n\n if (!data?.createSandbox?.id) {\n throw new Error('createSandbox returned empty response');\n }\n return data.createSandbox.id;\n}\n\nexport async function waitForSandboxReady(\n sandboxId: string,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext,\n maxWaitMs = 300_000\n): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < maxWaitMs) {\n const data = await executeSandboxGraphQL<{\n getSandbox: { status?: string; errorMessage?: string } | null;\n }>({\n document: GetSandboxDocument,\n variables: { id: sandboxId, context: buildSandboxContextInput(workspaceId, authContext) },\n workspaceId,\n authContext,\n });\n const status = data?.getSandbox?.status;\n const errorMessage = data?.getSandbox?.errorMessage as string | undefined;\n if (status === 'RUNNING') return;\n if (status === 'FAILED' || status === 'STOPPED' || status === 'EXPIRED') {\n throw new Error(\n errorMessage ? `Sandbox ${status.toLowerCase()}: ${errorMessage}` : `Sandbox ${status.toLowerCase()}`\n );\n }\n await new Promise((r) => setTimeout(r, 2000));\n }\n throw new Error('Sandbox startup timed out');\n}\n\n// ── Proxy calls to ai-assistant (via gateway → sandbox-svc) ───────\n\nasync function proxyToSandbox(\n sandboxId: string,\n workspaceId: string,\n path: string,\n method: string,\n body?: unknown,\n authContext?: AssistantSandboxAuthContext\n): Promise<Record<string, unknown>> {\n const result = await executeSandboxGraphQL<ProxyResponse>({\n document: ProxySandboxRequestDocument,\n variables: {\n input: {\n sandboxId,\n path,\n method,\n body,\n context: buildSandboxContextInput(workspaceId, authContext),\n },\n },\n workspaceId,\n authContext,\n });\n\n const proxyResult = result.proxySandboxRequest;\n if (!proxyResult || proxyResult.status >= 400) {\n const errBody = proxyResult?.body as Record<string, unknown> | undefined;\n throw new Error((errBody?.error as string) ?? `Proxy error: ${proxyResult?.status ?? 'unknown'}`);\n }\n\n return proxyResult.body;\n}\n\nexport async function waitForAssistantServiceReady(\n sandboxId: string,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext,\n maxWaitMs = 90_000\n): Promise<void> {\n const startedAt = Date.now();\n\n while (Date.now() - startedAt < maxWaitMs) {\n try {\n await proxyToSandbox(sandboxId, workspaceId, '/health', 'GET', undefined, authContext);\n return;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!/proxy error: 502|proxy error: 503|proxy error: 404|service not available/i.test(message)) {\n throw error;\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n\n throw new Error('Assistant service did not become healthy before timeout');\n}\n\n// ── Session management ─────────────────────────────────────────────\n\nexport async function createAssistantSession(\n sandboxId: string,\n workspaceId: string,\n mode: AssistantMode,\n authContext?: AssistantSandboxAuthContext\n): Promise<{ sessionId: string }> {\n const body = await proxyToSandbox(sandboxId, workspaceId, '/sessions', 'POST', { mode }, authContext);\n const session = body.session as Record<string, unknown>;\n return { sessionId: session.id as string };\n}\n\n// ── Send prompt ────────────────────────────────────────────────────\n\nexport async function sendAssistantPromptAsync(\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n prompt: string,\n mode: AssistantMode,\n pageContext?: PageContext,\n authContext?: AssistantSandboxAuthContext\n): Promise<void> {\n const requestBody = {\n mode,\n prompt,\n pageContext: pageContext ?? undefined,\n };\n\n await proxyToSandbox(sandboxId, workspaceId, `/sessions/${sessionId}/prompt-async`, 'POST', requestBody, authContext);\n}\n\nexport async function getAssistantMessages(\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: AssistantSandboxAuthContext,\n limit = 50\n): Promise<AssistantRawMessage[]> {\n const body = await proxyToSandbox(\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/messages?limit=${limit}`,\n 'GET',\n undefined,\n authContext\n );\n\n return (body.messages as AssistantRawMessage[] | undefined) ?? [];\n}\n\n// ── TTL extension (keep the sandbox warm across the turn) ──────────\n\nexport async function extendAssistantSandboxTTL(\n sandboxId: string,\n workspaceId: string,\n additionalSeconds = 600,\n authContext?: AssistantSandboxAuthContext\n): Promise<void> {\n await executeSandboxGraphQL<{ extendSandboxTTL: { id: string } }>({\n document: ExtendSandboxTtlDocument,\n variables: {\n id: sandboxId,\n additionalSeconds,\n context: buildSandboxContextInput(workspaceId, authContext),\n },\n workspaceId,\n authContext,\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { createAssistantSandbox as e, createAssistantSession as t, extendAssistantSandboxTTL as n, findExistingSandbox as r, getAssistantMessages as i, sendAssistantPromptAsync as a, waitForAssistantServiceReady as o, waitForSandboxReady as s } from "./assistantApi.js";
2
+ import { gatherPageContext as c } from "./pageContext.js";
3
+ import { useCallback as l, useMemo as u, useRef as d } from "react";
4
+ import { useAuthToken as f } from "@burdenoff/fe-libs/shared/providers/shell";
5
+ //#region src/bigconsole/assistant/createSandboxAssistantTransport.ts
6
+ var p = "assistant", m = 18e4, h = 1500, g = 3e4;
7
+ function _(e) {
8
+ try {
9
+ let t = e === "workspaceId" ? "burdenoff-active-context-workspace" : "burdenoff-active-context-organization", n = localStorage.getItem(t);
10
+ if (n) return n;
11
+ let r = sessionStorage.getItem("bf-active-profile");
12
+ if (!r) return "";
13
+ let i = localStorage.getItem(`bf-p-${r}-context`);
14
+ return i ? JSON.parse(i)[e] ?? "" : "";
15
+ } catch {
16
+ return "";
17
+ }
18
+ }
19
+ function v(e) {
20
+ return new URLSearchParams(window.location.search).get("workspace") ?? _("workspaceId") ?? e ?? "";
21
+ }
22
+ function y() {
23
+ return new URLSearchParams(window.location.search).get("org") ?? _("organizationId");
24
+ }
25
+ function b(e) {
26
+ return e.info?.time?.created ?? 0;
27
+ }
28
+ function x(e) {
29
+ return (e ?? []).filter((e) => e.type === "text" && typeof e.text == "string").map((e) => e.text?.trim() ?? "").filter(Boolean).join("\n");
30
+ }
31
+ function S(e) {
32
+ return (e ?? []).filter((e) => e.type === "tool" && e.tool).map((e) => {
33
+ let t = e.state?.status ?? "running", n = e.tool ?? "tool";
34
+ return t === "completed" ? `Completed: ${n}` : t === "failed" ? `Failed: ${n}` : `Running: ${n}`;
35
+ });
36
+ }
37
+ function C(e, t) {
38
+ let n = e.filter((e) => e.info?.role === "assistant" && b(e) >= t).sort((e, t) => b(e) - b(t));
39
+ if (n.length === 0) return {
40
+ content: "Thinking…",
41
+ done: !1
42
+ };
43
+ let r = n[n.length - 1], i = x(r.parts), a = S(r.parts);
44
+ return {
45
+ content: [i, ...a].filter(Boolean).join("\n\n") || "Thinking…",
46
+ done: !!r.info?.time?.completed && (!!i || a.length > 0)
47
+ };
48
+ }
49
+ function w(e) {
50
+ return e.replace(/(Authorization\s*:\s*Bearer\s+)[^\s\n]+/gi, "$1[REDACTED]").replace(/(X-Workspace-Authorization\s*:\s*Bearer\s+)[^\s\n]+/gi, "$1[REDACTED]").replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+\b/g, "[REDACTED_JWT]").replace(/\bsk-ant-[A-Za-z0-9-]+\b/g, "[REDACTED_API_KEY]");
51
+ }
52
+ function T(e) {
53
+ let t = e instanceof Error ? e.message.toLowerCase() : String(e).toLowerCase();
54
+ return t.includes("rate limit exceeded") || t.includes("unauthorized") || t.includes("k8s api error 401") ? !1 : [
55
+ "sandbox not found",
56
+ "sandbox is not running",
57
+ "sandbox service not available yet",
58
+ "sandbox failed",
59
+ "sandbox startup timed out",
60
+ "assistant service did not become healthy",
61
+ "proxy error: 404",
62
+ "proxy error: 502",
63
+ "proxy error: 503"
64
+ ].some((e) => t.includes(e));
65
+ }
66
+ function E() {
67
+ let { getAccessToken: _, getWorkspaceToken: b, userId: x, workspaceId: S } = f(), E = d(null), D = d(null), O = l(async (n, i) => {
68
+ let a = E.current;
69
+ if (!a) {
70
+ if (a = await r(n, p, i), !a) {
71
+ if (!_()) throw Error("The assistant requires an authenticated session. Please sign in again.");
72
+ a = await e(p, n, i);
73
+ }
74
+ await s(a, n, i), await o(a, n, i), E.current = a;
75
+ }
76
+ let c = D.current;
77
+ return c || (c = (await t(a, n, p, i)).sessionId, D.current = c), {
78
+ sandboxId: a,
79
+ sessionId: c
80
+ };
81
+ }, [_]), k = l(async ({ prompt: e, onProgress: t, signal: r }) => {
82
+ let o = v(S);
83
+ if (!o) throw Error("The assistant needs an active workspace. Open a workspace and try again.");
84
+ let s = {
85
+ accessToken: _(),
86
+ workspaceToken: b(),
87
+ userId: x,
88
+ organizationId: y()
89
+ }, l = async (u) => {
90
+ try {
91
+ let { sandboxId: l, sessionId: u } = await O(o, s), d = Date.now();
92
+ await a(l, o, u, e, p, c(), s);
93
+ let f = Date.now() + m, _ = Date.now(), v = C([], d);
94
+ for (; Date.now() < f;) {
95
+ if (r.aborted) throw Error("Cancelled");
96
+ if (v = C(await i(l, o, u, s, 50), d), t(w(v.content)), v.done) break;
97
+ Date.now() - _ > g && (await n(l, o, 600, s).catch(() => void 0), _ = Date.now()), await new Promise((e) => setTimeout(e, h));
98
+ }
99
+ if (!v.done) throw Error("The assistant timed out while responding. Please try again.");
100
+ return { text: w(v.content) };
101
+ } catch (e) {
102
+ if (u === 1 && T(e)) return E.current = null, D.current = null, l(2);
103
+ throw e;
104
+ }
105
+ };
106
+ return l(1);
107
+ }, [
108
+ S,
109
+ O,
110
+ _,
111
+ b,
112
+ x
113
+ ]);
114
+ return u(() => ({ sendPrompt: k }), [k]);
115
+ }
116
+ //#endregion
117
+ export { E as useSandboxAssistantTransport };
118
+
119
+ //# sourceMappingURL=createSandboxAssistantTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSandboxAssistantTransport.js","names":[],"sources":["../../../src/bigconsole/assistant/createSandboxAssistantTransport.ts"],"sourcesContent":["/**\n * BigConsole adapter for the shared fe-libs AssistantWidget.\n *\n * The floating widget (fe-libs, Layer 1) is backend-agnostic — it calls an\n * injected `AssistantTransport`. This hook builds a transport that drives the\n * sandbox AI assistant (combined `assistant` mode = docs Q&A + api-calls): it\n * provisions/reuses a sandbox, opens a session, dispatches the prompt async,\n * then polls for the streamed answer. The agent introspects the GraphQL schema\n * and performs API calls on the user's behalf using their workspace token,\n * contextual to the current screen (via `gatherPageContext`).\n *\n * This is a faithful port of microfe-vibecontrols'\n * `services/createSandboxAssistantTransport.ts`; the only product-specific\n * difference lives in `assistantApi.createAssistantSandbox`\n * (`AI_ASSISTANT_PRODUCT=bigconsole`).\n */\n\nimport { useCallback, useMemo, useRef } from 'react';\nimport { useAuthToken } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n createAssistantSandbox,\n createAssistantSession,\n extendAssistantSandboxTTL,\n findExistingSandbox,\n getAssistantMessages,\n sendAssistantPromptAsync,\n waitForAssistantServiceReady,\n waitForSandboxReady,\n} from './assistantApi';\nimport { gatherPageContext } from './pageContext';\nimport type { AssistantMode, AssistantRawMessage, AssistantSandboxAuthContext } from './types';\n\n/**\n * Locally-defined mirror of the fe-libs `AssistantTransport` contract.\n *\n * Intentionally NOT imported from `@burdenoff/fe-libs`: microfe's tsconfig maps\n * `@burdenoff/fe-libs/*` to fe-libs *source*, so vite-plugin-dts would rewrite a\n * cross-package type used in this hook's public signature to a broken\n * source-relative path in the emitted `.d.ts`. Structural typing makes this\n * shape assignable to fe-libs' `AssistantTransport` at the call site\n * (bigconsole-app's AppShell), which is where compatibility is enforced.\n */\ninterface AssistantSendArgs {\n prompt: string;\n onProgress: (partialText: string) => void;\n signal: AbortSignal;\n}\n\nexport interface AssistantTransport {\n sendPrompt: (args: AssistantSendArgs) => Promise<{ text: string }>;\n}\n\nconst MODE: AssistantMode = 'assistant';\nconst STREAM_BUDGET_MS = 180_000;\nconst POLL_INTERVAL_MS = 1500;\nconst TTL_EXTEND_INTERVAL_MS = 30_000;\n\n// ── Context helpers (mirror vibecontrols' resolution) ────────────────\n\nfunction getProfileContextValue(key: 'workspaceId' | 'organizationId'): string {\n try {\n const activeContextKey =\n key === 'workspaceId' ? 'burdenoff-active-context-workspace' : 'burdenoff-active-context-organization';\n const activeContextValue = localStorage.getItem(activeContextKey);\n if (activeContextValue) return activeContextValue;\n\n const activeProfileId = sessionStorage.getItem('bf-active-profile');\n if (!activeProfileId) return '';\n const raw = localStorage.getItem(`bf-p-${activeProfileId}-context`);\n if (!raw) return '';\n const context = JSON.parse(raw) as { workspaceId?: string; organizationId?: string };\n return context[key] ?? '';\n } catch {\n return '';\n }\n}\n\nfunction getWorkspaceId(fallback: string | null): string {\n const params = new URLSearchParams(window.location.search);\n return params.get('workspace') ?? getProfileContextValue('workspaceId') ?? fallback ?? '';\n}\n\nfunction getOrganizationId(): string {\n const params = new URLSearchParams(window.location.search);\n return params.get('org') ?? getProfileContextValue('organizationId');\n}\n\n// ── Message-progress helpers (pure; mirror vibecontrols) ─────────────\n\nfunction getRawMessageCreatedAt(message: AssistantRawMessage): number {\n return message.info?.time?.created ?? 0;\n}\n\nfunction getAssistantText(parts: AssistantRawMessage['parts']): string {\n return (parts ?? [])\n .filter((part) => part.type === 'text' && typeof part.text === 'string')\n .map((part) => part.text?.trim() ?? '')\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction getToolProgress(parts: AssistantRawMessage['parts']): string[] {\n return (parts ?? [])\n .filter((part) => part.type === 'tool' && part.tool)\n .map((part) => {\n const status = part.state?.status ?? 'running';\n const tool = part.tool ?? 'tool';\n if (status === 'completed') return `Completed: ${tool}`;\n if (status === 'failed') return `Failed: ${tool}`;\n return `Running: ${tool}`;\n });\n}\n\nfunction buildProgress(messages: AssistantRawMessage[], sinceMs: number): { content: string; done: boolean } {\n const relevant = messages\n .filter((message) => message.info?.role === 'assistant' && getRawMessageCreatedAt(message) >= sinceMs)\n .sort((left, right) => getRawMessageCreatedAt(left) - getRawMessageCreatedAt(right));\n\n if (relevant.length === 0) return { content: 'Thinking…', done: false };\n\n const latest = relevant[relevant.length - 1]!;\n const text = getAssistantText(latest.parts);\n const toolProgress = getToolProgress(latest.parts);\n const content = [text, ...toolProgress].filter(Boolean).join('\\n\\n') || 'Thinking…';\n\n return {\n content,\n done: Boolean(latest.info?.time?.completed) && (Boolean(text) || toolProgress.length > 0),\n };\n}\n\nfunction sanitize(response: string): string {\n return response\n .replace(/(Authorization\\s*:\\s*Bearer\\s+)[^\\s\\n]+/gi, '$1[REDACTED]')\n .replace(/(X-Workspace-Authorization\\s*:\\s*Bearer\\s+)[^\\s\\n]+/gi, '$1[REDACTED]')\n .replace(/\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9._-]+\\.[A-Za-z0-9._-]+\\b/g, '[REDACTED_JWT]')\n .replace(/\\bsk-ant-[A-Za-z0-9-]+\\b/g, '[REDACTED_API_KEY]');\n}\n\nfunction isRecoverable(error: unknown): boolean {\n const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();\n if (\n message.includes('rate limit exceeded') ||\n message.includes('unauthorized') ||\n message.includes('k8s api error 401')\n ) {\n return false;\n }\n return [\n 'sandbox not found',\n 'sandbox is not running',\n 'sandbox service not available yet',\n 'sandbox failed',\n 'sandbox startup timed out',\n 'assistant service did not become healthy',\n 'proxy error: 404',\n 'proxy error: 502',\n 'proxy error: 503',\n ].some((fragment) => message.includes(fragment));\n}\n\n/**\n * Returns a memoized `AssistantTransport` wired to the BigConsole sandbox\n * assistant agent. The sandbox + session are cached in refs so follow-up turns\n * reuse the warm environment for the lifetime of the host shell.\n */\nexport function useSandboxAssistantTransport(): AssistantTransport {\n const { getAccessToken, getWorkspaceToken, userId, workspaceId: ctxWorkspaceId } = useAuthToken();\n\n const sandboxIdRef = useRef<string | null>(null);\n const sessionIdRef = useRef<string | null>(null);\n\n const ensureRuntime = useCallback(\n async (\n workspaceId: string,\n authContext: AssistantSandboxAuthContext\n ): Promise<{ sandboxId: string; sessionId: string }> => {\n let sandboxId = sandboxIdRef.current;\n if (!sandboxId) {\n sandboxId = await findExistingSandbox(workspaceId, MODE, authContext);\n if (!sandboxId) {\n if (!getAccessToken()) {\n throw new Error('The assistant requires an authenticated session. Please sign in again.');\n }\n sandboxId = await createAssistantSandbox(MODE, workspaceId, authContext);\n }\n await waitForSandboxReady(sandboxId, workspaceId, authContext);\n await waitForAssistantServiceReady(sandboxId, workspaceId, authContext);\n sandboxIdRef.current = sandboxId;\n }\n\n let sessionId = sessionIdRef.current;\n if (!sessionId) {\n const result = await createAssistantSession(sandboxId, workspaceId, MODE, authContext);\n sessionId = result.sessionId;\n sessionIdRef.current = sessionId;\n }\n\n return { sandboxId, sessionId };\n },\n [getAccessToken]\n );\n\n const sendPrompt = useCallback(\n async ({ prompt, onProgress, signal }: AssistantSendArgs): Promise<{ text: string }> => {\n const workspaceId = getWorkspaceId(ctxWorkspaceId);\n if (!workspaceId) {\n throw new Error('The assistant needs an active workspace. Open a workspace and try again.');\n }\n const authContext: AssistantSandboxAuthContext = {\n accessToken: getAccessToken(),\n workspaceToken: getWorkspaceToken(),\n userId,\n organizationId: getOrganizationId(),\n };\n\n const run = async (attempt: 1 | 2): Promise<{ text: string }> => {\n try {\n const { sandboxId, sessionId } = await ensureRuntime(workspaceId, authContext);\n\n const startedAt = Date.now();\n await sendAssistantPromptAsync(\n sandboxId,\n workspaceId,\n sessionId,\n prompt,\n MODE,\n gatherPageContext(),\n authContext\n );\n\n const timeoutAt = Date.now() + STREAM_BUDGET_MS;\n let lastTtlExtensionAt = Date.now();\n let progress = buildProgress([], startedAt);\n\n while (Date.now() < timeoutAt) {\n if (signal.aborted) throw new Error('Cancelled');\n\n const messages = await getAssistantMessages(sandboxId, workspaceId, sessionId, authContext, 50);\n progress = buildProgress(messages, startedAt);\n onProgress(sanitize(progress.content));\n if (progress.done) break;\n\n if (Date.now() - lastTtlExtensionAt > TTL_EXTEND_INTERVAL_MS) {\n await extendAssistantSandboxTTL(sandboxId, workspaceId, 600, authContext).catch(() => undefined);\n lastTtlExtensionAt = Date.now();\n }\n\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n }\n\n if (!progress.done) {\n throw new Error('The assistant timed out while responding. Please try again.');\n }\n\n return { text: sanitize(progress.content) };\n } catch (error) {\n // A stale/expired sandbox or session is recoverable — drop the warm\n // refs and retry once from a clean runtime.\n if (attempt === 1 && isRecoverable(error)) {\n sandboxIdRef.current = null;\n sessionIdRef.current = null;\n return run(2);\n }\n throw error;\n }\n };\n\n return run(1);\n },\n [ctxWorkspaceId, ensureRuntime, getAccessToken, getWorkspaceToken, userId]\n );\n\n return useMemo<AssistantTransport>(() => ({ sendPrompt }), [sendPrompt]);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import "./pageContext.js";
2
+ import "./createSandboxAssistantTransport.js";
@@ -0,0 +1,51 @@
1
+ //#region src/bigconsole/assistant/pageContext.ts
2
+ function e() {
3
+ let e = window.location.href, t = window.location.pathname.split("/").filter(Boolean).slice(0, 3).join("/") || "home", r = n(window.location.pathname, window.location.search);
4
+ return {
5
+ currentUrl: e,
6
+ currentPage: t,
7
+ entityType: r.entityType,
8
+ entityId: r.entityId,
9
+ platform: "bigconsole",
10
+ version: "2026.430.500",
11
+ viewportSize: `${window.innerWidth}x${window.innerHeight}`,
12
+ userAgent: navigator.userAgent,
13
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
14
+ };
15
+ }
16
+ function t(e, t) {
17
+ return t.match(e);
18
+ }
19
+ function n(e, n) {
20
+ let i = new URLSearchParams(n);
21
+ for (let [n, i] of [
22
+ [/^\/bigconsole\/dashboards\/[^/]+\/parsers\/([^/]+)(?:\/edit)?$/, "BIGCONSOLE_PARSER"],
23
+ [/^\/bigconsole\/dashboards\/([^/]+)(?:\/builder)?$/, "BIGCONSOLE_DASHBOARD"],
24
+ [/^\/bigconsole\/datasinks\/([^/]+)(?:\/edit)?$/, "BIGCONSOLE_DATASINK"],
25
+ [/^\/bigconsole\/parsers\/([^/]+)(?:\/edit)?$/, "BIGCONSOLE_PARSER"],
26
+ [/^\/bigconsole\/pipelines\/([^/]+)(?:\/edit)?$/, "BIGCONSOLE_PIPELINE"],
27
+ [/^\/bigconsole\/workflows\/([^/]+)(?:\/edit)?$/, "BIGCONSOLE_WORKFLOW"]
28
+ ]) {
29
+ let a = t(n, e);
30
+ if (a && a[1] && !r(a[1])) return {
31
+ entityType: i,
32
+ entityId: a[1],
33
+ metadata: { routePattern: n.source }
34
+ };
35
+ }
36
+ let a = i.get("tab") ?? (() => {
37
+ let t = e.split("/").filter(Boolean);
38
+ return t.length > 2 ? t[t.length - 1] : void 0;
39
+ })();
40
+ return {
41
+ activeTab: a ?? void 0,
42
+ metadata: { ...a ? { activeTab: a } : {} }
43
+ };
44
+ }
45
+ function r(e) {
46
+ return e === "new" || e === "builder" || e === "list";
47
+ }
48
+ //#endregion
49
+ export { e as gatherPageContext, n as resolveBigConsoleConversationContext };
50
+
51
+ //# sourceMappingURL=pageContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageContext.js","names":[],"sources":["../../../src/bigconsole/assistant/pageContext.ts"],"sourcesContent":["/**\n * Page context gathering for BigConsole — captures the user's current browser\n * context to be sent alongside every assistant prompt for better AI awareness.\n *\n * Mirrors microfe-vibecontrols' `utils/pageContext.ts`. The agent filters the\n * payload to an allow-list (`ai-assistant/src/context-loader.ts` →\n * `ALLOWED_CONTEXT_KEYS`), so the keys MUST be `currentUrl` (NOT `activeUrl`)\n * and the generic `entityType` / `entityId`, or the value is silently dropped.\n */\n\ninterface ConversationContextShape {\n entityType?: string;\n entityId?: string;\n activeTab?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface PageContext {\n // `currentUrl` (NOT `activeUrl`) — must match the agent's allowed-context-key\n // contract, otherwise the agent filters it out.\n currentUrl: string;\n currentPage: string;\n // The entity the user is currently looking at, resolved from the route. Lets\n // the assistant act on \"this / current / here\" without asking for an id.\n entityType?: string;\n entityId?: string;\n platform: string;\n version: string;\n viewportSize: string;\n userAgent: string;\n timestamp: string;\n}\n\nexport function gatherPageContext(): PageContext {\n const url = window.location.href;\n const pathSegments = window.location.pathname.split('/').filter(Boolean);\n const currentPage = pathSegments.slice(0, 3).join('/') || 'home';\n const entity = resolveBigConsoleConversationContext(window.location.pathname, window.location.search);\n\n return {\n currentUrl: url,\n currentPage,\n entityType: entity.entityType,\n entityId: entity.entityId,\n platform: 'bigconsole',\n version: import.meta.env.VITE_APP_VERSION ?? '2026.430.500',\n viewportSize: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n timestamp: new Date().toISOString(),\n };\n}\n\nfunction matchPath(pattern: RegExp, pathname: string): RegExpMatchArray | null {\n return pathname.match(pattern);\n}\n\n/**\n * Maps the current BigConsole route to `{ entityType, entityId }`. The BigConsole\n * MFE mounts under the `/bigconsole` base path in the host shell, so detail\n * routes are matched as `/bigconsole/<collection>/:id`.\n *\n * More specific routes (e.g. dashboard-scoped parsers, builder/edit sub-routes)\n * are matched before their parent so the most relevant entity wins.\n */\nexport function resolveBigConsoleConversationContext(pathname: string, search: string): ConversationContextShape {\n const params = new URLSearchParams(search);\n\n const directMatches: Array<[RegExp, string]> = [\n // Dashboard-scoped parser detail (more specific than the bare parser route).\n [/^\\/bigconsole\\/dashboards\\/[^/]+\\/parsers\\/([^/]+)(?:\\/edit)?$/, 'BIGCONSOLE_PARSER'],\n // Dashboard detail + builder.\n [/^\\/bigconsole\\/dashboards\\/([^/]+)(?:\\/builder)?$/, 'BIGCONSOLE_DASHBOARD'],\n // Data sinks.\n [/^\\/bigconsole\\/datasinks\\/([^/]+)(?:\\/edit)?$/, 'BIGCONSOLE_DATASINK'],\n // Parsers.\n [/^\\/bigconsole\\/parsers\\/([^/]+)(?:\\/edit)?$/, 'BIGCONSOLE_PARSER'],\n // Pipelines.\n [/^\\/bigconsole\\/pipelines\\/([^/]+)(?:\\/edit)?$/, 'BIGCONSOLE_PIPELINE'],\n // Workflows (BigConsole-native list/view; the SDK builder uses /workflow/...).\n [/^\\/bigconsole\\/workflows\\/([^/]+)(?:\\/edit)?$/, 'BIGCONSOLE_WORKFLOW'],\n ];\n\n for (const [pattern, entityType] of directMatches) {\n const match = matchPath(pattern, pathname);\n if (match && match[1] && !isReservedSegment(match[1])) {\n return {\n entityType,\n entityId: match[1],\n metadata: {\n routePattern: pattern.source,\n },\n };\n }\n }\n\n const activeTab =\n params.get('tab') ??\n (() => {\n const segments = pathname.split('/').filter(Boolean);\n return segments.length > 2 ? segments[segments.length - 1] : undefined;\n })();\n\n return {\n activeTab: activeTab ?? undefined,\n metadata: {\n ...(activeTab ? { activeTab } : {}),\n },\n };\n}\n\n/**\n * Static segments that share a route shape with `:id` detail routes\n * (e.g. `/bigconsole/datasinks/new`, `/bigconsole/parsers/new`). These are\n * pages, not entities, so they must not be reported as an `entityId`.\n */\nfunction isReservedSegment(segment: string): boolean {\n return segment === 'new' || segment === 'builder' || segment === 'list';\n}\n"],"mappings":";AAiCA,SAAgB,IAAiC;CAC/C,IAAM,IAAM,OAAO,SAAS,MAEtB,IADe,OAAO,SAAS,SAAS,MAAM,IAAI,CAAC,OAAO,QAAQ,CACvC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,IAAI,QACpD,IAAS,EAAqC,OAAO,SAAS,UAAU,OAAO,SAAS,OAAO;AAErG,QAAO;EACL,YAAY;EACZ;EACA,YAAY,EAAO;EACnB,UAAU,EAAO;EACjB,UAAU;EACV,SAA6C;EAC7C,cAAc,GAAG,OAAO,WAAW,GAAG,OAAO;EAC7C,WAAW,UAAU;EACrB,4BAAW,IAAI,MAAM,EAAC,aAAa;EACpC;;AAGH,SAAS,EAAU,GAAiB,GAA2C;AAC7E,QAAO,EAAS,MAAM,EAAQ;;AAWhC,SAAgB,EAAqC,GAAkB,GAA0C;CAC/G,IAAM,IAAS,IAAI,gBAAgB,EAAO;AAiB1C,MAAK,IAAM,CAAC,GAAS,MAf0B;EAE7C,CAAC,kEAAkE,oBAAoB;EAEvF,CAAC,qDAAqD,uBAAuB;EAE7E,CAAC,iDAAiD,sBAAsB;EAExE,CAAC,+CAA+C,oBAAoB;EAEpE,CAAC,iDAAiD,sBAAsB;EAExE,CAAC,iDAAiD,sBAAsB;EACzE,EAEkD;EACjD,IAAM,IAAQ,EAAU,GAAS,EAAS;AAC1C,MAAI,KAAS,EAAM,MAAM,CAAC,EAAkB,EAAM,GAAG,CACnD,QAAO;GACL;GACA,UAAU,EAAM;GAChB,UAAU,EACR,cAAc,EAAQ,QACvB;GACF;;CAIL,IAAM,IACJ,EAAO,IAAI,MAAM,WACV;EACL,IAAM,IAAW,EAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;AACpD,SAAO,EAAS,SAAS,IAAI,EAAS,EAAS,SAAS,KAAK,KAAA;KAC3D;AAEN,QAAO;EACL,WAAW,KAAa,KAAA;EACxB,UAAU,EACR,GAAI,IAAY,EAAE,cAAW,GAAG,EAAE,EACnC;EACF;;AAQH,SAAS,EAAkB,GAA0B;AACnD,QAAO,MAAY,SAAS,MAAY,aAAa,MAAY"}
@@ -29,14 +29,14 @@ var o = t(function({ renderDashboard: t, onClose: o }) {
29
29
  onClick: (e) => e.stopPropagation(),
30
30
  children: [
31
31
  /* @__PURE__ */ a("div", {
32
- className: "flex-shrink-0 flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-muted/50 rounded-t-xl",
32
+ className: "flex-shrink-0 flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-sunken/50 rounded-t-xl",
33
33
  children: [/* @__PURE__ */ a("div", {
34
34
  className: "flex items-center gap-3",
35
35
  children: [
36
36
  d.length > 0 && /* @__PURE__ */ i("button", {
37
37
  type: "button",
38
38
  onClick: h,
39
- className: "p-1.5 rounded-md hover:bg-bg-muted transition-colors",
39
+ className: "p-1.5 rounded-md hover:bg-bg-sunken transition-colors",
40
40
  title: "Go back",
41
41
  children: /* @__PURE__ */ i("svg", {
42
42
  className: "w-5 h-5 text-text-secondary",
@@ -70,7 +70,7 @@ var o = t(function({ renderDashboard: t, onClose: o }) {
70
70
  }), /* @__PURE__ */ i("button", {
71
71
  type: "button",
72
72
  onClick: m,
73
- className: "p-2 rounded-md hover:bg-bg-muted transition-colors",
73
+ className: "p-2 rounded-md hover:bg-bg-sunken transition-colors",
74
74
  title: "Close (Esc)",
75
75
  children: /* @__PURE__ */ i("svg", {
76
76
  className: "w-5 h-5 text-text-secondary",
@@ -91,7 +91,7 @@ var o = t(function({ renderDashboard: t, onClose: o }) {
91
91
  children: t ? t(l, u) : /* @__PURE__ */ i(s, {})
92
92
  }),
93
93
  /* @__PURE__ */ i("div", {
94
- className: "flex-shrink-0 px-4 py-2 border-t border-border-default bg-bg-muted/30 rounded-b-xl",
94
+ className: "flex-shrink-0 px-4 py-2 border-t border-border-default bg-bg-sunken/30 rounded-b-xl",
95
95
  children: /* @__PURE__ */ a("div", {
96
96
  className: "flex items-center justify-between text-xs text-text-tertiary",
97
97
  children: [/* @__PURE__ */ a("span", { children: [
@@ -1 +1 @@
1
- {"version":3,"file":"DrilldownModal.js","names":[],"sources":["../../../src/bigconsole/components/DrilldownModal.tsx"],"sourcesContent":["/**\n * DrilldownModal Component\n *\n * Modal overlay for displaying drilldown dashboards.\n * Supports nested drilldowns with back navigation.\n */\n\nimport { type FC, useEffect, useCallback, memo } from 'react';\nimport { useDrilldownStore } from '../store/drilldownStore';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DrilldownModalProps {\n /** Custom content renderer for the dashboard */\n renderDashboard?: (dashboardId: string, params: Record<string, unknown>) => React.ReactNode;\n /** Called when modal closes */\n onClose?: () => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DrilldownModal: FC<DrilldownModalProps> = memo(function DrilldownModal({ renderDashboard, onClose }) {\n const isOpen = useDrilldownStore((state) => state.isOpen);\n const dashboardId = useDrilldownStore((state) => state.dashboardId);\n const params = useDrilldownStore((state) => state.params);\n const history = useDrilldownStore((state) => state.history);\n const closeModal = useDrilldownStore((state) => state.closeModal);\n const popDrilldown = useDrilldownStore((state) => state.popDrilldown);\n\n // Define handlers before effects that use them\n const handleClose = useCallback(() => {\n closeModal();\n onClose?.();\n }, [closeModal, onClose]);\n\n const handleBack = useCallback(() => {\n popDrilldown();\n }, [popDrilldown]);\n\n const handleBackdropClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n handleClose();\n }\n },\n [handleClose]\n );\n\n // Handle escape key\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && isOpen) {\n handleClose();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, handleClose]);\n\n // Prevent body scroll when modal is open\n useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n return () => {\n document.body.style.overflow = '';\n };\n }, [isOpen]);\n\n if (!isOpen || !dashboardId) {\n return null;\n }\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center p-4\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"drilldown-modal-title\"\n onClick={handleBackdropClick}\n >\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-black/60 backdrop-blur-sm\" />\n\n {/* Modal Content - contained within viewport */}\n <div\n className=\"relative z-10 w-full max-w-5xl bg-bg-surface rounded-xl shadow-2xl flex flex-col\"\n style={{ maxHeight: 'calc(100vh - 2rem)' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex-shrink-0 flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-muted/50 rounded-t-xl\">\n <div className=\"flex items-center gap-3\">\n {/* Back button */}\n {history.length > 0 && (\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-1.5 rounded-md hover:bg-bg-muted transition-colors\"\n title=\"Go back\"\n >\n <svg className=\"w-5 h-5 text-text-secondary\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n\n {/* Title */}\n <h2 id=\"drilldown-modal-title\" className=\"text-sm font-medium text-text-primary\">\n Drilldown View\n </h2>\n\n {/* Breadcrumb indicator */}\n {history.length > 0 && (\n <span className=\"text-xs text-text-tertiary\">\n ({history.length + 1} level{history.length > 0 ? 's' : ''} deep)\n </span>\n )}\n </div>\n\n {/* Close button */}\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"p-2 rounded-md hover:bg-bg-muted transition-colors\"\n title=\"Close (Esc)\"\n >\n <svg className=\"w-5 h-5 text-text-secondary\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Dashboard Content - scrollable */}\n <div className=\"flex-1 overflow-y-auto min-h-0 p-4\">\n {renderDashboard ? renderDashboard(dashboardId, params) : <DrilldownFallback />}\n </div>\n\n {/* Footer */}\n <div className=\"flex-shrink-0 px-4 py-2 border-t border-border-default bg-bg-muted/30 rounded-b-xl\">\n <div className=\"flex items-center justify-between text-xs text-text-tertiary\">\n <span>\n Parameters:{' '}\n {Object.keys(params).filter((k) => !k.startsWith('__')).length > 0\n ? Object.keys(params)\n .filter((k) => !k.startsWith('__'))\n .join(', ')\n : 'None'}\n </span>\n <span>Press Esc to close</span>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\n// Fallback when no renderDashboard prop is provided (should not happen in normal usage\n// since BigConsoleRoot always passes DrilldownDashboardRenderer).\nfunction DrilldownFallback() {\n return (\n <div className=\"flex items-center justify-center h-full text-sm text-text-secondary\">\n Unable to load drilldown content. Please try again.\n </div>\n );\n}\n\nexport default DrilldownModal;\n"],"mappings":"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"}
1
+ {"version":3,"file":"DrilldownModal.js","names":[],"sources":["../../../src/bigconsole/components/DrilldownModal.tsx"],"sourcesContent":["/**\n * DrilldownModal Component\n *\n * Modal overlay for displaying drilldown dashboards.\n * Supports nested drilldowns with back navigation.\n */\n\nimport { type FC, useEffect, useCallback, memo } from 'react';\nimport { useDrilldownStore } from '../store/drilldownStore';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DrilldownModalProps {\n /** Custom content renderer for the dashboard */\n renderDashboard?: (dashboardId: string, params: Record<string, unknown>) => React.ReactNode;\n /** Called when modal closes */\n onClose?: () => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DrilldownModal: FC<DrilldownModalProps> = memo(function DrilldownModal({ renderDashboard, onClose }) {\n const isOpen = useDrilldownStore((state) => state.isOpen);\n const dashboardId = useDrilldownStore((state) => state.dashboardId);\n const params = useDrilldownStore((state) => state.params);\n const history = useDrilldownStore((state) => state.history);\n const closeModal = useDrilldownStore((state) => state.closeModal);\n const popDrilldown = useDrilldownStore((state) => state.popDrilldown);\n\n // Define handlers before effects that use them\n const handleClose = useCallback(() => {\n closeModal();\n onClose?.();\n }, [closeModal, onClose]);\n\n const handleBack = useCallback(() => {\n popDrilldown();\n }, [popDrilldown]);\n\n const handleBackdropClick = useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n handleClose();\n }\n },\n [handleClose]\n );\n\n // Handle escape key\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && isOpen) {\n handleClose();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, handleClose]);\n\n // Prevent body scroll when modal is open\n useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n return () => {\n document.body.style.overflow = '';\n };\n }, [isOpen]);\n\n if (!isOpen || !dashboardId) {\n return null;\n }\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center p-4\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"drilldown-modal-title\"\n onClick={handleBackdropClick}\n >\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-black/60 backdrop-blur-sm\" />\n\n {/* Modal Content - contained within viewport */}\n <div\n className=\"relative z-10 w-full max-w-5xl bg-bg-surface rounded-xl shadow-2xl flex flex-col\"\n style={{ maxHeight: 'calc(100vh - 2rem)' }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div className=\"flex-shrink-0 flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-sunken/50 rounded-t-xl\">\n <div className=\"flex items-center gap-3\">\n {/* Back button */}\n {history.length > 0 && (\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-1.5 rounded-md hover:bg-bg-sunken transition-colors\"\n title=\"Go back\"\n >\n <svg className=\"w-5 h-5 text-text-secondary\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n\n {/* Title */}\n <h2 id=\"drilldown-modal-title\" className=\"text-sm font-medium text-text-primary\">\n Drilldown View\n </h2>\n\n {/* Breadcrumb indicator */}\n {history.length > 0 && (\n <span className=\"text-xs text-text-tertiary\">\n ({history.length + 1} level{history.length > 0 ? 's' : ''} deep)\n </span>\n )}\n </div>\n\n {/* Close button */}\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"p-2 rounded-md hover:bg-bg-sunken transition-colors\"\n title=\"Close (Esc)\"\n >\n <svg className=\"w-5 h-5 text-text-secondary\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Dashboard Content - scrollable */}\n <div className=\"flex-1 overflow-y-auto min-h-0 p-4\">\n {renderDashboard ? renderDashboard(dashboardId, params) : <DrilldownFallback />}\n </div>\n\n {/* Footer */}\n <div className=\"flex-shrink-0 px-4 py-2 border-t border-border-default bg-bg-sunken/30 rounded-b-xl\">\n <div className=\"flex items-center justify-between text-xs text-text-tertiary\">\n <span>\n Parameters:{' '}\n {Object.keys(params).filter((k) => !k.startsWith('__')).length > 0\n ? Object.keys(params)\n .filter((k) => !k.startsWith('__'))\n .join(', ')\n : 'None'}\n </span>\n <span>Press Esc to close</span>\n </div>\n </div>\n </div>\n </div>\n );\n});\n\n// Fallback when no renderDashboard prop is provided (should not happen in normal usage\n// since BigConsoleRoot always passes DrilldownDashboardRenderer).\nfunction DrilldownFallback() {\n return (\n <div className=\"flex items-center justify-center h-full text-sm text-text-secondary\">\n Unable to load drilldown content. Please try again.\n </div>\n );\n}\n\nexport default DrilldownModal;\n"],"mappings":"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"}