@elevasis/ui 1.19.0 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/auth/index.js +3 -3
  3. package/dist/charts/index.css +14 -0
  4. package/dist/charts/index.js +8 -6
  5. package/dist/{chunk-7ATCF6UL.js → chunk-3DIU726S.js} +11 -4
  6. package/dist/chunk-4SY4EQSK.js +68 -0
  7. package/dist/{chunk-2Z7LYTIX.js → chunk-AQ5MQDSS.js} +30 -17
  8. package/dist/chunk-AWMZCYKH.js +639 -0
  9. package/dist/{chunk-BVNAC4SQ.js → chunk-C7AD6N23.js} +38 -48
  10. package/dist/{chunk-ZFCG5SHW.js → chunk-COTI2QPO.js} +1 -1
  11. package/dist/{chunk-WAPZN2U3.js → chunk-EMN755L5.js} +7 -41
  12. package/dist/{chunk-LBY7FVFD.js → chunk-ERVB3QJQ.js} +31 -715
  13. package/dist/chunk-GBMNCNHX.js +105 -0
  14. package/dist/{chunk-MBZDE6UT.js → chunk-IOKL7BKE.js} +9 -1
  15. package/dist/{chunk-35UWYH2A.js → chunk-JFRG2JJE.js} +8 -2
  16. package/dist/chunk-JIABC3AE.js +2622 -0
  17. package/dist/chunk-JZEXFQ6N.js +671 -0
  18. package/dist/chunk-LGKLC5MG.js +44 -0
  19. package/dist/chunk-MG3NF7QL.js +63 -0
  20. package/dist/{chunk-KBLGVZBD.js → chunk-NNKKBSJN.js} +2 -22
  21. package/dist/{chunk-JNBHUCKW.js → chunk-NVOCKXUQ.js} +1 -1
  22. package/dist/chunk-OFAXUZPZ.js +2411 -0
  23. package/dist/chunk-PDHTXPSF.js +12 -0
  24. package/dist/chunk-QJ2S46NI.js +23 -0
  25. package/dist/{chunk-NUULWBAD.js → chunk-R3R367QY.js} +1 -1
  26. package/dist/{chunk-UANJP5P7.js → chunk-R7WLWGPO.js} +5 -5
  27. package/dist/{chunk-CC3SDRIF.js → chunk-RWQIFKMJ.js} +1 -1
  28. package/dist/chunk-UMFPUM7Q.js +1281 -0
  29. package/dist/{chunk-KNJKCD73.js → chunk-VLTVZXP6.js} +4 -4
  30. package/dist/chunk-WWEMNIHW.js +37 -0
  31. package/dist/{chunk-UTWJZEOJ.js → chunk-XOTN3X3Z.js} +3 -3
  32. package/dist/components/index.css +14 -0
  33. package/dist/components/index.d.ts +41 -7
  34. package/dist/components/index.js +564 -5023
  35. package/dist/components/navigation/index.js +2 -63
  36. package/dist/features/auth/index.css +579 -0
  37. package/dist/features/auth/index.d.ts +2557 -0
  38. package/dist/features/auth/index.js +125 -0
  39. package/dist/features/dashboard/index.css +579 -0
  40. package/dist/features/dashboard/index.d.ts +244 -0
  41. package/dist/features/dashboard/index.js +650 -0
  42. package/dist/features/monitoring/index.css +579 -0
  43. package/dist/features/monitoring/index.d.ts +121 -0
  44. package/dist/features/monitoring/index.js +538 -0
  45. package/dist/features/operations/index.css +14 -0
  46. package/dist/features/operations/index.d.ts +1675 -2
  47. package/dist/features/operations/index.js +2148 -28
  48. package/dist/features/settings/index.css +579 -0
  49. package/dist/features/settings/index.d.ts +2589 -0
  50. package/dist/features/settings/index.js +1437 -0
  51. package/dist/hooks/index.css +14 -0
  52. package/dist/hooks/index.d.ts +29 -11
  53. package/dist/hooks/index.js +13 -13
  54. package/dist/hooks/published.css +14 -0
  55. package/dist/hooks/published.d.ts +29 -11
  56. package/dist/hooks/published.js +12 -12
  57. package/dist/index.css +14 -0
  58. package/dist/index.d.ts +41 -12
  59. package/dist/index.js +15 -15
  60. package/dist/initialization/index.js +2 -2
  61. package/dist/layout/index.d.ts +7 -1
  62. package/dist/layout/index.js +7 -5
  63. package/dist/organization/index.js +2 -2
  64. package/dist/provider/index.css +14 -0
  65. package/dist/provider/index.d.ts +1 -1
  66. package/dist/provider/index.js +10 -10
  67. package/dist/provider/published.d.ts +1 -1
  68. package/dist/provider/published.js +6 -6
  69. package/dist/theme/index.d.ts +1 -1
  70. package/dist/theme/index.js +3 -3
  71. package/dist/theme/presets/__tests__/getPreset.test.d.ts +2 -0
  72. package/dist/theme/presets/__tests__/getPreset.test.d.ts.map +1 -0
  73. package/dist/theme/presets/__tests__/getPreset.test.js +92 -0
  74. package/dist/theme/presets/cyber-volt.d.ts +12 -0
  75. package/dist/theme/presets/cyber-volt.d.ts.map +1 -0
  76. package/dist/theme/presets/cyber-volt.js +70 -0
  77. package/dist/theme/presets/regal.d.ts +8 -0
  78. package/dist/theme/presets/regal.d.ts.map +1 -0
  79. package/dist/theme/presets/regal.js +69 -0
  80. package/dist/theme/presets/rose-gold.d.ts +12 -0
  81. package/dist/theme/presets/rose-gold.d.ts.map +1 -0
  82. package/dist/theme/presets/rose-gold.js +76 -0
  83. package/dist/types/index.d.ts +1 -1
  84. package/dist/utils/index.d.ts +12 -1
  85. package/dist/utils/index.js +1 -1
  86. package/dist/zustand/index.d.ts +80 -0
  87. package/dist/zustand/index.js +105 -0
  88. package/package.json +55 -4
  89. package/dist/chunk-2YW3LDFT.js +0 -1542
  90. package/dist/theme/presets/cyber-void.d.ts +0 -12
  91. package/dist/theme/presets/cyber-void.d.ts.map +0 -1
  92. package/dist/theme/presets/cyber-void.js +0 -75
  93. package/dist/{chunk-DVKEEY5J.js → chunk-TUXTSEAF.js} +1 -1
  94. package/dist/{chunk-U2522LSW.js → chunk-V7XHGJQZ.js} +1 -1
@@ -0,0 +1,538 @@
1
+ import { ExecutionLogsFilters, ExecutionLogsTable, ExecutionHealthCard, ErrorBreakdownTable, ErrorAnalysisCard, CostByModelTable, ActivityFilters, ActivityTable, ActivityCard, NotificationList } from '../../chunk-UMFPUM7Q.js';
2
+ import '../../chunk-PDHTXPSF.js';
3
+ import '../../chunk-LGKLC5MG.js';
4
+ import '../../chunk-4SY4EQSK.js';
5
+ import { CustomModal } from '../../chunk-GBMNCNHX.js';
6
+ import { CostTrendChart, ActivityTrendChart } from '../../chunk-ERVB3QJQ.js';
7
+ import { PageTitleCaption, JsonViewer, EmptyState } from '../../chunk-AWMZCYKH.js';
8
+ import '../../chunk-NNKKBSJN.js';
9
+ import { AppShellLoader } from '../../chunk-WWEMNIHW.js';
10
+ import '../../chunk-QJ2S46NI.js';
11
+ import { useExecutionLogsFilters, useTimeRangeDates, useActivityFilters } from '../../chunk-XOTN3X3Z.js';
12
+ import { usePaginationState, useExecutionLogs, useExecutionHealth, useErrorAnalysis, useErrorDetail, useResolveErrorsByExecution, useResources, useCostTrends, useCostSummary, useCostByModel, useActivityTrend, useActivities, useNotifications, useMarkAllAsRead, useTestNotification } from '../../chunk-AQ5MQDSS.js';
13
+ import '../../chunk-NJJ3NQ7B.js';
14
+ import { getTimeRangeDates } from '../../chunk-LXHZYSMQ.js';
15
+ import '../../chunk-MHW43EOH.js';
16
+ import '../../chunk-F6RBK7NJ.js';
17
+ import '../../chunk-XA34RETF.js';
18
+ import '../../chunk-ELJIFLCB.js';
19
+ import '../../chunk-L4XXM55J.js';
20
+ import '../../chunk-RNP5R5I3.js';
21
+ import '../../chunk-VLTVZXP6.js';
22
+ import '../../chunk-R3R367QY.js';
23
+ import '../../chunk-SZHARWKU.js';
24
+ import '../../chunk-OFAXUZPZ.js';
25
+ import '../../chunk-3DIU726S.js';
26
+ import '../../chunk-R7WLWGPO.js';
27
+ import '../../chunk-NVOCKXUQ.js';
28
+ import '../../chunk-V7XHGJQZ.js';
29
+ import '../../chunk-QJ2KCHKX.js';
30
+ import { PAGE_SIZE_DEFAULT } from '../../chunk-IOKL7BKE.js';
31
+ import '../../chunk-RWQIFKMJ.js';
32
+ import '../../chunk-ALA56RGZ.js';
33
+ import '../../chunk-TUXTSEAF.js';
34
+ import '../../chunk-DD3CCMCZ.js';
35
+ import '../../chunk-QEPXAWE2.js';
36
+ import '../../chunk-BRJ3QZ4E.js';
37
+ import '../../chunk-Q7DJKLEN.js';
38
+ import { useMemo, useCallback, useState } from 'react';
39
+ import { Stack, Paper, Group, Pagination, Center, Loader, Alert, Title, Text, Badge, Divider, Code, CopyButton, Tooltip, ActionIcon, Accordion, Button } from '@mantine/core';
40
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
41
+ import { IconAlertCircle, IconBug, IconCheck, IconCopy, IconExternalLink, IconCircleCheck, IconCircleDashed, IconInfoCircle, IconActivity, IconPlus } from '@tabler/icons-react';
42
+
43
+ function ExecutionLogsPage({
44
+ timeRange,
45
+ pageSize = 20,
46
+ onNavigateToExecution,
47
+ renderTrendChart
48
+ }) {
49
+ const { filters, updateFilter, resetFilters } = useExecutionLogsFilters(timeRange);
50
+ const startDate = useMemo(() => {
51
+ const { startDate: sd } = getTimeRangeDates(timeRange);
52
+ return new Date(sd).getTime();
53
+ }, [timeRange]);
54
+ const { page, setPage, offset, totalPages } = usePaginationState(pageSize, [
55
+ filters.resourceId,
56
+ filters.status,
57
+ filters.resourceStatus,
58
+ timeRange
59
+ ]);
60
+ const { data, isLoading } = useExecutionLogs({
61
+ resourceId: filters.resourceId,
62
+ status: filters.status !== "all" ? filters.status : void 0,
63
+ resourceStatus: filters.resourceStatus !== "all" ? filters.resourceStatus : void 0,
64
+ startDate,
65
+ limit: pageSize,
66
+ offset
67
+ });
68
+ const total = data?.total ?? 0;
69
+ return /* @__PURE__ */ jsxs(Stack, { children: [
70
+ /* @__PURE__ */ jsx(PageTitleCaption, { title: "Execution Logs", caption: "View and filter execution history across all resources" }),
71
+ renderTrendChart({ timeRange }),
72
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
73
+ /* @__PURE__ */ jsx(ExecutionLogsFilters, { filters, onFilterChange: updateFilter, onReset: resetFilters }),
74
+ /* @__PURE__ */ jsx(
75
+ ExecutionLogsTable,
76
+ {
77
+ executions: data?.executions || [],
78
+ isLoading,
79
+ onRowClick: onNavigateToExecution
80
+ }
81
+ ),
82
+ totalPages(total) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { value: page, onChange: setPage, total: totalPages(total), size: "sm", boundaries: 1 }) })
83
+ ] }) })
84
+ ] });
85
+ }
86
+ function ExecutionHealth({ timeRange, onErrorClick }) {
87
+ const { data, isLoading, error } = useExecutionHealth({ timeRange });
88
+ const { data: errorData, isLoading: errorLoading, error: errorError } = useErrorAnalysis(timeRange);
89
+ const { startDate, endDate } = useTimeRangeDates(timeRange);
90
+ if (isLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
91
+ return /* @__PURE__ */ jsxs(Stack, { children: [
92
+ /* @__PURE__ */ jsx(
93
+ PageTitleCaption,
94
+ {
95
+ title: "Execution Health",
96
+ caption: "Detailed execution metrics, success rates, and performance trends"
97
+ }
98
+ ),
99
+ /* @__PURE__ */ jsx(ExecutionHealthCard, { data: data?.executionHealth, isLoading, error }),
100
+ /* @__PURE__ */ jsx(
101
+ ErrorBreakdownTable,
102
+ {
103
+ startDate,
104
+ endDate,
105
+ onErrorClick: (executionId) => onErrorClick(executionId)
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsx(ErrorAnalysisCard, { data: errorData, isLoading: errorLoading, error: errorError })
109
+ ] });
110
+ }
111
+ function ErrorDetailsModal({ executionId, opened, onClose, organizationName }) {
112
+ const { data: errors, isLoading, isError } = useErrorDetail(executionId);
113
+ const resolveErrors = useResolveErrorsByExecution();
114
+ const { data: resources } = useResources();
115
+ const resourceNameMap = useMemo(() => {
116
+ const map = /* @__PURE__ */ new Map();
117
+ if (resources) {
118
+ for (const r of [...resources.workflows, ...resources.agents]) {
119
+ map.set(r.resourceId, r.name);
120
+ }
121
+ }
122
+ return map;
123
+ }, [resources]);
124
+ const primaryError = errors?.[0];
125
+ const resolvedResourceName = primaryError ? resourceNameMap.get(primaryError.resourceId) ?? primaryError.resourceId : void 0;
126
+ const allResolved = errors?.every((e) => e.resolved) ?? false;
127
+ const hasRetries = errors && errors.length > 1;
128
+ const handleCopyDetails = () => {
129
+ if (!primaryError) return;
130
+ const detailsText = `
131
+ Error ID: ${primaryError.id}
132
+ Timestamp: ${primaryError.timestamp}
133
+ Type: ${primaryError.errorType}
134
+ Severity: ${primaryError.severity}
135
+ Execution ID: ${primaryError.executionId}
136
+ Resource: ${primaryError.resourceName}
137
+
138
+ Message:
139
+ ${primaryError.message}
140
+
141
+ Stack Trace:
142
+ ${primaryError.stackTrace || "No stack trace available"}
143
+
144
+ Context:
145
+ ${primaryError.errorContext ? JSON.stringify(primaryError.errorContext, null, 2) : "No context available"}
146
+ `.trim();
147
+ navigator.clipboard.writeText(detailsText);
148
+ };
149
+ return /* @__PURE__ */ jsx(CustomModal, { opened, onClose, size: "xl", children: /* @__PURE__ */ jsxs(Stack, { children: [
150
+ isLoading && /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }),
151
+ isError && /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, {}), title: "Error Loading Details", children: "Failed to load error details. Please try again." }),
152
+ !isLoading && !isError && !primaryError && /* @__PURE__ */ jsx(Alert, { color: "gray", icon: /* @__PURE__ */ jsx(IconBug, {}), children: "No error details found for this execution." }),
153
+ !isLoading && !isError && primaryError && /* @__PURE__ */ jsxs(Fragment, { children: [
154
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
155
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
156
+ /* @__PURE__ */ jsx(IconAlertCircle, { size: 24, color: "var(--color-error)" }),
157
+ /* @__PURE__ */ jsxs("div", { children: [
158
+ /* @__PURE__ */ jsx(Title, { order: 3, children: primaryError.errorType }),
159
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: new Date(primaryError.timestamp).toLocaleString("en-US", {
160
+ month: "long",
161
+ day: "numeric",
162
+ year: "numeric",
163
+ hour: "2-digit",
164
+ minute: "2-digit",
165
+ second: "2-digit"
166
+ }) })
167
+ ] })
168
+ ] }),
169
+ /* @__PURE__ */ jsx(
170
+ Badge,
171
+ {
172
+ color: primaryError.severity === "critical" ? "red" : primaryError.severity === "warning" ? "orange" : "blue",
173
+ variant: "light",
174
+ children: primaryError.severity
175
+ }
176
+ )
177
+ ] }),
178
+ /* @__PURE__ */ jsx(Divider, {}),
179
+ /* @__PURE__ */ jsxs("div", { children: [
180
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Error Message" }),
181
+ /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconBug, { size: 16 }), children: primaryError.message })
182
+ ] }),
183
+ hasRetries && /* @__PURE__ */ jsxs(Alert, { color: "yellow", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), children: [
184
+ "This execution has ",
185
+ errors.length,
186
+ " errors (including retries). Showing most recent error."
187
+ ] }),
188
+ /* @__PURE__ */ jsxs("div", { children: [
189
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Execution Context" }),
190
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
191
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
192
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Execution ID" }),
193
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
194
+ /* @__PURE__ */ jsx(Code, { children: primaryError.executionId }),
195
+ /* @__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 }) }) }) }),
196
+ /* @__PURE__ */ jsx(
197
+ ActionIcon,
198
+ {
199
+ variant: "subtle",
200
+ size: "sm",
201
+ component: "a",
202
+ href: `/operations/resources/workflow/${primaryError.resourceId}`,
203
+ target: "_blank",
204
+ title: "View Execution Log",
205
+ children: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 })
206
+ }
207
+ )
208
+ ] })
209
+ ] }),
210
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
211
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Resource Name" }),
212
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: resolvedResourceName })
213
+ ] }),
214
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
215
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Resource ID" }),
216
+ /* @__PURE__ */ jsx(Code, { children: primaryError.resourceId })
217
+ ] }),
218
+ primaryError.retryAttempt && /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
219
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Retry Attempt" }),
220
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: primaryError.retryAttempt })
221
+ ] }),
222
+ primaryError.stepName && /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
223
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Step Name" }),
224
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: primaryError.stepName })
225
+ ] })
226
+ ] })
227
+ ] }),
228
+ primaryError.stackTrace && /* @__PURE__ */ jsxs("div", { children: [
229
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", mb: "xs", children: [
230
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Stack Trace" }),
231
+ /* @__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 }) }) }) })
232
+ ] }),
233
+ /* @__PURE__ */ jsx(
234
+ Code,
235
+ {
236
+ block: true,
237
+ style: {
238
+ maxHeight: 300,
239
+ overflow: "auto",
240
+ fontSize: "12px",
241
+ lineHeight: "1.5"
242
+ },
243
+ children: primaryError.stackTrace
244
+ }
245
+ )
246
+ ] }),
247
+ primaryError.errorContext && /* @__PURE__ */ jsxs("div", { children: [
248
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Error Context" }),
249
+ /* @__PURE__ */ jsx(JsonViewer, { data: primaryError.errorContext, maxHeight: 200, fontSize: "12px" })
250
+ ] }),
251
+ primaryError.executionContext && /* @__PURE__ */ jsxs("div", { children: [
252
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Execution Context" }),
253
+ /* @__PURE__ */ jsx(JsonViewer, { data: primaryError.executionContext, maxHeight: 200, fontSize: "12px" })
254
+ ] }),
255
+ hasRetries && /* @__PURE__ */ jsxs("div", { children: [
256
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "All Errors (including retries)" }),
257
+ /* @__PURE__ */ jsx(Accordion, { children: errors.map((error, index) => /* @__PURE__ */ jsxs(Accordion.Item, { value: error.id, children: [
258
+ /* @__PURE__ */ jsx(Accordion.Control, { children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
259
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
260
+ "Attempt ",
261
+ error.retryAttempt || index + 1,
262
+ " - ",
263
+ error.errorType
264
+ ] }),
265
+ /* @__PURE__ */ jsx(
266
+ Badge,
267
+ {
268
+ size: "sm",
269
+ color: error.severity === "critical" ? "red" : error.severity === "warning" ? "orange" : "blue",
270
+ children: error.severity
271
+ }
272
+ )
273
+ ] }) }),
274
+ /* @__PURE__ */ jsx(Accordion.Panel, { children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
275
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: error.message }),
276
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: new Date(error.timestamp).toLocaleString() }),
277
+ error.stackTrace && /* @__PURE__ */ jsx(Code, { block: true, style: { fontSize: "11px", maxHeight: 150, overflow: "auto" }, children: error.stackTrace })
278
+ ] }) })
279
+ ] }, error.id)) })
280
+ ] }),
281
+ /* @__PURE__ */ jsx(Divider, {}),
282
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
283
+ /* @__PURE__ */ jsxs(Group, { children: [
284
+ /* @__PURE__ */ jsx(Button, { variant: "light", leftSection: /* @__PURE__ */ jsx(IconCopy, { size: 16 }), onClick: handleCopyDetails, children: "Copy Error Details" }),
285
+ allResolved ? /* @__PURE__ */ jsx(
286
+ Badge,
287
+ {
288
+ size: "lg",
289
+ color: "green",
290
+ variant: "light",
291
+ leftSection: /* @__PURE__ */ jsx(IconCircleCheck, { size: 14 }),
292
+ style: { cursor: "default" },
293
+ children: "Resolved"
294
+ }
295
+ ) : /* @__PURE__ */ jsx(
296
+ Button,
297
+ {
298
+ variant: "light",
299
+ color: "teal",
300
+ leftSection: /* @__PURE__ */ jsx(IconCircleDashed, { size: 16 }),
301
+ loading: resolveErrors.isPending,
302
+ onClick: () => executionId && resolveErrors.mutate(executionId),
303
+ children: "Resolve"
304
+ }
305
+ )
306
+ ] }),
307
+ /* @__PURE__ */ jsxs(Group, { children: [
308
+ /* @__PURE__ */ jsx(Button, { variant: "default", onClick: onClose, children: "Close" }),
309
+ /* @__PURE__ */ jsx(
310
+ Button,
311
+ {
312
+ component: "a",
313
+ href: `/operations/resources/workflow/${primaryError.resourceId}`,
314
+ target: "_blank",
315
+ leftSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 }),
316
+ children: "View Execution Log"
317
+ }
318
+ )
319
+ ] })
320
+ ] })
321
+ ] })
322
+ ] }) });
323
+ }
324
+ function CostAnalytics({ timeRange }) {
325
+ const { data: trendsData, isLoading: trendsLoading, error: trendsError } = useCostTrends(timeRange);
326
+ const { data: summaryData } = useCostSummary(timeRange);
327
+ const { data: modelData, isLoading: modelLoading, error: modelError } = useCostByModel(timeRange);
328
+ if (trendsLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
329
+ return /* @__PURE__ */ jsxs(Stack, { children: [
330
+ /* @__PURE__ */ jsx(
331
+ PageTitleCaption,
332
+ {
333
+ title: "Cost Analytics",
334
+ caption: "Comprehensive cost tracking, budgets, ROI analysis, and labor savings"
335
+ }
336
+ ),
337
+ /* @__PURE__ */ jsx(CostTrendChart, { data: trendsData, summaryData, isLoading: trendsLoading, error: trendsError }),
338
+ /* @__PURE__ */ jsx(CostByModelTable, { data: modelData, isLoading: modelLoading, error: modelError })
339
+ ] });
340
+ }
341
+ function getNavigationPath(activity) {
342
+ switch (activity.activityType) {
343
+ case "workflow_execution":
344
+ return `/operations/resources/workflow/${activity.entityId}`;
345
+ case "agent_run":
346
+ return `/operations/resources/agent/${activity.entityId}`;
347
+ case "hitl_action":
348
+ return "/command-queue";
349
+ case "credential_change":
350
+ return "/settings/credentials";
351
+ case "api_key_change":
352
+ return "/settings/api-keys";
353
+ case "deployment_change":
354
+ return "/settings/deployments";
355
+ case "membership_change":
356
+ return "/settings/organization";
357
+ default:
358
+ return null;
359
+ }
360
+ }
361
+ function ActivityLog({ timeRange, pageSize = PAGE_SIZE_DEFAULT, onNavigate }) {
362
+ const { filters, updateFilter, resetFilters } = useActivityFilters(timeRange);
363
+ const startDate = useMemo(() => {
364
+ const { startDate: startDate2 } = getTimeRangeDates(timeRange);
365
+ return startDate2;
366
+ }, [timeRange]);
367
+ const activityType = filters.activityType !== "all" ? filters.activityType : void 0;
368
+ const { page, setPage, offset, totalPages } = usePaginationState(pageSize, [
369
+ filters.activityType,
370
+ filters.status,
371
+ filters.search,
372
+ timeRange
373
+ ]);
374
+ const { data: chartData, isLoading: isChartLoading } = useActivityTrend({
375
+ activityType,
376
+ startDate
377
+ });
378
+ const tableParams = useMemo(() => {
379
+ const params = {
380
+ limit: pageSize,
381
+ offset,
382
+ startDate
383
+ };
384
+ if (filters.activityType && filters.activityType !== "all") {
385
+ params.activityType = filters.activityType;
386
+ }
387
+ if (filters.status && filters.status !== "all") {
388
+ params.status = filters.status;
389
+ }
390
+ if (filters.search?.trim()) {
391
+ params.search = filters.search.trim();
392
+ }
393
+ return params;
394
+ }, [offset, startDate, filters.activityType, filters.status, filters.search, pageSize]);
395
+ const { data: tableData, isLoading: isTableLoading } = useActivities(tableParams);
396
+ const total = tableData?.total ?? 0;
397
+ const handleRowClick = useCallback(
398
+ (activity) => {
399
+ const path = getNavigationPath(activity);
400
+ if (path) {
401
+ onNavigate(path);
402
+ }
403
+ },
404
+ [onNavigate]
405
+ );
406
+ if (isChartLoading && isTableLoading) return /* @__PURE__ */ jsx(AppShellLoader, {});
407
+ return /* @__PURE__ */ jsxs(Stack, { children: [
408
+ /* @__PURE__ */ jsx(
409
+ PageTitleCaption,
410
+ {
411
+ title: "Activity Log",
412
+ caption: "Real-time activity feed with automatic updates every 30 seconds"
413
+ }
414
+ ),
415
+ /* @__PURE__ */ jsx(
416
+ ActivityTrendChart,
417
+ {
418
+ timestamps: chartData?.timestamps ?? [],
419
+ total: chartData?.total ?? 0,
420
+ isLoading: isChartLoading,
421
+ timeRange
422
+ }
423
+ ),
424
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
425
+ /* @__PURE__ */ jsx(ActivityFilters, { filters, onFilterChange: updateFilter, onReset: resetFilters }),
426
+ /* @__PURE__ */ jsx(
427
+ ActivityTable,
428
+ {
429
+ activities: tableData?.activities ?? [],
430
+ isLoading: isTableLoading,
431
+ onRowClick: handleRowClick
432
+ }
433
+ ),
434
+ totalPages(total) > 1 && /* @__PURE__ */ jsx(Group, { justify: "flex-start", children: /* @__PURE__ */ jsx(Pagination, { value: page, onChange: setPage, total: totalPages(total), size: "sm", boundaries: 1 }) })
435
+ ] }) })
436
+ ] });
437
+ }
438
+ function ActivityFeed({
439
+ limit = 50,
440
+ activityType,
441
+ entityType,
442
+ entityId,
443
+ filters,
444
+ clientFilters,
445
+ overrideData,
446
+ overrideLoading
447
+ }) {
448
+ const [currentLimit, setCurrentLimit] = useState(limit);
449
+ const shouldFetch = !overrideData;
450
+ const fetchResult = useActivities({
451
+ limit: currentLimit,
452
+ activityType: filters?.activityType || activityType,
453
+ entityType,
454
+ entityId,
455
+ startDate: filters?.startDate
456
+ });
457
+ const data = overrideData ?? fetchResult.data;
458
+ const error = shouldFetch ? fetchResult.error : null;
459
+ const isLoading = overrideLoading ?? (shouldFetch ? fetchResult.isLoading : false);
460
+ const handleLoadMore = () => {
461
+ setCurrentLimit((prev) => prev + 50);
462
+ };
463
+ const filteredActivities = useMemo(() => {
464
+ if (!data?.activities) return [];
465
+ let filtered = data.activities;
466
+ if (clientFilters?.status) {
467
+ filtered = filtered.filter((activity) => activity.status === clientFilters.status);
468
+ }
469
+ if (clientFilters?.search) {
470
+ const searchLower = clientFilters.search.toLowerCase();
471
+ filtered = filtered.filter(
472
+ (activity) => activity.title.toLowerCase().includes(searchLower) || activity.description?.toLowerCase().includes(searchLower) || activity.entityName?.toLowerCase().includes(searchLower)
473
+ );
474
+ }
475
+ return filtered;
476
+ }, [data?.activities, clientFilters]);
477
+ if (isLoading) {
478
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
479
+ }
480
+ if (error) {
481
+ 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" }) });
482
+ }
483
+ if (!filteredActivities.length) {
484
+ return /* @__PURE__ */ jsx(EmptyState, { icon: IconActivity, title: "No activities found" });
485
+ }
486
+ const hasMore = data ? data.total > currentLimit : false;
487
+ const showingCount = filteredActivities.length;
488
+ const totalCount = data?.total || 0;
489
+ return /* @__PURE__ */ jsxs(Stack, { children: [
490
+ /* @__PURE__ */ jsx(Group, { justify: "space-between", children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
491
+ "Showing ",
492
+ showingCount,
493
+ " of ",
494
+ totalCount,
495
+ " activities"
496
+ ] }) }),
497
+ /* @__PURE__ */ jsx(Stack, { children: filteredActivities.map((activity) => /* @__PURE__ */ jsx(ActivityCard, { activity }, activity.id)) }),
498
+ hasMore && /* @__PURE__ */ jsx(Center, { children: /* @__PURE__ */ jsx(Button, { variant: "light", onClick: handleLoadMore, loading: isLoading, children: "Load More" }) })
499
+ ] });
500
+ }
501
+ function NotificationCenter({ pageSize = 20 }) {
502
+ const { page, setPage, offset, totalPages } = usePaginationState(pageSize);
503
+ const { data, isLoading } = useNotifications({ limit: pageSize, offset });
504
+ const notifications = data?.notifications ?? [];
505
+ const markAllAsRead = useMarkAllAsRead();
506
+ const testNotification = useTestNotification();
507
+ const hasUnread = notifications.some((n) => !n.read);
508
+ const handleMarkAllAsRead = async () => {
509
+ await markAllAsRead.mutateAsync();
510
+ };
511
+ const handleCreateTest = async () => {
512
+ await testNotification.mutateAsync();
513
+ };
514
+ const isDevelopment = process.env.NODE_ENV === "development";
515
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
516
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
517
+ /* @__PURE__ */ jsx(Title, { order: 1, children: "Notifications" }),
518
+ /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
519
+ isDevelopment && /* @__PURE__ */ jsx(
520
+ Button,
521
+ {
522
+ variant: "light",
523
+ size: "sm",
524
+ leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 16 }),
525
+ onClick: handleCreateTest,
526
+ loading: testNotification.isPending,
527
+ children: "Create Test Notification"
528
+ }
529
+ ),
530
+ hasUnread && /* @__PURE__ */ jsx(Button, { variant: "light", size: "sm", onClick: handleMarkAllAsRead, loading: markAllAsRead.isPending, children: "Mark all as read" })
531
+ ] })
532
+ ] }),
533
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsx(NotificationList, { notifications, isLoading }) }),
534
+ 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 }) })
535
+ ] });
536
+ }
537
+
538
+ export { ActivityFeed, ActivityLog, CostAnalytics, ErrorDetailsModal, ExecutionHealth, ExecutionLogsPage, NotificationCenter };
@@ -91,6 +91,9 @@
91
91
  animation: chevronPulse 2s ease-in-out infinite;
92
92
  filter: drop-shadow(0 0 1.5px var(--loader-color));
93
93
  }
94
+ [data-mantine-color-scheme=light] .chevron {
95
+ filter: none;
96
+ }
94
97
  .c1 {
95
98
  animation-delay: 0s;
96
99
  }
@@ -110,6 +113,17 @@
110
113
  filter: drop-shadow(0 0 3px var(--loader-color));
111
114
  }
112
115
  }
116
+ [data-mantine-color-scheme=light] .chevron {
117
+ animation-name: chevronPulseLight;
118
+ }
119
+ @keyframes chevronPulseLight {
120
+ 0%, 100% {
121
+ opacity: 0.2;
122
+ }
123
+ 40%, 60% {
124
+ opacity: 1;
125
+ }
126
+ }
113
127
 
114
128
  /* src/theme/custom.css */
115
129
  .mantine-Accordion-control:hover {