@burdenoff/microfe-vibecontrols 2026.623.1 → 2026.623.2

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 (293) hide show
  1. package/dist/components/actions/ActionCard.js +2 -2
  2. package/dist/components/actions/ActionCard.js.map +1 -1
  3. package/dist/components/actions/ExecutionHistory.js +1 -1
  4. package/dist/components/actions/ExecutionHistory.js.map +1 -1
  5. package/dist/components/agent-manager/AgentManagerAdminBar.js +1 -1
  6. package/dist/components/agent-manager/AgentManagerAdminBar.js.map +1 -1
  7. package/dist/components/agent-manager/AgentManagerChatPane.js +2 -2
  8. package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
  9. package/dist/components/agent-manager/AgentManagerInputArea.js +4 -4
  10. package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
  11. package/dist/components/agent-manager/AgentManagerLayout.js +1 -1
  12. package/dist/components/agent-manager/AgentManagerLayout.js.map +1 -1
  13. package/dist/components/agent-manager/AgentManagerMessageItem.js +1 -1
  14. package/dist/components/agent-manager/AgentManagerMessageItem.js.map +1 -1
  15. package/dist/components/agent-manager/AgentManagerSidebar.js +5 -5
  16. package/dist/components/agent-manager/AgentManagerSidebar.js.map +1 -1
  17. package/dist/components/agent-manager/AgentManagerTab.js +1 -1
  18. package/dist/components/agent-manager/AgentManagerTab.js.map +1 -1
  19. package/dist/components/agent-manager/AgentManagerTabBar.js +1 -1
  20. package/dist/components/agent-manager/AgentManagerTabBar.js.map +1 -1
  21. package/dist/components/agent-manager/BridleConfigPanel.js +23 -23
  22. package/dist/components/agent-manager/BridleConfigPanel.js.map +1 -1
  23. package/dist/components/agent-manager/PluginInstallModal.js +1 -1
  24. package/dist/components/agent-manager/PluginInstallModal.js.map +1 -1
  25. package/dist/components/agent-manager/ProfilesPanel.js +5 -5
  26. package/dist/components/agent-manager/ProfilesPanel.js.map +1 -1
  27. package/dist/components/agent-manager/controls/AutonomySelector.js +1 -1
  28. package/dist/components/agent-manager/controls/AutonomySelector.js.map +1 -1
  29. package/dist/components/agent-manager/controls/SdkSelector.js +1 -1
  30. package/dist/components/agent-manager/controls/SdkSelector.js.map +1 -1
  31. package/dist/components/agent-manager/controls/VoiceToggle.js +1 -1
  32. package/dist/components/agent-manager/controls/VoiceToggle.js.map +1 -1
  33. package/dist/components/agent-manager/detail/SessionConfigPanel.js +6 -6
  34. package/dist/components/agent-manager/detail/SessionConfigPanel.js.map +1 -1
  35. package/dist/components/agent-manager/detail/SessionLogsPanel.js +5 -5
  36. package/dist/components/agent-manager/detail/SessionLogsPanel.js.map +1 -1
  37. package/dist/components/agent-manager/detail/SessionToolsPanel.js +1 -1
  38. package/dist/components/agent-manager/detail/SessionToolsPanel.js.map +1 -1
  39. package/dist/components/agent-manager/dialogs/NewSessionDialog.js +2 -2
  40. package/dist/components/agent-manager/dialogs/NewSessionDialog.js.map +1 -1
  41. package/dist/components/agent-manager/dialogs/RenameSessionDialog.js +1 -1
  42. package/dist/components/agent-manager/dialogs/RenameSessionDialog.js.map +1 -1
  43. package/dist/components/agents/AgentCard.js +14 -11
  44. package/dist/components/agents/AgentCard.js.map +1 -1
  45. package/dist/components/ai/AIContextsTab.js +1 -1
  46. package/dist/components/ai/AIContextsTab.js.map +1 -1
  47. package/dist/components/ai/AIOverviewTab.js +4 -4
  48. package/dist/components/ai/AIOverviewTab.js.map +1 -1
  49. package/dist/components/ai/AIPlanPanel.js +4 -4
  50. package/dist/components/ai/AIPlanPanel.js.map +1 -1
  51. package/dist/components/ai/AIPlaygroundTab.js +1 -1
  52. package/dist/components/ai/AIPlaygroundTab.js.map +1 -1
  53. package/dist/components/ai/AIPromptsTab.js +2 -2
  54. package/dist/components/ai/AIPromptsTab.js.map +1 -1
  55. package/dist/components/ai/AIProviderCredentialsCard.js +4 -4
  56. package/dist/components/ai/AIProviderCredentialsCard.js.map +1 -1
  57. package/dist/components/ai/AIQueueTab.js +4 -4
  58. package/dist/components/ai/AIQueueTab.js.map +1 -1
  59. package/dist/components/ai/AISessionsTab.js +4 -4
  60. package/dist/components/ai/AISessionsTab.js.map +1 -1
  61. package/dist/components/ai/AITasksTab.js +1 -1
  62. package/dist/components/ai/AITasksTab.js.map +1 -1
  63. package/dist/components/ai/ClaudeCredentialsCard.js +3 -3
  64. package/dist/components/ai/ClaudeCredentialsCard.js.map +1 -1
  65. package/dist/components/ai/PluginHarnessPicker.js +3 -3
  66. package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
  67. package/dist/components/analytics/AnalyticsBreakdownChart.js +8 -8
  68. package/dist/components/analytics/AnalyticsBreakdownChart.js.map +1 -1
  69. package/dist/components/analytics/AnalyticsTimeSeriesChart.js +5 -5
  70. package/dist/components/analytics/AnalyticsTimeSeriesChart.js.map +1 -1
  71. package/dist/components/audit/AuditDeleteDialog.js +2 -2
  72. package/dist/components/audit/AuditDeleteDialog.js.map +1 -1
  73. package/dist/components/audit/AuditExportButton.js +5 -5
  74. package/dist/components/audit/AuditExportButton.js.map +1 -1
  75. package/dist/components/audit/AuditLogDetail.js +9 -9
  76. package/dist/components/audit/AuditLogDetail.js.map +1 -1
  77. package/dist/components/audit/AuditLogFilters.js +1 -1
  78. package/dist/components/audit/AuditLogFilters.js.map +1 -1
  79. package/dist/components/audit/AuditLogStats.js +1 -1
  80. package/dist/components/audit/AuditLogStats.js.map +1 -1
  81. package/dist/components/audit/AuditLogTable.js +28 -28
  82. package/dist/components/audit/AuditLogTable.js.map +1 -1
  83. package/dist/components/catalog/CatalogCard.js +3 -3
  84. package/dist/components/catalog/CatalogCard.js.map +1 -1
  85. package/dist/components/catalog/CatalogForm.js +1 -1
  86. package/dist/components/catalog/CatalogForm.js.map +1 -1
  87. package/dist/components/common/ActionAgentTargetNotice.js +6 -6
  88. package/dist/components/common/ActionAgentTargetNotice.js.map +1 -1
  89. package/dist/components/common/CommandEditor.js +1 -1
  90. package/dist/components/common/CommandEditor.js.map +1 -1
  91. package/dist/components/docs/DocsPageTree.js +1 -1
  92. package/dist/components/docs/DocsPageTree.js.map +1 -1
  93. package/dist/components/docs/DocsPreviewPanel.js +1 -1
  94. package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
  95. package/dist/components/docs/DocsRevisionHistory.js +4 -4
  96. package/dist/components/docs/DocsRevisionHistory.js.map +1 -1
  97. package/dist/components/docs/DocsSettingsPanel.js +7 -7
  98. package/dist/components/docs/DocsSettingsPanel.js.map +1 -1
  99. package/dist/components/docs/DocsTabPanel.js +1 -1
  100. package/dist/components/docs/DocsTabPanel.js.map +1 -1
  101. package/dist/components/graph/ConnectionPermissionsDialog.js +2 -2
  102. package/dist/components/graph/ConnectionPermissionsDialog.js.map +1 -1
  103. package/dist/components/graph/MeshDeployWizard.js +3 -3
  104. package/dist/components/graph/MeshDeployWizard.js.map +1 -1
  105. package/dist/components/graph/MeshRequestPanel.js +2 -2
  106. package/dist/components/graph/MeshRequestPanel.js.map +1 -1
  107. package/dist/components/idp-components/ComponentCard.js +5 -5
  108. package/dist/components/idp-components/ComponentCard.js.map +1 -1
  109. package/dist/components/idp-components/ComponentForm.js +1 -1
  110. package/dist/components/idp-components/ComponentForm.js.map +1 -1
  111. package/dist/components/idp-components/DependencyGraphTab.js +7 -7
  112. package/dist/components/idp-components/DependencyGraphTab.js.map +1 -1
  113. package/dist/components/logs/LogViewer.js +14 -14
  114. package/dist/components/logs/LogViewer.js.map +1 -1
  115. package/dist/components/notes/NoteCard.js +1 -1
  116. package/dist/components/notes/NoteCard.js.map +1 -1
  117. package/dist/components/notes/NoteEditor.js +2 -2
  118. package/dist/components/notes/NoteEditor.js.map +1 -1
  119. package/dist/components/notes/NoteList.js +1 -1
  120. package/dist/components/notes/NoteList.js.map +1 -1
  121. package/dist/components/notes/NotesTabPanel.js +1 -1
  122. package/dist/components/notes/NotesTabPanel.js.map +1 -1
  123. package/dist/components/scorecard/ScorecardEmptyState.js +1 -1
  124. package/dist/components/scorecard/ScorecardEmptyState.js.map +1 -1
  125. package/dist/components/scorecard/ScorecardPanel.js +3 -3
  126. package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
  127. package/dist/components/security/SecurityScanList.js +11 -11
  128. package/dist/components/security/SecurityScanList.js.map +1 -1
  129. package/dist/components/sessions/SessionCard.js +26 -19
  130. package/dist/components/sessions/SessionCard.js.map +1 -1
  131. package/dist/components/sessions/SessionStatusBadge.js +7 -7
  132. package/dist/components/sessions/SessionStatusBadge.js.map +1 -1
  133. package/dist/components/shared/AgentSelector.js +4 -4
  134. package/dist/components/shared/AgentSelector.js.map +1 -1
  135. package/dist/components/shared/AgentSetupBanner.js +3 -3
  136. package/dist/components/shared/AgentSetupBanner.js.map +1 -1
  137. package/dist/components/shared/Card.js +4 -4
  138. package/dist/components/shared/Card.js.map +1 -1
  139. package/dist/components/shared/ErrorState.js +15 -9
  140. package/dist/components/shared/ErrorState.js.map +1 -1
  141. package/dist/components/shared/FilterDropdown.js +2 -2
  142. package/dist/components/shared/FilterDropdown.js.map +1 -1
  143. package/dist/components/shared/PageSkeleton.js +6 -6
  144. package/dist/components/shared/PageSkeleton.js.map +1 -1
  145. package/dist/components/shared/SearchInput.js +1 -1
  146. package/dist/components/shared/SearchInput.js.map +1 -1
  147. package/dist/components/shared/StatCard.js +7 -7
  148. package/dist/components/shared/StatCard.js.map +1 -1
  149. package/dist/components/templates/PublishTemplateForm.js +2 -2
  150. package/dist/components/templates/PublishTemplateForm.js.map +1 -1
  151. package/dist/components/templates/TemplateCard.js +5 -5
  152. package/dist/components/templates/TemplateCard.js.map +1 -1
  153. package/dist/components/templates/TemplateWizard.js +2 -2
  154. package/dist/components/templates/TemplateWizard.js.map +1 -1
  155. package/dist/components/tunnels/DomainVerificationBadge.js +4 -4
  156. package/dist/components/tunnels/DomainVerificationBadge.js.map +1 -1
  157. package/dist/components/tunnels/ProviderBadge.js +1 -1
  158. package/dist/components/tunnels/ProviderBadge.js.map +1 -1
  159. package/dist/components/tunnels/TunnelCard.js +16 -16
  160. package/dist/components/tunnels/TunnelCard.js.map +1 -1
  161. package/dist/components/tunnels/TunnelCreateWizard.js +1 -1
  162. package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
  163. package/dist/components/tunnels/TunnelPublicAccessPanel.js +1 -1
  164. package/dist/components/tunnels/TunnelPublicAccessPanel.js.map +1 -1
  165. package/dist/components/tunnels/TunnelStatusBadge.js +4 -4
  166. package/dist/components/tunnels/TunnelStatusBadge.js.map +1 -1
  167. package/dist/components/vibecalendar/LogsDrawer.js +2 -2
  168. package/dist/components/vibecalendar/LogsDrawer.js.map +1 -1
  169. package/dist/components/vibecalendar/ScheduleTaskModal.js +5 -5
  170. package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
  171. package/dist/components/vibecalendar/VibeCalAgendaView.js +2 -2
  172. package/dist/components/vibecalendar/VibeCalAgendaView.js.map +1 -1
  173. package/dist/components/vibecalendar/VibeCalDayView.js +3 -3
  174. package/dist/components/vibecalendar/VibeCalDayView.js.map +1 -1
  175. package/dist/components/vibecalendar/VibeCalMonthView.js +1 -1
  176. package/dist/components/vibecalendar/VibeCalMonthView.js.map +1 -1
  177. package/dist/components/vibecalendar/VibeCalWeekView.js +4 -4
  178. package/dist/components/vibecalendar/VibeCalWeekView.js.map +1 -1
  179. package/dist/components/vibecalendar/VibeCalendarHeader.js +4 -4
  180. package/dist/components/vibecalendar/VibeCalendarHeader.js.map +1 -1
  181. package/dist/components/vibecalendar/VibeTaskBlock.js +2 -2
  182. package/dist/components/vibecalendar/VibeTaskBlock.js.map +1 -1
  183. package/dist/components/vibecalendar/types.js +6 -6
  184. package/dist/components/vibecalendar/types.js.map +1 -1
  185. package/dist/components/vibedeck/VibeDeckButtonForm.js +9 -9
  186. package/dist/components/vibedeck/VibeDeckButtonForm.js.map +1 -1
  187. package/dist/components/vibedeck/VibeDeckButtonTile.js +6 -6
  188. package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
  189. package/dist/components/vibedeck/VibeDeckExecutionLog.js +10 -10
  190. package/dist/components/vibedeck/VibeDeckExecutionLog.js.map +1 -1
  191. package/dist/components/vibedeck/VibeDeckForm.js +8 -8
  192. package/dist/components/vibedeck/VibeDeckForm.js.map +1 -1
  193. package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
  194. package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
  195. package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js +2 -2
  196. package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js.map +1 -1
  197. package/dist/components/vibedeck/VibeDeckSwitcher.js +8 -8
  198. package/dist/components/vibedeck/VibeDeckSwitcher.js.map +1 -1
  199. package/dist/components/vibes/VibeCard.js +22 -18
  200. package/dist/components/vibes/VibeCard.js.map +1 -1
  201. package/dist/components/vibes/VibeList.js +16 -12
  202. package/dist/components/vibes/VibeList.js.map +1 -1
  203. package/dist/pages/ActionsPage.js +4 -3
  204. package/dist/pages/ActionsPage.js.map +1 -1
  205. package/dist/pages/AgentDetailsPage.js +9 -9
  206. package/dist/pages/AgentDetailsPage.js.map +1 -1
  207. package/dist/pages/AgentsLandingPage.js +4 -4
  208. package/dist/pages/AgentsLandingPage.js.map +1 -1
  209. package/dist/pages/AgentsPage.js +14 -14
  210. package/dist/pages/AgentsPage.js.map +1 -1
  211. package/dist/pages/AnalyticsPage.js +8 -8
  212. package/dist/pages/AnalyticsPage.js.map +1 -1
  213. package/dist/pages/CatalogDetailPage.js +11 -11
  214. package/dist/pages/CatalogDetailPage.js.map +1 -1
  215. package/dist/pages/CatalogPage.js +12 -9
  216. package/dist/pages/CatalogPage.js.map +1 -1
  217. package/dist/pages/ComponentDetailPage.js +7 -7
  218. package/dist/pages/ComponentDetailPage.js.map +1 -1
  219. package/dist/pages/ComponentsPage.js +12 -9
  220. package/dist/pages/ComponentsPage.js.map +1 -1
  221. package/dist/pages/EnvTopologyPage.js +2 -2
  222. package/dist/pages/EnvTopologyPage.js.map +1 -1
  223. package/dist/pages/GettingStartedPage.js +12 -12
  224. package/dist/pages/GettingStartedPage.js.map +1 -1
  225. package/dist/pages/HealthPage.js +12 -12
  226. package/dist/pages/HealthPage.js.map +1 -1
  227. package/dist/pages/LogsPage.js +4 -4
  228. package/dist/pages/LogsPage.js.map +1 -1
  229. package/dist/pages/NoteDetailsPage.js +5 -5
  230. package/dist/pages/NoteDetailsPage.js.map +1 -1
  231. package/dist/pages/OverviewPage.js +74 -41
  232. package/dist/pages/OverviewPage.js.map +1 -1
  233. package/dist/pages/PluginsCatalogPage.js +6 -3
  234. package/dist/pages/PluginsCatalogPage.js.map +1 -1
  235. package/dist/pages/ScheduledJobDetailPage.js +7 -7
  236. package/dist/pages/ScheduledJobDetailPage.js.map +1 -1
  237. package/dist/pages/SessionDetailsPage.js +21 -21
  238. package/dist/pages/SessionDetailsPage.js.map +1 -1
  239. package/dist/pages/SessionsPage.js +20 -20
  240. package/dist/pages/SessionsPage.js.map +1 -1
  241. package/dist/pages/SettingsPage.js +64 -52
  242. package/dist/pages/SettingsPage.js.map +1 -1
  243. package/dist/pages/SharedSessionPage.js +21 -21
  244. package/dist/pages/SharedSessionPage.js.map +1 -1
  245. package/dist/pages/SharedVibeDeckPage.js +5 -5
  246. package/dist/pages/SharedVibeDeckPage.js.map +1 -1
  247. package/dist/pages/TargetDetailsPage.js +56 -65
  248. package/dist/pages/TargetDetailsPage.js.map +1 -1
  249. package/dist/pages/TargetsPage.js +4 -4
  250. package/dist/pages/TargetsPage.js.map +1 -1
  251. package/dist/pages/TemplateDetailPage.js +10 -10
  252. package/dist/pages/TemplateDetailPage.js.map +1 -1
  253. package/dist/pages/TemplatesPage.js +6 -5
  254. package/dist/pages/TemplatesPage.js.map +1 -1
  255. package/dist/pages/VibeAuditPage.js +3 -3
  256. package/dist/pages/VibeAuditPage.js.map +1 -1
  257. package/dist/pages/VibeCalendarPage.js +3 -3
  258. package/dist/pages/VibeCalendarPage.js.map +1 -1
  259. package/dist/pages/VibeDeckPage.js +3 -3
  260. package/dist/pages/VibeDeckPage.js.map +1 -1
  261. package/dist/pages/VibeDetailsPage.js +15 -15
  262. package/dist/pages/VibeDetailsPage.js.map +1 -1
  263. package/dist/pages/VibeTaskDetailPage.js +5 -5
  264. package/dist/pages/VibeTaskDetailPage.js.map +1 -1
  265. package/dist/pages/VibesPage.js +18 -18
  266. package/dist/pages/VibesPage.js.map +1 -1
  267. package/dist/pages/WebhooksPage.js +11 -11
  268. package/dist/pages/WebhooksPage.js.map +1 -1
  269. package/dist/pages/ai/AIBookmarksPage.js +1 -1
  270. package/dist/pages/ai/AIBookmarksPage.js.map +1 -1
  271. package/dist/pages/ai/AISessionDetailPage.js +6 -6
  272. package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
  273. package/dist/pages/tunnels/AuditTab.js +1 -1
  274. package/dist/pages/tunnels/AuditTab.js.map +1 -1
  275. package/dist/pages/tunnels/DomainsTab.js +1 -1
  276. package/dist/pages/tunnels/DomainsTab.js.map +1 -1
  277. package/dist/pages/tunnels/ProvidersTab.js +1 -1
  278. package/dist/pages/tunnels/ProvidersTab.js.map +1 -1
  279. package/dist/pages/tunnels/SessionsTab.js +1 -1
  280. package/dist/pages/tunnels/SessionsTab.js.map +1 -1
  281. package/dist/pages/tunnels/TunnelDetailsPage.js +3 -3
  282. package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
  283. package/dist/pages/tunnels/UsageTab.js +1 -1
  284. package/dist/pages/tunnels/UsageTab.js.map +1 -1
  285. package/dist/pages/tunnels/tabs/TunnelDomainsTab.js +16 -16
  286. package/dist/pages/tunnels/tabs/TunnelDomainsTab.js.map +1 -1
  287. package/dist/pages/tunnels/tabs/TunnelOverviewTab.js +1 -1
  288. package/dist/pages/tunnels/tabs/TunnelOverviewTab.js.map +1 -1
  289. package/dist/pages/tunnels/tabs/TunnelSessionsTab.js +52 -49
  290. package/dist/pages/tunnels/tabs/TunnelSessionsTab.js.map +1 -1
  291. package/dist/pages/tunnels/tabs/TunnelSettingsTab.js +9 -9
  292. package/dist/pages/tunnels/tabs/TunnelSettingsTab.js.map +1 -1
  293. package/package.json +1 -1
@@ -79,7 +79,7 @@ function j() {
79
79
  children: /* @__PURE__ */ T("div", {
80
80
  className: "text-center space-y-2",
81
81
  children: [/* @__PURE__ */ w("h2", {
82
- className: "text-lg font-semibold text-foreground",
82
+ className: "text-lg font-semibold text-text-primary",
83
83
  children: "Access Denied"
84
84
  }), /* @__PURE__ */ w("p", {
85
85
  className: "text-sm text-text-secondary",
@@ -88,7 +88,7 @@ function j() {
88
88
  })
89
89
  });
90
90
  if (!a) return /* @__PURE__ */ T(E, {
91
- className: "min-h-screen space-y-6 bg-bg-surface p-4 sm:p-6",
91
+ className: "min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6",
92
92
  children: [/* @__PURE__ */ w(r, { title: W("nav.analytics", "Analytics") }), /* @__PURE__ */ w("div", {
93
93
  className: "text-sm text-text-secondary",
94
94
  children: "Waiting for workspace context…"
@@ -97,9 +97,9 @@ function j() {
97
97
  if (X && !Q) {
98
98
  let e = X.message ?? "", t = e.includes("upstream connect error") || e.includes("Connection refused") || e.includes("disconnect/reset before headers") || e.includes("Unexpected response");
99
99
  return /* @__PURE__ */ T(E, {
100
- className: "min-h-screen space-y-6 bg-bg-surface p-4 sm:p-6",
100
+ className: "min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6",
101
101
  children: [/* @__PURE__ */ w(r, { title: W("nav.analytics", "Analytics") }), /* @__PURE__ */ T("div", {
102
- className: "space-y-3 rounded-lg border border-status-warning-border bg-status-warning-bg/10 p-4 text-sm text-text-primary",
102
+ className: "space-y-3 rounded-card border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-text-primary",
103
103
  children: [t ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w("p", {
104
104
  className: "font-medium",
105
105
  children: W("analyticsPage.transientUnavailable", "Analytics is temporarily unavailable")
@@ -109,14 +109,14 @@ function j() {
109
109
  })] }) : /* @__PURE__ */ T("p", { children: ["Failed to load analytics: ", X.message] }), /* @__PURE__ */ w("button", {
110
110
  type: "button",
111
111
  onClick: $,
112
- className: "rounded-md bg-status-warning-bg/20 px-3 py-1.5 text-xs font-medium transition-colors hover:bg-status-warning-bg/30",
112
+ className: "rounded-button border border-status-warning-border bg-status-warning-bg-subtle px-3 py-1.5 text-xs font-medium text-status-warning-text transition-colors hover:bg-bg-sunken",
113
113
  children: W("analyticsPage.retry", "Retry")
114
114
  })]
115
115
  })]
116
116
  });
117
117
  }
118
118
  return /* @__PURE__ */ T(E, {
119
- className: "min-h-screen space-y-4 bg-bg-surface p-4 sm:p-6 vc-printable",
119
+ className: "min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6 vc-printable",
120
120
  children: [
121
121
  /* @__PURE__ */ w(r, { title: W("nav.analytics", "Analytics") }),
122
122
  /* @__PURE__ */ w("div", {
@@ -539,12 +539,12 @@ function j() {
539
539
  }
540
540
  function M({ label: e, value: t, variant: n }) {
541
541
  return /* @__PURE__ */ T("div", {
542
- className: `${n === "success" ? "bg-status-success-bg/10" : n === "warning" ? "bg-status-warning-bg/10" : n === "error" ? "bg-status-error-bg/10" : "bg-bg-surface"} rounded-lg border border-border-default p-3`,
542
+ className: `${n === "success" ? "bg-status-success-bg-subtle border-status-success-border" : n === "warning" ? "bg-status-warning-bg-subtle border-status-warning-border" : n === "error" ? "bg-status-error-bg-subtle border-status-error-border" : "bg-bg-surface border-border-subtle"} rounded-card border p-4 shadow-elevation-1`,
543
543
  children: [/* @__PURE__ */ w("p", {
544
544
  className: "text-xs text-text-secondary",
545
545
  children: e
546
546
  }), /* @__PURE__ */ w("p", {
547
- className: "mt-1 text-xl font-bold text-text-primary",
547
+ className: "mt-1 text-xl font-semibold text-text-primary tabular-nums",
548
548
  children: typeof t == "number" ? t.toLocaleString() : t
549
549
  })]
550
550
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../src/pages/AnalyticsPage.tsx"],"sourcesContent":["import { lazy, Suspense, useCallback, useMemo, useState } from 'react';\nimport { Download, Printer } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { PageHeader } from '@/components/shared';\nimport { SkeletonLine } from '@/components/shared/PageSkeleton';\nimport {\n AnalyticsBreakdownTable,\n AnalyticsEntityTabs,\n AnalyticsFilterBar,\n AnalyticsKpiGrid,\n SandboxAnalyticsSection,\n getAnalyticsTabConfig,\n getDateRange,\n} from '@/components/analytics';\n\n// Recharts is ~150KB+ gzipped and only mounts on the Analytics page once\n// the user lands on it. Lazy-load both chart components so the recharts\n// bundle is excluded from the initial page-load chunk.\nconst AnalyticsTimeSeriesChart = lazy(() =>\n import('@/components/analytics/AnalyticsTimeSeriesChart').then((m) => ({\n default: m.AnalyticsTimeSeriesChart,\n }))\n);\nconst AnalyticsBreakdownChart = lazy(() =>\n import('@/components/analytics/AnalyticsBreakdownChart').then((m) => ({\n default: m.AnalyticsBreakdownChart,\n }))\n);\n\nconst ChartFallback = () => (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <SkeletonLine height=\"h-40\" />\n </div>\n);\nimport type { EntityTab, Granularity, TimeRange } from '@/components/analytics';\nimport { useVibecontrolsAnalyticsQuery } from '@/generated/wspace-operations';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\n\nconst ANALYTICS_TABS: readonly EntityTab[] = [\n 'overview',\n 'agents',\n 'sessions',\n 'sandbox',\n 'vibes',\n 'actions',\n 'vibedecks',\n 'aievents',\n 'audit',\n 'docs',\n];\n\nconst ANALYTICS_SERIES_COLORS = {\n primary: 'var(--color-text-link)',\n success: 'var(--color-status-success-text)',\n accent: 'var(--color-accent-purple)',\n warning: 'var(--color-status-warning-text)',\n} as const;\n\nexport function AnalyticsPage() {\n const { workspaceId } = useVibeControls();\n const { t } = useI18n();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [timeRange, setTimeRange] = useState<TimeRange>('LAST_7D');\n const [granularity, setGranularity] = useState<Granularity>('DAY');\n const [activeTab, setActiveTab] = useQueryBackedTab<EntityTab>(ANALYTICS_TABS, 'overview');\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const { startDate, endDate } = useMemo(() => getDateRange(timeRange), [timeRange]);\n const activeTabConfig = useMemo(() => getAnalyticsTabConfig(activeTab), [activeTab]);\n\n const { data, loading, error, refetch } = useVibecontrolsAnalyticsQuery({\n variables: {\n input: {\n startDate: startDate.toISOString(),\n endDate: endDate.toISOString(),\n granularity,\n entityTypes: activeTabConfig.entityTypes,\n },\n },\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n notifyOnNetworkStatusChange: true,\n skip: !workspaceId,\n });\n\n const analytics = data?.vibecontrolsAnalytics;\n\n const handleRefresh = useCallback(() => {\n void refetch();\n }, [refetch]);\n\n const handlePrint = useCallback(() => {\n if (typeof window !== 'undefined') window.print();\n }, []);\n\n const handleExportCsv = useCallback(() => {\n if (!analytics) return;\n const rows = buildCsvRowsForTab(activeTab, analytics);\n if (rows.length === 0) return;\n const csv = rowsToCsv(rows);\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n const stamp = new Date().toISOString().slice(0, 10);\n a.download = `vibecontrols-analytics-${activeTab}-${stamp}.csv`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, [analytics, activeTab]);\n\n const handleCardClick = useCallback(\n (href: string) => {\n navigate(href);\n },\n [navigate]\n );\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.ANALYTICS_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n if (!workspaceId) {\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-surface p-4 sm:p-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"text-sm text-text-secondary\">Waiting for workspace context…</div>\n </MotionPage>\n );\n }\n\n if (error && !analytics) {\n // The wspace-vibecontrols-svc analytics resolver already safe-degrades\n // to an empty payload on its own; when this error path actually fires\n // the failure is upstream (ACA proxy returning \"upstream connect\n // error\" / \"Connection refused\" while the svc is restarting, or a\n // transient gateway hiccup). Show a transient-failure copy instead of\n // the raw Envoy-style message so users don't try to debug a string\n // that's meaningless to them.\n const raw = error.message ?? '';\n const looksTransient =\n raw.includes('upstream connect error') ||\n raw.includes('Connection refused') ||\n raw.includes('disconnect/reset before headers') ||\n raw.includes('Unexpected response');\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-surface p-4 sm:p-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"space-y-3 rounded-lg border border-status-warning-border bg-status-warning-bg/10 p-4 text-sm text-text-primary\">\n {looksTransient ? (\n <>\n <p className=\"font-medium\">\n {tr('analyticsPage.transientUnavailable', 'Analytics is temporarily unavailable')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'analyticsPage.transientHint',\n 'This is usually brief — please wait a moment and retry. Other VibeControls features are unaffected.'\n )}\n </p>\n </>\n ) : (\n <p>Failed to load analytics: {error.message}</p>\n )}\n <button\n type=\"button\"\n onClick={handleRefresh}\n className=\"rounded-md bg-status-warning-bg/20 px-3 py-1.5 text-xs font-medium transition-colors hover:bg-status-warning-bg/30\"\n >\n {tr('analyticsPage.retry', 'Retry')}\n </button>\n </div>\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"min-h-screen space-y-4 bg-bg-surface p-4 sm:p-6 vc-printable\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n\n {/* AnalyticsFilterBar / AnalyticsEntityTabs are custom components that\n don't forward rest props onto a DOM node, so the tour anchors are\n attached to wrapper <div>s (same pattern as VibeDeckSwitcher etc.)\n to keep `[data-tour=\"...\"]` selectors reachable in the DOM. */}\n <div data-tour=\"analytics-filter-bar\">\n <AnalyticsFilterBar\n timeRange={timeRange}\n granularity={granularity}\n onTimeRangeChange={setTimeRange}\n onGranularityChange={setGranularity}\n onRefresh={handleRefresh}\n loading={loading}\n executionTimeMs={analytics?.executionTimeMs}\n cached={analytics?.cached}\n />\n </div>\n\n <div data-tour=\"analytics-entity-tabs\">\n <AnalyticsEntityTabs activeTab={activeTab} onTabChange={setActiveTab} />\n </div>\n\n {/* F11: Per-tab export + print toolbar. Hidden in print output via the\n `vc-print-hide` class. */}\n <div\n data-tour=\"analytics-export-print-actions\"\n className=\"flex flex-wrap items-center justify-end gap-2 vc-print-hide\"\n >\n <button\n type=\"button\"\n onClick={handleExportCsv}\n disabled={loading || !analytics}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tr('analytics.exportCsvTitle', 'Export current tab as CSV')}\n >\n <Download size={14} />\n {tr('analytics.exportCsv', 'Export CSV')}\n </button>\n <button\n type=\"button\"\n onClick={handlePrint}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n title={tr('analytics.printTitle', 'Print this report')}\n >\n <Printer size={14} />\n {tr('analytics.print', 'Print')}\n </button>\n {/* TODO(boff-analytics-png): wire PNG export once html-to-image\n or recharts svg-to-image helper is added to deps. */}\n </div>\n\n <Suspense fallback={<ChartFallback />}>\n <section\n id={`analytics-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`analytics-tab-${activeTab}`}\n className=\"space-y-4\"\n >\n {activeTab === 'overview' ? (\n <div className=\"space-y-4\">\n <AnalyticsKpiGrid data={analytics} loading={loading} onCardClick={handleCardClick} />\n\n <AnalyticsTimeSeriesChart\n title=\"Activity Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics?.sessions?.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n {\n label: 'Executions',\n data: analytics?.actions?.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n {\n label: 'AI Events',\n data: analytics?.aiEvents?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n {\n label: 'Audit Logs',\n data: analytics?.audit?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Status\"\n data={analytics?.sessions?.byStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Vibes by Status\"\n data={analytics?.vibes?.byStatus}\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'agents' && analytics?.agents ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.agents.total} />\n <KpiCard label=\"Active\" value={analytics.agents.active} variant=\"success\" />\n <KpiCard label=\"Inactive\" value={analytics.agents.inactive} variant=\"warning\" />\n <KpiCard\n label=\"Stale Heartbeat\"\n value={analytics.agents.staleHeartbeatCount}\n variant=\"error\"\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Agents Created Over Time\"\n datasets={[\n {\n label: 'Agents',\n data: analytics.agents.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Platform\"\n data={analytics.agents.byPlatform}\n keyLabel=\"Platform\"\n />\n <AnalyticsBreakdownTable\n title=\"By Architecture\"\n data={analytics.agents.byArchitecture}\n keyLabel=\"Architecture\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sessions' && analytics?.sessions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.sessions.total} />\n <KpiCard label=\"Running\" value={analytics.sessions.active} variant=\"success\" />\n <KpiCard label=\"Collaborators\" value={analytics.sessions.totalCollaborators} />\n <KpiCard\n label=\"Shares\"\n value={analytics.sessions.totalShares + analytics.sessions.totalShareLinks}\n />\n </div>\n\n {analytics.sessions.avgDurationMs != null ? (\n <div className=\"text-sm text-text-secondary\">\n Average duration:{' '}\n <span className=\"font-medium text-text-primary\">\n {formatDuration(analytics.sessions.avgDurationMs)}\n </span>\n </div>\n ) : null}\n\n <AnalyticsTimeSeriesChart\n title=\"Sessions Created Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics.sessions.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Type\"\n data={analytics.sessions.byType}\n />\n <AnalyticsBreakdownTable\n title=\"Sessions by Status\"\n data={analytics.sessions.byStatus}\n keyLabel=\"Status\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sandbox' ? <SandboxAnalyticsSection /> : null}\n\n {activeTab === 'vibes' && analytics?.vibes ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.vibes.total} />\n <KpiCard label=\"With Agent\" value={analytics.vibes.withAgent} variant=\"success\" />\n <KpiCard label=\"Without Agent\" value={analytics.vibes.withoutAgent} />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Vibes Created Over Time\"\n datasets={[\n {\n label: 'Vibes',\n data: analytics.vibes.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"Vibes by Type\" data={analytics.vibes.byType} />\n <AnalyticsBreakdownChart title=\"Vibes by Status\" data={analytics.vibes.byStatus} />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'actions' && analytics?.actions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total Actions\" value={analytics.actions.total} />\n <KpiCard label=\"Executions\" value={analytics.actions.totalExecutions} />\n <KpiCard\n label=\"Success Rate\"\n value={\n analytics.actions.successRate != null\n ? `${analytics.actions.successRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.actions.successRate != null && analytics.actions.successRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n <KpiCard\n label=\"Avg Duration\"\n value={\n analytics.actions.avgDurationMs != null\n ? formatDuration(analytics.actions.avgDurationMs)\n : 'N/A'\n }\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Executions Over Time\"\n datasets={[\n {\n label: 'Executions',\n data: analytics.actions.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"By Action Type\"\n data={analytics.actions.byActionType}\n />\n <AnalyticsBreakdownChart\n title=\"Execution Status\"\n data={analytics.actions.executionsByStatus}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Trigger Type\"\n data={analytics.actions.byTriggerType}\n keyLabel=\"Trigger\"\n />\n <AnalyticsBreakdownTable\n title=\"By Source Type\"\n data={analytics.actions.bySourceType}\n keyLabel=\"Source\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'vibedecks' && analytics?.vibeDecks ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <KpiCard label=\"Decks\" value={analytics.vibeDecks.totalDecks} />\n <KpiCard label=\"Buttons\" value={analytics.vibeDecks.totalButtons} />\n </div>\n\n <AnalyticsBreakdownChart\n title=\"Buttons by Action Type\"\n data={analytics.vibeDecks.buttonsByActionType}\n />\n </div>\n ) : null}\n\n {activeTab === 'aievents' && analytics?.aiEvents ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total AI Events\" value={analytics.aiEvents.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"AI Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.aiEvents.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Source\" data={analytics.aiEvents.bySource} />\n <AnalyticsBreakdownTable\n title=\"By Event Type\"\n data={analytics.aiEvents.byEventType}\n keyLabel=\"Event Type\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'audit' && analytics?.audit ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total Audit Logs\" value={analytics.audit.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"Audit Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.audit.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Action\" data={analytics.audit.byAction} />\n <AnalyticsBreakdownChart title=\"By Status\" data={analytics.audit.byStatus} />\n </div>\n\n <AnalyticsBreakdownTable\n title=\"By Resource Type\"\n data={analytics.audit.byResourceType}\n keyLabel=\"Resource\"\n />\n </div>\n ) : null}\n\n {activeTab === 'docs' && analytics?.docs ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Sites\" value={analytics.docs.totalSites} />\n <KpiCard label=\"Pages\" value={analytics.docs.totalPages} />\n <KpiCard label=\"Revisions\" value={analytics.docs.totalRevisions} />\n <KpiCard\n label=\"Build Success\"\n value={\n analytics.docs.buildSuccessRate != null\n ? `${analytics.docs.buildSuccessRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.docs.buildSuccessRate != null && analytics.docs.buildSuccessRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Pages by Status\"\n data={analytics.docs.pagesByStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Revisions by Status\"\n data={analytics.docs.revisionsByStatus}\n />\n </div>\n </div>\n ) : null}\n </section>\n </Suspense>\n </MotionPage>\n );\n}\n\nfunction KpiCard({\n label,\n value,\n variant,\n}: {\n label: string;\n value: number | string;\n variant?: 'success' | 'warning' | 'error';\n}) {\n const surfaceClass =\n variant === 'success'\n ? 'bg-status-success-bg/10'\n : variant === 'warning'\n ? 'bg-status-warning-bg/10'\n : variant === 'error'\n ? 'bg-status-error-bg/10'\n : 'bg-bg-surface';\n\n return (\n <div className={`${surfaceClass} rounded-lg border border-border-default p-3`}>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className=\"mt-1 text-xl font-bold text-text-primary\">\n {typeof value === 'number' ? value.toLocaleString() : value}\n </p>\n </div>\n );\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (milliseconds < 1000) {\n return `${Math.round(milliseconds)}ms`;\n }\n\n if (milliseconds < 60000) {\n return `${(milliseconds / 1000).toFixed(1)}s`;\n }\n\n const minutes = Math.floor(milliseconds / 60000);\n const seconds = Math.round((milliseconds % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n// ── F11: CSV serialization for the active analytics tab ──────────────────\n\ntype CsvRow = (string | number)[];\n\nfunction rowsToCsv(rows: CsvRow[]): string {\n return rows\n .map((row) =>\n row\n .map((cell) => {\n const s = cell == null ? '' : String(cell);\n // Escape per RFC4180 — wrap in quotes when the cell contains a\n // separator, quote, or newline; double any internal quotes.\n if (/[\",\\n\\r]/.test(s)) return `\"${s.replace(/\"/g, '\"\"')}\"`;\n return s;\n })\n .join(',')\n )\n .join('\\r\\n');\n}\n\n/**\n * Build the CSV row matrix for an analytics tab. Each tab serialises its\n * primary table data; chart-only tabs fall back to a sparse summary.\n * The first row is always headers.\n */\ntype AnalyticsBreakdownEntry = {\n key?: string | null;\n label?: string | null;\n count?: number | null;\n};\n\ninterface AnalyticsTabSlice {\n total?: number | null;\n active?: number | null;\n inactive?: number | null;\n staleHeartbeatCount?: number | null;\n withAgent?: number | null;\n withoutAgent?: number | null;\n totalExecutions?: number | null;\n successRate?: number | null;\n avgDurationMs?: number | null;\n totalDecks?: number | null;\n totalButtons?: number | null;\n totalSites?: number | null;\n totalPages?: number | null;\n totalRevisions?: number | null;\n buildSuccessRate?: number | null;\n byPlatform?: ReadonlyArray<AnalyticsBreakdownEntry>;\n byType?: ReadonlyArray<AnalyticsBreakdownEntry>;\n}\n\ninterface AnalyticsSnapshot {\n sessions?: AnalyticsTabSlice;\n agents?: AnalyticsTabSlice;\n vibes?: AnalyticsTabSlice;\n actions?: AnalyticsTabSlice;\n aiEvents?: AnalyticsTabSlice;\n audit?: AnalyticsTabSlice;\n docs?: AnalyticsTabSlice;\n vibeDecks?: AnalyticsTabSlice;\n}\n\nfunction buildCsvRowsForTab(tab: EntityTab, analytics: AnalyticsSnapshot): CsvRow[] {\n const rows: CsvRow[] = [];\n if (tab === 'overview') {\n rows.push(['metric', 'value']);\n if (analytics.sessions) rows.push(['sessions.total', analytics.sessions.total ?? 0]);\n if (analytics.agents) rows.push(['agents.total', analytics.agents.total ?? 0]);\n if (analytics.vibes) rows.push(['vibes.total', analytics.vibes.total ?? 0]);\n if (analytics.actions) rows.push(['actions.total', analytics.actions.total ?? 0]);\n return rows;\n }\n if (tab === 'agents' && analytics.agents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.agents.total ?? 0]);\n rows.push(['active', analytics.agents.active ?? 0]);\n rows.push(['inactive', analytics.agents.inactive ?? 0]);\n rows.push(['staleHeartbeat', analytics.agents.staleHeartbeatCount ?? 0]);\n if (Array.isArray(analytics.agents.byPlatform)) {\n rows.push([], ['platform', 'count']);\n for (const e of analytics.agents.byPlatform)\n rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'sessions' && analytics.sessions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.sessions.total ?? 0]);\n rows.push(['running', analytics.sessions.active ?? 0]);\n rows.push(['avgDurationMs', analytics.sessions.avgDurationMs ?? '']);\n if (Array.isArray(analytics.sessions.byType)) {\n rows.push([], ['type', 'count']);\n for (const e of analytics.sessions.byType) rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'actions' && analytics.actions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.actions.total ?? 0]);\n rows.push(['totalExecutions', analytics.actions.totalExecutions ?? 0]);\n rows.push(['successRate', analytics.actions.successRate ?? '']);\n rows.push(['avgDurationMs', analytics.actions.avgDurationMs ?? '']);\n return rows;\n }\n if (tab === 'vibes' && analytics.vibes) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.vibes.total ?? 0]);\n rows.push(['withAgent', analytics.vibes.withAgent ?? 0]);\n rows.push(['withoutAgent', analytics.vibes.withoutAgent ?? 0]);\n return rows;\n }\n if (tab === 'vibedecks' && analytics.vibeDecks) {\n rows.push(['metric', 'value']);\n rows.push(['decks', analytics.vibeDecks.totalDecks ?? 0]);\n rows.push(['buttons', analytics.vibeDecks.totalButtons ?? 0]);\n return rows;\n }\n if (tab === 'aievents' && analytics.aiEvents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.aiEvents.total ?? 0]);\n return rows;\n }\n if (tab === 'audit' && analytics.audit) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.audit.total ?? 0]);\n return rows;\n }\n if (tab === 'docs' && analytics.docs) {\n rows.push(['metric', 'value']);\n rows.push(['sites', analytics.docs.totalSites ?? 0]);\n rows.push(['pages', analytics.docs.totalPages ?? 0]);\n rows.push(['revisions', analytics.docs.totalRevisions ?? 0]);\n rows.push(['buildSuccessRate', analytics.docs.buildSuccessRate ?? '']);\n return rows;\n }\n // sandbox + others fall back to a sparse summary\n rows.push(['metric', 'value']);\n rows.push(['note', `No CSV serialiser for ${tab} tab yet`]);\n return rows;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AnalyticsPage.js","names":[],"sources":["../../src/pages/AnalyticsPage.tsx"],"sourcesContent":["import { lazy, Suspense, useCallback, useMemo, useState } from 'react';\nimport { Download, Printer } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { PageHeader } from '@/components/shared';\nimport { SkeletonLine } from '@/components/shared/PageSkeleton';\nimport {\n AnalyticsBreakdownTable,\n AnalyticsEntityTabs,\n AnalyticsFilterBar,\n AnalyticsKpiGrid,\n SandboxAnalyticsSection,\n getAnalyticsTabConfig,\n getDateRange,\n} from '@/components/analytics';\n\n// Recharts is ~150KB+ gzipped and only mounts on the Analytics page once\n// the user lands on it. Lazy-load both chart components so the recharts\n// bundle is excluded from the initial page-load chunk.\nconst AnalyticsTimeSeriesChart = lazy(() =>\n import('@/components/analytics/AnalyticsTimeSeriesChart').then((m) => ({\n default: m.AnalyticsTimeSeriesChart,\n }))\n);\nconst AnalyticsBreakdownChart = lazy(() =>\n import('@/components/analytics/AnalyticsBreakdownChart').then((m) => ({\n default: m.AnalyticsBreakdownChart,\n }))\n);\n\nconst ChartFallback = () => (\n <div className=\"bg-bg-surface border border-border-default rounded-lg p-4\">\n <SkeletonLine height=\"h-40\" />\n </div>\n);\nimport type { EntityTab, Granularity, TimeRange } from '@/components/analytics';\nimport { useVibecontrolsAnalyticsQuery } from '@/generated/wspace-operations';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\n\nconst ANALYTICS_TABS: readonly EntityTab[] = [\n 'overview',\n 'agents',\n 'sessions',\n 'sandbox',\n 'vibes',\n 'actions',\n 'vibedecks',\n 'aievents',\n 'audit',\n 'docs',\n];\n\nconst ANALYTICS_SERIES_COLORS = {\n primary: 'var(--color-text-link)',\n success: 'var(--color-status-success-text)',\n accent: 'var(--color-accent-purple)',\n warning: 'var(--color-status-warning-text)',\n} as const;\n\nexport function AnalyticsPage() {\n const { workspaceId } = useVibeControls();\n const { t } = useI18n();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const [timeRange, setTimeRange] = useState<TimeRange>('LAST_7D');\n const [granularity, setGranularity] = useState<Granularity>('DAY');\n const [activeTab, setActiveTab] = useQueryBackedTab<EntityTab>(ANALYTICS_TABS, 'overview');\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const { startDate, endDate } = useMemo(() => getDateRange(timeRange), [timeRange]);\n const activeTabConfig = useMemo(() => getAnalyticsTabConfig(activeTab), [activeTab]);\n\n const { data, loading, error, refetch } = useVibecontrolsAnalyticsQuery({\n variables: {\n input: {\n startDate: startDate.toISOString(),\n endDate: endDate.toISOString(),\n granularity,\n entityTypes: activeTabConfig.entityTypes,\n },\n },\n fetchPolicy: 'cache-first',\n nextFetchPolicy: 'cache-first',\n notifyOnNetworkStatusChange: true,\n skip: !workspaceId,\n });\n\n const analytics = data?.vibecontrolsAnalytics;\n\n const handleRefresh = useCallback(() => {\n void refetch();\n }, [refetch]);\n\n const handlePrint = useCallback(() => {\n if (typeof window !== 'undefined') window.print();\n }, []);\n\n const handleExportCsv = useCallback(() => {\n if (!analytics) return;\n const rows = buildCsvRowsForTab(activeTab, analytics);\n if (rows.length === 0) return;\n const csv = rowsToCsv(rows);\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n const stamp = new Date().toISOString().slice(0, 10);\n a.download = `vibecontrols-analytics-${activeTab}-${stamp}.csv`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, [analytics, activeTab]);\n\n const handleCardClick = useCallback(\n (href: string) => {\n navigate(href);\n },\n [navigate]\n );\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.ANALYTICS_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n if (!workspaceId) {\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"text-sm text-text-secondary\">Waiting for workspace context…</div>\n </MotionPage>\n );\n }\n\n if (error && !analytics) {\n // The wspace-vibecontrols-svc analytics resolver already safe-degrades\n // to an empty payload on its own; when this error path actually fires\n // the failure is upstream (ACA proxy returning \"upstream connect\n // error\" / \"Connection refused\" while the svc is restarting, or a\n // transient gateway hiccup). Show a transient-failure copy instead of\n // the raw Envoy-style message so users don't try to debug a string\n // that's meaningless to them.\n const raw = error.message ?? '';\n const looksTransient =\n raw.includes('upstream connect error') ||\n raw.includes('Connection refused') ||\n raw.includes('disconnect/reset before headers') ||\n raw.includes('Unexpected response');\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n <div className=\"space-y-3 rounded-card border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-text-primary\">\n {looksTransient ? (\n <>\n <p className=\"font-medium\">\n {tr('analyticsPage.transientUnavailable', 'Analytics is temporarily unavailable')}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'analyticsPage.transientHint',\n 'This is usually brief — please wait a moment and retry. Other VibeControls features are unaffected.'\n )}\n </p>\n </>\n ) : (\n <p>Failed to load analytics: {error.message}</p>\n )}\n <button\n type=\"button\"\n onClick={handleRefresh}\n className=\"rounded-button border border-status-warning-border bg-status-warning-bg-subtle px-3 py-1.5 text-xs font-medium text-status-warning-text transition-colors hover:bg-bg-sunken\"\n >\n {tr('analyticsPage.retry', 'Retry')}\n </button>\n </div>\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"min-h-screen space-y-6 bg-bg-canvas px-6 lg:px-8 py-6 vc-printable\">\n <PageHeader title={tr('nav.analytics', 'Analytics')} />\n\n {/* AnalyticsFilterBar / AnalyticsEntityTabs are custom components that\n don't forward rest props onto a DOM node, so the tour anchors are\n attached to wrapper <div>s (same pattern as VibeDeckSwitcher etc.)\n to keep `[data-tour=\"...\"]` selectors reachable in the DOM. */}\n <div data-tour=\"analytics-filter-bar\">\n <AnalyticsFilterBar\n timeRange={timeRange}\n granularity={granularity}\n onTimeRangeChange={setTimeRange}\n onGranularityChange={setGranularity}\n onRefresh={handleRefresh}\n loading={loading}\n executionTimeMs={analytics?.executionTimeMs}\n cached={analytics?.cached}\n />\n </div>\n\n <div data-tour=\"analytics-entity-tabs\">\n <AnalyticsEntityTabs activeTab={activeTab} onTabChange={setActiveTab} />\n </div>\n\n {/* F11: Per-tab export + print toolbar. Hidden in print output via the\n `vc-print-hide` class. */}\n <div\n data-tour=\"analytics-export-print-actions\"\n className=\"flex flex-wrap items-center justify-end gap-2 vc-print-hide\"\n >\n <button\n type=\"button\"\n onClick={handleExportCsv}\n disabled={loading || !analytics}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tr('analytics.exportCsvTitle', 'Export current tab as CSV')}\n >\n <Download size={14} />\n {tr('analytics.exportCsv', 'Export CSV')}\n </button>\n <button\n type=\"button\"\n onClick={handlePrint}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n title={tr('analytics.printTitle', 'Print this report')}\n >\n <Printer size={14} />\n {tr('analytics.print', 'Print')}\n </button>\n {/* TODO(boff-analytics-png): wire PNG export once html-to-image\n or recharts svg-to-image helper is added to deps. */}\n </div>\n\n <Suspense fallback={<ChartFallback />}>\n <section\n id={`analytics-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`analytics-tab-${activeTab}`}\n className=\"space-y-4\"\n >\n {activeTab === 'overview' ? (\n <div className=\"space-y-4\">\n <AnalyticsKpiGrid data={analytics} loading={loading} onCardClick={handleCardClick} />\n\n <AnalyticsTimeSeriesChart\n title=\"Activity Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics?.sessions?.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n {\n label: 'Executions',\n data: analytics?.actions?.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n {\n label: 'AI Events',\n data: analytics?.aiEvents?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n {\n label: 'Audit Logs',\n data: analytics?.audit?.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Status\"\n data={analytics?.sessions?.byStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Vibes by Status\"\n data={analytics?.vibes?.byStatus}\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'agents' && analytics?.agents ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.agents.total} />\n <KpiCard label=\"Active\" value={analytics.agents.active} variant=\"success\" />\n <KpiCard label=\"Inactive\" value={analytics.agents.inactive} variant=\"warning\" />\n <KpiCard\n label=\"Stale Heartbeat\"\n value={analytics.agents.staleHeartbeatCount}\n variant=\"error\"\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Agents Created Over Time\"\n datasets={[\n {\n label: 'Agents',\n data: analytics.agents.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Platform\"\n data={analytics.agents.byPlatform}\n keyLabel=\"Platform\"\n />\n <AnalyticsBreakdownTable\n title=\"By Architecture\"\n data={analytics.agents.byArchitecture}\n keyLabel=\"Architecture\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sessions' && analytics?.sessions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.sessions.total} />\n <KpiCard label=\"Running\" value={analytics.sessions.active} variant=\"success\" />\n <KpiCard label=\"Collaborators\" value={analytics.sessions.totalCollaborators} />\n <KpiCard\n label=\"Shares\"\n value={analytics.sessions.totalShares + analytics.sessions.totalShareLinks}\n />\n </div>\n\n {analytics.sessions.avgDurationMs != null ? (\n <div className=\"text-sm text-text-secondary\">\n Average duration:{' '}\n <span className=\"font-medium text-text-primary\">\n {formatDuration(analytics.sessions.avgDurationMs)}\n </span>\n </div>\n ) : null}\n\n <AnalyticsTimeSeriesChart\n title=\"Sessions Created Over Time\"\n datasets={[\n {\n label: 'Sessions',\n data: analytics.sessions.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.primary,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Sessions by Type\"\n data={analytics.sessions.byType}\n />\n <AnalyticsBreakdownTable\n title=\"Sessions by Status\"\n data={analytics.sessions.byStatus}\n keyLabel=\"Status\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'sandbox' ? <SandboxAnalyticsSection /> : null}\n\n {activeTab === 'vibes' && analytics?.vibes ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total\" value={analytics.vibes.total} />\n <KpiCard label=\"With Agent\" value={analytics.vibes.withAgent} variant=\"success\" />\n <KpiCard label=\"Without Agent\" value={analytics.vibes.withoutAgent} />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Vibes Created Over Time\"\n datasets={[\n {\n label: 'Vibes',\n data: analytics.vibes.createdOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"Vibes by Type\" data={analytics.vibes.byType} />\n <AnalyticsBreakdownChart title=\"Vibes by Status\" data={analytics.vibes.byStatus} />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'actions' && analytics?.actions ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Total Actions\" value={analytics.actions.total} />\n <KpiCard label=\"Executions\" value={analytics.actions.totalExecutions} />\n <KpiCard\n label=\"Success Rate\"\n value={\n analytics.actions.successRate != null\n ? `${analytics.actions.successRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.actions.successRate != null && analytics.actions.successRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n <KpiCard\n label=\"Avg Duration\"\n value={\n analytics.actions.avgDurationMs != null\n ? formatDuration(analytics.actions.avgDurationMs)\n : 'N/A'\n }\n />\n </div>\n\n <AnalyticsTimeSeriesChart\n title=\"Executions Over Time\"\n datasets={[\n {\n label: 'Executions',\n data: analytics.actions.executionsOverTime,\n color: ANALYTICS_SERIES_COLORS.success,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"By Action Type\"\n data={analytics.actions.byActionType}\n />\n <AnalyticsBreakdownChart\n title=\"Execution Status\"\n data={analytics.actions.executionsByStatus}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownTable\n title=\"By Trigger Type\"\n data={analytics.actions.byTriggerType}\n keyLabel=\"Trigger\"\n />\n <AnalyticsBreakdownTable\n title=\"By Source Type\"\n data={analytics.actions.bySourceType}\n keyLabel=\"Source\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'vibedecks' && analytics?.vibeDecks ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3\">\n <KpiCard label=\"Decks\" value={analytics.vibeDecks.totalDecks} />\n <KpiCard label=\"Buttons\" value={analytics.vibeDecks.totalButtons} />\n </div>\n\n <AnalyticsBreakdownChart\n title=\"Buttons by Action Type\"\n data={analytics.vibeDecks.buttonsByActionType}\n />\n </div>\n ) : null}\n\n {activeTab === 'aievents' && analytics?.aiEvents ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total AI Events\" value={analytics.aiEvents.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"AI Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.aiEvents.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.accent,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Source\" data={analytics.aiEvents.bySource} />\n <AnalyticsBreakdownTable\n title=\"By Event Type\"\n data={analytics.aiEvents.byEventType}\n keyLabel=\"Event Type\"\n />\n </div>\n </div>\n ) : null}\n\n {activeTab === 'audit' && analytics?.audit ? (\n <div className=\"space-y-4\">\n <KpiCard label=\"Total Audit Logs\" value={analytics.audit.total} />\n\n <AnalyticsTimeSeriesChart\n title=\"Audit Events Over Time\"\n datasets={[\n {\n label: 'Events',\n data: analytics.audit.eventsOverTime,\n color: ANALYTICS_SERIES_COLORS.warning,\n },\n ]}\n height={250}\n />\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart title=\"By Action\" data={analytics.audit.byAction} />\n <AnalyticsBreakdownChart title=\"By Status\" data={analytics.audit.byStatus} />\n </div>\n\n <AnalyticsBreakdownTable\n title=\"By Resource Type\"\n data={analytics.audit.byResourceType}\n keyLabel=\"Resource\"\n />\n </div>\n ) : null}\n\n {activeTab === 'docs' && analytics?.docs ? (\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\n <KpiCard label=\"Sites\" value={analytics.docs.totalSites} />\n <KpiCard label=\"Pages\" value={analytics.docs.totalPages} />\n <KpiCard label=\"Revisions\" value={analytics.docs.totalRevisions} />\n <KpiCard\n label=\"Build Success\"\n value={\n analytics.docs.buildSuccessRate != null\n ? `${analytics.docs.buildSuccessRate.toFixed(1)}%`\n : 'N/A'\n }\n variant={\n analytics.docs.buildSuccessRate != null && analytics.docs.buildSuccessRate >= 90\n ? 'success'\n : 'warning'\n }\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">\n <AnalyticsBreakdownChart\n title=\"Pages by Status\"\n data={analytics.docs.pagesByStatus}\n />\n <AnalyticsBreakdownChart\n title=\"Revisions by Status\"\n data={analytics.docs.revisionsByStatus}\n />\n </div>\n </div>\n ) : null}\n </section>\n </Suspense>\n </MotionPage>\n );\n}\n\nfunction KpiCard({\n label,\n value,\n variant,\n}: {\n label: string;\n value: number | string;\n variant?: 'success' | 'warning' | 'error';\n}) {\n const surfaceClass =\n variant === 'success'\n ? 'bg-status-success-bg-subtle border-status-success-border'\n : variant === 'warning'\n ? 'bg-status-warning-bg-subtle border-status-warning-border'\n : variant === 'error'\n ? 'bg-status-error-bg-subtle border-status-error-border'\n : 'bg-bg-surface border-border-subtle';\n\n return (\n <div className={`${surfaceClass} rounded-card border p-4 shadow-elevation-1`}>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className=\"mt-1 text-xl font-semibold text-text-primary tabular-nums\">\n {typeof value === 'number' ? value.toLocaleString() : value}\n </p>\n </div>\n );\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (milliseconds < 1000) {\n return `${Math.round(milliseconds)}ms`;\n }\n\n if (milliseconds < 60000) {\n return `${(milliseconds / 1000).toFixed(1)}s`;\n }\n\n const minutes = Math.floor(milliseconds / 60000);\n const seconds = Math.round((milliseconds % 60000) / 1000);\n return `${minutes}m ${seconds}s`;\n}\n\n// ── F11: CSV serialization for the active analytics tab ──────────────────\n\ntype CsvRow = (string | number)[];\n\nfunction rowsToCsv(rows: CsvRow[]): string {\n return rows\n .map((row) =>\n row\n .map((cell) => {\n const s = cell == null ? '' : String(cell);\n // Escape per RFC4180 — wrap in quotes when the cell contains a\n // separator, quote, or newline; double any internal quotes.\n if (/[\",\\n\\r]/.test(s)) return `\"${s.replace(/\"/g, '\"\"')}\"`;\n return s;\n })\n .join(',')\n )\n .join('\\r\\n');\n}\n\n/**\n * Build the CSV row matrix for an analytics tab. Each tab serialises its\n * primary table data; chart-only tabs fall back to a sparse summary.\n * The first row is always headers.\n */\ntype AnalyticsBreakdownEntry = {\n key?: string | null;\n label?: string | null;\n count?: number | null;\n};\n\ninterface AnalyticsTabSlice {\n total?: number | null;\n active?: number | null;\n inactive?: number | null;\n staleHeartbeatCount?: number | null;\n withAgent?: number | null;\n withoutAgent?: number | null;\n totalExecutions?: number | null;\n successRate?: number | null;\n avgDurationMs?: number | null;\n totalDecks?: number | null;\n totalButtons?: number | null;\n totalSites?: number | null;\n totalPages?: number | null;\n totalRevisions?: number | null;\n buildSuccessRate?: number | null;\n byPlatform?: ReadonlyArray<AnalyticsBreakdownEntry>;\n byType?: ReadonlyArray<AnalyticsBreakdownEntry>;\n}\n\ninterface AnalyticsSnapshot {\n sessions?: AnalyticsTabSlice;\n agents?: AnalyticsTabSlice;\n vibes?: AnalyticsTabSlice;\n actions?: AnalyticsTabSlice;\n aiEvents?: AnalyticsTabSlice;\n audit?: AnalyticsTabSlice;\n docs?: AnalyticsTabSlice;\n vibeDecks?: AnalyticsTabSlice;\n}\n\nfunction buildCsvRowsForTab(tab: EntityTab, analytics: AnalyticsSnapshot): CsvRow[] {\n const rows: CsvRow[] = [];\n if (tab === 'overview') {\n rows.push(['metric', 'value']);\n if (analytics.sessions) rows.push(['sessions.total', analytics.sessions.total ?? 0]);\n if (analytics.agents) rows.push(['agents.total', analytics.agents.total ?? 0]);\n if (analytics.vibes) rows.push(['vibes.total', analytics.vibes.total ?? 0]);\n if (analytics.actions) rows.push(['actions.total', analytics.actions.total ?? 0]);\n return rows;\n }\n if (tab === 'agents' && analytics.agents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.agents.total ?? 0]);\n rows.push(['active', analytics.agents.active ?? 0]);\n rows.push(['inactive', analytics.agents.inactive ?? 0]);\n rows.push(['staleHeartbeat', analytics.agents.staleHeartbeatCount ?? 0]);\n if (Array.isArray(analytics.agents.byPlatform)) {\n rows.push([], ['platform', 'count']);\n for (const e of analytics.agents.byPlatform)\n rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'sessions' && analytics.sessions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.sessions.total ?? 0]);\n rows.push(['running', analytics.sessions.active ?? 0]);\n rows.push(['avgDurationMs', analytics.sessions.avgDurationMs ?? '']);\n if (Array.isArray(analytics.sessions.byType)) {\n rows.push([], ['type', 'count']);\n for (const e of analytics.sessions.byType) rows.push([e.key ?? e.label ?? '', e.count ?? 0]);\n }\n return rows;\n }\n if (tab === 'actions' && analytics.actions) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.actions.total ?? 0]);\n rows.push(['totalExecutions', analytics.actions.totalExecutions ?? 0]);\n rows.push(['successRate', analytics.actions.successRate ?? '']);\n rows.push(['avgDurationMs', analytics.actions.avgDurationMs ?? '']);\n return rows;\n }\n if (tab === 'vibes' && analytics.vibes) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.vibes.total ?? 0]);\n rows.push(['withAgent', analytics.vibes.withAgent ?? 0]);\n rows.push(['withoutAgent', analytics.vibes.withoutAgent ?? 0]);\n return rows;\n }\n if (tab === 'vibedecks' && analytics.vibeDecks) {\n rows.push(['metric', 'value']);\n rows.push(['decks', analytics.vibeDecks.totalDecks ?? 0]);\n rows.push(['buttons', analytics.vibeDecks.totalButtons ?? 0]);\n return rows;\n }\n if (tab === 'aievents' && analytics.aiEvents) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.aiEvents.total ?? 0]);\n return rows;\n }\n if (tab === 'audit' && analytics.audit) {\n rows.push(['metric', 'value']);\n rows.push(['total', analytics.audit.total ?? 0]);\n return rows;\n }\n if (tab === 'docs' && analytics.docs) {\n rows.push(['metric', 'value']);\n rows.push(['sites', analytics.docs.totalSites ?? 0]);\n rows.push(['pages', analytics.docs.totalPages ?? 0]);\n rows.push(['revisions', analytics.docs.totalRevisions ?? 0]);\n rows.push(['buildSuccessRate', analytics.docs.buildSuccessRate ?? '']);\n return rows;\n }\n // sandbox + others fall back to a sparse summary\n rows.push(['metric', 'value']);\n rows.push(['note', `No CSV serialiser for ${tab} tab yet`]);\n return rows;\n}\n"],"mappings":"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"}
@@ -77,7 +77,7 @@ function W() {
77
77
  children: /* @__PURE__ */ j("div", {
78
78
  className: "text-center space-y-2",
79
79
  children: [/* @__PURE__ */ A("h2", {
80
- className: "text-lg font-semibold text-foreground",
80
+ className: "text-lg font-semibold text-text-primary",
81
81
  children: "Access Denied"
82
82
  }), /* @__PURE__ */ A("p", {
83
83
  className: "text-sm text-text-secondary",
@@ -143,7 +143,7 @@ function W() {
143
143
  }
144
144
  ];
145
145
  return Y && !Z ? /* @__PURE__ */ j(P, {
146
- className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
146
+ className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
147
147
  children: [/* @__PURE__ */ j("button", {
148
148
  type: "button",
149
149
  onClick: $,
@@ -151,7 +151,7 @@ function W() {
151
151
  children: [/* @__PURE__ */ A(S, { className: "size-4" }), I("catalog.backToCatalogs", "Back to Catalogs")]
152
152
  }), /* @__PURE__ */ A(te, { variant: "detail" })]
153
153
  }) : X && !Z ? /* @__PURE__ */ j(P, {
154
- className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
154
+ className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
155
155
  children: [/* @__PURE__ */ j("button", {
156
156
  type: "button",
157
157
  onClick: $,
@@ -163,7 +163,7 @@ function W() {
163
163
  onRetry: () => Ce()
164
164
  })]
165
165
  }) : Z ? /* @__PURE__ */ j(P, {
166
- className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
166
+ className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
167
167
  children: [
168
168
  q && /* @__PURE__ */ A("div", {
169
169
  className: "fixed top-4 left-4 right-4 sm:left-auto z-50 bg-status-success-bg text-status-success-text px-4 py-3 rounded-md shadow-lg",
@@ -194,7 +194,7 @@ function W() {
194
194
  type: "button",
195
195
  onClick: () => Ce(),
196
196
  disabled: Y,
197
- className: "flex items-center justify-center p-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50",
197
+ className: "flex items-center justify-center p-2 bg-bg-sunken text-text-primary rounded-md hover:bg-action-secondary-bg-hover transition-colors disabled:opacity-50",
198
198
  title: I("common.refresh", "Refresh"),
199
199
  children: /* @__PURE__ */ A(ue, { className: `size-4 ${Y ? "animate-spin" : ""}` })
200
200
  }),
@@ -256,7 +256,7 @@ function W() {
256
256
  /* @__PURE__ */ A(t, { className: "size-4" }),
257
257
  e.label,
258
258
  e.badge && /* @__PURE__ */ A("span", {
259
- className: `hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${n ? "bg-action-primary-bg/10 text-action-primary-bg" : "bg-bg-sunken text-text-muted"}`,
259
+ className: `hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${n ? "bg-[var(--color-accent-soft)] text-action-primary-bg" : "bg-bg-sunken text-text-muted"}`,
260
260
  children: e.badge
261
261
  })
262
262
  ]
@@ -525,7 +525,7 @@ function W() {
525
525
  })
526
526
  ]
527
527
  }) : /* @__PURE__ */ j(P, {
528
- className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
528
+ className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
529
529
  children: [/* @__PURE__ */ j("button", {
530
530
  type: "button",
531
531
  onClick: $,
@@ -600,7 +600,7 @@ function q(e, t) {
600
600
  /* @__PURE__ */ j("div", {
601
601
  style: {
602
602
  fontSize: 10,
603
- color: o > 0 ? "rgba(255,255,255,0.75)" : "var(--color-text-muted)",
603
+ color: o > 0 ? "var(--color-action-primary-text)" : "var(--color-text-muted)",
604
604
  marginTop: 2
605
605
  },
606
606
  children: [e.type, e.version ? ` v${e.version}` : ""]
@@ -609,7 +609,7 @@ function q(e, t) {
609
609
  style: {
610
610
  fontSize: 10,
611
611
  marginTop: 3,
612
- color: "rgba(255,255,255,0.85)"
612
+ color: "var(--color-action-primary-text)"
613
613
  },
614
614
  children: [
615
615
  o,
@@ -621,13 +621,13 @@ function q(e, t) {
621
621
  }) },
622
622
  style: {
623
623
  background: o > 0 ? "var(--color-action-primary-bg)" : "var(--color-bg-sunken)",
624
- color: o > 0 ? "#fff" : "var(--color-text-primary)",
624
+ color: o > 0 ? "var(--color-action-primary-text)" : "var(--color-text-primary)",
625
625
  border: `1px solid ${o > 0 ? "transparent" : "var(--color-border-default)"}`,
626
626
  borderRadius: 10,
627
627
  padding: "10px 14px",
628
628
  width: 180,
629
629
  fontSize: 12,
630
- boxShadow: o > 0 ? "0 2px 8px rgba(0,0,0,0.15)" : "none",
630
+ boxShadow: o > 0 ? "var(--shadow-elevation-2)" : "none",
631
631
  textAlign: "center",
632
632
  cursor: "pointer"
633
633
  }