@elevasis/ui 2.66.0 → 2.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.js +3 -3
  3. package/dist/app/index.d.ts +16 -15
  4. package/dist/app/index.js +31 -21
  5. package/dist/auth/index.js +10 -12
  6. package/dist/charts/index.js +10 -12
  7. package/dist/chunk-2MTP3H3A.js +425 -0
  8. package/dist/chunk-3KMDHCAR.js +52 -0
  9. package/dist/chunk-3MEXPLWT.js +265 -0
  10. package/dist/{chunk-XNW3O6QW.js → chunk-5NRJ2BLQ.js} +1 -1
  11. package/dist/chunk-75NOC536.js +2162 -0
  12. package/dist/chunk-76IVMVI3.js +1764 -0
  13. package/dist/chunk-AH52XQB7.js +1 -0
  14. package/dist/chunk-BZZCNLT6.js +12 -0
  15. package/dist/chunk-DLR4SDZW.js +51 -0
  16. package/dist/chunk-FK3K2VK2.js +2103 -0
  17. package/dist/chunk-GBXTRSAU.js +37 -0
  18. package/dist/chunk-HJVPVS57.js +1934 -0
  19. package/dist/{chunk-M535KHLW.js → chunk-JC5W55J3.js} +1 -1
  20. package/dist/{chunk-I7BZVVVU.js → chunk-L3HFJFYF.js} +89 -382
  21. package/dist/chunk-LGKLC5MG.js +44 -0
  22. package/dist/{chunk-4DV4ECMG.js → chunk-N7U24M2J.js} +4 -0
  23. package/dist/chunk-NDHMZT2G.js +383 -0
  24. package/dist/chunk-OOACTYRA.js +10 -0
  25. package/dist/chunk-PDHTXPSF.js +12 -0
  26. package/dist/chunk-QYI5BZKM.js +85 -0
  27. package/dist/{chunk-4OEVLV66.js → chunk-R6NMRXNO.js} +112 -147
  28. package/dist/chunk-SIVUCZXQ.js +1194 -0
  29. package/dist/{chunk-JFBZ6XDW.js → chunk-SNZDFCOQ.js} +3 -49
  30. package/dist/chunk-TGPJNKDU.js +1595 -0
  31. package/dist/chunk-TUMSNGTX.js +35 -0
  32. package/dist/chunk-TYKAKJGW.js +67 -0
  33. package/dist/chunk-UD657ICS.js +589 -0
  34. package/dist/chunk-WPIASV3H.js +194 -0
  35. package/dist/chunk-ZFISGKYW.js +39 -0
  36. package/dist/chunk-ZGCWTWBD.js +16127 -0
  37. package/dist/chunk-ZNKZMK2E.js +4528 -0
  38. package/dist/chunk-ZWS3TCQR.js +11032 -0
  39. package/dist/components/chat/index.js +2 -1
  40. package/dist/components/index.d.ts +23 -11
  41. package/dist/components/index.js +2773 -14
  42. package/dist/components/navigation/index.js +11 -12
  43. package/dist/features/auth/index.d.ts +0 -4
  44. package/dist/features/auth/index.js +12 -13
  45. package/dist/features/clients/index.js +14 -12
  46. package/dist/features/crm/index.d.ts +1371 -15
  47. package/dist/features/crm/index.js +15 -12
  48. package/dist/features/dashboard/index.d.ts +1 -2
  49. package/dist/features/dashboard/index.js +15 -12
  50. package/dist/features/delivery/index.d.ts +0 -4
  51. package/dist/features/delivery/index.js +15 -12
  52. package/dist/features/knowledge/index.js +10 -12
  53. package/dist/features/lead-gen/index.d.ts +35 -15
  54. package/dist/features/lead-gen/index.js +16 -12
  55. package/dist/features/monitoring/index.js +15 -12
  56. package/dist/features/monitoring/requests/index.js +13 -13
  57. package/dist/features/operations/index.d.ts +1 -2
  58. package/dist/features/operations/index.js +21 -12
  59. package/dist/features/public-agent-chat/index.js +2 -1
  60. package/dist/features/seo/index.js +2 -1
  61. package/dist/features/settings/index.d.ts +0 -4
  62. package/dist/features/settings/index.js +14 -12
  63. package/dist/hooks/access/index.js +10 -12
  64. package/dist/hooks/delivery/index.d.ts +0 -4
  65. package/dist/hooks/delivery/index.js +2 -23
  66. package/dist/hooks/index.d.ts +13 -7
  67. package/dist/hooks/index.js +10 -12
  68. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +1 -2
  69. package/dist/hooks/published.d.ts +13 -7
  70. package/dist/hooks/published.js +10 -12
  71. package/dist/initialization/index.d.ts +1 -5
  72. package/dist/knowledge/index.d.ts +1 -2
  73. package/dist/knowledge/index.js +15 -13
  74. package/dist/layout/index.js +14 -12
  75. package/dist/organization/index.d.ts +3 -3
  76. package/dist/organization/index.js +1 -21
  77. package/dist/profile/index.d.ts +0 -4
  78. package/dist/provider/index.d.ts +2 -7
  79. package/dist/provider/index.js +10 -12
  80. package/dist/provider/published.d.ts +2 -7
  81. package/dist/provider/published.js +10 -12
  82. package/dist/supabase/index.d.ts +0 -8
  83. package/dist/test-utils/index.d.ts +5 -0
  84. package/dist/test-utils/index.js +5 -5
  85. package/dist/test-utils/setup-integration.js +1 -1
  86. package/dist/test-utils/setup.js +1 -1
  87. package/dist/theme/index.js +2 -1
  88. package/dist/typeform/index.js +2049 -1
  89. package/dist/types/index.d.ts +13 -7
  90. package/dist/utils/index.d.ts +1 -2
  91. package/dist/utils/index.js +1 -1
  92. package/package.json +5 -5
  93. package/dist/chunk-ANNM5R7S.js +0 -51404
  94. package/dist/chunk-AUDNF2Q7.js +0 -2050
  95. package/dist/index.css +0 -659
  96. package/dist/index.d.ts +0 -17888
  97. package/dist/index.js +0 -30
  98. package/dist/{chunk-GMXGDO3I.js → chunk-MISHPEJX.js} +1 -1
@@ -0,0 +1,1764 @@
1
+ import { AppShellLoader } from './chunk-GBXTRSAU.js';
2
+ import { FilterBar } from './chunk-PDHTXPSF.js';
3
+ import { CenteredErrorState, StatsCardSkeleton, CyberAreaChart, TrendIndicator, DetailCardSkeleton, useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, EmptyState, useMarkAsRead, useExecutionLogsFilters, useExecutionLogs, PageTitleCaption, useExecutionHealth, useErrorAnalysis, useTimeRangeDates, useErrorDetail, useResolveErrorsByExecution, useResources, CustomModal, JsonViewer, useCostTrends, useCostSummary, useCostByModel, useCostBreakdown, CostTrendChart, useActivityFilters, useActivityTrend, useActivities, ActivityTrendChart, useNotifications, useMarkAllAsRead } from './chunk-ZGCWTWBD.js';
4
+ import { CardHeader } from './chunk-62GVNH5U.js';
5
+ import { formatDuration } from './chunk-BLXJEIQS.js';
6
+ import { PAGE_SIZE_DEFAULT } from './chunk-L3HFJFYF.js';
7
+ import { formatBucketTime, getTimeRangeDates } from './chunk-Y6I3IC45.js';
8
+ import { useRouterContext } from './chunk-Q7DJKLEN.js';
9
+ import { useState, useMemo, useCallback } from 'react';
10
+ import { Table, Text, Badge, Tooltip, Card, Group, Select, SegmentedControl, Button, TextInput, Stack, Paper, Center, Loader, ActionIcon, NumberFormatter, Box, Alert, Switch, Pagination, UnstyledButton, Title, Divider, Code, CopyButton, Accordion } from '@mantine/core';
11
+ import { IconFilterOff, IconCircleCheck, IconThumbDown, IconThumbUp, IconClock, IconCircleX, IconSearch, IconArrowUpRight, IconAlertTriangle, IconAlertCircle, IconExternalLink, IconChartPie, IconHeartbeat, IconDownload, IconCpu, IconTrendingUp, IconChartBar, IconCash, IconInfoCircle, IconExclamationCircle, IconBug, IconChecks, IconCircle, IconCircleFilled, IconCheck, IconCopy, IconCircleDashed, IconActivity, IconArrowUp, IconArrowDown, IconFileOff, IconRobot, IconKey, IconUser } from '@tabler/icons-react';
12
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
+ import { formatDistanceToNow } from 'date-fns';
14
+
15
+ function formatStartTime(timestamp) {
16
+ return new Date(timestamp).toLocaleString("en-US", {
17
+ month: "short",
18
+ day: "numeric",
19
+ hour: "numeric",
20
+ minute: "2-digit"
21
+ });
22
+ }
23
+ function getStatusConfig(status) {
24
+ switch (status) {
25
+ case "running":
26
+ return {
27
+ icon: /* @__PURE__ */ jsx(IconCircle, { size: 14, color: "var(--color-primary)" }),
28
+ label: "Running",
29
+ color: "blue"
30
+ };
31
+ case "completed":
32
+ return {
33
+ icon: /* @__PURE__ */ jsx(IconCircleCheck, { size: 14, color: "var(--color-success)" }),
34
+ label: "Completed",
35
+ color: "green"
36
+ };
37
+ case "failed":
38
+ return {
39
+ icon: /* @__PURE__ */ jsx(IconCircleX, { size: 14, color: "var(--color-error)" }),
40
+ label: "Failed",
41
+ color: "red"
42
+ };
43
+ case "warning":
44
+ return {
45
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 14, color: "var(--color-warning)" }),
46
+ label: "Warning",
47
+ color: "yellow"
48
+ };
49
+ case "pending":
50
+ default:
51
+ return {
52
+ icon: /* @__PURE__ */ jsx(IconCircle, { size: 14, color: "var(--mantine-color-gray-6)" }),
53
+ label: "Pending",
54
+ color: "gray"
55
+ };
56
+ }
57
+ }
58
+ function LoadingState() {
59
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
60
+ }
61
+ function EmptyState2() {
62
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "xs", children: [
63
+ /* @__PURE__ */ jsx(IconFileOff, { size: 48, color: "var(--color-text-subtle)" }),
64
+ /* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, c: "dimmed", children: "No executions found" }),
65
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Executions will appear here when workflows or agents are run" })
66
+ ] }) });
67
+ }
68
+ function ExecutionLogsTable({ executions, isLoading, onRowClick }) {
69
+ const handleRowClick = (execution) => {
70
+ onRowClick?.({
71
+ resourceType: execution.resourceType,
72
+ resourceId: execution.resourceId,
73
+ executionId: execution.id
74
+ });
75
+ };
76
+ return /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
77
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
78
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
79
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
80
+ /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
81
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Duration" }),
82
+ /* @__PURE__ */ jsx(Table.Th, { ta: "center", children: "Env" }),
83
+ /* @__PURE__ */ jsx(Table.Th, { ta: "center", children: "Version" })
84
+ ] }) }),
85
+ /* @__PURE__ */ jsx(Table.Tbody, { children: isLoading ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: 6, children: /* @__PURE__ */ jsx(LoadingState, {}) }) }) : executions.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: 6, children: /* @__PURE__ */ jsx(EmptyState2, {}) }) }) : executions.map((execution) => {
86
+ const statusConfig3 = getStatusConfig(execution.status);
87
+ return /* @__PURE__ */ jsxs(
88
+ Table.Tr,
89
+ {
90
+ style: { cursor: onRowClick ? "pointer" : void 0 },
91
+ onClick: () => handleRowClick(execution),
92
+ children: [
93
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 200 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 1, title: execution.resourceName, children: execution.resourceName }) }),
94
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: statusConfig3.color, variant: "light", size: "sm", leftSection: statusConfig3.icon, children: statusConfig3.label }) }),
95
+ /* @__PURE__ */ jsx(Table.Td, { style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", children: formatStartTime(execution.startTime) }) }),
96
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: execution.status === "running" ? "dimmed" : void 0, children: formatDuration(execution.duration) }) }),
97
+ /* @__PURE__ */ jsx(Table.Td, { ta: "center", children: /* @__PURE__ */ jsx(Badge, { color: execution.resourceStatus === "prod" ? "green" : "gray", variant: "light", size: "sm", children: execution.resourceStatus.toUpperCase() }) }),
98
+ /* @__PURE__ */ jsx(Table.Td, { ta: "center", children: /* @__PURE__ */ jsx(
99
+ Tooltip,
100
+ {
101
+ label: `Resource: ${execution.resourceVersion ?? "-"}
102
+ API: ${execution.apiVersion ?? "-"}
103
+ SDK: ${execution.sdkVersion ?? "-"}`,
104
+ multiline: true,
105
+ position: "left",
106
+ children: /* @__PURE__ */ jsx(Text, { size: "sm", ff: "monospace", c: "dimmed", style: { cursor: "help" }, children: execution.resourceVersion ?? "-" })
107
+ }
108
+ ) })
109
+ ]
110
+ },
111
+ execution.id
112
+ );
113
+ }) })
114
+ ] });
115
+ }
116
+ var resourceOptions = [{ value: "", label: "All Resources" }];
117
+ var statusOptions = [
118
+ { value: "all", label: "All" },
119
+ { value: "running", label: "Running" },
120
+ { value: "completed", label: "Completed" },
121
+ { value: "warning", label: "Warning" },
122
+ { value: "failed", label: "Failed" }
123
+ ];
124
+ var environmentOptions = [
125
+ { value: "all", label: "All" },
126
+ { value: "dev", label: "Dev" },
127
+ { value: "prod", label: "Prod" }
128
+ ];
129
+ function ExecutionLogsFilters({ filters, onFilterChange, onReset }) {
130
+ const hasActiveFilters = filters.resourceId !== void 0 || filters.status !== "all" || filters.resourceStatus !== "all";
131
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "wrap", children: [
132
+ /* @__PURE__ */ jsx(
133
+ Select,
134
+ {
135
+ placeholder: "Resource",
136
+ data: resourceOptions,
137
+ value: filters.resourceId ?? "",
138
+ onChange: (value) => onFilterChange("resourceId", value === "" || value === null ? void 0 : value),
139
+ style: { minWidth: 180 }
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsx(
143
+ SegmentedControl,
144
+ {
145
+ data: statusOptions,
146
+ value: filters.status,
147
+ onChange: (value) => onFilterChange("status", value)
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsx(
151
+ SegmentedControl,
152
+ {
153
+ data: environmentOptions,
154
+ value: filters.resourceStatus,
155
+ onChange: (value) => onFilterChange("resourceStatus", value)
156
+ }
157
+ ),
158
+ hasActiveFilters && /* @__PURE__ */ jsx(Button, { variant: "subtle", color: "gray", leftSection: /* @__PURE__ */ jsx(IconFilterOff, { size: 16 }), onClick: onReset, children: "Reset" })
159
+ ] }) });
160
+ }
161
+ var statusConfig = {
162
+ success: { color: "green", icon: IconCircleCheck },
163
+ failure: { color: "red", icon: IconCircleX },
164
+ pending: { color: "yellow", icon: IconClock },
165
+ approved: { color: "green", icon: IconThumbUp },
166
+ rejected: { color: "red", icon: IconThumbDown },
167
+ completed: { color: "blue", icon: IconCircleCheck }
168
+ };
169
+ var activityTypeLabels = {
170
+ workflow_execution: "Workflow",
171
+ agent_run: "Agent",
172
+ hitl_action: "HITL Action",
173
+ webhook_received: "Webhook In",
174
+ webhook_executed: "Webhook Out",
175
+ webhook_failed: "Webhook Fail",
176
+ credential_change: "Credential",
177
+ credential_read: "Credential Read",
178
+ api_key_change: "API Key",
179
+ agent_access_grant_change: "Agent Grant",
180
+ deployment_change: "Deployment",
181
+ membership_change: "Membership"
182
+ };
183
+ function getActorDisplay(actorType) {
184
+ switch (actorType) {
185
+ case "user":
186
+ return { label: "User", color: "blue", icon: IconUser };
187
+ case "api_key":
188
+ return { label: "API Key", color: "violet", icon: IconKey };
189
+ default:
190
+ return { label: "System", color: "gray", icon: IconRobot };
191
+ }
192
+ }
193
+ var COLUMN_COUNT = 6;
194
+ function LoadingState2() {
195
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
196
+ }
197
+ function EmptyState3() {
198
+ return /* @__PURE__ */ jsx(Center, { py: "xl", children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "xs", children: [
199
+ /* @__PURE__ */ jsx(IconFileOff, { size: 48, color: "var(--color-text-subtle)" }),
200
+ /* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, c: "dimmed", children: "No activities found" }),
201
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Activities will appear here as workflows and agents run" })
202
+ ] }) });
203
+ }
204
+ function ActivityTable({ activities, isLoading, onRowClick }) {
205
+ return /* @__PURE__ */ jsxs(Table, { children: [
206
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
207
+ /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
208
+ /* @__PURE__ */ jsx(Table.Th, { children: "Type" }),
209
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
210
+ /* @__PURE__ */ jsx(Table.Th, { children: "Actor" }),
211
+ /* @__PURE__ */ jsx(Table.Th, { children: "Entity" }),
212
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Time" })
213
+ ] }) }),
214
+ /* @__PURE__ */ jsx(Table.Tbody, { children: isLoading ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: COLUMN_COUNT, children: /* @__PURE__ */ jsx(LoadingState2, {}) }) }) : activities.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, { colSpan: COLUMN_COUNT, children: /* @__PURE__ */ jsx(EmptyState3, {}) }) }) : activities.map((activity) => {
215
+ const config = statusConfig[activity.status];
216
+ const StatusIcon = config.icon;
217
+ const actor = getActorDisplay(activity.actorType);
218
+ const ActorIcon = actor.icon;
219
+ return /* @__PURE__ */ jsxs(
220
+ Table.Tr,
221
+ {
222
+ style: { cursor: onRowClick ? "pointer" : void 0 },
223
+ onClick: () => onRowClick?.(activity),
224
+ children: [
225
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 250 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 1, title: activity.title, children: activity.title }) }),
226
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", size: "sm", color: "gray", children: activityTypeLabels[activity.activityType] }) }),
227
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: config.color, variant: "light", size: "sm", leftSection: /* @__PURE__ */ jsx(StatusIcon, { size: 14 }), children: activity.status }) }),
228
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: actor.color, variant: "light", size: "sm", leftSection: /* @__PURE__ */ jsx(ActorIcon, { size: 14 }), children: actor.label }) }),
229
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 200 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", lineClamp: 1, title: activity.entityName || activity.entityId, children: activity.entityName || activity.entityId }) }),
230
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatDistanceToNow(activity.occurredAt, { addSuffix: true }) }) })
231
+ ]
232
+ },
233
+ activity.id
234
+ );
235
+ }) })
236
+ ] });
237
+ }
238
+ var activityTypeOptions = [
239
+ { value: "all", label: "All Types" },
240
+ { value: "workflow_execution", label: "Workflow Executions" },
241
+ { value: "agent_run", label: "Agent Runs" },
242
+ { value: "hitl_action", label: "HITL Actions" },
243
+ { value: "webhook_received", label: "Webhook Received" },
244
+ { value: "webhook_executed", label: "Webhook Executed" },
245
+ { value: "webhook_failed", label: "Webhook Failed" },
246
+ { value: "credential_change", label: "Credential Changes" },
247
+ { value: "credential_read", label: "Credential Reads" },
248
+ { value: "api_key_change", label: "API Key Changes" },
249
+ { value: "agent_access_grant_change", label: "Agent Grant Changes" },
250
+ { value: "deployment_change", label: "Deployment Changes" },
251
+ { value: "membership_change", label: "Membership Changes" }
252
+ ];
253
+ var statusOptions2 = [
254
+ { value: "all", label: "All Statuses" },
255
+ { value: "success", label: "Success" },
256
+ { value: "failure", label: "Failure" },
257
+ { value: "pending", label: "Pending" },
258
+ { value: "approved", label: "Approved" },
259
+ { value: "rejected", label: "Rejected" },
260
+ { value: "completed", label: "Completed" }
261
+ ];
262
+ function ActivityFilters({ filters, onFilterChange, onReset }) {
263
+ return /* @__PURE__ */ jsxs(
264
+ FilterBar,
265
+ {
266
+ actions: /* @__PURE__ */ jsx(Button, { variant: "subtle", color: "gray", leftSection: /* @__PURE__ */ jsx(IconFilterOff, { size: 16 }), onClick: onReset, children: "Reset" }),
267
+ children: [
268
+ /* @__PURE__ */ jsx(
269
+ Select,
270
+ {
271
+ placeholder: "Activity Type",
272
+ data: activityTypeOptions,
273
+ value: filters.activityType || "all",
274
+ onChange: (value) => onFilterChange("activityType", value),
275
+ style: { flex: 1, minWidth: 200 }
276
+ }
277
+ ),
278
+ /* @__PURE__ */ jsx(
279
+ Select,
280
+ {
281
+ placeholder: "Status",
282
+ data: statusOptions2,
283
+ value: filters.status || "all",
284
+ onChange: (value) => onFilterChange("status", value),
285
+ style: { flex: 1, minWidth: 150 }
286
+ }
287
+ ),
288
+ /* @__PURE__ */ jsx(
289
+ TextInput,
290
+ {
291
+ placeholder: "Search by name...",
292
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
293
+ value: filters.search || "",
294
+ onChange: (event) => onFilterChange("search", event.currentTarget.value),
295
+ style: { flex: 1, minWidth: 200 }
296
+ }
297
+ )
298
+ ]
299
+ }
300
+ );
301
+ }
302
+ var statusConfig2 = {
303
+ success: { color: "green", icon: IconCircleCheck },
304
+ failure: { color: "red", icon: IconCircleX },
305
+ pending: { color: "yellow", icon: IconClock },
306
+ approved: { color: "green", icon: IconThumbUp },
307
+ rejected: { color: "red", icon: IconThumbDown },
308
+ completed: { color: "blue", icon: IconCircleCheck }
309
+ };
310
+ function getActorDisplay2(actorType) {
311
+ switch (actorType) {
312
+ case "user":
313
+ return { label: "User", color: "blue", icon: IconUser };
314
+ case "api_key":
315
+ return { label: "API Key", color: "violet", icon: IconKey };
316
+ default:
317
+ return { label: "System", color: "gray", icon: IconRobot };
318
+ }
319
+ }
320
+ function getNavigationPath(activity) {
321
+ switch (activity.activityType) {
322
+ case "workflow_execution":
323
+ return `/operations/resources/workflow/${activity.entityId}`;
324
+ case "agent_run":
325
+ return `/operations/resources/agent/${activity.entityId}`;
326
+ case "hitl_action":
327
+ return "/command-queue";
328
+ case "credential_change":
329
+ case "credential_read":
330
+ return "/settings/credentials";
331
+ case "api_key_change":
332
+ return "/settings/api-keys";
333
+ case "deployment_change":
334
+ return "/settings/deployments";
335
+ case "membership_change":
336
+ return "/settings/organization";
337
+ default:
338
+ return null;
339
+ }
340
+ }
341
+ function ActivityCard({ activity }) {
342
+ const config = statusConfig2[activity.status];
343
+ const StatusIcon = config.icon;
344
+ const { navigate } = useRouterContext();
345
+ const navigationPath = getNavigationPath(activity);
346
+ const isClickable = navigationPath !== null;
347
+ const actor = getActorDisplay2(activity.actorType);
348
+ const ActorIcon = actor.icon;
349
+ const handleClick = () => {
350
+ if (navigationPath) {
351
+ navigate(navigationPath);
352
+ }
353
+ };
354
+ return /* @__PURE__ */ jsx(
355
+ Card,
356
+ {
357
+ withBorder: true,
358
+ style: {
359
+ cursor: isClickable ? "pointer" : "default",
360
+ transition: "box-shadow var(--duration-fast) var(--easing)"
361
+ },
362
+ onClick: handleClick,
363
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
364
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
365
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", style: { flex: 1, minWidth: 0 }, children: [
366
+ /* @__PURE__ */ jsx(StatusIcon, { size: 16, color: `var(--mantine-color-${config.color}-6)` }),
367
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, style: { flex: 1, fontFamily: "var(--elevasis-font-family-subtitle)" }, truncate: true, children: activity.title })
368
+ ] }),
369
+ /* @__PURE__ */ jsx(Badge, { size: "sm", color: config.color, variant: "light", children: activity.status })
370
+ ] }),
371
+ activity.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: activity.description }),
372
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
373
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, style: { flex: 1 }, children: activity.entityName || activity.entityId }),
374
+ /* @__PURE__ */ jsx(Badge, { size: "xs", color: actor.color, variant: "dot", leftSection: /* @__PURE__ */ jsx(ActorIcon, { size: 10 }), children: actor.label }),
375
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: "nowrap" }, children: formatDistanceToNow(activity.occurredAt, { addSuffix: true }) })
376
+ ] })
377
+ ] })
378
+ }
379
+ );
380
+ }
381
+ function ErrorAnalysisCard({ data, isLoading, error }) {
382
+ const topFailures = data?.topFailingResources.map((res) => ({
383
+ id: res.resourceId,
384
+ name: res.name,
385
+ errorCount: res.errorCount,
386
+ failureRate: res.failureRate
387
+ })) ?? [];
388
+ if (error) {
389
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load error analysis metrics" }) });
390
+ }
391
+ if (isLoading) {
392
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
393
+ }
394
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
395
+ /* @__PURE__ */ jsx(
396
+ CardHeader,
397
+ {
398
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 18 }),
399
+ title: "Error Analysis",
400
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
401
+ }
402
+ ),
403
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "sm", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Top Failing Resources" }),
404
+ /* @__PURE__ */ jsxs(Table, { children: [
405
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
406
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
407
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Errors" }),
408
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "% Failed" }),
409
+ /* @__PURE__ */ jsx(Table.Th, {})
410
+ ] }) }),
411
+ /* @__PURE__ */ jsx(Table.Tbody, { children: topFailures.map((resource) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
412
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
413
+ /* @__PURE__ */ jsx(IconAlertCircle, { size: 16, color: "var(--color-error)" }),
414
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: resource.name })
415
+ ] }) }),
416
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Badge, { color: "red", variant: "light", children: resource.errorCount }) }),
417
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: resource.failureRate > 10 ? "red" : "dimmed", children: [
418
+ resource.failureRate,
419
+ "%"
420
+ ] }) }),
421
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 }) }) })
422
+ ] }, resource.id)) })
423
+ ] })
424
+ ] });
425
+ }
426
+ function ExecutionBreakdownTable({ data, isLoading, error }) {
427
+ if (error) {
428
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load execution breakdown" }) });
429
+ }
430
+ if (isLoading) {
431
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
432
+ }
433
+ const totalExecutions = data?.totalExecutions ?? 0;
434
+ const statusCounts = data?.statusCounts ?? { success: 0, failed: 0, pending: 0, warning: 0 };
435
+ const p95Duration = data?.p95Duration ?? 0;
436
+ const statusRows = [
437
+ {
438
+ status: "Completed",
439
+ count: statusCounts.success,
440
+ percentage: totalExecutions > 0 ? statusCounts.success / totalExecutions * 100 : 0,
441
+ avgDuration: p95Duration * 0.85,
442
+ // Estimate avg duration from P95
443
+ color: "green"
444
+ },
445
+ {
446
+ status: "Warning",
447
+ count: statusCounts.warning,
448
+ percentage: totalExecutions > 0 ? statusCounts.warning / totalExecutions * 100 : 0,
449
+ avgDuration: p95Duration * 0.85,
450
+ // Warning executions completed, similar to success
451
+ color: "yellow"
452
+ },
453
+ {
454
+ status: "Failed",
455
+ count: statusCounts.failed,
456
+ percentage: totalExecutions > 0 ? statusCounts.failed / totalExecutions * 100 : 0,
457
+ avgDuration: p95Duration * 0.6,
458
+ // Failed executions typically shorter
459
+ color: "red"
460
+ },
461
+ {
462
+ status: "Running",
463
+ count: 0,
464
+ // No running count in current data structure
465
+ percentage: 0,
466
+ avgDuration: 0,
467
+ color: "blue"
468
+ },
469
+ {
470
+ status: "Pending",
471
+ count: statusCounts.pending,
472
+ percentage: totalExecutions > 0 ? statusCounts.pending / totalExecutions * 100 : 0,
473
+ avgDuration: 0,
474
+ // Pending has no duration
475
+ color: "gray"
476
+ }
477
+ ];
478
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
479
+ /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconChartPie, { size: 18 }), title: "Execution Status Breakdown" }),
480
+ /* @__PURE__ */ jsxs(Table, { children: [
481
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
482
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
483
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Count" }),
484
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Percentage" }),
485
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Avg Duration" })
486
+ ] }) }),
487
+ /* @__PURE__ */ jsx(Table.Tbody, { children: statusRows.map((row) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
488
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { color: row.color, variant: "light", children: row.status }) }),
489
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: row.count.toLocaleString() }) }),
490
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
491
+ row.percentage.toFixed(1),
492
+ "%"
493
+ ] }) }),
494
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: row.avgDuration > 0 ? `${(row.avgDuration / 1e3).toFixed(1)}s` : "-" }) })
495
+ ] }, row.status)) })
496
+ ] })
497
+ ] });
498
+ }
499
+ function ExecutionHealthCard({ data, isLoading, error }) {
500
+ const successRate = data?.successRate ?? 0;
501
+ const p95Duration = data?.p95Duration ?? 0;
502
+ const totalExecutions = data?.totalExecutions ?? 0;
503
+ const failedCount = data?.statusCounts.failed ?? 0;
504
+ const warningCount = data?.statusCounts.warning ?? 0;
505
+ const trendData = data?.trendData.map((d) => ({
506
+ hour: formatBucketTime(d.time, data?.granularity ?? "hour"),
507
+ errors: d.errorCount,
508
+ warnings: d.warningCount
509
+ })) ?? [];
510
+ const hasExecutions = totalExecutions > 0;
511
+ const statusColor = hasExecutions ? successRate >= 98 ? "green" : successRate >= 95 ? "yellow" : "red" : "gray";
512
+ const statusLabel = hasExecutions ? successRate >= 98 ? "Healthy" : successRate >= 95 ? "Warning" : "Critical" : "No Data";
513
+ if (error) {
514
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load execution health metrics" }) });
515
+ }
516
+ if (isLoading) {
517
+ return /* @__PURE__ */ jsx(StatsCardSkeleton, {});
518
+ }
519
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
520
+ /* @__PURE__ */ jsx(
521
+ CardHeader,
522
+ {
523
+ icon: /* @__PURE__ */ jsx(IconHeartbeat, { size: 18 }),
524
+ title: "Execution Health",
525
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
526
+ }
527
+ ),
528
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "md", children: [
529
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
530
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
531
+ /* @__PURE__ */ jsx(
532
+ Text,
533
+ {
534
+ size: "xl",
535
+ fw: 700,
536
+ c: "var(--color-error)",
537
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
538
+ children: failedCount
539
+ }
540
+ ),
541
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "failures" })
542
+ ] }),
543
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
544
+ /* @__PURE__ */ jsx(
545
+ Text,
546
+ {
547
+ size: "xl",
548
+ fw: 700,
549
+ c: warningCount > 0 ? "yellow" : "dimmed",
550
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
551
+ children: warningCount
552
+ }
553
+ ),
554
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "warnings" })
555
+ ] }),
556
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
557
+ /* @__PURE__ */ jsxs(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: [
558
+ (p95Duration / 1e3).toFixed(1),
559
+ "s"
560
+ ] }),
561
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "P95" })
562
+ ] })
563
+ ] }),
564
+ /* @__PURE__ */ jsx(Badge, { size: "md", variant: "dot", color: statusColor, children: statusLabel })
565
+ ] }),
566
+ /* @__PURE__ */ jsx(
567
+ CyberAreaChart,
568
+ {
569
+ data: trendData,
570
+ series: [
571
+ { dataKey: "warnings", color: "yellow", name: "Warnings" },
572
+ { dataKey: "errors", color: "red", name: "Errors" }
573
+ ],
574
+ xDataKey: "hour",
575
+ height: 200,
576
+ yDomain: [0, "auto"]
577
+ }
578
+ ),
579
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mt: "sm", children: [
580
+ totalExecutions.toLocaleString(),
581
+ " total executions"
582
+ ] })
583
+ ] });
584
+ }
585
+ function CostByModelTable({ data, isLoading, error }) {
586
+ const [sortField, setSortField] = useState("cost");
587
+ const [sortDirection, setSortDirection] = useState("desc");
588
+ const totalCost = data?.totalCostUsd ?? 0;
589
+ const tableData = data?.models.map((m) => ({
590
+ model: m.model,
591
+ cost: m.totalCostUsd,
592
+ percentage: totalCost > 0 ? m.totalCostUsd / totalCost * 100 : 0,
593
+ calls: m.callCount,
594
+ avgCost: m.avgCostPerCall,
595
+ inputTokens: m.totalInputTokens,
596
+ outputTokens: m.totalOutputTokens
597
+ })) ?? [];
598
+ const sortedData = [...tableData].sort((a, b) => {
599
+ const aValue = a[sortField];
600
+ const bValue = b[sortField];
601
+ if (typeof aValue === "string" && typeof bValue === "string") {
602
+ return sortDirection === "asc" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
603
+ }
604
+ return sortDirection === "asc" ? aValue - bValue : bValue - aValue;
605
+ });
606
+ const highestCost = Math.max(...tableData.map((d) => d.cost), 0);
607
+ const handleSort = (field) => {
608
+ if (sortField === field) {
609
+ setSortDirection(sortDirection === "asc" ? "desc" : "asc");
610
+ } else {
611
+ setSortField(field);
612
+ setSortDirection("desc");
613
+ }
614
+ };
615
+ const handleExport = () => {
616
+ if (!data) return;
617
+ const csvContent = [
618
+ ["Model", "Cost ($)", "Percentage (%)", "Calls", "Avg Cost/Call ($)", "Input Tokens", "Output Tokens"],
619
+ ...sortedData.map((d) => [
620
+ d.model,
621
+ d.cost.toFixed(4),
622
+ d.percentage.toFixed(2),
623
+ d.calls,
624
+ d.avgCost.toFixed(6),
625
+ d.inputTokens,
626
+ d.outputTokens
627
+ ]),
628
+ ["Total", totalCost.toFixed(4), "100.00", data.totalCallCount, "", "", ""]
629
+ ].map((row) => row.join(",")).join("\n");
630
+ const blob = new Blob([csvContent], { type: "text/csv" });
631
+ const url = URL.createObjectURL(blob);
632
+ const link = document.createElement("a");
633
+ link.href = url;
634
+ link.download = `cost-by-model-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`;
635
+ link.click();
636
+ URL.revokeObjectURL(url);
637
+ };
638
+ const SortIcon = ({ field }) => {
639
+ if (sortField !== field) return null;
640
+ return sortDirection === "asc" ? /* @__PURE__ */ jsx(IconArrowUp, { size: 14 }) : /* @__PURE__ */ jsx(IconArrowDown, { size: 14 });
641
+ };
642
+ const formatModelName = (model) => {
643
+ const parts = model.split("/");
644
+ const modelName = parts.length > 1 ? parts[1] : model;
645
+ return modelName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
646
+ };
647
+ if (error) {
648
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load cost by model" }) });
649
+ }
650
+ if (isLoading) {
651
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
652
+ }
653
+ return /* @__PURE__ */ jsxs(Paper, { children: [
654
+ /* @__PURE__ */ jsx(
655
+ CardHeader,
656
+ {
657
+ icon: /* @__PURE__ */ jsx(IconCpu, { size: 18 }),
658
+ title: "Cost by Model",
659
+ rightSection: /* @__PURE__ */ jsx(Button, { variant: "subtle", size: "xs", leftSection: /* @__PURE__ */ jsx(IconDownload, { size: 14 }), onClick: handleExport, children: "Export CSV" })
660
+ }
661
+ ),
662
+ /* @__PURE__ */ jsxs(Table, { children: [
663
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
664
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("model"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
665
+ "Model",
666
+ /* @__PURE__ */ jsx(SortIcon, { field: "model" })
667
+ ] }) }),
668
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("cost"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
669
+ "Cost",
670
+ /* @__PURE__ */ jsx(SortIcon, { field: "cost" })
671
+ ] }) }),
672
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("percentage"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
673
+ "Percentage",
674
+ /* @__PURE__ */ jsx(SortIcon, { field: "percentage" })
675
+ ] }) }),
676
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("calls"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
677
+ "Calls",
678
+ /* @__PURE__ */ jsx(SortIcon, { field: "calls" })
679
+ ] }) }),
680
+ /* @__PURE__ */ jsx(Table.Th, { style: { cursor: "pointer" }, onClick: () => handleSort("avgCost"), children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
681
+ "Avg Cost/Call",
682
+ /* @__PURE__ */ jsx(SortIcon, { field: "avgCost" })
683
+ ] }) })
684
+ ] }) }),
685
+ /* @__PURE__ */ jsxs(Table.Tbody, { children: [
686
+ sortedData.map((row) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
687
+ /* @__PURE__ */ jsxs(Table.Td, { children: [
688
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: row.cost === highestCost ? 600 : 400, children: formatModelName(row.model) }),
689
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: row.model })
690
+ ] }),
691
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", fw: row.cost === highestCost ? 600 : 400, children: [
692
+ "$",
693
+ row.cost.toFixed(4)
694
+ ] }) }),
695
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Badge, { color: row.percentage > 30 ? "red" : row.percentage > 15 ? "yellow" : "gray", children: [
696
+ row.percentage.toFixed(1),
697
+ "%"
698
+ ] }) }),
699
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: row.calls.toLocaleString() }) }),
700
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
701
+ "$",
702
+ row.avgCost.toFixed(6)
703
+ ] }) })
704
+ ] }, row.model)),
705
+ tableData.length > 0 && /* @__PURE__ */ jsxs(Table.Tr, { children: [
706
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: "Total" }) }),
707
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", fw: 700, children: [
708
+ "$",
709
+ totalCost.toFixed(4)
710
+ ] }) }),
711
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { children: "100.0%" }) }),
712
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: (data?.totalCallCount ?? 0).toLocaleString() }) }),
713
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "-" }) })
714
+ ] })
715
+ ] })
716
+ ] }),
717
+ tableData.length === 0 && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", py: "xl", children: "No cost data available for this time period" })
718
+ ] });
719
+ }
720
+ function BusinessImpactCard({
721
+ impactData,
722
+ summaryData,
723
+ trendsData,
724
+ data,
725
+ isLoading,
726
+ error,
727
+ laborRate = 75
728
+ }) {
729
+ const businessData = impactData ?? data;
730
+ const laborCostSavings = businessData?.totalSavingsUsd ?? 0;
731
+ const platformCost = businessData?.totalCostUsd ?? 0;
732
+ const netSavings = businessData?.netSavingsUsd ?? 0;
733
+ const roi = businessData?.roi ?? 0;
734
+ const hoursSaved = Math.round(laborCostSavings / laborRate);
735
+ const previousCost = summaryData?.previous.totalCostUsd ?? platformCost;
736
+ const previousSavings = laborCostSavings * (previousCost > 0 ? (summaryData?.previous.totalCostUsd ?? platformCost) / platformCost : 0.8);
737
+ const previousHoursSaved = Math.round(previousSavings / laborRate);
738
+ const totalTrendCost = trendsData?.totalCostUsd ?? 0;
739
+ const trendData = (trendsData?.trendData ?? []).map((point) => {
740
+ const date = new Date(point.time);
741
+ const timeLabel = trendsData?.granularity === "hour" ? date.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" }) : date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
742
+ const proportion = totalTrendCost > 0 ? point.totalCostUsd / totalTrendCost : 1 / (trendsData?.trendData.length ?? 1);
743
+ return {
744
+ time: timeLabel,
745
+ savings: laborCostSavings * proportion
746
+ };
747
+ });
748
+ if (error) {
749
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load business impact metrics" }) });
750
+ }
751
+ if (isLoading) {
752
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) });
753
+ }
754
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
755
+ /* @__PURE__ */ jsx(
756
+ CardHeader,
757
+ {
758
+ icon: /* @__PURE__ */ jsx(IconTrendingUp, { size: 18 }),
759
+ title: "Business Impact",
760
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
761
+ }
762
+ ),
763
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "md", children: [
764
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
765
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
766
+ /* @__PURE__ */ jsx(
767
+ Text,
768
+ {
769
+ size: "xl",
770
+ fw: 700,
771
+ c: "var(--color-primary)",
772
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
773
+ children: hoursSaved
774
+ }
775
+ ),
776
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "hrs saved" }),
777
+ /* @__PURE__ */ jsx(TrendIndicator, { current: hoursSaved, previous: previousHoursSaved })
778
+ ] }),
779
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
780
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: laborCostSavings, thousandSeparator: true }) }),
781
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "labor saved" })
782
+ ] })
783
+ ] }),
784
+ /* @__PURE__ */ jsx(
785
+ Badge,
786
+ {
787
+ size: "lg",
788
+ variant: roi > 0 ? "dot" : "light",
789
+ color: roi > 1e3 ? "green" : roi > 500 ? "yellow" : "gray",
790
+ children: roi > 0 ? `${roi.toFixed(0)}x ROI` : "N/A"
791
+ }
792
+ )
793
+ ] }),
794
+ /* @__PURE__ */ jsx(
795
+ CyberAreaChart,
796
+ {
797
+ data: trendData,
798
+ series: [{ dataKey: "savings", color: "blue", name: "Savings" }],
799
+ xDataKey: "time",
800
+ height: 200,
801
+ yTickFormatter: (v) => `$${v.toFixed(2)}`
802
+ }
803
+ ),
804
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "sm", children: [
805
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
806
+ "Platform cost: ",
807
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: platformCost, decimalScale: 2 })
808
+ ] }),
809
+ /* @__PURE__ */ jsxs(Text, { size: "xs", fw: 500, c: netSavings < 0 ? "var(--color-error)" : "var(--color-primary)", children: [
810
+ "Net savings: ",
811
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: netSavings, thousandSeparator: true, decimalScale: 2 })
812
+ ] })
813
+ ] })
814
+ ] });
815
+ }
816
+ function CostBreakdownCard({
817
+ breakdownData,
818
+ summaryData,
819
+ data,
820
+ isLoading,
821
+ error,
822
+ budget = 1500
823
+ }) {
824
+ const resourceData = breakdownData ?? data;
825
+ const legacyTotalCost = resourceData?.resources.reduce((sum, r) => sum + r.totalCostUsd, 0) ?? 0;
826
+ const mtdCost = summaryData?.mtd.totalCostUsd ?? legacyTotalCost * 2;
827
+ const projectedMonthlyCost = summaryData?.projection.monthlyCostUsd ?? mtdCost * 1.05;
828
+ const workflowCosts = resourceData?.resources.slice(0, 4).map((r) => ({
829
+ name: r.resourceId,
830
+ cost: r.totalCostUsd,
831
+ executions: r.executionCount,
832
+ avgCost: r.avgCostUsd
833
+ })) ?? [];
834
+ if (error) {
835
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load cost breakdown" }) });
836
+ }
837
+ if (isLoading) {
838
+ return /* @__PURE__ */ jsx(DetailCardSkeleton, { rows: 3 });
839
+ }
840
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
841
+ /* @__PURE__ */ jsx(
842
+ CardHeader,
843
+ {
844
+ icon: /* @__PURE__ */ jsx(IconChartBar, { size: 18 }),
845
+ title: "AI Costs Breakdown",
846
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
847
+ }
848
+ ),
849
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", mb: "md", children: [
850
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Top Spenders" }),
851
+ workflowCosts.length > 0 ? workflowCosts.map((workflow) => /* @__PURE__ */ jsx(
852
+ Box,
853
+ {
854
+ p: "sm",
855
+ style: {
856
+ borderLeft: "3px solid var(--color-primary)",
857
+ backgroundColor: "var(--color-surface)",
858
+ borderRadius: 4
859
+ },
860
+ children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
861
+ /* @__PURE__ */ jsxs(Stack, { gap: 0, style: { flex: 1 }, children: [
862
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: workflow.name }),
863
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
864
+ workflow.executions,
865
+ " executions - $",
866
+ workflow.avgCost.toFixed(4),
867
+ "/exec"
868
+ ] })
869
+ ] }),
870
+ /* @__PURE__ */ jsx(
871
+ Text,
872
+ {
873
+ size: "sm",
874
+ fw: 600,
875
+ c: "var(--color-primary)",
876
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
877
+ children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: workflow.cost, decimalScale: 4 })
878
+ }
879
+ )
880
+ ] })
881
+ },
882
+ workflow.name
883
+ )) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", py: "md", children: "No resource data available" })
884
+ ] }),
885
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "sm", children: [
886
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
887
+ "Projected: ",
888
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: projectedMonthlyCost, thousandSeparator: true, decimalScale: 2 })
889
+ ] }),
890
+ /* @__PURE__ */ jsxs(
891
+ Text,
892
+ {
893
+ size: "xs",
894
+ fw: 600,
895
+ c: projectedMonthlyCost > budget ? "red" : "dimmed",
896
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
897
+ children: [
898
+ "Budget: ",
899
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: budget, thousandSeparator: true, decimalScale: 2 })
900
+ ]
901
+ }
902
+ )
903
+ ] })
904
+ ] });
905
+ }
906
+ function CostMetricsCard({
907
+ summaryData,
908
+ trendsData,
909
+ data,
910
+ isLoading,
911
+ error,
912
+ budget = 1500
913
+ }) {
914
+ const legacyTotalCost = data?.resources.reduce((sum, r) => sum + r.totalCostUsd, 0) ?? 0;
915
+ const todayCost = summaryData?.current.totalCostUsd ?? legacyTotalCost;
916
+ const previousCost = summaryData?.previous.totalCostUsd ?? legacyTotalCost * 0.9;
917
+ const mtdCost = summaryData?.mtd.totalCostUsd ?? legacyTotalCost * 2;
918
+ const projectedMonthlyCost = summaryData?.projection.monthlyCostUsd ?? mtdCost * 1.05;
919
+ const confidence = summaryData?.projection.confidence ?? "low";
920
+ const budgetStatus = projectedMonthlyCost <= budget ? "green" : projectedMonthlyCost <= budget * 1.1 ? "yellow" : "red";
921
+ const budgetLabel = projectedMonthlyCost <= budget ? "On Budget" : projectedMonthlyCost <= budget * 1.1 ? "Warning" : "Over Budget";
922
+ const chartData = trendsData?.trendData.slice(-7).map((point, idx) => {
923
+ const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
924
+ return {
925
+ day: trendsData.granularity === "day" ? new Date(point.time).toLocaleDateString("en-US", { weekday: "short" }) : days[idx % 7],
926
+ cost: point.totalCostUsd
927
+ };
928
+ }) ?? data?.resources.slice(0, 7).map((r, idx) => ({
929
+ day: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][idx] || `Day ${idx + 1}`,
930
+ cost: r.totalCostUsd
931
+ })) ?? [];
932
+ if (error) {
933
+ return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load cost metrics" }) });
934
+ }
935
+ if (isLoading) {
936
+ return /* @__PURE__ */ jsx(StatsCardSkeleton, {});
937
+ }
938
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
939
+ /* @__PURE__ */ jsx(
940
+ CardHeader,
941
+ {
942
+ icon: /* @__PURE__ */ jsx(IconCash, { size: 18 }),
943
+ title: "AI Costs",
944
+ rightSection: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: /* @__PURE__ */ jsx(IconArrowUpRight, { size: 16 }) })
945
+ }
946
+ ),
947
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", mb: "md", children: [
948
+ /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
949
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
950
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: todayCost, decimalScale: 2 }) }),
951
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "period" }),
952
+ /* @__PURE__ */ jsx(TrendIndicator, { current: todayCost, previous: previousCost, inverse: true })
953
+ ] }),
954
+ /* @__PURE__ */ jsxs(Group, { gap: 6, align: "baseline", children: [
955
+ /* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: mtdCost, thousandSeparator: true, decimalScale: 2 }) }),
956
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "MTD" })
957
+ ] })
958
+ ] }),
959
+ /* @__PURE__ */ jsx(Badge, { size: "md", variant: "dot", color: budgetStatus, children: budgetLabel })
960
+ ] }),
961
+ chartData.length > 0 ? /* @__PURE__ */ jsx(
962
+ CyberAreaChart,
963
+ {
964
+ data: chartData,
965
+ series: [{ dataKey: "cost", color: "blue", name: "Cost" }],
966
+ xDataKey: "day",
967
+ height: 120,
968
+ yTickFormatter: (v) => `$${v.toFixed(2)}`
969
+ }
970
+ ) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", py: "lg", children: "No trend data available" }),
971
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mt: "sm", children: [
972
+ /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
973
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
974
+ "Projected monthly:",
975
+ " ",
976
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: projectedMonthlyCost, thousandSeparator: true, decimalScale: 2 })
977
+ ] }),
978
+ /* @__PURE__ */ jsx(Tooltip, { label: `Projection confidence: ${confidence}`, children: /* @__PURE__ */ jsx(IconInfoCircle, { size: 12, color: "var(--color-text-subtle)" }) })
979
+ ] }),
980
+ /* @__PURE__ */ jsxs(
981
+ Text,
982
+ {
983
+ size: "xs",
984
+ fw: 600,
985
+ c: projectedMonthlyCost > budget ? "red" : "dimmed",
986
+ style: { fontFamily: "var(--mantine-font-family-headings)" },
987
+ children: [
988
+ "Budget: ",
989
+ /* @__PURE__ */ jsx(NumberFormatter, { prefix: "$", value: budget, thousandSeparator: true, decimalScale: 2 })
990
+ ]
991
+ }
992
+ )
993
+ ] })
994
+ ] });
995
+ }
996
+ function ErrorBreakdownTable({ startDate, endDate, onErrorClick }) {
997
+ const [searchQuery, setSearchQuery] = useState("");
998
+ const [filterType, setFilterType] = useState("all");
999
+ const [filterSeverity, setFilterSeverity] = useState();
1000
+ const [showResolved, setShowResolved] = useState(false);
1001
+ const resolveError = useResolveError();
1002
+ const resolveAll = useResolveAllErrors();
1003
+ const { page, setPage, totalPages } = usePaginationState(PAGE_SIZE_DEFAULT, [
1004
+ filterType,
1005
+ filterSeverity,
1006
+ searchQuery,
1007
+ showResolved,
1008
+ startDate,
1009
+ endDate
1010
+ ]);
1011
+ const { data, isLoading, isError, error } = useErrorDetails({
1012
+ errorType: filterType === "all" ? void 0 : filterType,
1013
+ severity: filterSeverity,
1014
+ search: searchQuery || void 0,
1015
+ startDate,
1016
+ endDate,
1017
+ page,
1018
+ limit: PAGE_SIZE_DEFAULT,
1019
+ resolved: showResolved ? void 0 : false
1020
+ });
1021
+ if (isLoading) {
1022
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(Stack, { align: "center", justify: "center", mih: 200, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) }) });
1023
+ }
1024
+ if (isError) {
1025
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, {}), title: "Error Loading Data", children: error?.message || "Failed to load error details. Please try again." }) });
1026
+ }
1027
+ if (!data || data.errors.length === 0) {
1028
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1029
+ /* @__PURE__ */ jsx(
1030
+ CardHeader,
1031
+ {
1032
+ icon: /* @__PURE__ */ jsx(IconExclamationCircle, { size: 18 }),
1033
+ title: "Recent Errors",
1034
+ subtitle: "0 errors found",
1035
+ rightSection: /* @__PURE__ */ jsx(
1036
+ Switch,
1037
+ {
1038
+ label: "Show resolved",
1039
+ checked: showResolved,
1040
+ onChange: (e) => setShowResolved(e.currentTarget.checked),
1041
+ size: "sm"
1042
+ }
1043
+ )
1044
+ }
1045
+ ),
1046
+ /* @__PURE__ */ jsx(
1047
+ EmptyState,
1048
+ {
1049
+ icon: IconBug,
1050
+ title: "No errors found",
1051
+ description: showResolved ? "No errors found for the selected time range" : "All errors have been resolved"
1052
+ }
1053
+ )
1054
+ ] }) });
1055
+ }
1056
+ const filteredErrors = data.errors;
1057
+ const errorTypes = Array.from(new Set(data.errors.map((e) => e.errorType)));
1058
+ const total = data.total;
1059
+ const getSeverityIcon = (severity) => {
1060
+ switch (severity) {
1061
+ case "critical":
1062
+ return /* @__PURE__ */ jsx(IconAlertCircle, { size: 16, color: "var(--color-error)" });
1063
+ case "warning":
1064
+ return /* @__PURE__ */ jsx(IconAlertTriangle, { size: 16, color: "var(--mantine-color-orange-6)" });
1065
+ default:
1066
+ return /* @__PURE__ */ jsx(IconBug, { size: 16, color: "var(--color-primary)" });
1067
+ }
1068
+ };
1069
+ const getSeverityColor = (severity) => {
1070
+ switch (severity) {
1071
+ case "critical":
1072
+ return "red";
1073
+ case "warning":
1074
+ return "orange";
1075
+ default:
1076
+ return "blue";
1077
+ }
1078
+ };
1079
+ return /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1080
+ /* @__PURE__ */ jsx(
1081
+ CardHeader,
1082
+ {
1083
+ icon: /* @__PURE__ */ jsx(IconExclamationCircle, { size: 18 }),
1084
+ title: "Recent Errors",
1085
+ subtitle: `${filteredErrors.length} error${filteredErrors.length !== 1 ? "s" : ""} found`,
1086
+ rightSection: /* @__PURE__ */ jsxs(Group, { children: [
1087
+ /* @__PURE__ */ jsx(
1088
+ Switch,
1089
+ {
1090
+ label: "Show resolved",
1091
+ checked: showResolved,
1092
+ onChange: (e) => setShowResolved(e.currentTarget.checked),
1093
+ size: "sm"
1094
+ }
1095
+ ),
1096
+ !showResolved && filteredErrors.some((e) => !e.resolved) && /* @__PURE__ */ jsx(
1097
+ Button,
1098
+ {
1099
+ leftSection: /* @__PURE__ */ jsx(IconChecks, { size: 16 }),
1100
+ variant: "light",
1101
+ loading: resolveAll.isPending,
1102
+ onClick: () => resolveAll.mutate(),
1103
+ children: "Resolve All"
1104
+ }
1105
+ )
1106
+ ] })
1107
+ }
1108
+ ),
1109
+ /* @__PURE__ */ jsxs(FilterBar, { children: [
1110
+ /* @__PURE__ */ jsx(
1111
+ TextInput,
1112
+ {
1113
+ placeholder: "Search errors...",
1114
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
1115
+ value: searchQuery,
1116
+ onChange: (e) => {
1117
+ setSearchQuery(e.currentTarget.value);
1118
+ },
1119
+ style: { flex: 1 }
1120
+ }
1121
+ ),
1122
+ /* @__PURE__ */ jsx(
1123
+ Select,
1124
+ {
1125
+ placeholder: "Filter by type",
1126
+ value: filterType,
1127
+ onChange: (value) => {
1128
+ setFilterType(value || "all");
1129
+ },
1130
+ data: [{ value: "all", label: "All Types" }, ...errorTypes.map((type) => ({ value: type, label: type }))],
1131
+ style: { width: 200 },
1132
+ clearable: true
1133
+ }
1134
+ ),
1135
+ /* @__PURE__ */ jsx(
1136
+ Select,
1137
+ {
1138
+ placeholder: "Filter by severity",
1139
+ value: filterSeverity,
1140
+ onChange: (value) => {
1141
+ setFilterSeverity(value);
1142
+ },
1143
+ data: [
1144
+ { value: "critical", label: "Critical" },
1145
+ { value: "warning", label: "Warning" },
1146
+ { value: "info", label: "Info" }
1147
+ ],
1148
+ style: { width: 200 },
1149
+ clearable: true
1150
+ }
1151
+ )
1152
+ ] }),
1153
+ /* @__PURE__ */ jsxs(Table, { children: [
1154
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1155
+ /* @__PURE__ */ jsx(Table.Th, { children: "Timestamp" }),
1156
+ /* @__PURE__ */ jsx(Table.Th, { children: "Type" }),
1157
+ /* @__PURE__ */ jsx(Table.Th, { children: "Message" }),
1158
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1159
+ /* @__PURE__ */ jsx(Table.Th, { ta: "center", children: "Severity" }),
1160
+ /* @__PURE__ */ jsx(Table.Th, { ta: "right", children: "Actions" })
1161
+ ] }) }),
1162
+ /* @__PURE__ */ jsx(Table.Tbody, { children: filteredErrors.map((error2) => /* @__PURE__ */ jsxs(Table.Tr, { style: { cursor: "pointer" }, onClick: () => onErrorClick?.(error2.executionId), children: [
1163
+ /* @__PURE__ */ jsx(Table.Td, { style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", children: new Date(error2.timestamp).toLocaleString("en-US", {
1164
+ month: "short",
1165
+ day: "numeric",
1166
+ hour: "2-digit",
1167
+ minute: "2-digit"
1168
+ }) }) }),
1169
+ /* @__PURE__ */ jsx(Table.Td, { style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(Badge, { variant: "light", size: "sm", children: error2.errorType }) }),
1170
+ /* @__PURE__ */ jsx(Table.Td, { style: { maxWidth: 300 }, children: /* @__PURE__ */ jsx(Text, { size: "sm", lineClamp: 1, children: error2.message }) }),
1171
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: error2.resourceName }) }),
1172
+ /* @__PURE__ */ jsx(Table.Td, { ta: "center", style: { whiteSpace: "nowrap" }, children: /* @__PURE__ */ jsx(
1173
+ Badge,
1174
+ {
1175
+ color: getSeverityColor(error2.severity),
1176
+ variant: "light",
1177
+ size: "sm",
1178
+ leftSection: getSeverityIcon(error2.severity),
1179
+ children: error2.severity.toUpperCase()
1180
+ }
1181
+ ) }),
1182
+ /* @__PURE__ */ jsx(Table.Td, { ta: "right", children: /* @__PURE__ */ jsxs(Group, { gap: 4, justify: "flex-end", wrap: "nowrap", children: [
1183
+ error2.resolved ? /* @__PURE__ */ jsx(Badge, { color: "green", variant: "light", size: "sm", style: { cursor: "default" }, children: "Resolved" }) : /* @__PURE__ */ jsx(
1184
+ Badge,
1185
+ {
1186
+ color: "gray",
1187
+ variant: "light",
1188
+ size: "sm",
1189
+ style: {
1190
+ cursor: resolveError.isPending && resolveError.variables === error2.id ? "wait" : "pointer",
1191
+ opacity: resolveError.isPending && resolveError.variables === error2.id ? 0.5 : 1
1192
+ },
1193
+ onClick: (e) => {
1194
+ e.stopPropagation();
1195
+ resolveError.mutate(error2.id);
1196
+ },
1197
+ children: "Resolve"
1198
+ }
1199
+ ),
1200
+ /* @__PURE__ */ jsx(
1201
+ ActionIcon,
1202
+ {
1203
+ variant: "subtle",
1204
+ size: "sm",
1205
+ onClick: (e) => {
1206
+ e.stopPropagation();
1207
+ onErrorClick?.(error2.executionId);
1208
+ },
1209
+ children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
1210
+ }
1211
+ )
1212
+ ] }) })
1213
+ ] }, error2.id)) })
1214
+ ] }),
1215
+ totalPages(total) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { total: totalPages(total), value: page, onChange: setPage, size: "sm", boundaries: 1 }) })
1216
+ ] }) });
1217
+ }
1218
+ var categoryColors = {
1219
+ info: "blue",
1220
+ queue: "cyan",
1221
+ alert: "yellow",
1222
+ error: "red",
1223
+ system: "gray"
1224
+ };
1225
+ function NotificationItem({ notification, onClose, onNavigate }) {
1226
+ const markAsRead = useMarkAsRead();
1227
+ const handleClick = async () => {
1228
+ if (!notification.read) {
1229
+ await markAsRead.mutateAsync(notification.id);
1230
+ }
1231
+ if (notification.actionUrl) {
1232
+ onNavigate?.(notification.actionUrl);
1233
+ }
1234
+ onClose?.();
1235
+ };
1236
+ const categoryColor = categoryColors[notification.category] || "gray";
1237
+ return /* @__PURE__ */ jsx(
1238
+ UnstyledButton,
1239
+ {
1240
+ onClick: handleClick,
1241
+ style: {
1242
+ width: "100%",
1243
+ padding: "12px",
1244
+ backgroundColor: "transparent",
1245
+ transition: "background-color var(--duration-fast) var(--easing)"
1246
+ },
1247
+ styles: {
1248
+ root: {
1249
+ "&:hover": {
1250
+ backgroundColor: "var(--color-surface-hover)"
1251
+ }
1252
+ }
1253
+ },
1254
+ children: /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", children: [
1255
+ /* @__PURE__ */ jsx(Box, { mt: 4, children: notification.read ? /* @__PURE__ */ jsx(IconCircle, { size: 12, color: "var(--mantine-color-gray-5)" }) : /* @__PURE__ */ jsx(IconCircleFilled, { size: 12, color: `var(--mantine-color-${categoryColor}-6)` }) }),
1256
+ /* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: 1 }, children: [
1257
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: notification.read ? 400 : 600, children: notification.title }),
1258
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: notification.message }),
1259
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatDistanceToNow(new Date(notification.createdAt), { addSuffix: true }) })
1260
+ ] })
1261
+ ] })
1262
+ }
1263
+ );
1264
+ }
1265
+ function NotificationList({ notifications, isLoading, onClose, onNavigate }) {
1266
+ if (isLoading) {
1267
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) });
1268
+ }
1269
+ if (notifications.length === 0) {
1270
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No notifications" }) });
1271
+ }
1272
+ return /* @__PURE__ */ jsx(Stack, { gap: 0, children: notifications.map((notification) => /* @__PURE__ */ jsx(NotificationItem, { notification, onClose, onNavigate }, notification.id)) });
1273
+ }
1274
+ function ExecutionLogsPage({
1275
+ timeRange,
1276
+ pageSize = 20,
1277
+ onNavigateToExecution,
1278
+ renderTrendChart
1279
+ }) {
1280
+ const { filters, updateFilter, resetFilters } = useExecutionLogsFilters(timeRange);
1281
+ const startDate = useMemo(() => {
1282
+ const { startDate: sd } = getTimeRangeDates(timeRange);
1283
+ return new Date(sd).getTime();
1284
+ }, [timeRange]);
1285
+ const { page, setPage, offset, totalPages } = usePaginationState(pageSize, [
1286
+ filters.resourceId,
1287
+ filters.status,
1288
+ filters.resourceStatus,
1289
+ timeRange
1290
+ ]);
1291
+ const { data, isLoading } = useExecutionLogs({
1292
+ resourceId: filters.resourceId,
1293
+ status: filters.status !== "all" ? filters.status : void 0,
1294
+ resourceStatus: filters.resourceStatus !== "all" ? filters.resourceStatus : void 0,
1295
+ startDate,
1296
+ limit: pageSize,
1297
+ offset
1298
+ });
1299
+ const total = data?.total ?? 0;
1300
+ return /* @__PURE__ */ jsxs(Stack, { children: [
1301
+ /* @__PURE__ */ jsx(PageTitleCaption, { title: "Execution Logs", caption: "View and filter execution history across all resources" }),
1302
+ renderTrendChart({ timeRange }),
1303
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1304
+ /* @__PURE__ */ jsx(ExecutionLogsFilters, { filters, onFilterChange: updateFilter, onReset: resetFilters }),
1305
+ /* @__PURE__ */ jsx(
1306
+ ExecutionLogsTable,
1307
+ {
1308
+ executions: data?.executions || [],
1309
+ isLoading,
1310
+ onRowClick: onNavigateToExecution
1311
+ }
1312
+ ),
1313
+ totalPages(total) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { value: page, onChange: setPage, total: totalPages(total), size: "sm", boundaries: 1 }) })
1314
+ ] }) })
1315
+ ] });
1316
+ }
1317
+ function ExecutionHealth({ timeRange, onErrorClick }) {
1318
+ const { data, isLoading, error } = useExecutionHealth({ timeRange });
1319
+ const { data: errorData, isLoading: errorLoading, error: errorError } = useErrorAnalysis(timeRange);
1320
+ const { startDate, endDate } = useTimeRangeDates(timeRange);
1321
+ if (isLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
1322
+ return /* @__PURE__ */ jsxs(Stack, { children: [
1323
+ /* @__PURE__ */ jsx(
1324
+ PageTitleCaption,
1325
+ {
1326
+ title: "Execution Health",
1327
+ caption: "Detailed execution metrics, success rates, and performance trends"
1328
+ }
1329
+ ),
1330
+ /* @__PURE__ */ jsx(ExecutionHealthCard, { data: data?.executionHealth, isLoading, error }),
1331
+ /* @__PURE__ */ jsx(
1332
+ ErrorBreakdownTable,
1333
+ {
1334
+ startDate,
1335
+ endDate,
1336
+ onErrorClick: (executionId) => onErrorClick(executionId)
1337
+ }
1338
+ ),
1339
+ /* @__PURE__ */ jsx(ErrorAnalysisCard, { data: errorData, isLoading: errorLoading, error: errorError })
1340
+ ] });
1341
+ }
1342
+ function ErrorDetailsModal({ executionId, opened, onClose, organizationName }) {
1343
+ const { data: errors, isLoading, isError } = useErrorDetail(executionId);
1344
+ const resolveErrors = useResolveErrorsByExecution();
1345
+ const { data: resources } = useResources();
1346
+ const resourceNameMap = useMemo(() => {
1347
+ const map = /* @__PURE__ */ new Map();
1348
+ if (resources) {
1349
+ for (const r of [...resources.workflows, ...resources.agents]) {
1350
+ map.set(r.resourceId, r.name);
1351
+ }
1352
+ }
1353
+ return map;
1354
+ }, [resources]);
1355
+ const resourceTypeMap = useMemo(() => {
1356
+ const map = /* @__PURE__ */ new Map();
1357
+ if (resources) {
1358
+ for (const r of resources.workflows) {
1359
+ map.set(r.resourceId, "workflow");
1360
+ }
1361
+ for (const r of resources.agents) {
1362
+ map.set(r.resourceId, "agent");
1363
+ }
1364
+ }
1365
+ return map;
1366
+ }, [resources]);
1367
+ const primaryError = errors?.[0];
1368
+ const resolvedResourceName = primaryError ? resourceNameMap.get(primaryError.resourceId) ?? primaryError.resourceId : void 0;
1369
+ const resolvedResourceType = primaryError ? resourceTypeMap.get(primaryError.resourceId) : void 0;
1370
+ const resourceDetailHref = primaryError && resolvedResourceType ? `/operations/resources/${resolvedResourceType}/${primaryError.resourceId}` : null;
1371
+ const allResolved = errors?.every((e) => e.resolved) ?? false;
1372
+ const hasRetries = errors && errors.length > 1;
1373
+ const handleCopyDetails = () => {
1374
+ if (!primaryError) return;
1375
+ const detailsText = `
1376
+ Error ID: ${primaryError.id}
1377
+ Timestamp: ${primaryError.timestamp}
1378
+ Type: ${primaryError.errorType}
1379
+ Severity: ${primaryError.severity}
1380
+ Execution ID: ${primaryError.executionId}
1381
+ Resource: ${primaryError.resourceName}
1382
+
1383
+ Message:
1384
+ ${primaryError.message}
1385
+
1386
+ Stack Trace:
1387
+ ${primaryError.stackTrace || "No stack trace available"}
1388
+
1389
+ Context:
1390
+ ${primaryError.errorContext ? JSON.stringify(primaryError.errorContext, null, 2) : "No context available"}
1391
+ `.trim();
1392
+ navigator.clipboard.writeText(detailsText);
1393
+ };
1394
+ return /* @__PURE__ */ jsx(CustomModal, { opened, onClose, size: "xl", children: /* @__PURE__ */ jsxs(Stack, { children: [
1395
+ isLoading && /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }),
1396
+ isError && /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, {}), title: "Error Loading Details", children: "Failed to load error details. Please try again." }),
1397
+ !isLoading && !isError && !primaryError && /* @__PURE__ */ jsx(Alert, { color: "gray", icon: /* @__PURE__ */ jsx(IconBug, {}), children: "No error details found for this execution." }),
1398
+ !isLoading && !isError && primaryError && /* @__PURE__ */ jsxs(Fragment, { children: [
1399
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1400
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1401
+ /* @__PURE__ */ jsx(IconAlertCircle, { size: 24, color: "var(--color-error)" }),
1402
+ /* @__PURE__ */ jsxs("div", { children: [
1403
+ /* @__PURE__ */ jsx(Title, { order: 3, children: primaryError.errorType }),
1404
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: new Date(primaryError.timestamp).toLocaleString("en-US", {
1405
+ month: "long",
1406
+ day: "numeric",
1407
+ year: "numeric",
1408
+ hour: "2-digit",
1409
+ minute: "2-digit",
1410
+ second: "2-digit"
1411
+ }) })
1412
+ ] })
1413
+ ] }),
1414
+ /* @__PURE__ */ jsx(
1415
+ Badge,
1416
+ {
1417
+ color: primaryError.severity === "critical" ? "red" : primaryError.severity === "warning" ? "orange" : "blue",
1418
+ variant: "light",
1419
+ children: primaryError.severity
1420
+ }
1421
+ )
1422
+ ] }),
1423
+ /* @__PURE__ */ jsx(Divider, {}),
1424
+ /* @__PURE__ */ jsxs("div", { children: [
1425
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Error Message" }),
1426
+ /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconBug, { size: 16 }), children: primaryError.message })
1427
+ ] }),
1428
+ hasRetries && /* @__PURE__ */ jsxs(Alert, { color: "yellow", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), children: [
1429
+ "This execution has ",
1430
+ errors.length,
1431
+ " errors (including retries). Showing most recent error."
1432
+ ] }),
1433
+ /* @__PURE__ */ jsxs("div", { children: [
1434
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Execution Context" }),
1435
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1436
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1437
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Execution ID" }),
1438
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1439
+ /* @__PURE__ */ jsx(Code, { children: primaryError.executionId }),
1440
+ /* @__PURE__ */ jsx(CopyButton, { value: `"${organizationName}/${primaryError.resourceId}" ${primaryError.executionId}`, children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy Execution Ref", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", color: copied ? "teal" : "gray", onClick: copy, children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 }) }) }) }),
1441
+ resourceDetailHref && /* @__PURE__ */ jsx(
1442
+ ActionIcon,
1443
+ {
1444
+ variant: "subtle",
1445
+ size: "sm",
1446
+ component: "a",
1447
+ href: resourceDetailHref,
1448
+ target: "_blank",
1449
+ title: "View Execution Log",
1450
+ children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
1451
+ }
1452
+ )
1453
+ ] })
1454
+ ] }),
1455
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1456
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Resource Name" }),
1457
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: resolvedResourceName })
1458
+ ] }),
1459
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1460
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Resource ID" }),
1461
+ /* @__PURE__ */ jsx(Code, { children: primaryError.resourceId })
1462
+ ] }),
1463
+ primaryError.retryAttempt && /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1464
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Retry Attempt" }),
1465
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: primaryError.retryAttempt })
1466
+ ] }),
1467
+ primaryError.stepName && /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1468
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Step Name" }),
1469
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: primaryError.stepName })
1470
+ ] })
1471
+ ] })
1472
+ ] }),
1473
+ primaryError.stackTrace && /* @__PURE__ */ jsxs("div", { children: [
1474
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mb: "xs", children: [
1475
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Stack Trace" }),
1476
+ /* @__PURE__ */ jsx(CopyButton, { value: primaryError.stackTrace, children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy stack trace", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", onClick: copy, children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 }) }) }) })
1477
+ ] }),
1478
+ /* @__PURE__ */ jsx(
1479
+ Code,
1480
+ {
1481
+ block: true,
1482
+ style: {
1483
+ maxHeight: 300,
1484
+ overflow: "auto",
1485
+ fontSize: "12px",
1486
+ lineHeight: "1.5"
1487
+ },
1488
+ children: primaryError.stackTrace
1489
+ }
1490
+ )
1491
+ ] }),
1492
+ primaryError.errorContext && /* @__PURE__ */ jsxs("div", { children: [
1493
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Error Context" }),
1494
+ /* @__PURE__ */ jsx(JsonViewer, { data: primaryError.errorContext, maxHeight: 200, fontSize: "12px" })
1495
+ ] }),
1496
+ primaryError.executionContext && /* @__PURE__ */ jsxs("div", { children: [
1497
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Execution Context" }),
1498
+ /* @__PURE__ */ jsx(JsonViewer, { data: primaryError.executionContext, maxHeight: 200, fontSize: "12px" })
1499
+ ] }),
1500
+ hasRetries && /* @__PURE__ */ jsxs("div", { children: [
1501
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "All Errors (including retries)" }),
1502
+ /* @__PURE__ */ jsx(Accordion, { children: errors.map((error, index) => /* @__PURE__ */ jsxs(Accordion.Item, { value: error.id, children: [
1503
+ /* @__PURE__ */ jsx(Accordion.Control, { children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1504
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1505
+ "Attempt ",
1506
+ error.retryAttempt || index + 1,
1507
+ " - ",
1508
+ error.errorType
1509
+ ] }),
1510
+ /* @__PURE__ */ jsx(
1511
+ Badge,
1512
+ {
1513
+ size: "sm",
1514
+ color: error.severity === "critical" ? "red" : error.severity === "warning" ? "orange" : "blue",
1515
+ children: error.severity
1516
+ }
1517
+ )
1518
+ ] }) }),
1519
+ /* @__PURE__ */ jsx(Accordion.Panel, { children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1520
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: error.message }),
1521
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: new Date(error.timestamp).toLocaleString() }),
1522
+ error.stackTrace && /* @__PURE__ */ jsx(Code, { block: true, style: { fontSize: "11px", maxHeight: 150, overflow: "auto" }, children: error.stackTrace })
1523
+ ] }) })
1524
+ ] }, error.id)) })
1525
+ ] }),
1526
+ /* @__PURE__ */ jsx(Divider, {}),
1527
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1528
+ /* @__PURE__ */ jsxs(Group, { children: [
1529
+ /* @__PURE__ */ jsx(Button, { variant: "light", leftSection: /* @__PURE__ */ jsx(IconCopy, { size: 16 }), onClick: handleCopyDetails, children: "Copy Error Details" }),
1530
+ allResolved ? /* @__PURE__ */ jsx(
1531
+ Badge,
1532
+ {
1533
+ size: "lg",
1534
+ color: "green",
1535
+ variant: "light",
1536
+ leftSection: /* @__PURE__ */ jsx(IconCircleCheck, { size: 14 }),
1537
+ style: { cursor: "default" },
1538
+ children: "Resolved"
1539
+ }
1540
+ ) : /* @__PURE__ */ jsx(
1541
+ Button,
1542
+ {
1543
+ variant: "light",
1544
+ color: "teal",
1545
+ leftSection: /* @__PURE__ */ jsx(IconCircleDashed, { size: 16 }),
1546
+ loading: resolveErrors.isPending,
1547
+ onClick: () => executionId && resolveErrors.mutate(executionId),
1548
+ children: "Resolve"
1549
+ }
1550
+ )
1551
+ ] }),
1552
+ /* @__PURE__ */ jsxs(Group, { children: [
1553
+ /* @__PURE__ */ jsx(Button, { variant: "default", onClick: onClose, children: "Close" }),
1554
+ resourceDetailHref && /* @__PURE__ */ jsx(Button, { component: "a", href: resourceDetailHref, target: "_blank", leftSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 }), children: "View Execution Log" })
1555
+ ] })
1556
+ ] })
1557
+ ] })
1558
+ ] }) });
1559
+ }
1560
+ function CostAnalytics({ timeRange }) {
1561
+ const { data: trendsData, isLoading: trendsLoading, error: trendsError } = useCostTrends(timeRange);
1562
+ const { data: summaryData } = useCostSummary(timeRange);
1563
+ const { data: modelData, isLoading: modelLoading, error: modelError } = useCostByModel(timeRange);
1564
+ const { data: breakdownData, isLoading: breakdownLoading, error: breakdownError } = useCostBreakdown(timeRange);
1565
+ if (trendsLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
1566
+ return /* @__PURE__ */ jsxs(Stack, { children: [
1567
+ /* @__PURE__ */ jsx(
1568
+ PageTitleCaption,
1569
+ {
1570
+ title: "Cost Analytics",
1571
+ caption: "Comprehensive cost tracking, budgets, ROI analysis, and labor savings"
1572
+ }
1573
+ ),
1574
+ /* @__PURE__ */ jsx(CostTrendChart, { data: trendsData, summaryData, isLoading: trendsLoading, error: trendsError }),
1575
+ /* @__PURE__ */ jsx(
1576
+ CostBreakdownCard,
1577
+ {
1578
+ breakdownData,
1579
+ summaryData,
1580
+ isLoading: breakdownLoading,
1581
+ error: breakdownError
1582
+ }
1583
+ ),
1584
+ /* @__PURE__ */ jsx(CostByModelTable, { data: modelData, isLoading: modelLoading, error: modelError })
1585
+ ] });
1586
+ }
1587
+ function getNavigationPath2(activity) {
1588
+ switch (activity.activityType) {
1589
+ case "workflow_execution":
1590
+ return `/operations/resources/workflow/${activity.entityId}`;
1591
+ case "agent_run":
1592
+ return `/operations/resources/agent/${activity.entityId}`;
1593
+ case "hitl_action":
1594
+ return "/operations/command-queue";
1595
+ case "credential_change":
1596
+ case "credential_read":
1597
+ return "/settings/credentials";
1598
+ case "api_key_change":
1599
+ return "/settings/api-keys";
1600
+ case "deployment_change":
1601
+ return "/settings/deployments";
1602
+ case "membership_change":
1603
+ return "/settings/organization";
1604
+ default:
1605
+ return null;
1606
+ }
1607
+ }
1608
+ function ActivityLog({ timeRange, pageSize = PAGE_SIZE_DEFAULT, onNavigate }) {
1609
+ const { filters, updateFilter, resetFilters } = useActivityFilters(timeRange);
1610
+ const startDate = useMemo(() => {
1611
+ const { startDate: startDate2 } = getTimeRangeDates(timeRange);
1612
+ return startDate2;
1613
+ }, [timeRange]);
1614
+ const activityType = filters.activityType !== "all" ? filters.activityType : void 0;
1615
+ const { page, setPage, offset, totalPages } = usePaginationState(pageSize, [
1616
+ filters.activityType,
1617
+ filters.status,
1618
+ filters.search,
1619
+ timeRange
1620
+ ]);
1621
+ const { data: chartData, isLoading: isChartLoading } = useActivityTrend({
1622
+ activityType,
1623
+ startDate
1624
+ });
1625
+ const tableParams = useMemo(() => {
1626
+ const params = {
1627
+ limit: pageSize,
1628
+ offset,
1629
+ startDate
1630
+ };
1631
+ if (filters.activityType && filters.activityType !== "all") {
1632
+ params.activityType = filters.activityType;
1633
+ }
1634
+ if (filters.status && filters.status !== "all") {
1635
+ params.status = filters.status;
1636
+ }
1637
+ if (filters.search?.trim()) {
1638
+ params.search = filters.search.trim();
1639
+ }
1640
+ return params;
1641
+ }, [offset, startDate, filters.activityType, filters.status, filters.search, pageSize]);
1642
+ const { data: tableData, isLoading: isTableLoading } = useActivities(tableParams);
1643
+ const total = tableData?.total ?? 0;
1644
+ const handleRowClick = useCallback(
1645
+ (activity) => {
1646
+ const path = getNavigationPath2(activity);
1647
+ if (path) {
1648
+ onNavigate(path);
1649
+ }
1650
+ },
1651
+ [onNavigate]
1652
+ );
1653
+ if (isChartLoading && isTableLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
1654
+ return /* @__PURE__ */ jsxs(Stack, { children: [
1655
+ /* @__PURE__ */ jsx(
1656
+ PageTitleCaption,
1657
+ {
1658
+ title: "Activity Log",
1659
+ caption: "Real-time activity feed with automatic updates every 30 seconds"
1660
+ }
1661
+ ),
1662
+ /* @__PURE__ */ jsx(
1663
+ ActivityTrendChart,
1664
+ {
1665
+ timestamps: chartData?.timestamps ?? [],
1666
+ total: chartData?.total ?? 0,
1667
+ isLoading: isChartLoading,
1668
+ timeRange
1669
+ }
1670
+ ),
1671
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1672
+ /* @__PURE__ */ jsx(ActivityFilters, { filters, onFilterChange: updateFilter, onReset: resetFilters }),
1673
+ /* @__PURE__ */ jsx(
1674
+ ActivityTable,
1675
+ {
1676
+ activities: tableData?.activities ?? [],
1677
+ isLoading: isTableLoading,
1678
+ onRowClick: handleRowClick
1679
+ }
1680
+ ),
1681
+ totalPages(total) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { value: page, onChange: setPage, total: totalPages(total), size: "sm", boundaries: 1 }) })
1682
+ ] }) })
1683
+ ] });
1684
+ }
1685
+ function ActivityFeed({
1686
+ limit = 50,
1687
+ activityType,
1688
+ entityType,
1689
+ entityId,
1690
+ filters,
1691
+ clientFilters,
1692
+ overrideData,
1693
+ overrideLoading
1694
+ }) {
1695
+ const [currentLimit, setCurrentLimit] = useState(limit);
1696
+ const shouldFetch = !overrideData;
1697
+ const fetchResult = useActivities({
1698
+ limit: currentLimit,
1699
+ activityType: filters?.activityType || activityType,
1700
+ entityType,
1701
+ entityId,
1702
+ startDate: filters?.startDate
1703
+ });
1704
+ const data = overrideData ?? fetchResult.data;
1705
+ const error = shouldFetch ? fetchResult.error : null;
1706
+ const isLoading = overrideLoading ?? (shouldFetch ? fetchResult.isLoading : false);
1707
+ const handleLoadMore = () => {
1708
+ setCurrentLimit((prev) => prev + 50);
1709
+ };
1710
+ const filteredActivities = useMemo(() => {
1711
+ if (!data?.activities) return [];
1712
+ let filtered = data.activities;
1713
+ if (clientFilters?.status) {
1714
+ filtered = filtered.filter((activity) => activity.status === clientFilters.status);
1715
+ }
1716
+ if (clientFilters?.search) {
1717
+ const searchLower = clientFilters.search.toLowerCase();
1718
+ filtered = filtered.filter(
1719
+ (activity) => activity.title.toLowerCase().includes(searchLower) || activity.description?.toLowerCase().includes(searchLower) || activity.entityName?.toLowerCase().includes(searchLower)
1720
+ );
1721
+ }
1722
+ return filtered;
1723
+ }, [data?.activities, clientFilters]);
1724
+ if (isLoading) {
1725
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
1726
+ }
1727
+ if (error) {
1728
+ return /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconInfoCircle, { size: 16 }), title: "Error loading activities", color: "red", children: /* @__PURE__ */ jsx(Text, { size: "sm", children: error instanceof Error ? error.message : "Failed to load activities" }) });
1729
+ }
1730
+ if (!filteredActivities.length) {
1731
+ return /* @__PURE__ */ jsx(EmptyState, { icon: IconActivity, title: "No activities found" });
1732
+ }
1733
+ const hasMore = data ? data.total > currentLimit : false;
1734
+ const showingCount = filteredActivities.length;
1735
+ const totalCount = data?.total || 0;
1736
+ return /* @__PURE__ */ jsxs(Stack, { children: [
1737
+ /* @__PURE__ */ jsx(Group, { justify: "space-between", children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1738
+ "Showing ",
1739
+ showingCount,
1740
+ " of ",
1741
+ totalCount,
1742
+ " activities"
1743
+ ] }) }),
1744
+ /* @__PURE__ */ jsx(Stack, { children: filteredActivities.map((activity) => /* @__PURE__ */ jsx(ActivityCard, { activity }, activity.id)) }),
1745
+ hasMore && /* @__PURE__ */ jsx(Center, { children: /* @__PURE__ */ jsx(Button, { variant: "light", onClick: handleLoadMore, loading: isLoading, children: "Load More" }) })
1746
+ ] });
1747
+ }
1748
+ function NotificationCenter({ pageSize = 20 }) {
1749
+ const { page, setPage, offset, totalPages } = usePaginationState(pageSize);
1750
+ const { data, isLoading } = useNotifications({ limit: pageSize, offset });
1751
+ const notifications = data?.notifications ?? [];
1752
+ const markAllAsRead = useMarkAllAsRead();
1753
+ const hasUnread = notifications.some((n) => !n.read);
1754
+ const handleMarkAllAsRead = async () => {
1755
+ await markAllAsRead.mutateAsync();
1756
+ };
1757
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1758
+ hasUnread && /* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(Button, { variant: "light", size: "sm", onClick: handleMarkAllAsRead, loading: markAllAsRead.isPending, children: "Mark all as read" }) }),
1759
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(NotificationList, { notifications, isLoading }) }),
1760
+ totalPages(data?.total ?? 0) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { value: page, onChange: setPage, total: totalPages(data?.total ?? 0), size: "sm", boundaries: 1 }) })
1761
+ ] });
1762
+ }
1763
+
1764
+ export { ActivityCard, ActivityFeed, ActivityFilters, ActivityLog, ActivityTable, BusinessImpactCard, CostAnalytics, CostBreakdownCard, CostByModelTable, CostMetricsCard, ErrorAnalysisCard, ErrorBreakdownTable, ErrorDetailsModal, ExecutionBreakdownTable, ExecutionHealth, ExecutionHealthCard, ExecutionLogsFilters, ExecutionLogsPage, ExecutionLogsTable, NotificationCenter, NotificationItem, NotificationList };