@elevasis/ui 1.8.0 → 1.8.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.
- package/dist/charts/index.js +2 -2
- package/dist/{chunk-EHXOR5LA.js → chunk-3I2P4XG6.js} +1 -1
- package/dist/{chunk-YZ6GTZXL.js → chunk-ELJIFLCB.js} +4 -1
- package/dist/chunk-WSVFUERF.js +1438 -0
- package/dist/{chunk-3Q5V2T6L.js → chunk-XA34RETF.js} +1 -1
- package/dist/components/index.d.ts +666 -2
- package/dist/components/index.js +3562 -32
- package/dist/execution/index.js +2 -2
- package/dist/index.js +3 -3
- package/dist/layout/index.js +3 -1438
- package/package.json +3 -3
package/dist/components/index.js
CHANGED
|
@@ -1,42 +1,48 @@
|
|
|
1
|
-
import { useCyberColors, EmptyState, CyberLegendItem, CyberAreaChart, APIErrorAlert, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, ContextViewer, JsonViewer, StyledMarkdown } from '../chunk-
|
|
2
|
-
export { APIErrorAlert, CardHeader, CollapsibleSection, ContextViewer, CustomSelector, DetailCardSkeleton, EmptyState, JsonViewer, ListSkeleton, PageNotFound, PageTitleCaption, ResourceCard, StatCard, StatCardSkeleton, StatsCardSkeleton, StyledMarkdown, TabCountBadge, TimeRangeSelector, TrendIndicator, catalogItemToResourceDefinition } from '../chunk-
|
|
1
|
+
import { useCyberColors, EmptyState, CyberLegendItem, CyberAreaChart, APIErrorAlert, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, ContextViewer, JsonViewer, StyledMarkdown, PageTitleCaption, StatCard, CyberDonut, CollapsibleSection } from '../chunk-3I2P4XG6.js';
|
|
2
|
+
export { APIErrorAlert, CardHeader, CollapsibleSection, ContextViewer, CustomSelector, DetailCardSkeleton, EmptyState, JsonViewer, ListSkeleton, PageNotFound, PageTitleCaption, ResourceCard, StatCard, StatCardSkeleton, StatsCardSkeleton, StyledMarkdown, TabCountBadge, TimeRangeSelector, TrendIndicator, catalogItemToResourceDefinition } from '../chunk-3I2P4XG6.js';
|
|
3
|
+
import { SubshellLoader, SubshellContainer, SubshellSidebar, SubshellRightSideContainer, SubshellContentContainer, PageContainer, AppShellLoader, SubshellSidebarSection, CollapsibleSidebarGroup, SidebarListItem } from '../chunk-WSVFUERF.js';
|
|
4
|
+
import { ElevasisLoader } from '../chunk-YGYF6G7W.js';
|
|
3
5
|
export { ElevasisLoader, NavigationButton } from '../chunk-YGYF6G7W.js';
|
|
6
|
+
import { showApiErrorNotification, showSuccessNotification, showErrorNotification } from '../chunk-QWYJHM3S.js';
|
|
4
7
|
export { showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification } from '../chunk-QWYJHM3S.js';
|
|
5
|
-
import { useResourcesHealth, useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead, useMarkAllAsRead, useNotificationCount, useNotifications, useSubmitAction, useDeleteTask } from '../chunk-BWZMI4KP.js';
|
|
8
|
+
import { useCommandViewLayout, useResourcesHealth, useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead, useMarkAllAsRead, useNotificationCount, useNotifications, useSubmitAction, useDeleteTask, useErrorDetail, useExecution, useDeleteExecution, useRetryExecution, useCancelExecution, useResources, useResourceDefinition, isSessionCapable, useDeploymentDocs, useCreateSchedule, useListSchedules, usePauseSchedule, useResumeSchedule, useCancelSchedule, useDeleteSchedule, useCommandQueueTotals } from '../chunk-BWZMI4KP.js';
|
|
6
9
|
import { getTimeRangeDates, formatBucketTime } from '../chunk-ARZM3OTI.js';
|
|
7
10
|
import '../chunk-JGJSZ3UE.js';
|
|
8
11
|
import '../chunk-LHQTTUL2.js';
|
|
9
|
-
import { Graph_module_css_default, useDirectedChainHighlighting, useNodeSelection, useFitViewTrigger, useGraphHighlighting, calculateGraphHeight
|
|
12
|
+
import { Graph_module_css_default, useDirectedChainHighlighting, useNodeSelection, GRAPH_CONSTANTS, useFitViewTrigger, useGraphHighlighting, calculateGraphHeight } from '../chunk-F6RBK7NJ.js';
|
|
10
13
|
export { Graph_module_css_default as graphStyles } from '../chunk-F6RBK7NJ.js';
|
|
11
|
-
import { STATUS_COLORS, getStatusIcon, formatDuration, getStatusColors, AGENT_CONSTANTS, shouldAnimateEdge, TIMELINE_CONSTANTS, calculateBarPosition, CONTAINER_CONSTANTS, useExecutionPath, useUnifiedWorkflowLayout, WORKFLOW_CONSTANTS, useReactFlowAgent } from '../chunk-
|
|
12
|
-
export { CONTAINER_CONSTANTS, SHARED_VIZ_CONSTANTS } from '../chunk-
|
|
13
|
-
import '../chunk-
|
|
14
|
+
import { STATUS_COLORS, getStatusIcon, formatDuration, getStatusColors, AGENT_CONSTANTS, shouldAnimateEdge, TIMELINE_CONSTANTS, calculateBarPosition, CONTAINER_CONSTANTS, useExecutionPath, useUnifiedWorkflowLayout, WORKFLOW_CONSTANTS, useReactFlowAgent, getResourceStatusColor } from '../chunk-XA34RETF.js';
|
|
15
|
+
export { CONTAINER_CONSTANTS, SHARED_VIZ_CONSTANTS } from '../chunk-XA34RETF.js';
|
|
16
|
+
import { ResourceStatusColors, toWorkflowLogMessages } from '../chunk-ELJIFLCB.js';
|
|
14
17
|
import '../chunk-3I2LOKQU.js';
|
|
18
|
+
import '../chunk-3PURTICE.js';
|
|
15
19
|
import '../chunk-RNP5R5I3.js';
|
|
16
20
|
import '../chunk-ESOQEOOX.js';
|
|
17
21
|
import '../chunk-KB5NKPTN.js';
|
|
18
22
|
import '../chunk-JRJW2H57.js';
|
|
19
23
|
import '../chunk-2YBPRE6H.js';
|
|
20
24
|
import '../chunk-JUPCUF77.js';
|
|
21
|
-
import { formatChartAxisDate, PAGE_SIZE_DEFAULT, getErrorInfo, formatErrorMessage } from '../chunk-Z4TPHMRD.js';
|
|
25
|
+
import { getResourceIcon, getResourceColor, formatChartAxisDate, PAGE_SIZE_DEFAULT, getErrorInfo, formatErrorMessage } from '../chunk-Z4TPHMRD.js';
|
|
22
26
|
import '../chunk-6TMW6VQ2.js';
|
|
23
27
|
import '../chunk-FWZJH3TL.js';
|
|
24
|
-
import '../chunk-WUQWCUCB.js';
|
|
25
|
-
import '../chunk-GZVH423C.js';
|
|
26
|
-
import '../chunk-DD3CCMCZ.js';
|
|
28
|
+
import { useInitialization } from '../chunk-WUQWCUCB.js';
|
|
29
|
+
import { useElevasisServices } from '../chunk-GZVH423C.js';
|
|
30
|
+
import { useOrganization } from '../chunk-DD3CCMCZ.js';
|
|
27
31
|
import '../chunk-7PLEQFHO.js';
|
|
28
32
|
import { useRouterContext } from '../chunk-Q7DJKLEN.js';
|
|
29
|
-
import { Paper, Stack, Text, Group, Badge, Box, useComputedColorScheme, Modal, Center, Space, Button, Title, TextInput, Table, Textarea, Radio, Checkbox, Select, NumberInput, Tooltip,
|
|
33
|
+
import { Paper, Stack, Text, Group, Badge, Box, ThemeIcon, useComputedColorScheme, Card, ActionIcon, Modal, Center, Space, Button, Title, TextInput, Table, Textarea, Radio, Checkbox, Select, NumberInput, Tooltip, Loader, SegmentedControl, NumberFormatter, Alert, Switch, Pagination, UnstyledButton, Divider, ScrollArea, Popover, Indicator, Menu, Accordion, Collapse, SimpleGrid, CopyButton, Code, useMantineTheme, Timeline, RangeSlider, Progress } from '@mantine/core';
|
|
30
34
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
31
|
-
import { memo, useMemo, cloneElement, useState, useEffect, useCallback, Fragment as Fragment$1 } from 'react';
|
|
32
|
-
import { IconPlayerPlay, IconPlayerStop, IconArrowsSplit, IconSquare, IconBrain, IconFileText,
|
|
35
|
+
import { memo, forwardRef, useMemo, useImperativeHandle, cloneElement, useState, useEffect, useCallback, Fragment as Fragment$1, useRef } from 'react';
|
|
36
|
+
import { IconPlayerPlay, IconPlayerStop, IconArrowsSplit, IconSquare, IconBrain, IconFileText, IconDatabase, IconMessage, IconAlertCircle, IconCircleX, IconCircleCheck, IconBolt, IconHandClick, IconClock, IconWebhook, IconExternalLink, IconFocus2, IconMail, IconSend, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconChevronUp, IconChevronDown, IconSelector, IconTrash, IconChartBar, IconThumbDown, IconThumbUp, IconSearch, IconFilterOff, IconArrowUpRight, IconDownload, IconInfoCircle, IconBug, IconChecks, IconCircle, IconCircleFilled, IconBell, IconRobot, IconGitBranch, IconDotsVertical, IconChevronRight, IconTool, IconSettings, IconCpu, IconClockHour4, IconVersions, IconNetwork, IconSitemap, IconCopy, IconReload, IconArrowLeft, IconBook2, IconFileOff, IconList, IconCalendarRepeat, IconCalendarEvent, IconCalendarTime, IconPlus, IconCalendar, IconKey, IconPlayerPause, IconCalendarDue, IconCalendarStats, IconCalendarOff, IconListCheck, IconFilter, IconCategory, IconArrowDown, IconUser, IconFolderOpen, IconFolder } from '@tabler/icons-react';
|
|
33
37
|
import { AreaChart } from '@mantine/charts';
|
|
34
38
|
import { formatDistanceToNow } from 'date-fns';
|
|
35
|
-
import { useDisclosure } from '@mantine/hooks';
|
|
36
|
-
import { Position, Handle, getSmoothStepPath, BaseEdge as BaseEdge$1, EdgeLabelRenderer,
|
|
39
|
+
import { useDisclosure, useClipboard } from '@mantine/hooks';
|
|
40
|
+
import { Position, Handle, getSmoothStepPath, BaseEdge as BaseEdge$1, EdgeLabelRenderer, useReactFlow, ReactFlow, ReactFlowProvider, Panel, Controls } from '@xyflow/react';
|
|
37
41
|
import '@xyflow/react/dist/style.css';
|
|
38
42
|
import { useForm } from '@mantine/form';
|
|
39
43
|
import dagre from '@dagrejs/dagre';
|
|
44
|
+
import { notifications } from '@mantine/notifications';
|
|
45
|
+
import { useNavigate } from '@tanstack/react-router';
|
|
40
46
|
|
|
41
47
|
var CustomModal = ({ children, opened, onClose, loading, style, size }) => {
|
|
42
48
|
const canClose = loading === true ? false : true;
|
|
@@ -1560,18 +1566,18 @@ function NotificationItem({ notification, onClose, onNavigate }) {
|
|
|
1560
1566
|
}
|
|
1561
1567
|
);
|
|
1562
1568
|
}
|
|
1563
|
-
function NotificationList({ notifications, isLoading, onClose, onNavigate }) {
|
|
1569
|
+
function NotificationList({ notifications: notifications2, isLoading, onClose, onNavigate }) {
|
|
1564
1570
|
if (isLoading) {
|
|
1565
1571
|
return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) });
|
|
1566
1572
|
}
|
|
1567
|
-
if (
|
|
1573
|
+
if (notifications2.length === 0) {
|
|
1568
1574
|
return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No notifications" }) });
|
|
1569
1575
|
}
|
|
1570
|
-
return /* @__PURE__ */ jsx(Stack, { gap: 0, children:
|
|
1576
|
+
return /* @__PURE__ */ jsx(Stack, { gap: 0, children: notifications2.map((notification) => /* @__PURE__ */ jsx(NotificationItem, { notification, onClose, onNavigate }, notification.id)) });
|
|
1571
1577
|
}
|
|
1572
|
-
function NotificationPanel({ notifications, isLoading, onClose, onNavigate }) {
|
|
1578
|
+
function NotificationPanel({ notifications: notifications2, isLoading, onClose, onNavigate }) {
|
|
1573
1579
|
const markAllAsRead = useMarkAllAsRead();
|
|
1574
|
-
const hasUnread =
|
|
1580
|
+
const hasUnread = notifications2.some((n) => !n.read);
|
|
1575
1581
|
const handleMarkAllAsRead = async () => {
|
|
1576
1582
|
await markAllAsRead.mutateAsync();
|
|
1577
1583
|
};
|
|
@@ -1584,7 +1590,7 @@ function NotificationPanel({ notifications, isLoading, onClose, onNavigate }) {
|
|
|
1584
1590
|
/* @__PURE__ */ jsx(ScrollArea, { h: 400, type: "auto", children: /* @__PURE__ */ jsx(
|
|
1585
1591
|
NotificationList,
|
|
1586
1592
|
{
|
|
1587
|
-
notifications,
|
|
1593
|
+
notifications: notifications2,
|
|
1588
1594
|
isLoading,
|
|
1589
1595
|
onClose,
|
|
1590
1596
|
onNavigate
|
|
@@ -1596,14 +1602,14 @@ function NotificationBell({ unreadCount, onNavigate }) {
|
|
|
1596
1602
|
const [opened, { toggle, close }] = useDisclosure(false);
|
|
1597
1603
|
const { data: apiCount = 0 } = useNotificationCount();
|
|
1598
1604
|
const { data, isLoading } = useNotifications({ limit: 20 });
|
|
1599
|
-
const
|
|
1605
|
+
const notifications2 = data?.notifications ?? [];
|
|
1600
1606
|
const count = unreadCount ?? apiCount;
|
|
1601
1607
|
return /* @__PURE__ */ jsxs(Popover, { opened, onChange: toggle, position: "bottom-end", width: 400, children: [
|
|
1602
1608
|
/* @__PURE__ */ jsx(Tooltip, { label: "Notifications", disabled: opened, children: /* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(Indicator, { label: count > 99 ? "99+" : count, disabled: count === 0, size: 16, offset: 4, children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "lg", onClick: toggle, children: /* @__PURE__ */ jsx(IconBell, { size: 20, color: "var(--color-text-subtle)" }) }) }) }) }),
|
|
1603
1609
|
/* @__PURE__ */ jsx(Popover.Dropdown, { p: 0, children: /* @__PURE__ */ jsx(
|
|
1604
1610
|
NotificationPanel,
|
|
1605
1611
|
{
|
|
1606
|
-
notifications,
|
|
1612
|
+
notifications: notifications2,
|
|
1607
1613
|
isLoading,
|
|
1608
1614
|
onClose: close,
|
|
1609
1615
|
onNavigate
|
|
@@ -2944,12 +2950,12 @@ function TaskCard({ task, onViewExecution, richTextRenderer }) {
|
|
|
2944
2950
|
}
|
|
2945
2951
|
setConfirmAction(null);
|
|
2946
2952
|
};
|
|
2947
|
-
const
|
|
2953
|
+
const getPriorityColor2 = (priority) => {
|
|
2948
2954
|
if (priority >= 8) return "red";
|
|
2949
2955
|
if (priority >= 5) return "yellow";
|
|
2950
2956
|
return "gray";
|
|
2951
2957
|
};
|
|
2952
|
-
const
|
|
2958
|
+
const getStatusColor4 = (status) => {
|
|
2953
2959
|
switch (status) {
|
|
2954
2960
|
case "pending":
|
|
2955
2961
|
return "blue";
|
|
@@ -2974,7 +2980,7 @@ function TaskCard({ task, onViewExecution, richTextRenderer }) {
|
|
|
2974
2980
|
});
|
|
2975
2981
|
}
|
|
2976
2982
|
};
|
|
2977
|
-
const
|
|
2983
|
+
const formatDate2 = (date) => {
|
|
2978
2984
|
const now = /* @__PURE__ */ new Date();
|
|
2979
2985
|
const diffMs = now.getTime() - date.getTime();
|
|
2980
2986
|
const diffMins = Math.floor(diffMs / 6e4);
|
|
@@ -3002,7 +3008,7 @@ function TaskCard({ task, onViewExecution, richTextRenderer }) {
|
|
|
3002
3008
|
/* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
|
|
3003
3009
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", mb: 4, children: [
|
|
3004
3010
|
/* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: task.description || "Task approval required" }),
|
|
3005
|
-
/* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "light", color:
|
|
3011
|
+
/* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "light", color: getPriorityColor2(task.priority), radius: "sm", children: [
|
|
3006
3012
|
"P",
|
|
3007
3013
|
task.priority
|
|
3008
3014
|
] })
|
|
@@ -3016,7 +3022,7 @@ function TaskCard({ task, onViewExecution, richTextRenderer }) {
|
|
|
3016
3022
|
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2022" }),
|
|
3017
3023
|
/* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
3018
3024
|
/* @__PURE__ */ jsx(IconClock, { size: 12 }),
|
|
3019
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children:
|
|
3025
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatDate2(task.createdAt) })
|
|
3020
3026
|
] })
|
|
3021
3027
|
] })
|
|
3022
3028
|
] })
|
|
@@ -3027,7 +3033,7 @@ function TaskCard({ task, onViewExecution, richTextRenderer }) {
|
|
|
3027
3033
|
{
|
|
3028
3034
|
size: "sm",
|
|
3029
3035
|
variant: "light",
|
|
3030
|
-
color:
|
|
3036
|
+
color: getStatusColor4(task.status),
|
|
3031
3037
|
radius: "sm",
|
|
3032
3038
|
leftSection: task.status === "processing" ? /* @__PURE__ */ jsx(Loader, { size: 6 }) : void 0,
|
|
3033
3039
|
children: task.status.charAt(0).toUpperCase() + task.status.slice(1)
|
|
@@ -3084,7 +3090,7 @@ function TaskCard({ task, onViewExecution, richTextRenderer }) {
|
|
|
3084
3090
|
task.actionPayload !== void 0 && task.actionPayload !== null && /* @__PURE__ */ jsx(JsonViewer, { data: task.actionPayload, maxHeight: 200 }),
|
|
3085
3091
|
task.completedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
3086
3092
|
"Completed ",
|
|
3087
|
-
|
|
3093
|
+
formatDate2(task.completedAt),
|
|
3088
3094
|
task.completedBy ? ` by ${task.completedBy}` : ""
|
|
3089
3095
|
] }),
|
|
3090
3096
|
task.targetExecutionId && /* @__PURE__ */ jsx(
|
|
@@ -3791,4 +3797,3528 @@ function ResourceDefinitionSection({
|
|
|
3791
3797
|
return /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", fs: "italic", children: "Unknown resource type" }) });
|
|
3792
3798
|
}
|
|
3793
3799
|
|
|
3794
|
-
|
|
3800
|
+
// src/components/operations/executions/logConstants.ts
|
|
3801
|
+
var LOG_LEVEL_CONFIG = {
|
|
3802
|
+
debug: {
|
|
3803
|
+
label: "DEBUG",
|
|
3804
|
+
color: "gray",
|
|
3805
|
+
textColor: "var(--color-text-subtle)",
|
|
3806
|
+
icon: "\u{1F50D}"
|
|
3807
|
+
},
|
|
3808
|
+
info: {
|
|
3809
|
+
label: "INFO",
|
|
3810
|
+
color: "blue",
|
|
3811
|
+
textColor: "var(--color-text-dimmed)",
|
|
3812
|
+
icon: "\u2139\uFE0F"
|
|
3813
|
+
},
|
|
3814
|
+
warn: {
|
|
3815
|
+
label: "WARN",
|
|
3816
|
+
color: "yellow",
|
|
3817
|
+
textColor: "var(--color-warning)",
|
|
3818
|
+
icon: "\u26A0\uFE0F"
|
|
3819
|
+
},
|
|
3820
|
+
error: {
|
|
3821
|
+
label: "ERROR",
|
|
3822
|
+
color: "red",
|
|
3823
|
+
textColor: "var(--color-error)",
|
|
3824
|
+
icon: "\u274C"
|
|
3825
|
+
}
|
|
3826
|
+
};
|
|
3827
|
+
var EXECUTION_STATUS_CONFIG = {
|
|
3828
|
+
pending: {
|
|
3829
|
+
label: "Pending",
|
|
3830
|
+
color: "gray",
|
|
3831
|
+
textColor: "var(--color-text-dimmed)"
|
|
3832
|
+
},
|
|
3833
|
+
running: {
|
|
3834
|
+
label: "Running",
|
|
3835
|
+
color: "blue",
|
|
3836
|
+
textColor: "var(--color-primary)"
|
|
3837
|
+
},
|
|
3838
|
+
completed: {
|
|
3839
|
+
label: "Completed",
|
|
3840
|
+
color: "green",
|
|
3841
|
+
textColor: "var(--color-success)"
|
|
3842
|
+
},
|
|
3843
|
+
failed: {
|
|
3844
|
+
label: "Failed",
|
|
3845
|
+
color: "red",
|
|
3846
|
+
textColor: "var(--color-error)"
|
|
3847
|
+
},
|
|
3848
|
+
warning: {
|
|
3849
|
+
label: "Warning",
|
|
3850
|
+
color: "yellow",
|
|
3851
|
+
textColor: "var(--color-warning)"
|
|
3852
|
+
}
|
|
3853
|
+
};
|
|
3854
|
+
function getLogLevelConfig(level) {
|
|
3855
|
+
const normalizedLevel = level.toLowerCase();
|
|
3856
|
+
return LOG_LEVEL_CONFIG[normalizedLevel] || LOG_LEVEL_CONFIG.info;
|
|
3857
|
+
}
|
|
3858
|
+
function getExecutionStatusConfig(status) {
|
|
3859
|
+
const normalizedStatus = status.toLowerCase();
|
|
3860
|
+
return EXECUTION_STATUS_CONFIG[normalizedStatus] || EXECUTION_STATUS_CONFIG.pending;
|
|
3861
|
+
}
|
|
3862
|
+
function BaseExecutionLogsHeader({
|
|
3863
|
+
execution,
|
|
3864
|
+
resourceId,
|
|
3865
|
+
onDeleteClick,
|
|
3866
|
+
onRetryClick,
|
|
3867
|
+
onCancelClick,
|
|
3868
|
+
renderMetrics
|
|
3869
|
+
}) {
|
|
3870
|
+
const { currentMembership } = useOrganization();
|
|
3871
|
+
const organizationName = currentMembership?.organization?.name;
|
|
3872
|
+
const resourceTag = organizationName ? `${organizationName}/${resourceId}` : resourceId;
|
|
3873
|
+
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
3874
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
|
|
3875
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
3876
|
+
/* @__PURE__ */ jsx(Title, { order: 3, children: "Execution Logs" }),
|
|
3877
|
+
/* @__PURE__ */ jsx(Badge, { color: getExecutionStatusConfig(execution.status).color, size: "sm", children: getExecutionStatusConfig(execution.status).label.toUpperCase() }),
|
|
3878
|
+
/* @__PURE__ */ jsx(Badge, { color: getResourceStatusColor(execution.resourceStatus), size: "sm", variant: "outline", children: execution.resourceStatus.toUpperCase() })
|
|
3879
|
+
] }),
|
|
3880
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
3881
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "var(--color-text-subtle)", ff: "monospace", children: execution.id }),
|
|
3882
|
+
/* @__PURE__ */ jsx(CopyButton, { value: `${resourceTag} ${execution.id}`, children: ({ copied, copy }) => /* @__PURE__ */ jsx(ActionIcon, { onClick: copy, variant: "subtle", color: copied ? "green" : "var(--color-text-subtle)", children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 16 }) : /* @__PURE__ */ jsx(IconCopy, { size: 16 }) }) }),
|
|
3883
|
+
onCancelClick && /* @__PURE__ */ jsx(ActionIcon, { onClick: onCancelClick, variant: "subtle", color: "orange", children: /* @__PURE__ */ jsx(IconPlayerStop, { size: 16 }) }),
|
|
3884
|
+
onRetryClick && /* @__PURE__ */ jsx(ActionIcon, { onClick: onRetryClick, variant: "subtle", children: /* @__PURE__ */ jsx(IconReload, { size: 16 }) }),
|
|
3885
|
+
/* @__PURE__ */ jsx(ActionIcon, { onClick: onDeleteClick, variant: "subtle", color: "var(--color-error)", children: /* @__PURE__ */ jsx(IconTrash, { size: 16 }) })
|
|
3886
|
+
] })
|
|
3887
|
+
] }),
|
|
3888
|
+
renderMetrics ? renderMetrics(execution) : /* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
|
|
3889
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
3890
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 500, children: "Started:" }),
|
|
3891
|
+
" ",
|
|
3892
|
+
new Date(execution.startTime).toLocaleString()
|
|
3893
|
+
] }),
|
|
3894
|
+
execution.endTime && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3895
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
3896
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 500, children: "Ended:" }),
|
|
3897
|
+
" ",
|
|
3898
|
+
new Date(execution.endTime).toLocaleString()
|
|
3899
|
+
] }),
|
|
3900
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
3901
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 500, children: "Duration:" }),
|
|
3902
|
+
" ",
|
|
3903
|
+
((execution.endTime - execution.startTime) / 1e3).toFixed(2),
|
|
3904
|
+
"s"
|
|
3905
|
+
] })
|
|
3906
|
+
] }),
|
|
3907
|
+
execution.apiVersion && /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
3908
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 500, children: "API:" }),
|
|
3909
|
+
" ",
|
|
3910
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", color: "gray", children: [
|
|
3911
|
+
"v",
|
|
3912
|
+
execution.apiVersion
|
|
3913
|
+
] })
|
|
3914
|
+
] }),
|
|
3915
|
+
execution.resourceVersion && /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
3916
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 500, children: "Resource:" }),
|
|
3917
|
+
" ",
|
|
3918
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", color: "gray", children: [
|
|
3919
|
+
"v",
|
|
3920
|
+
execution.resourceVersion
|
|
3921
|
+
] })
|
|
3922
|
+
] }),
|
|
3923
|
+
execution.sdkVersion && /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
3924
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 500, children: "SDK:" }),
|
|
3925
|
+
" ",
|
|
3926
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", color: "gray", children: [
|
|
3927
|
+
"v",
|
|
3928
|
+
execution.sdkVersion
|
|
3929
|
+
] })
|
|
3930
|
+
] })
|
|
3931
|
+
] })
|
|
3932
|
+
] });
|
|
3933
|
+
}
|
|
3934
|
+
function BaseExecutionLogsStates({ executionId, isLoading, execution }) {
|
|
3935
|
+
if (!executionId) {
|
|
3936
|
+
return /* @__PURE__ */ jsx(Center, { h: "100%", children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Select an execution to view details" }) });
|
|
3937
|
+
}
|
|
3938
|
+
if (isLoading) {
|
|
3939
|
+
return /* @__PURE__ */ jsx(Center, { h: "100%", children: /* @__PURE__ */ jsx(Loader, { size: "lg", loaders: { elevasis: ElevasisLoader }, type: "elevasis" }) });
|
|
3940
|
+
}
|
|
3941
|
+
if (!execution) {
|
|
3942
|
+
return /* @__PURE__ */ jsx(Center, { h: "100%", children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Execution not found" }) });
|
|
3943
|
+
}
|
|
3944
|
+
return null;
|
|
3945
|
+
}
|
|
3946
|
+
function ExecutionErrorSection({ executionId, fallbackError }) {
|
|
3947
|
+
const { data: errors, isLoading, isError } = useErrorDetail(executionId);
|
|
3948
|
+
const [showStack, setShowStack] = useState(false);
|
|
3949
|
+
const [showErrorContext, setShowErrorContext] = useState(false);
|
|
3950
|
+
const primaryError = errors?.[0];
|
|
3951
|
+
if (isLoading || isError || !primaryError) {
|
|
3952
|
+
return /* @__PURE__ */ jsxs(
|
|
3953
|
+
Paper,
|
|
3954
|
+
{
|
|
3955
|
+
withBorder: true,
|
|
3956
|
+
p: "sm",
|
|
3957
|
+
bg: "color-mix(in srgb, var(--color-error) 10%, transparent)",
|
|
3958
|
+
style: { borderColor: "var(--color-error)" },
|
|
3959
|
+
children: [
|
|
3960
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, c: "var(--color-error)", mb: "xs", children: "Error" }),
|
|
3961
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "var(--color-error)", ff: "monospace", style: { whiteSpace: "pre-wrap" }, children: fallbackError })
|
|
3962
|
+
]
|
|
3963
|
+
}
|
|
3964
|
+
);
|
|
3965
|
+
}
|
|
3966
|
+
const severityColor = primaryError.severity === "critical" ? "red" : primaryError.severity === "warning" ? "orange" : "blue";
|
|
3967
|
+
return /* @__PURE__ */ jsx(
|
|
3968
|
+
Paper,
|
|
3969
|
+
{
|
|
3970
|
+
withBorder: true,
|
|
3971
|
+
p: "sm",
|
|
3972
|
+
bg: "color-mix(in srgb, var(--color-error) 10%, transparent)",
|
|
3973
|
+
style: { borderColor: "var(--color-error)" },
|
|
3974
|
+
children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
3975
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
3976
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
3977
|
+
/* @__PURE__ */ jsx(
|
|
3978
|
+
Text,
|
|
3979
|
+
{
|
|
3980
|
+
fw: 600,
|
|
3981
|
+
size: "sm",
|
|
3982
|
+
c: "var(--color-error)",
|
|
3983
|
+
style: { fontFamily: "var(--mantine-font-family-headings)" },
|
|
3984
|
+
children: primaryError.errorType
|
|
3985
|
+
}
|
|
3986
|
+
),
|
|
3987
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", size: "sm", children: primaryError.category })
|
|
3988
|
+
] }),
|
|
3989
|
+
/* @__PURE__ */ jsx(Badge, { color: severityColor, variant: "light", size: "sm", children: primaryError.severity })
|
|
3990
|
+
] }),
|
|
3991
|
+
/* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconBug, { size: 16 }), children: primaryError.message }),
|
|
3992
|
+
errors && errors.length > 1 && /* @__PURE__ */ jsxs(Alert, { color: "yellow", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), children: [
|
|
3993
|
+
"This execution has ",
|
|
3994
|
+
errors.length,
|
|
3995
|
+
" errors (including retries). Showing most recent."
|
|
3996
|
+
] }),
|
|
3997
|
+
primaryError.stackTrace && /* @__PURE__ */ jsxs("div", { children: [
|
|
3998
|
+
/* @__PURE__ */ jsxs(
|
|
3999
|
+
Group,
|
|
4000
|
+
{
|
|
4001
|
+
justify: "space-between",
|
|
4002
|
+
mb: "xs",
|
|
4003
|
+
onClick: () => setShowStack(!showStack),
|
|
4004
|
+
style: { cursor: "pointer" },
|
|
4005
|
+
children: [
|
|
4006
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: "Stack Trace" }),
|
|
4007
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4008
|
+
/* @__PURE__ */ jsx(CopyButton, { value: primaryError.stackTrace, children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy stack trace", children: /* @__PURE__ */ jsx(
|
|
4009
|
+
ActionIcon,
|
|
4010
|
+
{
|
|
4011
|
+
variant: "subtle",
|
|
4012
|
+
size: "sm",
|
|
4013
|
+
onClick: (e) => {
|
|
4014
|
+
e.stopPropagation();
|
|
4015
|
+
copy();
|
|
4016
|
+
},
|
|
4017
|
+
children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 })
|
|
4018
|
+
}
|
|
4019
|
+
) }) }),
|
|
4020
|
+
/* @__PURE__ */ jsx(
|
|
4021
|
+
IconChevronDown,
|
|
4022
|
+
{
|
|
4023
|
+
size: 14,
|
|
4024
|
+
style: {
|
|
4025
|
+
transform: showStack ? "rotate(180deg)" : "rotate(0)",
|
|
4026
|
+
transition: "transform var(--duration-fast)"
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
)
|
|
4030
|
+
] })
|
|
4031
|
+
]
|
|
4032
|
+
}
|
|
4033
|
+
),
|
|
4034
|
+
/* @__PURE__ */ jsx(Collapse, { in: showStack, children: /* @__PURE__ */ jsx(Code, { block: true, style: { maxHeight: 300, overflow: "auto", fontSize: "12px", lineHeight: "1.5" }, children: primaryError.stackTrace }) })
|
|
4035
|
+
] }),
|
|
4036
|
+
primaryError.errorContext && Object.keys(primaryError.errorContext).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
4037
|
+
/* @__PURE__ */ jsxs(
|
|
4038
|
+
Group,
|
|
4039
|
+
{
|
|
4040
|
+
justify: "space-between",
|
|
4041
|
+
mb: "xs",
|
|
4042
|
+
onClick: () => setShowErrorContext(!showErrorContext),
|
|
4043
|
+
style: { cursor: "pointer" },
|
|
4044
|
+
children: [
|
|
4045
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: "Error Context" }),
|
|
4046
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4047
|
+
/* @__PURE__ */ jsx(CopyButton, { value: JSON.stringify(primaryError.errorContext, null, 2), children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy error context", children: /* @__PURE__ */ jsx(
|
|
4048
|
+
ActionIcon,
|
|
4049
|
+
{
|
|
4050
|
+
variant: "subtle",
|
|
4051
|
+
size: "sm",
|
|
4052
|
+
onClick: (e) => {
|
|
4053
|
+
e.stopPropagation();
|
|
4054
|
+
copy();
|
|
4055
|
+
},
|
|
4056
|
+
children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconCopy, { size: 14 })
|
|
4057
|
+
}
|
|
4058
|
+
) }) }),
|
|
4059
|
+
/* @__PURE__ */ jsx(
|
|
4060
|
+
IconChevronDown,
|
|
4061
|
+
{
|
|
4062
|
+
size: 14,
|
|
4063
|
+
style: {
|
|
4064
|
+
transform: showErrorContext ? "rotate(180deg)" : "rotate(0)",
|
|
4065
|
+
transition: "transform var(--duration-fast)"
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
)
|
|
4069
|
+
] })
|
|
4070
|
+
]
|
|
4071
|
+
}
|
|
4072
|
+
),
|
|
4073
|
+
/* @__PURE__ */ jsx(Collapse, { in: showErrorContext, children: /* @__PURE__ */ jsx(JsonViewer, { data: primaryError.errorContext, maxHeight: 200, fontSize: "12px" }) })
|
|
4074
|
+
] })
|
|
4075
|
+
] })
|
|
4076
|
+
}
|
|
4077
|
+
);
|
|
4078
|
+
}
|
|
4079
|
+
function BaseExecutionLogs({
|
|
4080
|
+
resourceId,
|
|
4081
|
+
resourceType,
|
|
4082
|
+
executionId,
|
|
4083
|
+
execution: externalExecution,
|
|
4084
|
+
onExecutionDeleted,
|
|
4085
|
+
renderLogsSection,
|
|
4086
|
+
renderMetrics,
|
|
4087
|
+
hideInput = false,
|
|
4088
|
+
hideResult = false,
|
|
4089
|
+
hideError = false
|
|
4090
|
+
}) {
|
|
4091
|
+
const { data: fetchedExecution, isLoading } = useExecution(resourceId, executionId || "");
|
|
4092
|
+
const typedExecution = externalExecution ?? fetchedExecution;
|
|
4093
|
+
const [deleteModalOpened, setDeleteModalOpened] = useState(false);
|
|
4094
|
+
const [retryModalOpened, setRetryModalOpened] = useState(false);
|
|
4095
|
+
const [cancelModalOpened, setCancelModalOpened] = useState(false);
|
|
4096
|
+
const [retryError, setRetryError] = useState(null);
|
|
4097
|
+
const deleteExecutionMutation = useDeleteExecution();
|
|
4098
|
+
const retryExecutionMutation = useRetryExecution();
|
|
4099
|
+
const cancelExecutionMutation = useCancelExecution();
|
|
4100
|
+
const handleDelete = async () => {
|
|
4101
|
+
if (!executionId) return;
|
|
4102
|
+
try {
|
|
4103
|
+
await deleteExecutionMutation.mutateAsync({
|
|
4104
|
+
resourceId,
|
|
4105
|
+
executionId
|
|
4106
|
+
});
|
|
4107
|
+
setDeleteModalOpened(false);
|
|
4108
|
+
onExecutionDeleted?.();
|
|
4109
|
+
} catch (error) {
|
|
4110
|
+
console.error("Failed to delete execution:", error);
|
|
4111
|
+
showApiErrorNotification(error);
|
|
4112
|
+
}
|
|
4113
|
+
};
|
|
4114
|
+
const handleCancel = async () => {
|
|
4115
|
+
if (!executionId) return;
|
|
4116
|
+
try {
|
|
4117
|
+
await cancelExecutionMutation.mutateAsync({
|
|
4118
|
+
resourceId,
|
|
4119
|
+
executionId
|
|
4120
|
+
});
|
|
4121
|
+
setCancelModalOpened(false);
|
|
4122
|
+
} catch (error) {
|
|
4123
|
+
console.error("Failed to cancel execution:", error);
|
|
4124
|
+
showApiErrorNotification(error);
|
|
4125
|
+
}
|
|
4126
|
+
};
|
|
4127
|
+
const handleRetry = async () => {
|
|
4128
|
+
if (!typedExecution || !resourceType) return;
|
|
4129
|
+
setRetryError(null);
|
|
4130
|
+
try {
|
|
4131
|
+
await retryExecutionMutation.mutateAsync({
|
|
4132
|
+
resourceId,
|
|
4133
|
+
resourceType,
|
|
4134
|
+
input: typedExecution.input
|
|
4135
|
+
});
|
|
4136
|
+
setRetryModalOpened(false);
|
|
4137
|
+
showSuccessNotification("Resource re-executed with the same inputs.");
|
|
4138
|
+
} catch (error) {
|
|
4139
|
+
const message = error instanceof Error ? error.message : "Failed to re-execute resource";
|
|
4140
|
+
setRetryError(message);
|
|
4141
|
+
}
|
|
4142
|
+
};
|
|
4143
|
+
if (!executionId || isLoading || !typedExecution) {
|
|
4144
|
+
return /* @__PURE__ */ jsx(BaseExecutionLogsStates, { executionId, isLoading, execution: typedExecution });
|
|
4145
|
+
}
|
|
4146
|
+
return /* @__PURE__ */ jsxs(Stack, { h: "100%", children: [
|
|
4147
|
+
/* @__PURE__ */ jsx(
|
|
4148
|
+
BaseExecutionLogsHeader,
|
|
4149
|
+
{
|
|
4150
|
+
execution: typedExecution,
|
|
4151
|
+
resourceId,
|
|
4152
|
+
onDeleteClick: () => setDeleteModalOpened(true),
|
|
4153
|
+
onCancelClick: typedExecution.status === "running" ? () => setCancelModalOpened(true) : void 0,
|
|
4154
|
+
onRetryClick: resourceType ? () => {
|
|
4155
|
+
setRetryError(null);
|
|
4156
|
+
setRetryModalOpened(true);
|
|
4157
|
+
} : void 0,
|
|
4158
|
+
renderMetrics
|
|
4159
|
+
}
|
|
4160
|
+
),
|
|
4161
|
+
!hideInput && typedExecution.input != null && /* @__PURE__ */ jsx(Paper, { withBorder: true, bg: "none", children: /* @__PURE__ */ jsx(CollapsibleJsonSection, { title: /* @__PURE__ */ jsx(Text, { fw: 500, children: "Input" }), data: typedExecution.input }) }),
|
|
4162
|
+
renderLogsSection?.(typedExecution),
|
|
4163
|
+
!hideResult && typedExecution.result != null && /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(
|
|
4164
|
+
CollapsibleJsonSection,
|
|
4165
|
+
{
|
|
4166
|
+
title: /* @__PURE__ */ jsx(Text, { fw: 500, c: "var(--color-success)", children: "Result" }),
|
|
4167
|
+
data: typedExecution.result
|
|
4168
|
+
}
|
|
4169
|
+
) }),
|
|
4170
|
+
!hideError && typedExecution.error && /* @__PURE__ */ jsx(ExecutionErrorSection, { executionId: typedExecution.id, fallbackError: typedExecution.error }),
|
|
4171
|
+
/* @__PURE__ */ jsx(
|
|
4172
|
+
ConfirmationModal,
|
|
4173
|
+
{
|
|
4174
|
+
opened: deleteModalOpened,
|
|
4175
|
+
onClose: () => setDeleteModalOpened(false),
|
|
4176
|
+
icon: /* @__PURE__ */ jsx(IconTrash, { color: "red" }),
|
|
4177
|
+
title: "Delete Execution Log",
|
|
4178
|
+
text: "Are you sure you want to delete this execution log? This action cannot be undone.",
|
|
4179
|
+
buttonText: "Delete",
|
|
4180
|
+
buttonColor: "red",
|
|
4181
|
+
confirmationHandler: handleDelete,
|
|
4182
|
+
loading: deleteExecutionMutation.isPending
|
|
4183
|
+
}
|
|
4184
|
+
),
|
|
4185
|
+
/* @__PURE__ */ jsx(
|
|
4186
|
+
ConfirmationModal,
|
|
4187
|
+
{
|
|
4188
|
+
opened: cancelModalOpened,
|
|
4189
|
+
onClose: () => setCancelModalOpened(false),
|
|
4190
|
+
icon: /* @__PURE__ */ jsx(IconPlayerStop, {}),
|
|
4191
|
+
title: "Stop Execution",
|
|
4192
|
+
text: "Are you sure you want to stop this running execution? This action cannot be undone.",
|
|
4193
|
+
buttonText: "Stop",
|
|
4194
|
+
buttonColor: "orange",
|
|
4195
|
+
confirmationHandler: handleCancel,
|
|
4196
|
+
loading: cancelExecutionMutation.isPending
|
|
4197
|
+
}
|
|
4198
|
+
),
|
|
4199
|
+
/* @__PURE__ */ jsx(
|
|
4200
|
+
CustomModal,
|
|
4201
|
+
{
|
|
4202
|
+
opened: retryModalOpened,
|
|
4203
|
+
onClose: () => setRetryModalOpened(false),
|
|
4204
|
+
size: "sm",
|
|
4205
|
+
loading: retryExecutionMutation.isPending,
|
|
4206
|
+
children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
4207
|
+
/* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
4208
|
+
/* @__PURE__ */ jsx(IconReload, { size: 24, color: "var(--color-primary)" }),
|
|
4209
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "Re-execute Resource" })
|
|
4210
|
+
] }),
|
|
4211
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
4212
|
+
"This will re-execute",
|
|
4213
|
+
" ",
|
|
4214
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 600, children: resourceId }),
|
|
4215
|
+
" ",
|
|
4216
|
+
"with the exact same inputs from this execution."
|
|
4217
|
+
] }),
|
|
4218
|
+
typedExecution?.input != null && /* @__PURE__ */ jsx(Paper, { withBorder: true, bg: "none", style: { maxHeight: 150, overflow: "auto" }, children: /* @__PURE__ */ jsx(Text, { size: "xs", ff: "monospace", style: { whiteSpace: "pre-wrap" }, children: JSON.stringify(typedExecution.input, null, 2) }) }),
|
|
4219
|
+
retryError && /* @__PURE__ */ jsx(
|
|
4220
|
+
Paper,
|
|
4221
|
+
{
|
|
4222
|
+
withBorder: true,
|
|
4223
|
+
p: "xs",
|
|
4224
|
+
bg: "color-mix(in srgb, var(--color-error) 10%, transparent)",
|
|
4225
|
+
style: { borderColor: "var(--color-error)" },
|
|
4226
|
+
children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "var(--color-error)", children: retryError })
|
|
4227
|
+
}
|
|
4228
|
+
),
|
|
4229
|
+
/* @__PURE__ */ jsxs(Group, { justify: "flex-end", mt: "md", children: [
|
|
4230
|
+
/* @__PURE__ */ jsx(
|
|
4231
|
+
Button,
|
|
4232
|
+
{
|
|
4233
|
+
variant: "light",
|
|
4234
|
+
onClick: () => setRetryModalOpened(false),
|
|
4235
|
+
disabled: retryExecutionMutation.isPending,
|
|
4236
|
+
children: "Cancel"
|
|
4237
|
+
}
|
|
4238
|
+
),
|
|
4239
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleRetry, loading: retryExecutionMutation.isPending, children: "Re-execute" })
|
|
4240
|
+
] })
|
|
4241
|
+
] })
|
|
4242
|
+
}
|
|
4243
|
+
)
|
|
4244
|
+
] });
|
|
4245
|
+
}
|
|
4246
|
+
function LogEntry({ log, index }) {
|
|
4247
|
+
const hasContext = log.context && Object.keys(log.context).length > 0;
|
|
4248
|
+
const logConfig = getLogLevelConfig(log.level);
|
|
4249
|
+
const logTitle = /* @__PURE__ */ jsxs(Group, { gap: "xs", style: { flex: 1 }, wrap: "nowrap", children: [
|
|
4250
|
+
/* @__PURE__ */ jsx(
|
|
4251
|
+
Badge,
|
|
4252
|
+
{
|
|
4253
|
+
size: "sm",
|
|
4254
|
+
variant: "light",
|
|
4255
|
+
color: logConfig.color,
|
|
4256
|
+
style: { minWidth: "60px", fontFamily: "var(--mantine-font-family-monospace)" },
|
|
4257
|
+
children: logConfig.label
|
|
4258
|
+
}
|
|
4259
|
+
),
|
|
4260
|
+
/* @__PURE__ */ jsx(Text, { span: true, c: "dimmed", size: "xs", style: { fontFamily: "var(--mantine-font-family-monospace)" }, children: new Date(log.timestamp).toLocaleTimeString("en-US", {
|
|
4261
|
+
hour12: false,
|
|
4262
|
+
hour: "2-digit",
|
|
4263
|
+
minute: "2-digit",
|
|
4264
|
+
second: "2-digit",
|
|
4265
|
+
fractionalSecondDigits: 3
|
|
4266
|
+
}) }),
|
|
4267
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", span: true, style: { fontFamily: "var(--mantine-font-family-monospace)" }, children: log.message })
|
|
4268
|
+
] });
|
|
4269
|
+
if (!hasContext) {
|
|
4270
|
+
return /* @__PURE__ */ jsx(
|
|
4271
|
+
"div",
|
|
4272
|
+
{
|
|
4273
|
+
style: {
|
|
4274
|
+
padding: "0.375rem 0.5rem",
|
|
4275
|
+
borderRadius: "var(--mantine-radius-default)"
|
|
4276
|
+
},
|
|
4277
|
+
children: logTitle
|
|
4278
|
+
},
|
|
4279
|
+
index
|
|
4280
|
+
);
|
|
4281
|
+
}
|
|
4282
|
+
return /* @__PURE__ */ jsx(CollapsibleJsonSection, { title: logTitle, data: log.context }, index);
|
|
4283
|
+
}
|
|
4284
|
+
function LogGroup({ title, logs, statusBadge }) {
|
|
4285
|
+
return /* @__PURE__ */ jsxs(
|
|
4286
|
+
"div",
|
|
4287
|
+
{
|
|
4288
|
+
style: {
|
|
4289
|
+
borderRadius: "8px",
|
|
4290
|
+
padding: "12px",
|
|
4291
|
+
border: "1px solid var(--color-border)"
|
|
4292
|
+
},
|
|
4293
|
+
children: [
|
|
4294
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", mb: "xs", children: [
|
|
4295
|
+
/* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", c: "var(--color-text)", style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, children: title }),
|
|
4296
|
+
statusBadge && /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: statusBadge.color, children: statusBadge.label }),
|
|
4297
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", color: "gray", children: [
|
|
4298
|
+
logs.length,
|
|
4299
|
+
" ",
|
|
4300
|
+
logs.length === 1 ? "log" : "logs"
|
|
4301
|
+
] })
|
|
4302
|
+
] }),
|
|
4303
|
+
/* @__PURE__ */ jsx(Stack, { gap: 4, children: logs.map((log, logIndex) => /* @__PURE__ */ jsx(LogEntry, { log, index: logIndex }, logIndex)) })
|
|
4304
|
+
]
|
|
4305
|
+
}
|
|
4306
|
+
);
|
|
4307
|
+
}
|
|
4308
|
+
var ResourceFilter = ({ value, onChange, fullWidth }) => {
|
|
4309
|
+
const buttonStyles = fullWidth ? { padding: "2px 8px", height: "28px", fontSize: "12px", flex: 1 } : { padding: "2px 8px", height: "24px", fontSize: "12px" };
|
|
4310
|
+
return /* @__PURE__ */ jsxs(Button.Group, { style: fullWidth ? { width: "100%" } : void 0, children: [
|
|
4311
|
+
/* @__PURE__ */ jsx(
|
|
4312
|
+
Button,
|
|
4313
|
+
{
|
|
4314
|
+
variant: value === "all" ? "filled" : "default",
|
|
4315
|
+
size: "xs",
|
|
4316
|
+
onClick: () => onChange("all"),
|
|
4317
|
+
bg: value === "all" ? void 0 : "var(--color-background)",
|
|
4318
|
+
styles: { root: buttonStyles },
|
|
4319
|
+
children: "All"
|
|
4320
|
+
}
|
|
4321
|
+
),
|
|
4322
|
+
/* @__PURE__ */ jsx(
|
|
4323
|
+
Button,
|
|
4324
|
+
{
|
|
4325
|
+
variant: value === "dev" ? "filled" : "default",
|
|
4326
|
+
size: "xs",
|
|
4327
|
+
onClick: () => onChange("dev"),
|
|
4328
|
+
bg: value === "dev" ? void 0 : "var(--color-background)",
|
|
4329
|
+
styles: { root: buttonStyles },
|
|
4330
|
+
children: "Dev"
|
|
4331
|
+
}
|
|
4332
|
+
),
|
|
4333
|
+
/* @__PURE__ */ jsx(
|
|
4334
|
+
Button,
|
|
4335
|
+
{
|
|
4336
|
+
variant: value === "prod" ? "filled" : "default",
|
|
4337
|
+
size: "xs",
|
|
4338
|
+
onClick: () => onChange("prod"),
|
|
4339
|
+
bg: value === "prod" ? void 0 : "var(--color-background)",
|
|
4340
|
+
styles: { root: buttonStyles },
|
|
4341
|
+
children: "Prod"
|
|
4342
|
+
}
|
|
4343
|
+
)
|
|
4344
|
+
] });
|
|
4345
|
+
};
|
|
4346
|
+
function ResourceHeader({ resource, type, connected, runningCount, sessionCapable }) {
|
|
4347
|
+
const { currentMembership } = useOrganization();
|
|
4348
|
+
const organizationName = currentMembership?.organization?.name;
|
|
4349
|
+
const navigate = useNavigate();
|
|
4350
|
+
const Icon = getResourceIcon(type);
|
|
4351
|
+
const clipboard = useClipboard({ timeout: 2e3 });
|
|
4352
|
+
const handleCopyId = () => {
|
|
4353
|
+
clipboard.copy(`"${organizationName}/${resource.resourceId}"`);
|
|
4354
|
+
notifications.show({
|
|
4355
|
+
message: "Resource ID copied to clipboard",
|
|
4356
|
+
color: "teal"
|
|
4357
|
+
});
|
|
4358
|
+
};
|
|
4359
|
+
const handleGoToSessions = () => {
|
|
4360
|
+
navigate({
|
|
4361
|
+
to: "/operations/sessions",
|
|
4362
|
+
search: { agent: resource.resourceId }
|
|
4363
|
+
});
|
|
4364
|
+
};
|
|
4365
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4366
|
+
/* @__PURE__ */ jsx(
|
|
4367
|
+
PageTitleCaption,
|
|
4368
|
+
{
|
|
4369
|
+
title: resource.name,
|
|
4370
|
+
caption: resource.description || `${type.charAt(0).toUpperCase()}${type.slice(1)} details`
|
|
4371
|
+
}
|
|
4372
|
+
),
|
|
4373
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
4374
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4375
|
+
/* @__PURE__ */ jsx(Icon, { size: 20, color: "var(--color-primary)" }),
|
|
4376
|
+
/* @__PURE__ */ jsxs(Badge, { color: "blue", variant: "light", children: [
|
|
4377
|
+
type.charAt(0).toUpperCase(),
|
|
4378
|
+
type.slice(1)
|
|
4379
|
+
] }),
|
|
4380
|
+
/* @__PURE__ */ jsx(Badge, { color: ResourceStatusColors[resource.status], variant: "outline", size: "sm", children: resource.status.toUpperCase() }),
|
|
4381
|
+
resource.version && /* @__PURE__ */ jsxs(Badge, { variant: "outline", size: "sm", children: [
|
|
4382
|
+
"v",
|
|
4383
|
+
resource.version
|
|
4384
|
+
] }),
|
|
4385
|
+
/* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
4386
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", ff: "monospace", c: "dimmed", children: [
|
|
4387
|
+
organizationName,
|
|
4388
|
+
"/",
|
|
4389
|
+
resource.resourceId
|
|
4390
|
+
] }),
|
|
4391
|
+
/* @__PURE__ */ jsx(Tooltip, { label: clipboard.copied ? "Copied!" : "Copy ID", children: /* @__PURE__ */ jsx(ActionIcon, { size: "sm", variant: "subtle", onClick: handleCopyId, color: clipboard.copied ? "teal" : "gray", children: /* @__PURE__ */ jsx(IconCopy, { size: 14, color: clipboard.copied ? "teal" : "gray" }) }) })
|
|
4392
|
+
] })
|
|
4393
|
+
] }),
|
|
4394
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4395
|
+
connected && /* @__PURE__ */ jsx(Badge, { color: "green", variant: "dot", children: "CONNECTED" }),
|
|
4396
|
+
runningCount && runningCount > 0 && /* @__PURE__ */ jsxs(Badge, { color: "blue", variant: "filled", children: [
|
|
4397
|
+
runningCount,
|
|
4398
|
+
" running"
|
|
4399
|
+
] }),
|
|
4400
|
+
type === "agent" && sessionCapable && /* @__PURE__ */ jsx(Button, { size: "xs", variant: "light", leftSection: /* @__PURE__ */ jsx(IconMessage, { size: 16 }), onClick: handleGoToSessions, children: "Go to Sessions" }),
|
|
4401
|
+
/* @__PURE__ */ jsx(
|
|
4402
|
+
Button,
|
|
4403
|
+
{
|
|
4404
|
+
size: "sm",
|
|
4405
|
+
variant: "light",
|
|
4406
|
+
leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
|
|
4407
|
+
onClick: () => navigate({ to: "/operations/resources" }),
|
|
4408
|
+
children: "Resources"
|
|
4409
|
+
}
|
|
4410
|
+
)
|
|
4411
|
+
] })
|
|
4412
|
+
] })
|
|
4413
|
+
] });
|
|
4414
|
+
}
|
|
4415
|
+
function ResourceErrorState({ error }) {
|
|
4416
|
+
return /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Stack, { align: "center", children: [
|
|
4417
|
+
/* @__PURE__ */ jsx(Text, { c: "red", children: "Failed to load resource" }),
|
|
4418
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: error.message })
|
|
4419
|
+
] }) }) });
|
|
4420
|
+
}
|
|
4421
|
+
function ResourceNotFoundState({ type, resourceId }) {
|
|
4422
|
+
const navigate = useNavigate();
|
|
4423
|
+
const { currentMembership } = useOrganization();
|
|
4424
|
+
const orgName = currentMembership?.organization?.name || "current organization";
|
|
4425
|
+
return /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Stack, { align: "center", children: [
|
|
4426
|
+
/* @__PURE__ */ jsx(Text, { size: "lg", c: "dimmed", fw: 500, children: "Resource not found" }),
|
|
4427
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", ta: "center", children: [
|
|
4428
|
+
"The ",
|
|
4429
|
+
type,
|
|
4430
|
+
' "',
|
|
4431
|
+
resourceId,
|
|
4432
|
+
'" could not be found in ',
|
|
4433
|
+
orgName,
|
|
4434
|
+
"."
|
|
4435
|
+
] }),
|
|
4436
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ta: "center", children: "This resource may exist in a different organization. Try switching organizations or returning to the overview." }),
|
|
4437
|
+
/* @__PURE__ */ jsx(
|
|
4438
|
+
Button,
|
|
4439
|
+
{
|
|
4440
|
+
variant: "light",
|
|
4441
|
+
leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
|
|
4442
|
+
onClick: () => navigate({ to: "/operations", search: { type: void 0 } }),
|
|
4443
|
+
children: "Back to Operations"
|
|
4444
|
+
}
|
|
4445
|
+
)
|
|
4446
|
+
] }) }) });
|
|
4447
|
+
}
|
|
4448
|
+
function ResourceDetailPage({
|
|
4449
|
+
type,
|
|
4450
|
+
resourceId,
|
|
4451
|
+
renderExecutionPanel,
|
|
4452
|
+
renderHealthPanel,
|
|
4453
|
+
renderDefinitionSection
|
|
4454
|
+
}) {
|
|
4455
|
+
const { organizationReady } = useInitialization();
|
|
4456
|
+
const { data, isLoading, error } = useResources();
|
|
4457
|
+
const [connected, setConnected] = useState(false);
|
|
4458
|
+
const [runningCount, setRunningCount] = useState(0);
|
|
4459
|
+
const resource = data ? (() => {
|
|
4460
|
+
const resources = [...data.workflows, ...data.agents];
|
|
4461
|
+
const found = resources.find((r) => r.resourceId === resourceId && r.type === type);
|
|
4462
|
+
return found || null;
|
|
4463
|
+
})() : null;
|
|
4464
|
+
const {
|
|
4465
|
+
data: resourceDefinition,
|
|
4466
|
+
isLoading: definitionLoading,
|
|
4467
|
+
error: definitionError
|
|
4468
|
+
} = useResourceDefinition(resourceId, true);
|
|
4469
|
+
const handleConnectionStatus = (isConnected, count) => {
|
|
4470
|
+
setConnected(isConnected);
|
|
4471
|
+
setRunningCount(count);
|
|
4472
|
+
};
|
|
4473
|
+
if (!organizationReady || isLoading || definitionLoading) {
|
|
4474
|
+
return /* @__PURE__ */ jsx(SubshellLoader, {});
|
|
4475
|
+
}
|
|
4476
|
+
if (error) {
|
|
4477
|
+
return /* @__PURE__ */ jsx(ResourceErrorState, { error });
|
|
4478
|
+
}
|
|
4479
|
+
if (!resource) {
|
|
4480
|
+
return /* @__PURE__ */ jsx(ResourceNotFoundState, { type, resourceId });
|
|
4481
|
+
}
|
|
4482
|
+
const validResource = resource;
|
|
4483
|
+
const sessionCapable = isSessionCapable(type, resourceDefinition);
|
|
4484
|
+
return /* @__PURE__ */ jsxs(Stack, { style: { overflow: "hidden", boxShadow: "var(--standard-box-shadow)" }, children: [
|
|
4485
|
+
/* @__PURE__ */ jsx(
|
|
4486
|
+
ResourceHeader,
|
|
4487
|
+
{
|
|
4488
|
+
resource: validResource,
|
|
4489
|
+
type,
|
|
4490
|
+
connected,
|
|
4491
|
+
runningCount,
|
|
4492
|
+
sessionCapable
|
|
4493
|
+
}
|
|
4494
|
+
),
|
|
4495
|
+
renderHealthPanel?.({ resourceId, resourceType: type }),
|
|
4496
|
+
resourceDefinition && renderDefinitionSection?.(resourceDefinition),
|
|
4497
|
+
/* @__PURE__ */ jsx(
|
|
4498
|
+
Paper,
|
|
4499
|
+
{
|
|
4500
|
+
withBorder: true,
|
|
4501
|
+
p: "0",
|
|
4502
|
+
style: {
|
|
4503
|
+
flex: 1,
|
|
4504
|
+
overflow: "hidden",
|
|
4505
|
+
display: "flex",
|
|
4506
|
+
flexDirection: "column"
|
|
4507
|
+
},
|
|
4508
|
+
children: definitionError ? /* @__PURE__ */ jsx(ResourceErrorState, { error: definitionError }) : !resourceDefinition ? /* @__PURE__ */ jsx(ResourceErrorState, { error: new Error("Resource definition not found") }) : renderExecutionPanel?.({
|
|
4509
|
+
resourceId,
|
|
4510
|
+
resourceType: type,
|
|
4511
|
+
resourceName: validResource.name,
|
|
4512
|
+
resourceDefinition,
|
|
4513
|
+
onConnectionStatus: handleConnectionStatus
|
|
4514
|
+
})
|
|
4515
|
+
}
|
|
4516
|
+
)
|
|
4517
|
+
] });
|
|
4518
|
+
}
|
|
4519
|
+
function AgentExecutionLogs({
|
|
4520
|
+
resourceId,
|
|
4521
|
+
executionId,
|
|
4522
|
+
execution: externalExecution,
|
|
4523
|
+
selectedIterationId,
|
|
4524
|
+
iterationData,
|
|
4525
|
+
onExecutionDeleted
|
|
4526
|
+
}) {
|
|
4527
|
+
const isIterationSelected = selectedIterationId !== null;
|
|
4528
|
+
const logGroups = useMemo(() => {
|
|
4529
|
+
if (!iterationData) {
|
|
4530
|
+
return [];
|
|
4531
|
+
}
|
|
4532
|
+
if (selectedIterationId !== null) {
|
|
4533
|
+
if (selectedIterationId === "initialization") {
|
|
4534
|
+
return [
|
|
4535
|
+
{
|
|
4536
|
+
title: "Initialization",
|
|
4537
|
+
groupKey: "initialization",
|
|
4538
|
+
logs: [],
|
|
4539
|
+
// Will be filled in renderLogsSection
|
|
4540
|
+
status: iterationData.initialization.status
|
|
4541
|
+
}
|
|
4542
|
+
];
|
|
4543
|
+
}
|
|
4544
|
+
if (selectedIterationId === "completion") {
|
|
4545
|
+
return [
|
|
4546
|
+
{
|
|
4547
|
+
title: "Completion",
|
|
4548
|
+
groupKey: "completion",
|
|
4549
|
+
logs: [],
|
|
4550
|
+
// Will be filled in renderLogsSection
|
|
4551
|
+
status: iterationData.completion.status
|
|
4552
|
+
}
|
|
4553
|
+
];
|
|
4554
|
+
}
|
|
4555
|
+
const selectedIteration = iterationData.iterations.find((iter) => iter.iterationNumber === selectedIterationId);
|
|
4556
|
+
if (!selectedIteration) {
|
|
4557
|
+
return [];
|
|
4558
|
+
}
|
|
4559
|
+
return [
|
|
4560
|
+
{
|
|
4561
|
+
title: `Iteration ${selectedIteration.iterationNumber}`,
|
|
4562
|
+
groupKey: selectedIteration.iterationNumber,
|
|
4563
|
+
logs: [],
|
|
4564
|
+
// Will be filled in renderLogsSection
|
|
4565
|
+
status: selectedIteration.status
|
|
4566
|
+
}
|
|
4567
|
+
];
|
|
4568
|
+
}
|
|
4569
|
+
const groups = [];
|
|
4570
|
+
groups.push({
|
|
4571
|
+
title: "Initialization",
|
|
4572
|
+
groupKey: "initialization",
|
|
4573
|
+
logs: [],
|
|
4574
|
+
status: iterationData.initialization.status
|
|
4575
|
+
});
|
|
4576
|
+
for (const iteration of iterationData.iterations) {
|
|
4577
|
+
groups.push({
|
|
4578
|
+
title: `Iteration ${iteration.iterationNumber}`,
|
|
4579
|
+
groupKey: iteration.iterationNumber,
|
|
4580
|
+
logs: [],
|
|
4581
|
+
status: iteration.status
|
|
4582
|
+
});
|
|
4583
|
+
}
|
|
4584
|
+
groups.push({
|
|
4585
|
+
title: "Completion",
|
|
4586
|
+
groupKey: "completion",
|
|
4587
|
+
logs: [],
|
|
4588
|
+
status: iterationData.completion.status
|
|
4589
|
+
});
|
|
4590
|
+
return groups;
|
|
4591
|
+
}, [selectedIterationId, iterationData]);
|
|
4592
|
+
const getSelectedNodeTitle = () => {
|
|
4593
|
+
if (selectedIterationId === null) return null;
|
|
4594
|
+
if (selectedIterationId === "initialization") return "Initialization";
|
|
4595
|
+
if (selectedIterationId === "completion") return "Completion";
|
|
4596
|
+
return `Iteration ${selectedIterationId}`;
|
|
4597
|
+
};
|
|
4598
|
+
const selectedNodeTitle = getSelectedNodeTitle();
|
|
4599
|
+
const getIterationStatusBadge = (_groupKey, status) => {
|
|
4600
|
+
if (status) {
|
|
4601
|
+
const statusConfig3 = getExecutionStatusConfig(status);
|
|
4602
|
+
return {
|
|
4603
|
+
label: statusConfig3.label,
|
|
4604
|
+
color: statusConfig3.color
|
|
4605
|
+
};
|
|
4606
|
+
}
|
|
4607
|
+
return null;
|
|
4608
|
+
};
|
|
4609
|
+
const renderLogsSection = (execution) => {
|
|
4610
|
+
if (!execution.executionLogs || execution.executionLogs.length === 0) {
|
|
4611
|
+
return /* @__PURE__ */ jsx(Text, { c: "dimmed", ta: "center", mt: "md", children: "No logs available" });
|
|
4612
|
+
}
|
|
4613
|
+
const logsByGroup = /* @__PURE__ */ new Map();
|
|
4614
|
+
for (const log of execution.executionLogs) {
|
|
4615
|
+
const context = log.context;
|
|
4616
|
+
let groupKey;
|
|
4617
|
+
if (context?.type === "agent" && "lifecycle" in context) {
|
|
4618
|
+
const lifecycle = context.lifecycle;
|
|
4619
|
+
if (lifecycle === "initialization") {
|
|
4620
|
+
groupKey = "initialization";
|
|
4621
|
+
} else if (lifecycle === "iteration" && "iteration" in context) {
|
|
4622
|
+
groupKey = context.iteration;
|
|
4623
|
+
} else if (lifecycle === "completion") {
|
|
4624
|
+
groupKey = "completion";
|
|
4625
|
+
} else {
|
|
4626
|
+
groupKey = "completion";
|
|
4627
|
+
}
|
|
4628
|
+
} else {
|
|
4629
|
+
groupKey = "completion";
|
|
4630
|
+
}
|
|
4631
|
+
if (!logsByGroup.has(groupKey)) {
|
|
4632
|
+
logsByGroup.set(groupKey, []);
|
|
4633
|
+
}
|
|
4634
|
+
logsByGroup.get(groupKey).push(log);
|
|
4635
|
+
}
|
|
4636
|
+
const populatedGroups = logGroups.map((group) => ({
|
|
4637
|
+
...group,
|
|
4638
|
+
logs: logsByGroup.get(group.groupKey) || []
|
|
4639
|
+
})).filter((group) => group.logs.length > 0);
|
|
4640
|
+
const totalLogsCount = populatedGroups.reduce((total, group) => total + group.logs.length, 0);
|
|
4641
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", style: { flex: 1, minHeight: 0 }, children: [
|
|
4642
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
4643
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: selectedNodeTitle ? `Logs for ${selectedNodeTitle} (${totalLogsCount})` : `Logs (${totalLogsCount})` }),
|
|
4644
|
+
iterationData && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4645
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
4646
|
+
"Iterations: ",
|
|
4647
|
+
iterationData.iterations.filter((i) => i.status === "completed").length,
|
|
4648
|
+
"/",
|
|
4649
|
+
iterationData.totalIterations
|
|
4650
|
+
] }),
|
|
4651
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
4652
|
+
"Events: ",
|
|
4653
|
+
iterationData.iterations.reduce((sum, iter) => sum + iter.iterationEvents.length, 0)
|
|
4654
|
+
] })
|
|
4655
|
+
] })
|
|
4656
|
+
] }),
|
|
4657
|
+
/* @__PURE__ */ jsx(ScrollArea, { style: { flex: 1 }, scrollbarSize: 8, children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
4658
|
+
populatedGroups.map((group) => {
|
|
4659
|
+
const statusBadge = getIterationStatusBadge(group.groupKey, group.status);
|
|
4660
|
+
return /* @__PURE__ */ jsx(
|
|
4661
|
+
LogGroup,
|
|
4662
|
+
{
|
|
4663
|
+
title: group.title,
|
|
4664
|
+
logs: group.logs,
|
|
4665
|
+
statusBadge: statusBadge || void 0
|
|
4666
|
+
},
|
|
4667
|
+
group.groupKey
|
|
4668
|
+
);
|
|
4669
|
+
}),
|
|
4670
|
+
populatedGroups.length === 0 && /* @__PURE__ */ jsx(Text, { c: "dimmed", ta: "center", mt: "md", children: selectedNodeTitle ? `No logs for ${selectedNodeTitle}` : "No logs available" })
|
|
4671
|
+
] }) })
|
|
4672
|
+
] });
|
|
4673
|
+
};
|
|
4674
|
+
return /* @__PURE__ */ jsx(
|
|
4675
|
+
BaseExecutionLogs,
|
|
4676
|
+
{
|
|
4677
|
+
resourceId,
|
|
4678
|
+
resourceType: "agent",
|
|
4679
|
+
executionId,
|
|
4680
|
+
execution: externalExecution,
|
|
4681
|
+
onExecutionDeleted,
|
|
4682
|
+
renderLogsSection,
|
|
4683
|
+
hideInput: isIterationSelected,
|
|
4684
|
+
hideResult: isIterationSelected,
|
|
4685
|
+
hideError: isIterationSelected
|
|
4686
|
+
}
|
|
4687
|
+
);
|
|
4688
|
+
}
|
|
4689
|
+
function WorkflowExecutionLogs({
|
|
4690
|
+
resourceId,
|
|
4691
|
+
executionId,
|
|
4692
|
+
execution: externalExecution,
|
|
4693
|
+
selectedStepId,
|
|
4694
|
+
timelineData,
|
|
4695
|
+
onExecutionDeleted
|
|
4696
|
+
}) {
|
|
4697
|
+
const { data: fetchedExecution } = useExecution(resourceId, executionId || "");
|
|
4698
|
+
const typedExecution = externalExecution ?? fetchedExecution;
|
|
4699
|
+
const isStepSelected = !!selectedStepId;
|
|
4700
|
+
const logGroups = useMemo(() => {
|
|
4701
|
+
if (selectedStepId && timelineData) {
|
|
4702
|
+
const selectedStep2 = timelineData.steps.find((s) => s.stepId === selectedStepId);
|
|
4703
|
+
return selectedStep2 ? [{ stepName: selectedStep2.stepName, stepId: selectedStep2.stepId, logs: selectedStep2.logs }] : [];
|
|
4704
|
+
}
|
|
4705
|
+
if (!timelineData || !typedExecution) {
|
|
4706
|
+
return [];
|
|
4707
|
+
}
|
|
4708
|
+
const groups = [];
|
|
4709
|
+
for (const step of timelineData.steps) {
|
|
4710
|
+
if (step.logs.length > 0) {
|
|
4711
|
+
groups.push({
|
|
4712
|
+
stepName: step.stepName,
|
|
4713
|
+
stepId: step.stepId,
|
|
4714
|
+
logs: step.logs
|
|
4715
|
+
});
|
|
4716
|
+
}
|
|
4717
|
+
}
|
|
4718
|
+
const stepLogTimestamps = new Set(timelineData.steps.flatMap((s) => s.logs.map((l) => l.timestamp)));
|
|
4719
|
+
const generalExecutionLogs = typedExecution.executionLogs.filter((log) => !stepLogTimestamps.has(log.timestamp));
|
|
4720
|
+
const generalWorkflowLogs = toWorkflowLogMessages(generalExecutionLogs);
|
|
4721
|
+
if (generalWorkflowLogs.length > 0) {
|
|
4722
|
+
groups.unshift({
|
|
4723
|
+
stepName: "General",
|
|
4724
|
+
stepId: "general",
|
|
4725
|
+
logs: generalWorkflowLogs
|
|
4726
|
+
});
|
|
4727
|
+
}
|
|
4728
|
+
return groups;
|
|
4729
|
+
}, [selectedStepId, timelineData, typedExecution]);
|
|
4730
|
+
const selectedStep = selectedStepId && timelineData ? timelineData.steps.find((s) => s.stepId === selectedStepId) : null;
|
|
4731
|
+
const totalLogsCount = logGroups.reduce((total, group) => total + group.logs.length, 0);
|
|
4732
|
+
const scrollViewportRef = useRef(null);
|
|
4733
|
+
const isNearBottomRef = useRef(true);
|
|
4734
|
+
const handleScroll = useCallback(() => {
|
|
4735
|
+
const viewport = scrollViewportRef.current;
|
|
4736
|
+
if (!viewport) return;
|
|
4737
|
+
isNearBottomRef.current = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight < 50;
|
|
4738
|
+
}, []);
|
|
4739
|
+
useEffect(() => {
|
|
4740
|
+
if (!isNearBottomRef.current) return;
|
|
4741
|
+
const viewport = scrollViewportRef.current;
|
|
4742
|
+
if (!viewport) return;
|
|
4743
|
+
viewport.scrollTop = viewport.scrollHeight;
|
|
4744
|
+
}, [totalLogsCount]);
|
|
4745
|
+
const getStepStatusBadge = (stepId) => {
|
|
4746
|
+
if (stepId === "general") {
|
|
4747
|
+
return { label: "General", color: "blue" };
|
|
4748
|
+
}
|
|
4749
|
+
if (!timelineData) {
|
|
4750
|
+
return null;
|
|
4751
|
+
}
|
|
4752
|
+
const step = timelineData.steps.find((s) => s.stepId === stepId);
|
|
4753
|
+
if (!step) {
|
|
4754
|
+
return null;
|
|
4755
|
+
}
|
|
4756
|
+
const statusConfig3 = getExecutionStatusConfig(step.status);
|
|
4757
|
+
return {
|
|
4758
|
+
label: statusConfig3.label,
|
|
4759
|
+
color: statusConfig3.color
|
|
4760
|
+
};
|
|
4761
|
+
};
|
|
4762
|
+
const renderLogsSection = () => {
|
|
4763
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", style: { flex: 1, minHeight: 0 }, children: [
|
|
4764
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
4765
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: selectedStep ? `Logs for ${selectedStep.stepName} (${totalLogsCount})` : `Logs (${totalLogsCount})` }),
|
|
4766
|
+
timelineData && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4767
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
4768
|
+
"Steps: ",
|
|
4769
|
+
timelineData.steps.filter((s) => s.status === "completed").length,
|
|
4770
|
+
"/",
|
|
4771
|
+
timelineData.steps.length
|
|
4772
|
+
] }),
|
|
4773
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
4774
|
+
"Duration:",
|
|
4775
|
+
" ",
|
|
4776
|
+
timelineData.totalDuration < 1e3 ? `${timelineData.totalDuration}ms` : `${(timelineData.totalDuration / 1e3).toFixed(2)}s`
|
|
4777
|
+
] })
|
|
4778
|
+
] })
|
|
4779
|
+
] }),
|
|
4780
|
+
/* @__PURE__ */ jsx(
|
|
4781
|
+
ScrollArea,
|
|
4782
|
+
{
|
|
4783
|
+
style: { flex: 1 },
|
|
4784
|
+
scrollbarSize: 8,
|
|
4785
|
+
viewportRef: scrollViewportRef,
|
|
4786
|
+
onScrollPositionChange: handleScroll,
|
|
4787
|
+
children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
4788
|
+
logGroups.map((group) => {
|
|
4789
|
+
const statusBadge = getStepStatusBadge(group.stepId);
|
|
4790
|
+
return /* @__PURE__ */ jsx(
|
|
4791
|
+
LogGroup,
|
|
4792
|
+
{
|
|
4793
|
+
title: group.stepName,
|
|
4794
|
+
logs: group.logs,
|
|
4795
|
+
statusBadge: statusBadge || void 0
|
|
4796
|
+
},
|
|
4797
|
+
group.stepId
|
|
4798
|
+
);
|
|
4799
|
+
}),
|
|
4800
|
+
logGroups.length === 0 && /* @__PURE__ */ jsx(Text, { c: "dimmed", ta: "center", mt: "md", children: selectedStep ? `No logs for ${selectedStep.stepName}` : "No logs available" })
|
|
4801
|
+
] })
|
|
4802
|
+
}
|
|
4803
|
+
)
|
|
4804
|
+
] });
|
|
4805
|
+
};
|
|
4806
|
+
return /* @__PURE__ */ jsx(
|
|
4807
|
+
BaseExecutionLogs,
|
|
4808
|
+
{
|
|
4809
|
+
resourceId,
|
|
4810
|
+
resourceType: "workflow",
|
|
4811
|
+
executionId,
|
|
4812
|
+
onExecutionDeleted,
|
|
4813
|
+
renderLogsSection,
|
|
4814
|
+
hideInput: isStepSelected,
|
|
4815
|
+
hideResult: isStepSelected,
|
|
4816
|
+
hideError: isStepSelected
|
|
4817
|
+
}
|
|
4818
|
+
);
|
|
4819
|
+
}
|
|
4820
|
+
function buildTree(files) {
|
|
4821
|
+
const root = { label: "root", path: null, order: 0, isIndex: false, children: [] };
|
|
4822
|
+
for (const file of files) {
|
|
4823
|
+
const segments = file.path.split("/");
|
|
4824
|
+
let current = root;
|
|
4825
|
+
for (let i = 0; i < segments.length; i++) {
|
|
4826
|
+
const segment = segments[i];
|
|
4827
|
+
const isLastSegment = i === segments.length - 1;
|
|
4828
|
+
const isIndexFile = isLastSegment && (segment === "index.mdx" || segment === "index.md");
|
|
4829
|
+
if (isLastSegment) {
|
|
4830
|
+
if (isIndexFile) {
|
|
4831
|
+
current.path = file.path;
|
|
4832
|
+
current.label = file.frontmatter.title || current.label;
|
|
4833
|
+
current.order = file.frontmatter.order ?? current.order;
|
|
4834
|
+
current.isIndex = true;
|
|
4835
|
+
} else {
|
|
4836
|
+
current.children.push({
|
|
4837
|
+
label: file.frontmatter.title || segment.replace(/\.mdx?$/, ""),
|
|
4838
|
+
path: file.path,
|
|
4839
|
+
order: file.frontmatter.order ?? Infinity,
|
|
4840
|
+
isIndex: false,
|
|
4841
|
+
children: []
|
|
4842
|
+
});
|
|
4843
|
+
}
|
|
4844
|
+
} else {
|
|
4845
|
+
let child = current.children.find((c) => c.label === segment && c.path === null);
|
|
4846
|
+
if (!child) {
|
|
4847
|
+
child = {
|
|
4848
|
+
label: segment,
|
|
4849
|
+
path: null,
|
|
4850
|
+
order: Infinity,
|
|
4851
|
+
isIndex: false,
|
|
4852
|
+
children: []
|
|
4853
|
+
};
|
|
4854
|
+
current.children.push(child);
|
|
4855
|
+
}
|
|
4856
|
+
current = child;
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
}
|
|
4860
|
+
return sortNodes(root.children);
|
|
4861
|
+
}
|
|
4862
|
+
function sortNodes(nodes) {
|
|
4863
|
+
return nodes.map((node) => ({
|
|
4864
|
+
...node,
|
|
4865
|
+
children: sortNodes(node.children)
|
|
4866
|
+
})).sort((a, b) => {
|
|
4867
|
+
if (a.isIndex && !b.isIndex) return -1;
|
|
4868
|
+
if (!a.isIndex && b.isIndex) return 1;
|
|
4869
|
+
if (a.order !== b.order) return a.order - b.order;
|
|
4870
|
+
return a.label.localeCompare(b.label);
|
|
4871
|
+
});
|
|
4872
|
+
}
|
|
4873
|
+
function hasDescendant(node, targetPath) {
|
|
4874
|
+
if (!targetPath) return false;
|
|
4875
|
+
if (node.path === targetPath) return true;
|
|
4876
|
+
return node.children.some((child) => hasDescendant(child, targetPath));
|
|
4877
|
+
}
|
|
4878
|
+
function TreeNodeItem({
|
|
4879
|
+
node,
|
|
4880
|
+
selectedPath,
|
|
4881
|
+
onSelect,
|
|
4882
|
+
expandedPaths,
|
|
4883
|
+
onToggle
|
|
4884
|
+
}) {
|
|
4885
|
+
const isDirectory = node.children.length > 0;
|
|
4886
|
+
const key = node.path ?? node.label;
|
|
4887
|
+
if (isDirectory && node.path) {
|
|
4888
|
+
const isExpanded = expandedPaths[key] ?? true;
|
|
4889
|
+
const isActive = hasDescendant(node, selectedPath);
|
|
4890
|
+
return /* @__PURE__ */ jsx(
|
|
4891
|
+
CollapsibleSidebarGroup,
|
|
4892
|
+
{
|
|
4893
|
+
icon: isExpanded ? IconFolderOpen : IconFolder,
|
|
4894
|
+
label: node.label,
|
|
4895
|
+
isExpanded,
|
|
4896
|
+
onToggle: () => onToggle(key),
|
|
4897
|
+
isActive,
|
|
4898
|
+
onLabelClick: () => onSelect(node.path),
|
|
4899
|
+
children: node.children.map((child) => /* @__PURE__ */ jsx(
|
|
4900
|
+
TreeNodeItem,
|
|
4901
|
+
{
|
|
4902
|
+
node: child,
|
|
4903
|
+
selectedPath,
|
|
4904
|
+
onSelect,
|
|
4905
|
+
expandedPaths,
|
|
4906
|
+
onToggle
|
|
4907
|
+
},
|
|
4908
|
+
child.path ?? child.label
|
|
4909
|
+
))
|
|
4910
|
+
}
|
|
4911
|
+
);
|
|
4912
|
+
}
|
|
4913
|
+
if (isDirectory) {
|
|
4914
|
+
const isExpanded = expandedPaths[key] ?? true;
|
|
4915
|
+
const isActive = hasDescendant(node, selectedPath);
|
|
4916
|
+
return /* @__PURE__ */ jsx(
|
|
4917
|
+
CollapsibleSidebarGroup,
|
|
4918
|
+
{
|
|
4919
|
+
icon: isExpanded ? IconFolderOpen : IconFolder,
|
|
4920
|
+
label: node.label,
|
|
4921
|
+
isExpanded,
|
|
4922
|
+
onToggle: () => onToggle(key),
|
|
4923
|
+
isActive,
|
|
4924
|
+
children: node.children.map((child) => /* @__PURE__ */ jsx(
|
|
4925
|
+
TreeNodeItem,
|
|
4926
|
+
{
|
|
4927
|
+
node: child,
|
|
4928
|
+
selectedPath,
|
|
4929
|
+
onSelect,
|
|
4930
|
+
expandedPaths,
|
|
4931
|
+
onToggle
|
|
4932
|
+
},
|
|
4933
|
+
child.path ?? child.label
|
|
4934
|
+
))
|
|
4935
|
+
}
|
|
4936
|
+
);
|
|
4937
|
+
}
|
|
4938
|
+
return /* @__PURE__ */ jsx(
|
|
4939
|
+
SidebarListItem,
|
|
4940
|
+
{
|
|
4941
|
+
icon: IconFileText,
|
|
4942
|
+
label: node.label,
|
|
4943
|
+
isActive: node.path === selectedPath,
|
|
4944
|
+
onClick: () => {
|
|
4945
|
+
if (node.path) onSelect(node.path);
|
|
4946
|
+
}
|
|
4947
|
+
}
|
|
4948
|
+
);
|
|
4949
|
+
}
|
|
4950
|
+
function DocTreeNav({ files, selectedPath, onSelect }) {
|
|
4951
|
+
const theme = useMantineTheme();
|
|
4952
|
+
const tree = useMemo(() => buildTree(files), [files]);
|
|
4953
|
+
const [expandedPaths, setExpandedPaths] = useState(() => {
|
|
4954
|
+
const expanded = {};
|
|
4955
|
+
function collectKeys(nodes) {
|
|
4956
|
+
for (const node of nodes) {
|
|
4957
|
+
if (node.children.length > 0) {
|
|
4958
|
+
expanded[node.path ?? node.label] = true;
|
|
4959
|
+
collectKeys(node.children);
|
|
4960
|
+
}
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
collectKeys(tree);
|
|
4964
|
+
return expanded;
|
|
4965
|
+
});
|
|
4966
|
+
const handleToggle = (key) => {
|
|
4967
|
+
setExpandedPaths((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
4968
|
+
};
|
|
4969
|
+
return /* @__PURE__ */ jsx(
|
|
4970
|
+
Box,
|
|
4971
|
+
{
|
|
4972
|
+
style: {
|
|
4973
|
+
flex: 1,
|
|
4974
|
+
minHeight: 0,
|
|
4975
|
+
padding: theme.spacing.sm,
|
|
4976
|
+
display: "flex",
|
|
4977
|
+
flexDirection: "column",
|
|
4978
|
+
overflow: "hidden"
|
|
4979
|
+
},
|
|
4980
|
+
children: /* @__PURE__ */ jsx(ScrollArea, { style: { flex: 1, minHeight: 0 }, scrollbarSize: 8, children: /* @__PURE__ */ jsx(Stack, { gap: 0, children: tree.map((node) => /* @__PURE__ */ jsx(
|
|
4981
|
+
TreeNodeItem,
|
|
4982
|
+
{
|
|
4983
|
+
node,
|
|
4984
|
+
selectedPath,
|
|
4985
|
+
onSelect,
|
|
4986
|
+
expandedPaths,
|
|
4987
|
+
onToggle: handleToggle
|
|
4988
|
+
},
|
|
4989
|
+
node.path ?? node.label
|
|
4990
|
+
)) }) })
|
|
4991
|
+
}
|
|
4992
|
+
);
|
|
4993
|
+
}
|
|
4994
|
+
function KnowledgeBasePage({ mdxRenderer: MdxRenderer }) {
|
|
4995
|
+
const { organizationReady } = useInitialization();
|
|
4996
|
+
const [selectedDeploymentId, setSelectedDeploymentId] = useState(void 0);
|
|
4997
|
+
const [selectedPath, setSelectedPath] = useState(null);
|
|
4998
|
+
const { files, isLoading, error, activeDeployment, activeDeployments } = useDeploymentDocs(selectedDeploymentId);
|
|
4999
|
+
const effectivePath = useMemo(() => {
|
|
5000
|
+
if (selectedPath && files.some((f) => f.path === selectedPath)) {
|
|
5001
|
+
return selectedPath;
|
|
5002
|
+
}
|
|
5003
|
+
if (files.length === 0) return null;
|
|
5004
|
+
const indexFile = files.find((f) => f.path === "index.mdx" || f.path === "docs/index.mdx");
|
|
5005
|
+
if (indexFile) return indexFile.path;
|
|
5006
|
+
return files[0].path;
|
|
5007
|
+
}, [selectedPath, files]);
|
|
5008
|
+
const selectedFile = useMemo(() => {
|
|
5009
|
+
if (!effectivePath) return null;
|
|
5010
|
+
return files.find((f) => f.path === effectivePath) ?? null;
|
|
5011
|
+
}, [effectivePath, files]);
|
|
5012
|
+
const handleSelect = useCallback((path) => {
|
|
5013
|
+
setSelectedPath(path);
|
|
5014
|
+
}, []);
|
|
5015
|
+
const contentRef = useRef(null);
|
|
5016
|
+
const [headings, setHeadings] = useState([]);
|
|
5017
|
+
const [activeHeadingId, setActiveHeadingId] = useState(null);
|
|
5018
|
+
useEffect(() => {
|
|
5019
|
+
if (!contentRef.current) {
|
|
5020
|
+
setHeadings([]);
|
|
5021
|
+
return;
|
|
5022
|
+
}
|
|
5023
|
+
const timer = setTimeout(() => {
|
|
5024
|
+
if (!contentRef.current) return;
|
|
5025
|
+
const elements = contentRef.current.querySelectorAll("h3[id], h4[id]");
|
|
5026
|
+
const items = Array.from(elements).map((el) => ({
|
|
5027
|
+
id: el.id,
|
|
5028
|
+
text: el.textContent || "",
|
|
5029
|
+
level: parseInt(el.tagName[1])
|
|
5030
|
+
}));
|
|
5031
|
+
setHeadings(items);
|
|
5032
|
+
setActiveHeadingId(items[0]?.id ?? null);
|
|
5033
|
+
}, 100);
|
|
5034
|
+
return () => clearTimeout(timer);
|
|
5035
|
+
}, [selectedFile?.compiledSource]);
|
|
5036
|
+
useEffect(() => {
|
|
5037
|
+
if (headings.length === 0) return;
|
|
5038
|
+
const scrollContainer = contentRef.current?.closest('[style*="overflow"]');
|
|
5039
|
+
if (!scrollContainer) return;
|
|
5040
|
+
const handleScroll = () => {
|
|
5041
|
+
if (!contentRef.current) return;
|
|
5042
|
+
const elements = contentRef.current.querySelectorAll("h3[id], h4[id]");
|
|
5043
|
+
let current = headings[0]?.id ?? null;
|
|
5044
|
+
for (const el of elements) {
|
|
5045
|
+
const rect = el.getBoundingClientRect();
|
|
5046
|
+
if (rect.top <= 120) {
|
|
5047
|
+
current = el.id;
|
|
5048
|
+
} else {
|
|
5049
|
+
break;
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
setActiveHeadingId(current);
|
|
5053
|
+
};
|
|
5054
|
+
scrollContainer.addEventListener("scroll", handleScroll, { passive: true });
|
|
5055
|
+
return () => scrollContainer.removeEventListener("scroll", handleScroll);
|
|
5056
|
+
}, [headings]);
|
|
5057
|
+
if (!organizationReady || isLoading) return /* @__PURE__ */ jsx(SubshellLoader, {});
|
|
5058
|
+
const showError = !!error;
|
|
5059
|
+
const showNoDeployments = !error && !activeDeployment;
|
|
5060
|
+
const showNoDocs = !error && !!activeDeployment && files.length === 0;
|
|
5061
|
+
const showContent = !error && files.length > 0;
|
|
5062
|
+
return /* @__PURE__ */ jsxs(SubshellContainer, { children: [
|
|
5063
|
+
/* @__PURE__ */ jsxs(SubshellSidebar, { width: 250, children: [
|
|
5064
|
+
/* @__PURE__ */ jsx(
|
|
5065
|
+
Box,
|
|
5066
|
+
{
|
|
5067
|
+
p: "sm",
|
|
5068
|
+
style: { borderBottom: "1px solid var(--color-border)", borderRadius: "var(--mantine-radius-default)" },
|
|
5069
|
+
children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5070
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
5071
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5072
|
+
/* @__PURE__ */ jsx(IconBook2, { size: 16, color: "var(--color-text-subtle)" }),
|
|
5073
|
+
/* @__PURE__ */ jsx(
|
|
5074
|
+
Text,
|
|
5075
|
+
{
|
|
5076
|
+
size: "sm",
|
|
5077
|
+
fw: 600,
|
|
5078
|
+
c: "var(--color-text-subtle)",
|
|
5079
|
+
style: { fontFamily: "var(--mantine-font-family-headings)" },
|
|
5080
|
+
children: "Documentation"
|
|
5081
|
+
}
|
|
5082
|
+
)
|
|
5083
|
+
] }),
|
|
5084
|
+
activeDeployment && /* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "light", children: [
|
|
5085
|
+
"v",
|
|
5086
|
+
activeDeployment.sdkVersion
|
|
5087
|
+
] })
|
|
5088
|
+
] }),
|
|
5089
|
+
activeDeployments.length > 1 && /* @__PURE__ */ jsx(
|
|
5090
|
+
Select,
|
|
5091
|
+
{
|
|
5092
|
+
size: "xs",
|
|
5093
|
+
placeholder: "Select deployment",
|
|
5094
|
+
data: activeDeployments.map((d) => ({
|
|
5095
|
+
value: d.id,
|
|
5096
|
+
label: `${d.sdkVersion} -- ${new Date(d.createdAt).toLocaleDateString()}`
|
|
5097
|
+
})),
|
|
5098
|
+
value: activeDeployment?.id ?? null,
|
|
5099
|
+
onChange: (value) => setSelectedDeploymentId(value ?? void 0)
|
|
5100
|
+
}
|
|
5101
|
+
)
|
|
5102
|
+
] })
|
|
5103
|
+
}
|
|
5104
|
+
),
|
|
5105
|
+
showContent && /* @__PURE__ */ jsx(DocTreeNav, { files, selectedPath: effectivePath, onSelect: handleSelect })
|
|
5106
|
+
] }),
|
|
5107
|
+
/* @__PURE__ */ jsx(SubshellRightSideContainer, { children: /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
5108
|
+
/* @__PURE__ */ jsx(PageTitleCaption, { title: "Knowledge Base" }),
|
|
5109
|
+
showError && /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), title: "Failed to load documentation", color: "red", children: error instanceof Error ? error.message : "An unexpected error occurred" }),
|
|
5110
|
+
showNoDeployments && /* @__PURE__ */ jsx(Center, { style: { flex: 1 }, children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "sm", children: [
|
|
5111
|
+
/* @__PURE__ */ jsx(IconFileOff, { size: 48, color: "var(--color-text-subtle)" }),
|
|
5112
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "lg", children: "No active deployments" }),
|
|
5113
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", children: "Deploy your project using the Elevasis SDK to see documentation here." })
|
|
5114
|
+
] }) }),
|
|
5115
|
+
showNoDocs && /* @__PURE__ */ jsx(Center, { style: { flex: 1 }, children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "sm", children: [
|
|
5116
|
+
/* @__PURE__ */ jsx(IconFileOff, { size: 48, color: "var(--color-text-subtle)" }),
|
|
5117
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "lg", children: "No documentation found" }),
|
|
5118
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", children: "Add MDX files to your project's docs directory and redeploy." })
|
|
5119
|
+
] }) }),
|
|
5120
|
+
showContent && selectedFile && /* @__PURE__ */ jsxs(Box, { style: { display: "flex", gap: "1rem", alignItems: "flex-start" }, children: [
|
|
5121
|
+
/* @__PURE__ */ jsx(Box, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsx("div", { ref: contentRef, children: MdxRenderer ? /* @__PURE__ */ jsx(MdxRenderer, { compiledSource: selectedFile.compiledSource }) : /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "No MDX renderer provided" }) }) }) }),
|
|
5122
|
+
headings.length > 1 && /* @__PURE__ */ jsxs(
|
|
5123
|
+
Box,
|
|
5124
|
+
{
|
|
5125
|
+
style: {
|
|
5126
|
+
width: 200,
|
|
5127
|
+
flexShrink: 0,
|
|
5128
|
+
position: "sticky",
|
|
5129
|
+
top: 70,
|
|
5130
|
+
border: "1px solid var(--color-border)",
|
|
5131
|
+
padding: "0.75rem",
|
|
5132
|
+
background: "var(--glass-background)",
|
|
5133
|
+
backdropFilter: "var(--glass-blur)",
|
|
5134
|
+
borderRadius: "var(--mantine-radius-default)"
|
|
5135
|
+
},
|
|
5136
|
+
children: [
|
|
5137
|
+
/* @__PURE__ */ jsxs(Group, { gap: 6, mb: "xs", children: [
|
|
5138
|
+
/* @__PURE__ */ jsx(IconList, { size: 16, style: { opacity: 0.5 } }),
|
|
5139
|
+
/* @__PURE__ */ jsx(Title, { order: 6, c: "dimmed", tt: "uppercase", children: "On this page" })
|
|
5140
|
+
] }),
|
|
5141
|
+
/* @__PURE__ */ jsx(ScrollArea.Autosize, { mah: 400, scrollbarSize: 4, children: /* @__PURE__ */ jsx(Stack, { gap: 2, children: headings.map((heading) => /* @__PURE__ */ jsx(
|
|
5142
|
+
Text,
|
|
5143
|
+
{
|
|
5144
|
+
component: "a",
|
|
5145
|
+
href: `#${heading.id}`,
|
|
5146
|
+
size: "sm",
|
|
5147
|
+
onClick: (e) => {
|
|
5148
|
+
e.preventDefault();
|
|
5149
|
+
document.getElementById(heading.id)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
5150
|
+
},
|
|
5151
|
+
style: {
|
|
5152
|
+
display: "block",
|
|
5153
|
+
padding: "3px 8px",
|
|
5154
|
+
paddingLeft: heading.level === 4 ? "16px" : "8px",
|
|
5155
|
+
borderLeft: activeHeadingId === heading.id ? "2px solid var(--color-primary)" : "2px solid transparent",
|
|
5156
|
+
color: activeHeadingId === heading.id ? "var(--color-primary)" : "var(--color-text-subtle)",
|
|
5157
|
+
textDecoration: "none",
|
|
5158
|
+
borderRadius: 0,
|
|
5159
|
+
transition: "all var(--duration-fast) var(--easing)",
|
|
5160
|
+
cursor: "pointer",
|
|
5161
|
+
lineHeight: 1.4
|
|
5162
|
+
},
|
|
5163
|
+
onMouseEnter: (e) => {
|
|
5164
|
+
if (activeHeadingId !== heading.id) {
|
|
5165
|
+
e.currentTarget.style.color = "var(--color-text)";
|
|
5166
|
+
}
|
|
5167
|
+
},
|
|
5168
|
+
onMouseLeave: (e) => {
|
|
5169
|
+
if (activeHeadingId !== heading.id) {
|
|
5170
|
+
e.currentTarget.style.color = "var(--color-text-subtle)";
|
|
5171
|
+
}
|
|
5172
|
+
},
|
|
5173
|
+
children: heading.text
|
|
5174
|
+
},
|
|
5175
|
+
heading.id
|
|
5176
|
+
)) }) })
|
|
5177
|
+
]
|
|
5178
|
+
}
|
|
5179
|
+
)
|
|
5180
|
+
] }),
|
|
5181
|
+
showContent && !selectedFile && /* @__PURE__ */ jsx(Center, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Select a page from the navigation" }) })
|
|
5182
|
+
] }) }) }) })
|
|
5183
|
+
] });
|
|
5184
|
+
}
|
|
5185
|
+
function ScheduleTypeSelector({ value, onChange, disabled }) {
|
|
5186
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5187
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: "Schedule Type" }),
|
|
5188
|
+
/* @__PURE__ */ jsx(
|
|
5189
|
+
SegmentedControl,
|
|
5190
|
+
{
|
|
5191
|
+
value,
|
|
5192
|
+
onChange: (v) => onChange(v),
|
|
5193
|
+
disabled,
|
|
5194
|
+
data: [
|
|
5195
|
+
{
|
|
5196
|
+
value: "recurring",
|
|
5197
|
+
label: /* @__PURE__ */ jsxs(Stack, { gap: 4, align: "center", children: [
|
|
5198
|
+
/* @__PURE__ */ jsx(IconCalendarRepeat, { size: 20 }),
|
|
5199
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", children: "Recurring" })
|
|
5200
|
+
] })
|
|
5201
|
+
},
|
|
5202
|
+
{
|
|
5203
|
+
value: "relative",
|
|
5204
|
+
label: /* @__PURE__ */ jsxs(Stack, { gap: 4, align: "center", children: [
|
|
5205
|
+
/* @__PURE__ */ jsx(IconCalendarEvent, { size: 20 }),
|
|
5206
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", children: "Relative" })
|
|
5207
|
+
] })
|
|
5208
|
+
},
|
|
5209
|
+
{
|
|
5210
|
+
value: "absolute",
|
|
5211
|
+
label: /* @__PURE__ */ jsxs(Stack, { gap: 4, align: "center", children: [
|
|
5212
|
+
/* @__PURE__ */ jsx(IconCalendarTime, { size: 20 }),
|
|
5213
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", children: "Absolute" })
|
|
5214
|
+
] })
|
|
5215
|
+
}
|
|
5216
|
+
],
|
|
5217
|
+
fullWidth: true
|
|
5218
|
+
}
|
|
5219
|
+
),
|
|
5220
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
5221
|
+
value === "recurring" && "Run on a schedule (daily, weekly, or cron expression)",
|
|
5222
|
+
value === "relative" && "Run at offsets from an anchor date (e.g., 3 days before event)",
|
|
5223
|
+
value === "absolute" && "Run at specific dates and times"
|
|
5224
|
+
] })
|
|
5225
|
+
] });
|
|
5226
|
+
}
|
|
5227
|
+
function toDateTimeLocal(isoString) {
|
|
5228
|
+
if (!isoString) return "";
|
|
5229
|
+
const date = new Date(isoString);
|
|
5230
|
+
return date.toISOString().slice(0, 16);
|
|
5231
|
+
}
|
|
5232
|
+
function fromDateTimeLocal(dateTimeLocal) {
|
|
5233
|
+
if (!dateTimeLocal) return null;
|
|
5234
|
+
return new Date(dateTimeLocal).toISOString();
|
|
5235
|
+
}
|
|
5236
|
+
function RecurringScheduleForm({ value, onChange, disabled }) {
|
|
5237
|
+
const [useCron, setUseCron] = useState(!!value.cron);
|
|
5238
|
+
const handleChange = (updates) => {
|
|
5239
|
+
onChange({ ...value, ...updates });
|
|
5240
|
+
};
|
|
5241
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
5242
|
+
/* @__PURE__ */ jsx(
|
|
5243
|
+
Switch,
|
|
5244
|
+
{
|
|
5245
|
+
label: "Use cron expression",
|
|
5246
|
+
description: "Advanced scheduling with cron syntax",
|
|
5247
|
+
checked: useCron,
|
|
5248
|
+
onChange: (e) => {
|
|
5249
|
+
setUseCron(e.currentTarget.checked);
|
|
5250
|
+
if (e.currentTarget.checked) {
|
|
5251
|
+
handleChange({ cron: "0 9 * * *", interval: void 0, time: void 0 });
|
|
5252
|
+
} else {
|
|
5253
|
+
handleChange({ cron: void 0, interval: "daily", time: "09:00" });
|
|
5254
|
+
}
|
|
5255
|
+
},
|
|
5256
|
+
disabled
|
|
5257
|
+
}
|
|
5258
|
+
),
|
|
5259
|
+
useCron ? /* @__PURE__ */ jsx(
|
|
5260
|
+
TextInput,
|
|
5261
|
+
{
|
|
5262
|
+
label: "Cron Expression",
|
|
5263
|
+
placeholder: "0 9 * * 1 (Every Monday at 9am)",
|
|
5264
|
+
value: value.cron || "",
|
|
5265
|
+
onChange: (e) => handleChange({ cron: e.currentTarget.value }),
|
|
5266
|
+
description: "Format: minute hour day month weekday",
|
|
5267
|
+
disabled
|
|
5268
|
+
}
|
|
5269
|
+
) : /* @__PURE__ */ jsxs(Group, { grow: true, children: [
|
|
5270
|
+
/* @__PURE__ */ jsx(
|
|
5271
|
+
Select,
|
|
5272
|
+
{
|
|
5273
|
+
label: "Interval",
|
|
5274
|
+
data: [
|
|
5275
|
+
{ value: "daily", label: "Daily" },
|
|
5276
|
+
{ value: "weekly", label: "Weekly" },
|
|
5277
|
+
{ value: "monthly", label: "Monthly" }
|
|
5278
|
+
],
|
|
5279
|
+
value: value.interval || "daily",
|
|
5280
|
+
onChange: (v) => handleChange({ interval: v }),
|
|
5281
|
+
disabled
|
|
5282
|
+
}
|
|
5283
|
+
),
|
|
5284
|
+
/* @__PURE__ */ jsx(
|
|
5285
|
+
TextInput,
|
|
5286
|
+
{
|
|
5287
|
+
label: "Time",
|
|
5288
|
+
type: "time",
|
|
5289
|
+
value: value.time || "09:00",
|
|
5290
|
+
onChange: (e) => handleChange({ time: e.currentTarget.value }),
|
|
5291
|
+
disabled
|
|
5292
|
+
}
|
|
5293
|
+
)
|
|
5294
|
+
] }),
|
|
5295
|
+
/* @__PURE__ */ jsx(
|
|
5296
|
+
Select,
|
|
5297
|
+
{
|
|
5298
|
+
label: "Timezone",
|
|
5299
|
+
placeholder: "Select timezone",
|
|
5300
|
+
data: [
|
|
5301
|
+
{ value: "UTC", label: "UTC" },
|
|
5302
|
+
{ value: "America/New_York", label: "Eastern Time" },
|
|
5303
|
+
{ value: "America/Chicago", label: "Central Time" },
|
|
5304
|
+
{ value: "America/Denver", label: "Mountain Time" },
|
|
5305
|
+
{ value: "America/Los_Angeles", label: "Pacific Time" },
|
|
5306
|
+
{ value: "Europe/London", label: "London" },
|
|
5307
|
+
{ value: "Europe/Paris", label: "Paris" },
|
|
5308
|
+
{ value: "Asia/Tokyo", label: "Tokyo" }
|
|
5309
|
+
],
|
|
5310
|
+
value: value.timezone || "UTC",
|
|
5311
|
+
onChange: (v) => handleChange({ timezone: v || "UTC" }),
|
|
5312
|
+
searchable: true,
|
|
5313
|
+
disabled
|
|
5314
|
+
}
|
|
5315
|
+
),
|
|
5316
|
+
/* @__PURE__ */ jsx(
|
|
5317
|
+
TextInput,
|
|
5318
|
+
{
|
|
5319
|
+
label: "End Date (Optional)",
|
|
5320
|
+
type: "datetime-local",
|
|
5321
|
+
value: toDateTimeLocal(value.endAt),
|
|
5322
|
+
onChange: (e) => handleChange({ endAt: fromDateTimeLocal(e.currentTarget.value) }),
|
|
5323
|
+
disabled
|
|
5324
|
+
}
|
|
5325
|
+
)
|
|
5326
|
+
] });
|
|
5327
|
+
}
|
|
5328
|
+
function toDateTimeLocal2(isoString) {
|
|
5329
|
+
if (!isoString) return "";
|
|
5330
|
+
const date = new Date(isoString);
|
|
5331
|
+
return date.toISOString().slice(0, 16);
|
|
5332
|
+
}
|
|
5333
|
+
function fromDateTimeLocal2(dateTimeLocal) {
|
|
5334
|
+
if (!dateTimeLocal) return void 0;
|
|
5335
|
+
return new Date(dateTimeLocal).toISOString();
|
|
5336
|
+
}
|
|
5337
|
+
function RelativeScheduleForm({ value, onChange, disabled }) {
|
|
5338
|
+
const items = value.items || [];
|
|
5339
|
+
const handleAnchorChange = (dateTimeLocal) => {
|
|
5340
|
+
onChange({ ...value, anchorAt: fromDateTimeLocal2(dateTimeLocal) });
|
|
5341
|
+
};
|
|
5342
|
+
const handleItemChange = (index, updates) => {
|
|
5343
|
+
const newItems = [...items];
|
|
5344
|
+
newItems[index] = { ...newItems[index], ...updates };
|
|
5345
|
+
onChange({ ...value, items: newItems });
|
|
5346
|
+
};
|
|
5347
|
+
const handleAddItem = () => {
|
|
5348
|
+
const newItems = [...items, { offset: "+1d", payload: {}, label: "" }];
|
|
5349
|
+
onChange({ ...value, items: newItems });
|
|
5350
|
+
};
|
|
5351
|
+
const handleRemoveItem = (index) => {
|
|
5352
|
+
const newItems = items.filter((_, i) => i !== index);
|
|
5353
|
+
onChange({ ...value, items: newItems });
|
|
5354
|
+
};
|
|
5355
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
5356
|
+
/* @__PURE__ */ jsx(
|
|
5357
|
+
TextInput,
|
|
5358
|
+
{
|
|
5359
|
+
label: "Anchor Date",
|
|
5360
|
+
description: "Reference date for calculating run times",
|
|
5361
|
+
type: "datetime-local",
|
|
5362
|
+
value: toDateTimeLocal2(value.anchorAt),
|
|
5363
|
+
onChange: (e) => handleAnchorChange(e.currentTarget.value),
|
|
5364
|
+
required: true,
|
|
5365
|
+
disabled
|
|
5366
|
+
}
|
|
5367
|
+
),
|
|
5368
|
+
/* @__PURE__ */ jsx(
|
|
5369
|
+
TextInput,
|
|
5370
|
+
{
|
|
5371
|
+
label: "Anchor Label (Optional)",
|
|
5372
|
+
placeholder: "e.g., meeting_date, deadline, event_start",
|
|
5373
|
+
value: value.anchorLabel || "",
|
|
5374
|
+
onChange: (e) => onChange({ ...value, anchorLabel: e.currentTarget.value || void 0 }),
|
|
5375
|
+
disabled
|
|
5376
|
+
}
|
|
5377
|
+
),
|
|
5378
|
+
/* @__PURE__ */ jsxs(Stack, { children: [
|
|
5379
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
5380
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: "Schedule Items" }),
|
|
5381
|
+
/* @__PURE__ */ jsx(
|
|
5382
|
+
Button,
|
|
5383
|
+
{
|
|
5384
|
+
size: "xs",
|
|
5385
|
+
variant: "light",
|
|
5386
|
+
leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 14 }),
|
|
5387
|
+
onClick: handleAddItem,
|
|
5388
|
+
disabled,
|
|
5389
|
+
children: "Add Item"
|
|
5390
|
+
}
|
|
5391
|
+
)
|
|
5392
|
+
] }),
|
|
5393
|
+
items.length === 0 && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: 'No items yet. Click "Add Item" to create a schedule step.' }),
|
|
5394
|
+
items.map((item, index) => /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5395
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
5396
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, children: [
|
|
5397
|
+
"Step ",
|
|
5398
|
+
index + 1
|
|
5399
|
+
] }),
|
|
5400
|
+
/* @__PURE__ */ jsx(
|
|
5401
|
+
ActionIcon,
|
|
5402
|
+
{
|
|
5403
|
+
size: "sm",
|
|
5404
|
+
color: "red",
|
|
5405
|
+
variant: "subtle",
|
|
5406
|
+
onClick: () => handleRemoveItem(index),
|
|
5407
|
+
disabled,
|
|
5408
|
+
children: /* @__PURE__ */ jsx(IconTrash, { size: 14 })
|
|
5409
|
+
}
|
|
5410
|
+
)
|
|
5411
|
+
] }),
|
|
5412
|
+
/* @__PURE__ */ jsxs(Group, { grow: true, children: [
|
|
5413
|
+
/* @__PURE__ */ jsx(
|
|
5414
|
+
TextInput,
|
|
5415
|
+
{
|
|
5416
|
+
label: "Offset",
|
|
5417
|
+
placeholder: "+3d, -2h, +30m",
|
|
5418
|
+
value: item.offset,
|
|
5419
|
+
onChange: (e) => handleItemChange(index, { offset: e.currentTarget.value }),
|
|
5420
|
+
description: "+ after anchor, - before anchor",
|
|
5421
|
+
disabled
|
|
5422
|
+
}
|
|
5423
|
+
),
|
|
5424
|
+
/* @__PURE__ */ jsx(
|
|
5425
|
+
TextInput,
|
|
5426
|
+
{
|
|
5427
|
+
label: "Label (Optional)",
|
|
5428
|
+
placeholder: "e.g., Thank you, Follow up",
|
|
5429
|
+
value: item.label || "",
|
|
5430
|
+
onChange: (e) => handleItemChange(index, { label: e.currentTarget.value || void 0 }),
|
|
5431
|
+
disabled
|
|
5432
|
+
}
|
|
5433
|
+
)
|
|
5434
|
+
] }),
|
|
5435
|
+
/* @__PURE__ */ jsx(
|
|
5436
|
+
Textarea,
|
|
5437
|
+
{
|
|
5438
|
+
label: "Payload (JSON)",
|
|
5439
|
+
placeholder: '{"key": "value"}',
|
|
5440
|
+
value: JSON.stringify(item.payload, null, 2),
|
|
5441
|
+
onChange: (e) => {
|
|
5442
|
+
try {
|
|
5443
|
+
const payload = JSON.parse(e.currentTarget.value);
|
|
5444
|
+
handleItemChange(index, { payload });
|
|
5445
|
+
} catch {
|
|
5446
|
+
}
|
|
5447
|
+
},
|
|
5448
|
+
minRows: 2,
|
|
5449
|
+
disabled
|
|
5450
|
+
}
|
|
5451
|
+
)
|
|
5452
|
+
] }) }, index))
|
|
5453
|
+
] })
|
|
5454
|
+
] });
|
|
5455
|
+
}
|
|
5456
|
+
function toDateTimeLocal3(isoString) {
|
|
5457
|
+
if (!isoString) return "";
|
|
5458
|
+
const date = new Date(isoString);
|
|
5459
|
+
return date.toISOString().slice(0, 16);
|
|
5460
|
+
}
|
|
5461
|
+
function fromDateTimeLocal3(dateTimeLocal) {
|
|
5462
|
+
if (!dateTimeLocal) return "";
|
|
5463
|
+
return new Date(dateTimeLocal).toISOString();
|
|
5464
|
+
}
|
|
5465
|
+
function AbsoluteScheduleForm({ value, onChange, disabled }) {
|
|
5466
|
+
const items = value.items || [];
|
|
5467
|
+
const handleItemChange = (index, updates) => {
|
|
5468
|
+
const newItems = [...items];
|
|
5469
|
+
newItems[index] = { ...newItems[index], ...updates };
|
|
5470
|
+
onChange({ ...value, items: newItems });
|
|
5471
|
+
};
|
|
5472
|
+
const handleAddItem = () => {
|
|
5473
|
+
const newItems = [...items, { runAt: (/* @__PURE__ */ new Date()).toISOString(), payload: {}, label: "" }];
|
|
5474
|
+
onChange({ ...value, items: newItems });
|
|
5475
|
+
};
|
|
5476
|
+
const handleRemoveItem = (index) => {
|
|
5477
|
+
const newItems = items.filter((_, i) => i !== index);
|
|
5478
|
+
onChange({ ...value, items: newItems });
|
|
5479
|
+
};
|
|
5480
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
5481
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
5482
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: "Scheduled Executions" }),
|
|
5483
|
+
/* @__PURE__ */ jsx(
|
|
5484
|
+
Button,
|
|
5485
|
+
{
|
|
5486
|
+
size: "xs",
|
|
5487
|
+
variant: "light",
|
|
5488
|
+
leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 14 }),
|
|
5489
|
+
onClick: handleAddItem,
|
|
5490
|
+
disabled,
|
|
5491
|
+
children: "Add Execution"
|
|
5492
|
+
}
|
|
5493
|
+
)
|
|
5494
|
+
] }),
|
|
5495
|
+
items.length === 0 && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: 'No executions yet. Click "Add Execution" to schedule a run.' }),
|
|
5496
|
+
items.map((item, index) => /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5497
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
5498
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, children: [
|
|
5499
|
+
"Execution ",
|
|
5500
|
+
index + 1
|
|
5501
|
+
] }),
|
|
5502
|
+
/* @__PURE__ */ jsx(
|
|
5503
|
+
ActionIcon,
|
|
5504
|
+
{
|
|
5505
|
+
size: "sm",
|
|
5506
|
+
color: "red",
|
|
5507
|
+
variant: "subtle",
|
|
5508
|
+
onClick: () => handleRemoveItem(index),
|
|
5509
|
+
disabled,
|
|
5510
|
+
children: /* @__PURE__ */ jsx(IconTrash, { size: 14 })
|
|
5511
|
+
}
|
|
5512
|
+
)
|
|
5513
|
+
] }),
|
|
5514
|
+
/* @__PURE__ */ jsxs(Group, { grow: true, children: [
|
|
5515
|
+
/* @__PURE__ */ jsx(
|
|
5516
|
+
TextInput,
|
|
5517
|
+
{
|
|
5518
|
+
label: "Run At",
|
|
5519
|
+
type: "datetime-local",
|
|
5520
|
+
value: toDateTimeLocal3(item.runAt),
|
|
5521
|
+
onChange: (e) => handleItemChange(index, { runAt: fromDateTimeLocal3(e.currentTarget.value) }),
|
|
5522
|
+
required: true,
|
|
5523
|
+
disabled
|
|
5524
|
+
}
|
|
5525
|
+
),
|
|
5526
|
+
/* @__PURE__ */ jsx(
|
|
5527
|
+
TextInput,
|
|
5528
|
+
{
|
|
5529
|
+
label: "Label (Optional)",
|
|
5530
|
+
placeholder: "e.g., Launch, Phase 2",
|
|
5531
|
+
value: item.label || "",
|
|
5532
|
+
onChange: (e) => handleItemChange(index, { label: e.currentTarget.value || void 0 }),
|
|
5533
|
+
disabled
|
|
5534
|
+
}
|
|
5535
|
+
)
|
|
5536
|
+
] }),
|
|
5537
|
+
/* @__PURE__ */ jsx(
|
|
5538
|
+
Textarea,
|
|
5539
|
+
{
|
|
5540
|
+
label: "Payload (JSON)",
|
|
5541
|
+
placeholder: '{"key": "value"}',
|
|
5542
|
+
value: JSON.stringify(item.payload, null, 2),
|
|
5543
|
+
onChange: (e) => {
|
|
5544
|
+
try {
|
|
5545
|
+
const payload = JSON.parse(e.currentTarget.value);
|
|
5546
|
+
handleItemChange(index, { payload });
|
|
5547
|
+
} catch {
|
|
5548
|
+
}
|
|
5549
|
+
},
|
|
5550
|
+
minRows: 2,
|
|
5551
|
+
disabled
|
|
5552
|
+
}
|
|
5553
|
+
)
|
|
5554
|
+
] }) }, index))
|
|
5555
|
+
] });
|
|
5556
|
+
}
|
|
5557
|
+
var defaultRecurringConfig = {
|
|
5558
|
+
type: "recurring",
|
|
5559
|
+
interval: "daily",
|
|
5560
|
+
time: "09:00",
|
|
5561
|
+
timezone: "UTC",
|
|
5562
|
+
payload: {}
|
|
5563
|
+
};
|
|
5564
|
+
var defaultRelativeConfig = {
|
|
5565
|
+
type: "relative",
|
|
5566
|
+
items: []
|
|
5567
|
+
};
|
|
5568
|
+
var defaultAbsoluteConfig = {
|
|
5569
|
+
type: "absolute",
|
|
5570
|
+
items: []
|
|
5571
|
+
};
|
|
5572
|
+
function CreateScheduleModal({ opened, onClose }) {
|
|
5573
|
+
const [name, setName] = useState("");
|
|
5574
|
+
const [description, setDescription] = useState("");
|
|
5575
|
+
const [resourceId, setResourceId] = useState("");
|
|
5576
|
+
const [scheduleType, setScheduleType] = useState("recurring");
|
|
5577
|
+
const [recurringConfig, setRecurringConfig] = useState(defaultRecurringConfig);
|
|
5578
|
+
const [relativeConfig, setRelativeConfig] = useState(defaultRelativeConfig);
|
|
5579
|
+
const [absoluteConfig, setAbsoluteConfig] = useState(defaultAbsoluteConfig);
|
|
5580
|
+
const { data: resourcesData } = useResources();
|
|
5581
|
+
const createSchedule = useCreateSchedule();
|
|
5582
|
+
const allResources = useMemo(() => {
|
|
5583
|
+
if (!resourcesData) return [];
|
|
5584
|
+
const workflows = (resourcesData.workflows || []).map((w) => ({
|
|
5585
|
+
id: w.resourceId,
|
|
5586
|
+
type: "workflow"
|
|
5587
|
+
}));
|
|
5588
|
+
const agents = (resourcesData.agents || []).map((a) => ({
|
|
5589
|
+
id: a.resourceId,
|
|
5590
|
+
type: "agent"
|
|
5591
|
+
}));
|
|
5592
|
+
return [...workflows, ...agents];
|
|
5593
|
+
}, [resourcesData]);
|
|
5594
|
+
const resourceOptions2 = useMemo(() => {
|
|
5595
|
+
if (!resourcesData) return [];
|
|
5596
|
+
const workflowOptions = (resourcesData.workflows || []).filter((w) => w?.resourceId).map((w) => ({
|
|
5597
|
+
value: w.resourceId,
|
|
5598
|
+
label: `Workflow: ${w.resourceId}`
|
|
5599
|
+
}));
|
|
5600
|
+
const agentOptions = (resourcesData.agents || []).filter((a) => a?.resourceId).map((a) => ({
|
|
5601
|
+
value: a.resourceId,
|
|
5602
|
+
label: `Agent: ${a.resourceId}`
|
|
5603
|
+
}));
|
|
5604
|
+
return [...workflowOptions, ...agentOptions];
|
|
5605
|
+
}, [resourcesData]);
|
|
5606
|
+
const handleScheduleTypeChange = (newType) => {
|
|
5607
|
+
setScheduleType(newType);
|
|
5608
|
+
};
|
|
5609
|
+
const buildScheduleConfig = () => {
|
|
5610
|
+
switch (scheduleType) {
|
|
5611
|
+
case "recurring": {
|
|
5612
|
+
if (!recurringConfig.timezone) {
|
|
5613
|
+
showErrorNotification("Timezone is required");
|
|
5614
|
+
return null;
|
|
5615
|
+
}
|
|
5616
|
+
const config = {
|
|
5617
|
+
type: "recurring",
|
|
5618
|
+
timezone: recurringConfig.timezone,
|
|
5619
|
+
payload: recurringConfig.payload || {},
|
|
5620
|
+
endAt: recurringConfig.endAt
|
|
5621
|
+
};
|
|
5622
|
+
if (recurringConfig.cron) {
|
|
5623
|
+
config.cron = recurringConfig.cron;
|
|
5624
|
+
} else {
|
|
5625
|
+
config.interval = recurringConfig.interval || "daily";
|
|
5626
|
+
config.time = recurringConfig.time || "09:00";
|
|
5627
|
+
}
|
|
5628
|
+
return config;
|
|
5629
|
+
}
|
|
5630
|
+
case "relative": {
|
|
5631
|
+
if (!relativeConfig.anchorAt) {
|
|
5632
|
+
showErrorNotification("Anchor date is required for relative schedules");
|
|
5633
|
+
return null;
|
|
5634
|
+
}
|
|
5635
|
+
if (!relativeConfig.items || relativeConfig.items.length === 0) {
|
|
5636
|
+
showErrorNotification("At least one schedule item is required");
|
|
5637
|
+
return null;
|
|
5638
|
+
}
|
|
5639
|
+
return {
|
|
5640
|
+
type: "relative",
|
|
5641
|
+
anchorAt: relativeConfig.anchorAt,
|
|
5642
|
+
anchorLabel: relativeConfig.anchorLabel,
|
|
5643
|
+
items: relativeConfig.items
|
|
5644
|
+
};
|
|
5645
|
+
}
|
|
5646
|
+
case "absolute": {
|
|
5647
|
+
if (!absoluteConfig.items || absoluteConfig.items.length === 0) {
|
|
5648
|
+
showErrorNotification("At least one scheduled execution is required");
|
|
5649
|
+
return null;
|
|
5650
|
+
}
|
|
5651
|
+
return {
|
|
5652
|
+
type: "absolute",
|
|
5653
|
+
items: absoluteConfig.items
|
|
5654
|
+
};
|
|
5655
|
+
}
|
|
5656
|
+
default:
|
|
5657
|
+
return null;
|
|
5658
|
+
}
|
|
5659
|
+
};
|
|
5660
|
+
const handleSubmit = async (e) => {
|
|
5661
|
+
e.preventDefault();
|
|
5662
|
+
try {
|
|
5663
|
+
const resource = allResources.find((r) => r.id === resourceId);
|
|
5664
|
+
if (!resource) {
|
|
5665
|
+
showErrorNotification("Please select a valid resource");
|
|
5666
|
+
return;
|
|
5667
|
+
}
|
|
5668
|
+
if (!name.trim()) {
|
|
5669
|
+
showErrorNotification("Schedule name is required");
|
|
5670
|
+
return;
|
|
5671
|
+
}
|
|
5672
|
+
const scheduleConfig = buildScheduleConfig();
|
|
5673
|
+
if (!scheduleConfig) {
|
|
5674
|
+
return;
|
|
5675
|
+
}
|
|
5676
|
+
const input = {
|
|
5677
|
+
name: name.trim(),
|
|
5678
|
+
description: description.trim() || void 0,
|
|
5679
|
+
target: {
|
|
5680
|
+
resourceType: resource.type,
|
|
5681
|
+
resourceId: resource.id
|
|
5682
|
+
},
|
|
5683
|
+
scheduleConfig,
|
|
5684
|
+
maxRetries: 3,
|
|
5685
|
+
originResourceType: "api",
|
|
5686
|
+
originResourceId: "task-scheduler-ui"
|
|
5687
|
+
};
|
|
5688
|
+
await createSchedule.mutateAsync(input);
|
|
5689
|
+
showSuccessNotification("Schedule created successfully");
|
|
5690
|
+
handleClose();
|
|
5691
|
+
} catch (error) {
|
|
5692
|
+
showApiErrorNotification(error);
|
|
5693
|
+
}
|
|
5694
|
+
};
|
|
5695
|
+
const handleClose = () => {
|
|
5696
|
+
if (!createSchedule.isPending) {
|
|
5697
|
+
setName("");
|
|
5698
|
+
setDescription("");
|
|
5699
|
+
setResourceId("");
|
|
5700
|
+
setScheduleType("recurring");
|
|
5701
|
+
setRecurringConfig(defaultRecurringConfig);
|
|
5702
|
+
setRelativeConfig(defaultRelativeConfig);
|
|
5703
|
+
setAbsoluteConfig(defaultAbsoluteConfig);
|
|
5704
|
+
onClose();
|
|
5705
|
+
}
|
|
5706
|
+
};
|
|
5707
|
+
return /* @__PURE__ */ jsx(CustomModal, { opened, onClose: handleClose, size: "lg", loading: createSchedule.isPending, children: /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
5708
|
+
/* @__PURE__ */ jsx(Title, { order: 3, children: "Create Schedule" }),
|
|
5709
|
+
/* @__PURE__ */ jsx(
|
|
5710
|
+
TextInput,
|
|
5711
|
+
{
|
|
5712
|
+
label: "Schedule Name",
|
|
5713
|
+
placeholder: "e.g., Daily Sales Report, Weekly Sync",
|
|
5714
|
+
value: name,
|
|
5715
|
+
onChange: (e) => setName(e.currentTarget.value),
|
|
5716
|
+
required: true,
|
|
5717
|
+
disabled: createSchedule.isPending
|
|
5718
|
+
}
|
|
5719
|
+
),
|
|
5720
|
+
/* @__PURE__ */ jsx(
|
|
5721
|
+
Textarea,
|
|
5722
|
+
{
|
|
5723
|
+
label: "Description (Optional)",
|
|
5724
|
+
placeholder: "Describe what this schedule does...",
|
|
5725
|
+
value: description,
|
|
5726
|
+
onChange: (e) => setDescription(e.currentTarget.value),
|
|
5727
|
+
disabled: createSchedule.isPending
|
|
5728
|
+
}
|
|
5729
|
+
),
|
|
5730
|
+
/* @__PURE__ */ jsx(
|
|
5731
|
+
Select,
|
|
5732
|
+
{
|
|
5733
|
+
label: "Resource to Execute",
|
|
5734
|
+
placeholder: resourcesData ? "Select an agent or workflow" : "Loading resources...",
|
|
5735
|
+
data: resourceOptions2,
|
|
5736
|
+
value: resourceId,
|
|
5737
|
+
onChange: (value) => setResourceId(value || ""),
|
|
5738
|
+
searchable: true,
|
|
5739
|
+
required: true,
|
|
5740
|
+
disabled: !resourcesData || createSchedule.isPending
|
|
5741
|
+
}
|
|
5742
|
+
),
|
|
5743
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
5744
|
+
/* @__PURE__ */ jsx(
|
|
5745
|
+
ScheduleTypeSelector,
|
|
5746
|
+
{
|
|
5747
|
+
value: scheduleType,
|
|
5748
|
+
onChange: handleScheduleTypeChange,
|
|
5749
|
+
disabled: createSchedule.isPending
|
|
5750
|
+
}
|
|
5751
|
+
),
|
|
5752
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
5753
|
+
scheduleType === "recurring" && /* @__PURE__ */ jsx(
|
|
5754
|
+
RecurringScheduleForm,
|
|
5755
|
+
{
|
|
5756
|
+
value: recurringConfig,
|
|
5757
|
+
onChange: setRecurringConfig,
|
|
5758
|
+
disabled: createSchedule.isPending
|
|
5759
|
+
}
|
|
5760
|
+
),
|
|
5761
|
+
scheduleType === "relative" && /* @__PURE__ */ jsx(
|
|
5762
|
+
RelativeScheduleForm,
|
|
5763
|
+
{
|
|
5764
|
+
value: relativeConfig,
|
|
5765
|
+
onChange: setRelativeConfig,
|
|
5766
|
+
disabled: createSchedule.isPending
|
|
5767
|
+
}
|
|
5768
|
+
),
|
|
5769
|
+
scheduleType === "absolute" && /* @__PURE__ */ jsx(
|
|
5770
|
+
AbsoluteScheduleForm,
|
|
5771
|
+
{
|
|
5772
|
+
value: absoluteConfig,
|
|
5773
|
+
onChange: setAbsoluteConfig,
|
|
5774
|
+
disabled: createSchedule.isPending
|
|
5775
|
+
}
|
|
5776
|
+
),
|
|
5777
|
+
/* @__PURE__ */ jsxs(Group, { justify: "flex-end", mt: "md", children: [
|
|
5778
|
+
/* @__PURE__ */ jsx(Button, { variant: "light", onClick: handleClose, type: "button", disabled: createSchedule.isPending, children: "Cancel" }),
|
|
5779
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", loading: createSchedule.isPending, children: "Create Schedule" })
|
|
5780
|
+
] })
|
|
5781
|
+
] }) }) });
|
|
5782
|
+
}
|
|
5783
|
+
function DeleteScheduleModal({ opened, onClose, onConfirm, schedule, isDeleting }) {
|
|
5784
|
+
const handleClose = () => {
|
|
5785
|
+
if (!isDeleting) {
|
|
5786
|
+
onClose();
|
|
5787
|
+
}
|
|
5788
|
+
};
|
|
5789
|
+
return /* @__PURE__ */ jsx(CustomModal, { opened, onClose: handleClose, size: "sm", loading: isDeleting, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
5790
|
+
/* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
5791
|
+
/* @__PURE__ */ jsx(IconAlertTriangle, { size: 24, color: "var(--color-error)" }),
|
|
5792
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "Delete Schedule" })
|
|
5793
|
+
] }),
|
|
5794
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", children: [
|
|
5795
|
+
"Are you sure you want to delete",
|
|
5796
|
+
" ",
|
|
5797
|
+
/* @__PURE__ */ jsx(Text, { span: true, fw: 600, children: schedule?.name }),
|
|
5798
|
+
"?"
|
|
5799
|
+
] }),
|
|
5800
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "This action cannot be undone. Any pending executions will be cancelled." }),
|
|
5801
|
+
/* @__PURE__ */ jsxs(Group, { justify: "flex-end", mt: "md", children: [
|
|
5802
|
+
/* @__PURE__ */ jsx(Button, { variant: "light", onClick: handleClose, disabled: isDeleting, children: "Cancel" }),
|
|
5803
|
+
/* @__PURE__ */ jsx(Button, { color: "red", onClick: onConfirm, loading: isDeleting, children: "Delete" })
|
|
5804
|
+
] })
|
|
5805
|
+
] }) });
|
|
5806
|
+
}
|
|
5807
|
+
function getStatusColor(status) {
|
|
5808
|
+
switch (status) {
|
|
5809
|
+
case "active":
|
|
5810
|
+
return "green";
|
|
5811
|
+
case "paused":
|
|
5812
|
+
return "yellow";
|
|
5813
|
+
case "completed":
|
|
5814
|
+
return "blue";
|
|
5815
|
+
case "cancelled":
|
|
5816
|
+
return "gray";
|
|
5817
|
+
}
|
|
5818
|
+
}
|
|
5819
|
+
function formatDate(date) {
|
|
5820
|
+
if (!date) return "N/A";
|
|
5821
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
5822
|
+
return d.toLocaleString("en-US", {
|
|
5823
|
+
month: "short",
|
|
5824
|
+
day: "numeric",
|
|
5825
|
+
year: "numeric",
|
|
5826
|
+
hour: "numeric",
|
|
5827
|
+
minute: "2-digit",
|
|
5828
|
+
timeZoneName: "short"
|
|
5829
|
+
});
|
|
5830
|
+
}
|
|
5831
|
+
function ScheduleConfigDetails({ schedule }) {
|
|
5832
|
+
const config = schedule.scheduleConfig;
|
|
5833
|
+
switch (config.type) {
|
|
5834
|
+
case "recurring":
|
|
5835
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5836
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5837
|
+
/* @__PURE__ */ jsx(IconCalendarRepeat, { size: 16, color: "var(--color-text-subtle)" }),
|
|
5838
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: "Recurring Schedule" })
|
|
5839
|
+
] }),
|
|
5840
|
+
/* @__PURE__ */ jsx(Table, { withRowBorders: false, verticalSpacing: 4, children: /* @__PURE__ */ jsxs(Table.Tbody, { children: [
|
|
5841
|
+
config.cron && /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5842
|
+
/* @__PURE__ */ jsx(Table.Td, { w: 120, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Cron" }) }),
|
|
5843
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Code, { children: config.cron }) })
|
|
5844
|
+
] }),
|
|
5845
|
+
config.interval && /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5846
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Interval" }) }),
|
|
5847
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
5848
|
+
config.interval,
|
|
5849
|
+
" at ",
|
|
5850
|
+
config.time
|
|
5851
|
+
] }) })
|
|
5852
|
+
] }),
|
|
5853
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5854
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Timezone" }) }),
|
|
5855
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { children: config.timezone }) })
|
|
5856
|
+
] }),
|
|
5857
|
+
config.endAt && /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5858
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Ends" }) }),
|
|
5859
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { children: formatDate(config.endAt) }) })
|
|
5860
|
+
] }),
|
|
5861
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5862
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Overdue" }) }),
|
|
5863
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: config.overduePolicy === "execute" ? "orange" : "gray", children: config.overduePolicy ?? "skip" }) })
|
|
5864
|
+
] }),
|
|
5865
|
+
Object.keys(config.payload).length > 0 && /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5866
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Payload" }) }),
|
|
5867
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Code, { block: true, children: JSON.stringify(config.payload, null, 2) }) })
|
|
5868
|
+
] })
|
|
5869
|
+
] }) })
|
|
5870
|
+
] });
|
|
5871
|
+
case "relative":
|
|
5872
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5873
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5874
|
+
/* @__PURE__ */ jsx(IconCalendarEvent, { size: 16, color: "var(--color-text-subtle)" }),
|
|
5875
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: "Relative Schedule" })
|
|
5876
|
+
] }),
|
|
5877
|
+
/* @__PURE__ */ jsx(Table, { withRowBorders: false, verticalSpacing: 4, children: /* @__PURE__ */ jsxs(Table.Tbody, { children: [
|
|
5878
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5879
|
+
/* @__PURE__ */ jsx(Table.Td, { w: 120, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Anchor" }) }),
|
|
5880
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
5881
|
+
formatDate(config.anchorAt),
|
|
5882
|
+
config.anchorLabel && ` (${config.anchorLabel})`
|
|
5883
|
+
] }) })
|
|
5884
|
+
] }),
|
|
5885
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5886
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Steps" }) }),
|
|
5887
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Stack, { gap: 4, children: config.items.map((item, i) => /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5888
|
+
/* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: i === schedule.currentStep ? "blue" : "gray", children: item.offset }),
|
|
5889
|
+
item.label && /* @__PURE__ */ jsx(Text, { c: "dimmed", children: item.label })
|
|
5890
|
+
] }, i)) }) })
|
|
5891
|
+
] })
|
|
5892
|
+
] }) })
|
|
5893
|
+
] });
|
|
5894
|
+
case "absolute":
|
|
5895
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5896
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5897
|
+
/* @__PURE__ */ jsx(IconCalendarTime, { size: 16, color: "var(--color-text-subtle)" }),
|
|
5898
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: "Absolute Schedule" })
|
|
5899
|
+
] }),
|
|
5900
|
+
/* @__PURE__ */ jsx(Stack, { gap: 4, children: config.items.map((item, i) => /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5901
|
+
/* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: i === schedule.currentStep ? "blue" : "gray", children: i + 1 }),
|
|
5902
|
+
/* @__PURE__ */ jsx(Text, { children: formatDate(item.runAt) }),
|
|
5903
|
+
item.label && /* @__PURE__ */ jsxs(Text, { c: "dimmed", children: [
|
|
5904
|
+
"\u2014 ",
|
|
5905
|
+
item.label
|
|
5906
|
+
] })
|
|
5907
|
+
] }, i)) })
|
|
5908
|
+
] });
|
|
5909
|
+
}
|
|
5910
|
+
}
|
|
5911
|
+
function ScheduleDetailModal({ opened, onClose, schedule, resourceStatus }) {
|
|
5912
|
+
const ResourceIcon = schedule?.target.resourceType === "agent" ? IconRobot : IconGitBranch;
|
|
5913
|
+
const resourceNotFound = resourceStatus === void 0;
|
|
5914
|
+
return /* @__PURE__ */ jsx(CustomModal, { opened, onClose, size: "lg", children: schedule && /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
5915
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", children: [
|
|
5916
|
+
/* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
5917
|
+
/* @__PURE__ */ jsx(ResourceIcon, { size: 24, color: "var(--color-primary)" }),
|
|
5918
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
5919
|
+
/* @__PURE__ */ jsx(Title, { order: 4, style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, children: schedule.name }),
|
|
5920
|
+
schedule.description && /* @__PURE__ */ jsx(Text, { c: "dimmed", mt: 2, children: schedule.description })
|
|
5921
|
+
] })
|
|
5922
|
+
] }),
|
|
5923
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: getStatusColor(schedule.status), children: schedule.status })
|
|
5924
|
+
] }),
|
|
5925
|
+
resourceNotFound && /* @__PURE__ */ jsxs(Alert, { icon: /* @__PURE__ */ jsx(IconAlertTriangle, { size: 18 }), color: "red", variant: "light", title: "Resource not found", children: [
|
|
5926
|
+
"The target resource ",
|
|
5927
|
+
/* @__PURE__ */ jsx(Code, { children: schedule.target.resourceId }),
|
|
5928
|
+
" does not exist in the current deployment. This schedule will fail when it tries to execute. Consider deleting or updating it."
|
|
5929
|
+
] }),
|
|
5930
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
5931
|
+
/* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
|
|
5932
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5933
|
+
/* @__PURE__ */ jsx(ResourceIcon, { size: 14, color: "var(--color-text-subtle)" }),
|
|
5934
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Target" })
|
|
5935
|
+
] }),
|
|
5936
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5937
|
+
/* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", radius: "sm", children: schedule.target.resourceType }),
|
|
5938
|
+
/* @__PURE__ */ jsx(Code, { children: schedule.target.resourceId })
|
|
5939
|
+
] })
|
|
5940
|
+
] }),
|
|
5941
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
5942
|
+
/* @__PURE__ */ jsx(ScheduleConfigDetails, { schedule }),
|
|
5943
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
5944
|
+
/* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
5945
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
5946
|
+
/* @__PURE__ */ jsx(IconSettings, { size: 16, color: "var(--color-text-subtle)" }),
|
|
5947
|
+
/* @__PURE__ */ jsx(Text, { fw: 500, children: "Execution Details" })
|
|
5948
|
+
] }),
|
|
5949
|
+
/* @__PURE__ */ jsx(Table, { withRowBorders: false, verticalSpacing: 4, children: /* @__PURE__ */ jsxs(Table.Tbody, { children: [
|
|
5950
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5951
|
+
/* @__PURE__ */ jsx(Table.Td, { w: 140, children: /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
5952
|
+
/* @__PURE__ */ jsx(IconClock, { size: 12, color: "var(--color-text-subtle)" }),
|
|
5953
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Next Run" })
|
|
5954
|
+
] }) }),
|
|
5955
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { children: formatDate(schedule.nextRunAt) }) })
|
|
5956
|
+
] }),
|
|
5957
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5958
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
5959
|
+
/* @__PURE__ */ jsx(IconCalendar, { size: 12, color: "var(--color-text-subtle)" }),
|
|
5960
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Last Run" })
|
|
5961
|
+
] }) }),
|
|
5962
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { children: formatDate(schedule.lastRunAt) }) })
|
|
5963
|
+
] }),
|
|
5964
|
+
/* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5965
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
5966
|
+
/* @__PURE__ */ jsx(IconRefresh, { size: 12, color: "var(--color-text-subtle)" }),
|
|
5967
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Max Retries" })
|
|
5968
|
+
] }) }),
|
|
5969
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { children: schedule.maxRetries }) })
|
|
5970
|
+
] }),
|
|
5971
|
+
schedule.idempotencyKey && /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5972
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
5973
|
+
/* @__PURE__ */ jsx(IconKey, { size: 12, color: "var(--color-text-subtle)" }),
|
|
5974
|
+
/* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Idempotency" })
|
|
5975
|
+
] }) }),
|
|
5976
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Code, { children: schedule.idempotencyKey }) })
|
|
5977
|
+
] }),
|
|
5978
|
+
schedule.lastExecutionId && /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
5979
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "Last Execution" }) }),
|
|
5980
|
+
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Code, { children: schedule.lastExecutionId }) })
|
|
5981
|
+
] })
|
|
5982
|
+
] }) })
|
|
5983
|
+
] }),
|
|
5984
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
5985
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
5986
|
+
/* @__PURE__ */ jsxs(Group, { gap: "lg", children: [
|
|
5987
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
5988
|
+
"Created ",
|
|
5989
|
+
formatDate(schedule.createdAt)
|
|
5990
|
+
] }),
|
|
5991
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
5992
|
+
"Updated ",
|
|
5993
|
+
formatDate(schedule.updatedAt)
|
|
5994
|
+
] })
|
|
5995
|
+
] }),
|
|
5996
|
+
/* @__PURE__ */ jsx(
|
|
5997
|
+
Button,
|
|
5998
|
+
{
|
|
5999
|
+
variant: "light",
|
|
6000
|
+
size: "xs",
|
|
6001
|
+
rightSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 14 }),
|
|
6002
|
+
component: "a",
|
|
6003
|
+
href: schedule.target.resourceType === "agent" ? `/operations/resources/agent/${schedule.target.resourceId}` : `/operations/resources/workflow/${schedule.target.resourceId}`,
|
|
6004
|
+
target: "_blank",
|
|
6005
|
+
disabled: resourceNotFound,
|
|
6006
|
+
children: "Go to Resource"
|
|
6007
|
+
}
|
|
6008
|
+
)
|
|
6009
|
+
] })
|
|
6010
|
+
] }) });
|
|
6011
|
+
}
|
|
6012
|
+
function getScheduleTypeIcon(config) {
|
|
6013
|
+
switch (config.type) {
|
|
6014
|
+
case "recurring":
|
|
6015
|
+
return IconCalendarRepeat;
|
|
6016
|
+
case "relative":
|
|
6017
|
+
return IconCalendarEvent;
|
|
6018
|
+
case "absolute":
|
|
6019
|
+
return IconCalendarTime;
|
|
6020
|
+
}
|
|
6021
|
+
}
|
|
6022
|
+
function getScheduleTypeLabel(config) {
|
|
6023
|
+
switch (config.type) {
|
|
6024
|
+
case "recurring":
|
|
6025
|
+
if (config.cron) return `Cron: ${config.cron}`;
|
|
6026
|
+
if (config.interval)
|
|
6027
|
+
return `${config.interval.charAt(0).toUpperCase() + config.interval.slice(1)} at ${config.time}`;
|
|
6028
|
+
return "Recurring";
|
|
6029
|
+
case "relative":
|
|
6030
|
+
return `${config.items.length} steps from anchor`;
|
|
6031
|
+
case "absolute":
|
|
6032
|
+
return `${config.items.length} scheduled runs`;
|
|
6033
|
+
}
|
|
6034
|
+
}
|
|
6035
|
+
function getStatusColor2(status) {
|
|
6036
|
+
switch (status) {
|
|
6037
|
+
case "active":
|
|
6038
|
+
return "green";
|
|
6039
|
+
case "paused":
|
|
6040
|
+
return "yellow";
|
|
6041
|
+
case "completed":
|
|
6042
|
+
return "blue";
|
|
6043
|
+
case "cancelled":
|
|
6044
|
+
return "gray";
|
|
6045
|
+
}
|
|
6046
|
+
}
|
|
6047
|
+
function formatNextRun(date) {
|
|
6048
|
+
if (!date) return "";
|
|
6049
|
+
const now = /* @__PURE__ */ new Date();
|
|
6050
|
+
const diffMs = date.getTime() - now.getTime();
|
|
6051
|
+
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
6052
|
+
const diffHours = Math.floor(diffMs % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60));
|
|
6053
|
+
if (diffMs < 0) return "Overdue";
|
|
6054
|
+
if (diffDays === 0) {
|
|
6055
|
+
if (diffHours === 0) return "Less than an hour";
|
|
6056
|
+
return `In ${diffHours}h`;
|
|
6057
|
+
}
|
|
6058
|
+
if (diffDays === 1) return "Tomorrow";
|
|
6059
|
+
if (diffDays <= 7) return `In ${diffDays}d`;
|
|
6060
|
+
return date.toLocaleDateString("en-US", {
|
|
6061
|
+
month: "short",
|
|
6062
|
+
day: "numeric"
|
|
6063
|
+
});
|
|
6064
|
+
}
|
|
6065
|
+
function ScheduleCard({
|
|
6066
|
+
schedule,
|
|
6067
|
+
resourceStatus,
|
|
6068
|
+
onPause,
|
|
6069
|
+
onResume,
|
|
6070
|
+
onCancel,
|
|
6071
|
+
onDelete,
|
|
6072
|
+
onClick,
|
|
6073
|
+
isLoading
|
|
6074
|
+
}) {
|
|
6075
|
+
const [hovered, setHovered] = useState(false);
|
|
6076
|
+
const TypeIcon = getScheduleTypeIcon(schedule.scheduleConfig);
|
|
6077
|
+
const ResourceIcon = schedule.target.resourceType === "agent" ? IconRobot : IconGitBranch;
|
|
6078
|
+
const nextRunAt = schedule.nextRunAt ? typeof schedule.nextRunAt === "string" ? new Date(schedule.nextRunAt) : schedule.nextRunAt : void 0;
|
|
6079
|
+
const nextRunLabel = nextRunAt && schedule.status === "active" ? formatNextRun(nextRunAt) : "";
|
|
6080
|
+
return /* @__PURE__ */ jsx(
|
|
6081
|
+
Card,
|
|
6082
|
+
{
|
|
6083
|
+
style: {
|
|
6084
|
+
cursor: "pointer",
|
|
6085
|
+
border: "1px solid var(--color-border)",
|
|
6086
|
+
transition: "background 150ms ease",
|
|
6087
|
+
background: hovered ? "var(--active-background)" : "var(--glass-background)"
|
|
6088
|
+
},
|
|
6089
|
+
onClick: (e) => {
|
|
6090
|
+
if (e.target.closest("[data-menu-dropdown]") || e.target.closest("button")) {
|
|
6091
|
+
return;
|
|
6092
|
+
}
|
|
6093
|
+
onClick?.(schedule);
|
|
6094
|
+
},
|
|
6095
|
+
onMouseEnter: () => setHovered(true),
|
|
6096
|
+
onMouseLeave: () => setHovered(false),
|
|
6097
|
+
children: /* @__PURE__ */ jsxs(
|
|
6098
|
+
"div",
|
|
6099
|
+
{
|
|
6100
|
+
style: {
|
|
6101
|
+
display: "grid",
|
|
6102
|
+
gridTemplateColumns: "18px minmax(120px, 1.5fr) minmax(100px, 1fr) minmax(80px, 1fr) 270px",
|
|
6103
|
+
alignItems: "center",
|
|
6104
|
+
gap: "var(--mantine-spacing-sm)"
|
|
6105
|
+
},
|
|
6106
|
+
children: [
|
|
6107
|
+
/* @__PURE__ */ jsx(ResourceIcon, { size: 18, color: "var(--color-primary)" }),
|
|
6108
|
+
/* @__PURE__ */ jsx(Text, { fw: 600, size: "md", truncate: true, style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, children: schedule.name }),
|
|
6109
|
+
/* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
|
|
6110
|
+
/* @__PURE__ */ jsx(TypeIcon, { size: 14, color: "var(--color-text-subtle)", style: { flexShrink: 0 } }),
|
|
6111
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", truncate: true, children: getScheduleTypeLabel(schedule.scheduleConfig) })
|
|
6112
|
+
] }),
|
|
6113
|
+
/* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", style: { minWidth: 0 }, children: [
|
|
6114
|
+
/* @__PURE__ */ jsx(Tooltip, { label: resourceStatus ? `Deployed: ${resourceStatus}` : "Resource not found", children: /* @__PURE__ */ jsx(
|
|
6115
|
+
"div",
|
|
6116
|
+
{
|
|
6117
|
+
style: {
|
|
6118
|
+
width: 8,
|
|
6119
|
+
height: 8,
|
|
6120
|
+
borderRadius: "50%",
|
|
6121
|
+
flexShrink: 0,
|
|
6122
|
+
backgroundColor: resourceStatus ? resourceStatus === "prod" ? "var(--color-success)" : "var(--color-primary)" : "var(--mantine-color-red-6)"
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6125
|
+
) }),
|
|
6126
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", truncate: true, ff: "monospace", style: { minWidth: 0 }, children: schedule.target.resourceId })
|
|
6127
|
+
] }),
|
|
6128
|
+
/* @__PURE__ */ jsxs(Group, { gap: 8, wrap: "nowrap", justify: "flex-end", children: [
|
|
6129
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: schedule.target.resourceType }),
|
|
6130
|
+
nextRunLabel && /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
6131
|
+
/* @__PURE__ */ jsx(IconClock, { size: 12, color: "var(--color-text-subtle)" }),
|
|
6132
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { whiteSpace: "nowrap" }, children: nextRunLabel })
|
|
6133
|
+
] }),
|
|
6134
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(schedule.status), children: schedule.status }),
|
|
6135
|
+
/* @__PURE__ */ jsxs(Menu, { position: "bottom-end", withinPortal: true, children: [
|
|
6136
|
+
/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", disabled: isLoading, children: /* @__PURE__ */ jsx(IconDotsVertical, { size: 16 }) }) }),
|
|
6137
|
+
/* @__PURE__ */ jsxs(Menu.Dropdown, { children: [
|
|
6138
|
+
schedule.status === "active" && /* @__PURE__ */ jsx(Menu.Item, { leftSection: /* @__PURE__ */ jsx(IconPlayerPause, { size: 14 }), onClick: () => onPause(schedule.id), children: "Pause" }),
|
|
6139
|
+
schedule.status === "paused" && /* @__PURE__ */ jsx(Menu.Item, { leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 }), onClick: () => onResume(schedule.id), children: "Resume" }),
|
|
6140
|
+
(schedule.status === "active" || schedule.status === "paused") && /* @__PURE__ */ jsx(Menu.Item, { leftSection: /* @__PURE__ */ jsx(IconPlayerStop, { size: 14 }), onClick: () => onCancel(schedule.id), children: "Cancel" }),
|
|
6141
|
+
/* @__PURE__ */ jsx(Menu.Item, { leftSection: /* @__PURE__ */ jsx(IconTrash, { size: 14 }), color: "red", onClick: () => onDelete(schedule.id), children: "Delete" })
|
|
6142
|
+
] })
|
|
6143
|
+
] })
|
|
6144
|
+
] })
|
|
6145
|
+
]
|
|
6146
|
+
}
|
|
6147
|
+
)
|
|
6148
|
+
}
|
|
6149
|
+
);
|
|
6150
|
+
}
|
|
6151
|
+
var TaskScheduler = () => {
|
|
6152
|
+
const { isReady } = useElevasisServices();
|
|
6153
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
6154
|
+
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
|
6155
|
+
const [scheduleToDelete, setScheduleToDelete] = useState(null);
|
|
6156
|
+
const [selectedSchedule, setSelectedSchedule] = useState(null);
|
|
6157
|
+
const [viewMode, setViewMode] = useState("buckets");
|
|
6158
|
+
const [statusFilter, setStatusFilter] = useState("all");
|
|
6159
|
+
const [typeFilter, setTypeFilter] = useState("all");
|
|
6160
|
+
const queryFilters = useMemo(() => {
|
|
6161
|
+
const filters = {};
|
|
6162
|
+
if (statusFilter !== "all") {
|
|
6163
|
+
filters.status = statusFilter;
|
|
6164
|
+
}
|
|
6165
|
+
return filters;
|
|
6166
|
+
}, [statusFilter]);
|
|
6167
|
+
const { data, isLoading, error } = useListSchedules(queryFilters);
|
|
6168
|
+
const pauseSchedule = usePauseSchedule();
|
|
6169
|
+
const resumeSchedule = useResumeSchedule();
|
|
6170
|
+
const cancelSchedule = useCancelSchedule();
|
|
6171
|
+
const deleteSchedule = useDeleteSchedule();
|
|
6172
|
+
const filteredSchedules = useMemo(() => {
|
|
6173
|
+
if (!data?.schedules) return [];
|
|
6174
|
+
if (typeFilter === "all") return data.schedules;
|
|
6175
|
+
return data.schedules.filter((s) => s.scheduleConfig.type === typeFilter);
|
|
6176
|
+
}, [data?.schedules, typeFilter]);
|
|
6177
|
+
const isActionLoading = pauseSchedule.isPending || resumeSchedule.isPending || cancelSchedule.isPending || deleteSchedule.isPending;
|
|
6178
|
+
const schedulesByType = useMemo(() => {
|
|
6179
|
+
if (!data?.schedules) return { recurring: 0, relative: 0, absolute: 0 };
|
|
6180
|
+
return data.schedules.reduce(
|
|
6181
|
+
(acc, s) => {
|
|
6182
|
+
acc[s.scheduleConfig.type]++;
|
|
6183
|
+
return acc;
|
|
6184
|
+
},
|
|
6185
|
+
{ recurring: 0, relative: 0, absolute: 0 }
|
|
6186
|
+
);
|
|
6187
|
+
}, [data?.schedules]);
|
|
6188
|
+
const schedulesByStatus = useMemo(() => {
|
|
6189
|
+
if (!data?.schedules) return { active: 0, paused: 0, completed: 0, cancelled: 0 };
|
|
6190
|
+
return data.schedules.reduce(
|
|
6191
|
+
(acc, s) => {
|
|
6192
|
+
if (s.status === "active") acc.active++;
|
|
6193
|
+
else if (s.status === "paused") acc.paused++;
|
|
6194
|
+
else if (s.status === "completed") acc.completed++;
|
|
6195
|
+
else if (s.status === "cancelled") acc.cancelled++;
|
|
6196
|
+
return acc;
|
|
6197
|
+
},
|
|
6198
|
+
{ active: 0, paused: 0, completed: 0, cancelled: 0 }
|
|
6199
|
+
);
|
|
6200
|
+
}, [data?.schedules]);
|
|
6201
|
+
const { data: resourcesData } = useResources();
|
|
6202
|
+
const resourceStatusMap = useMemo(() => {
|
|
6203
|
+
const map = /* @__PURE__ */ new Map();
|
|
6204
|
+
if (!resourcesData) return map;
|
|
6205
|
+
for (const w of resourcesData.workflows) map.set(w.resourceId, w.status);
|
|
6206
|
+
for (const a of resourcesData.agents) map.set(a.resourceId, a.status);
|
|
6207
|
+
return map;
|
|
6208
|
+
}, [resourcesData]);
|
|
6209
|
+
const handleCardClick = useCallback((schedule) => {
|
|
6210
|
+
setSelectedSchedule(schedule);
|
|
6211
|
+
}, []);
|
|
6212
|
+
if (isLoading || !isReady) {
|
|
6213
|
+
return /* @__PURE__ */ jsx(AppShellLoader, {});
|
|
6214
|
+
}
|
|
6215
|
+
const handlePause = async (scheduleId) => {
|
|
6216
|
+
await pauseSchedule.mutateAsync(scheduleId);
|
|
6217
|
+
};
|
|
6218
|
+
const handleResume = async (scheduleId) => {
|
|
6219
|
+
await resumeSchedule.mutateAsync(scheduleId);
|
|
6220
|
+
};
|
|
6221
|
+
const handleCancel = async (scheduleId) => {
|
|
6222
|
+
await cancelSchedule.mutateAsync(scheduleId);
|
|
6223
|
+
};
|
|
6224
|
+
const handleDelete = (scheduleId) => {
|
|
6225
|
+
const schedule = data?.schedules.find((s) => s.id === scheduleId);
|
|
6226
|
+
if (schedule) {
|
|
6227
|
+
setScheduleToDelete(schedule);
|
|
6228
|
+
setIsDeleteModalOpen(true);
|
|
6229
|
+
}
|
|
6230
|
+
};
|
|
6231
|
+
const handleConfirmDelete = async () => {
|
|
6232
|
+
if (scheduleToDelete) {
|
|
6233
|
+
await deleteSchedule.mutateAsync(scheduleToDelete.id);
|
|
6234
|
+
setIsDeleteModalOpen(false);
|
|
6235
|
+
setScheduleToDelete(null);
|
|
6236
|
+
}
|
|
6237
|
+
};
|
|
6238
|
+
const handleCloseDeleteModal = () => {
|
|
6239
|
+
setIsDeleteModalOpen(false);
|
|
6240
|
+
setScheduleToDelete(null);
|
|
6241
|
+
};
|
|
6242
|
+
const formatNextRun2 = (schedule) => {
|
|
6243
|
+
if (!schedule.nextRunAt) return "Not scheduled";
|
|
6244
|
+
const date = typeof schedule.nextRunAt === "string" ? new Date(schedule.nextRunAt) : schedule.nextRunAt;
|
|
6245
|
+
const now = /* @__PURE__ */ new Date();
|
|
6246
|
+
const diffMs = date.getTime() - now.getTime();
|
|
6247
|
+
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
6248
|
+
if (diffMs < 0) return "Overdue";
|
|
6249
|
+
if (diffDays === 0) {
|
|
6250
|
+
return `Today at ${date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })}`;
|
|
6251
|
+
} else if (diffDays === 1) {
|
|
6252
|
+
return `Tomorrow at ${date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })}`;
|
|
6253
|
+
} else if (diffDays > 0 && diffDays <= 7) {
|
|
6254
|
+
return `In ${diffDays} days at ${date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })}`;
|
|
6255
|
+
} else {
|
|
6256
|
+
return date.toLocaleString("en-US", {
|
|
6257
|
+
month: "short",
|
|
6258
|
+
day: "numeric",
|
|
6259
|
+
hour: "numeric",
|
|
6260
|
+
minute: "2-digit"
|
|
6261
|
+
});
|
|
6262
|
+
}
|
|
6263
|
+
};
|
|
6264
|
+
const groupByTimeBucket = (schedules) => {
|
|
6265
|
+
const now = /* @__PURE__ */ new Date();
|
|
6266
|
+
const buckets = {
|
|
6267
|
+
today: [],
|
|
6268
|
+
tomorrow: [],
|
|
6269
|
+
thisWeek: [],
|
|
6270
|
+
later: [],
|
|
6271
|
+
noNextRun: []
|
|
6272
|
+
};
|
|
6273
|
+
schedules.forEach((schedule) => {
|
|
6274
|
+
if (!schedule.nextRunAt) {
|
|
6275
|
+
buckets.noNextRun.push(schedule);
|
|
6276
|
+
return;
|
|
6277
|
+
}
|
|
6278
|
+
const nextRun = typeof schedule.nextRunAt === "string" ? new Date(schedule.nextRunAt) : schedule.nextRunAt;
|
|
6279
|
+
const diffMs = nextRun.getTime() - now.getTime();
|
|
6280
|
+
const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
6281
|
+
if (diffDays < 0) {
|
|
6282
|
+
buckets.today.push(schedule);
|
|
6283
|
+
} else if (diffDays === 0) {
|
|
6284
|
+
buckets.today.push(schedule);
|
|
6285
|
+
} else if (diffDays === 1) {
|
|
6286
|
+
buckets.tomorrow.push(schedule);
|
|
6287
|
+
} else if (diffDays <= 7) {
|
|
6288
|
+
buckets.thisWeek.push(schedule);
|
|
6289
|
+
} else {
|
|
6290
|
+
buckets.later.push(schedule);
|
|
6291
|
+
}
|
|
6292
|
+
});
|
|
6293
|
+
return buckets;
|
|
6294
|
+
};
|
|
6295
|
+
if (error) {
|
|
6296
|
+
return /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load schedules" });
|
|
6297
|
+
}
|
|
6298
|
+
const timeBuckets = groupByTimeBucket(filteredSchedules);
|
|
6299
|
+
const renderScheduleCards = (schedules) => schedules.map((schedule) => /* @__PURE__ */ jsx(
|
|
6300
|
+
ScheduleCard,
|
|
6301
|
+
{
|
|
6302
|
+
schedule,
|
|
6303
|
+
resourceStatus: resourceStatusMap.get(schedule.target.resourceId),
|
|
6304
|
+
onPause: handlePause,
|
|
6305
|
+
onResume: handleResume,
|
|
6306
|
+
onCancel: handleCancel,
|
|
6307
|
+
onDelete: handleDelete,
|
|
6308
|
+
onClick: handleCardClick,
|
|
6309
|
+
isLoading: isActionLoading
|
|
6310
|
+
},
|
|
6311
|
+
schedule.id
|
|
6312
|
+
));
|
|
6313
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6314
|
+
/* @__PURE__ */ jsx(
|
|
6315
|
+
PageTitleCaption,
|
|
6316
|
+
{
|
|
6317
|
+
title: "Task Scheduler",
|
|
6318
|
+
caption: "Schedule agents and workflows to run automatically",
|
|
6319
|
+
rightSection: /* @__PURE__ */ jsx(
|
|
6320
|
+
SegmentedControl,
|
|
6321
|
+
{
|
|
6322
|
+
value: viewMode,
|
|
6323
|
+
onChange: (value) => setViewMode(value),
|
|
6324
|
+
data: [
|
|
6325
|
+
{ label: "Buckets", value: "buckets" },
|
|
6326
|
+
{ label: "Timeline", value: "timeline" }
|
|
6327
|
+
]
|
|
6328
|
+
}
|
|
6329
|
+
)
|
|
6330
|
+
}
|
|
6331
|
+
),
|
|
6332
|
+
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 2, sm: 5 }, children: [
|
|
6333
|
+
/* @__PURE__ */ jsx(StatCard, { variant: "hero", label: "Active", value: schedulesByStatus.active, icon: IconCalendarEvent }),
|
|
6334
|
+
/* @__PURE__ */ jsx(StatCard, { variant: "hero", label: "Paused", value: schedulesByStatus.paused, icon: IconCalendarDue }),
|
|
6335
|
+
/* @__PURE__ */ jsx(StatCard, { variant: "hero", label: "Completed", value: schedulesByStatus.completed, icon: IconCalendarStats }),
|
|
6336
|
+
/* @__PURE__ */ jsx(StatCard, { variant: "hero", label: "Cancelled", value: schedulesByStatus.cancelled, icon: IconCalendarOff }),
|
|
6337
|
+
/* @__PURE__ */ jsx(StatCard, { variant: "hero", label: "Total", value: data?.schedules.length || 0, icon: IconListCheck })
|
|
6338
|
+
] }),
|
|
6339
|
+
/* @__PURE__ */ jsxs(
|
|
6340
|
+
FilterBar,
|
|
6341
|
+
{
|
|
6342
|
+
actions: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6343
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", leftSection: /* @__PURE__ */ jsx(IconCalendarRepeat, { size: 12 }), children: [
|
|
6344
|
+
schedulesByType.recurring,
|
|
6345
|
+
" Recurring"
|
|
6346
|
+
] }),
|
|
6347
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", leftSection: /* @__PURE__ */ jsx(IconCalendarEvent, { size: 12 }), children: [
|
|
6348
|
+
schedulesByType.relative,
|
|
6349
|
+
" Relative"
|
|
6350
|
+
] }),
|
|
6351
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", leftSection: /* @__PURE__ */ jsx(IconCalendarTime, { size: 12 }), children: [
|
|
6352
|
+
schedulesByType.absolute,
|
|
6353
|
+
" Absolute"
|
|
6354
|
+
] })
|
|
6355
|
+
] }),
|
|
6356
|
+
children: [
|
|
6357
|
+
/* @__PURE__ */ jsx(
|
|
6358
|
+
Select,
|
|
6359
|
+
{
|
|
6360
|
+
size: "sm",
|
|
6361
|
+
placeholder: "Status",
|
|
6362
|
+
data: [
|
|
6363
|
+
{ value: "all", label: "All Statuses" },
|
|
6364
|
+
{ value: "active", label: "Active" },
|
|
6365
|
+
{ value: "paused", label: "Paused" },
|
|
6366
|
+
{ value: "completed", label: "Completed" },
|
|
6367
|
+
{ value: "cancelled", label: "Cancelled" }
|
|
6368
|
+
],
|
|
6369
|
+
value: statusFilter,
|
|
6370
|
+
onChange: (v) => setStatusFilter(v || "all"),
|
|
6371
|
+
clearable: false,
|
|
6372
|
+
style: { minWidth: 150 }
|
|
6373
|
+
}
|
|
6374
|
+
),
|
|
6375
|
+
/* @__PURE__ */ jsx(
|
|
6376
|
+
Select,
|
|
6377
|
+
{
|
|
6378
|
+
size: "sm",
|
|
6379
|
+
placeholder: "Type",
|
|
6380
|
+
data: [
|
|
6381
|
+
{ value: "all", label: "All Types" },
|
|
6382
|
+
{ value: "recurring", label: "Recurring" },
|
|
6383
|
+
{ value: "relative", label: "Relative" },
|
|
6384
|
+
{ value: "absolute", label: "Absolute" }
|
|
6385
|
+
],
|
|
6386
|
+
value: typeFilter,
|
|
6387
|
+
onChange: (v) => setTypeFilter(v || "all"),
|
|
6388
|
+
clearable: false,
|
|
6389
|
+
style: { minWidth: 150 }
|
|
6390
|
+
}
|
|
6391
|
+
)
|
|
6392
|
+
]
|
|
6393
|
+
}
|
|
6394
|
+
),
|
|
6395
|
+
viewMode === "timeline" && filteredSchedules.length > 0 && /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
6396
|
+
/* @__PURE__ */ jsx(CardHeader, { title: "All Schedules" }),
|
|
6397
|
+
/* @__PURE__ */ jsx(Timeline, { bulletSize: 24, lineWidth: 2, children: [...filteredSchedules].sort((a, b) => {
|
|
6398
|
+
const aDate = a.nextRunAt ? typeof a.nextRunAt === "string" ? new Date(a.nextRunAt) : a.nextRunAt : new Date(9999, 0);
|
|
6399
|
+
const bDate = b.nextRunAt ? typeof b.nextRunAt === "string" ? new Date(b.nextRunAt) : b.nextRunAt : new Date(9999, 0);
|
|
6400
|
+
return aDate.getTime() - bDate.getTime();
|
|
6401
|
+
}).map((schedule) => {
|
|
6402
|
+
const nextRun = schedule.nextRunAt ? typeof schedule.nextRunAt === "string" ? new Date(schedule.nextRunAt) : schedule.nextRunAt : null;
|
|
6403
|
+
const isOverdue = nextRun && nextRun.getTime() < Date.now();
|
|
6404
|
+
return /* @__PURE__ */ jsxs(
|
|
6405
|
+
Timeline.Item,
|
|
6406
|
+
{
|
|
6407
|
+
style: { cursor: "pointer" },
|
|
6408
|
+
onClick: () => handleCardClick(schedule),
|
|
6409
|
+
bullet: /* @__PURE__ */ jsx(ThemeIcon, { size: 24, radius: "xl", children: /* @__PURE__ */ jsx(IconClock, { size: 12 }) }),
|
|
6410
|
+
title: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
|
|
6411
|
+
/* @__PURE__ */ jsx(Text, { fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: schedule.name }),
|
|
6412
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
6413
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: isOverdue ? "orange" : void 0, children: formatNextRun2(schedule) }),
|
|
6414
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: schedule.status === "active" ? "green" : "yellow", children: schedule.status })
|
|
6415
|
+
] })
|
|
6416
|
+
] }),
|
|
6417
|
+
children: [
|
|
6418
|
+
schedule.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mt: 4, children: schedule.description }),
|
|
6419
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", mt: "xs", children: [
|
|
6420
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: schedule.target.resourceType }),
|
|
6421
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "outline", children: schedule.scheduleConfig.type })
|
|
6422
|
+
] })
|
|
6423
|
+
]
|
|
6424
|
+
},
|
|
6425
|
+
schedule.id
|
|
6426
|
+
);
|
|
6427
|
+
}) })
|
|
6428
|
+
] }) }),
|
|
6429
|
+
viewMode === "buckets" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6430
|
+
timeBuckets.today.length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
6431
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
6432
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "Today" }),
|
|
6433
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: timeBuckets.today.length })
|
|
6434
|
+
] }),
|
|
6435
|
+
renderScheduleCards(timeBuckets.today)
|
|
6436
|
+
] }),
|
|
6437
|
+
timeBuckets.tomorrow.length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
6438
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
6439
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "Tomorrow" }),
|
|
6440
|
+
/* @__PURE__ */ jsx(Badge, { color: "orange", size: "sm", variant: "light", children: timeBuckets.tomorrow.length })
|
|
6441
|
+
] }),
|
|
6442
|
+
renderScheduleCards(timeBuckets.tomorrow)
|
|
6443
|
+
] }),
|
|
6444
|
+
timeBuckets.thisWeek.length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
6445
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
6446
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "This Week" }),
|
|
6447
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: timeBuckets.thisWeek.length })
|
|
6448
|
+
] }),
|
|
6449
|
+
renderScheduleCards(timeBuckets.thisWeek)
|
|
6450
|
+
] }),
|
|
6451
|
+
timeBuckets.later.length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
6452
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
6453
|
+
/* @__PURE__ */ jsx(Title, { order: 4, children: "Later" }),
|
|
6454
|
+
/* @__PURE__ */ jsx(Badge, { color: "gray", size: "sm", variant: "light", children: timeBuckets.later.length })
|
|
6455
|
+
] }),
|
|
6456
|
+
renderScheduleCards(timeBuckets.later)
|
|
6457
|
+
] }),
|
|
6458
|
+
timeBuckets.noNextRun.length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
6459
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
6460
|
+
/* @__PURE__ */ jsx(Text, { fw: 600, size: "md", c: "dimmed", children: "No Scheduled Run" }),
|
|
6461
|
+
/* @__PURE__ */ jsx(Badge, { color: "gray", size: "sm", variant: "light", children: timeBuckets.noNextRun.length })
|
|
6462
|
+
] }),
|
|
6463
|
+
renderScheduleCards(timeBuckets.noNextRun)
|
|
6464
|
+
] })
|
|
6465
|
+
] }),
|
|
6466
|
+
filteredSchedules.length === 0 && /* @__PURE__ */ jsx(
|
|
6467
|
+
EmptyState,
|
|
6468
|
+
{
|
|
6469
|
+
icon: IconClock,
|
|
6470
|
+
title: "No schedules found",
|
|
6471
|
+
description: statusFilter !== "all" || typeFilter !== "all" ? "No schedules match your filters. Try adjusting the filters or create a new schedule." : "No schedules yet. Use the CLI to create automated task execution."
|
|
6472
|
+
}
|
|
6473
|
+
),
|
|
6474
|
+
/* @__PURE__ */ jsx(CreateScheduleModal, { opened: isModalOpen, onClose: () => setIsModalOpen(false) }),
|
|
6475
|
+
/* @__PURE__ */ jsx(
|
|
6476
|
+
DeleteScheduleModal,
|
|
6477
|
+
{
|
|
6478
|
+
opened: isDeleteModalOpen,
|
|
6479
|
+
onClose: handleCloseDeleteModal,
|
|
6480
|
+
onConfirm: handleConfirmDelete,
|
|
6481
|
+
schedule: scheduleToDelete,
|
|
6482
|
+
isDeleting: deleteSchedule.isPending
|
|
6483
|
+
}
|
|
6484
|
+
),
|
|
6485
|
+
/* @__PURE__ */ jsx(
|
|
6486
|
+
ScheduleDetailModal,
|
|
6487
|
+
{
|
|
6488
|
+
opened: !!selectedSchedule,
|
|
6489
|
+
onClose: () => setSelectedSchedule(null),
|
|
6490
|
+
schedule: selectedSchedule,
|
|
6491
|
+
resourceStatus: selectedSchedule ? resourceStatusMap.get(selectedSchedule.target.resourceId) : void 0
|
|
6492
|
+
}
|
|
6493
|
+
)
|
|
6494
|
+
] });
|
|
6495
|
+
};
|
|
6496
|
+
function getPriorityColor(priority) {
|
|
6497
|
+
if (priority >= 8) return "red";
|
|
6498
|
+
if (priority >= 5) return "yellow";
|
|
6499
|
+
return "gray";
|
|
6500
|
+
}
|
|
6501
|
+
function getPriorityLabel(priority) {
|
|
6502
|
+
if (priority >= 8) return "Critical";
|
|
6503
|
+
if (priority >= 5) return "High";
|
|
6504
|
+
if (priority >= 3) return "Medium";
|
|
6505
|
+
return "Low";
|
|
6506
|
+
}
|
|
6507
|
+
function getStatusColor3(status) {
|
|
6508
|
+
switch (status) {
|
|
6509
|
+
case "pending":
|
|
6510
|
+
return "blue";
|
|
6511
|
+
case "processing":
|
|
6512
|
+
return "blue";
|
|
6513
|
+
case "completed":
|
|
6514
|
+
return "green";
|
|
6515
|
+
case "failed":
|
|
6516
|
+
return "red";
|
|
6517
|
+
case "expired":
|
|
6518
|
+
return "orange";
|
|
6519
|
+
default:
|
|
6520
|
+
return "gray";
|
|
6521
|
+
}
|
|
6522
|
+
}
|
|
6523
|
+
function getPriorityDotColor(priority) {
|
|
6524
|
+
if (priority >= 8) return "var(--mantine-color-red-6)";
|
|
6525
|
+
if (priority >= 5) return "var(--mantine-color-yellow-6)";
|
|
6526
|
+
if (priority >= 3) return "var(--mantine-color-blue-6)";
|
|
6527
|
+
return "var(--color-text-subtle)";
|
|
6528
|
+
}
|
|
6529
|
+
function formatRelativeTime(date) {
|
|
6530
|
+
const now = /* @__PURE__ */ new Date();
|
|
6531
|
+
const diffMs = now.getTime() - date.getTime();
|
|
6532
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
6533
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
6534
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
6535
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
6536
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
6537
|
+
return `${diffDays}d ago`;
|
|
6538
|
+
}
|
|
6539
|
+
function CommandQueueTaskRow({ task, onClick, onDelete }) {
|
|
6540
|
+
const [hovered, setHovered] = useState(false);
|
|
6541
|
+
const OriginIcon = task.originResourceType === "agent" ? IconRobot : IconGitBranch;
|
|
6542
|
+
return /* @__PURE__ */ jsx(
|
|
6543
|
+
Card,
|
|
6544
|
+
{
|
|
6545
|
+
padding: 0,
|
|
6546
|
+
style: {
|
|
6547
|
+
cursor: "pointer",
|
|
6548
|
+
border: "1px solid var(--color-border)",
|
|
6549
|
+
transition: "background var(--duration-fast) var(--easing)",
|
|
6550
|
+
background: hovered ? "var(--active-background)" : "var(--glass-background)"
|
|
6551
|
+
},
|
|
6552
|
+
onClick: (e) => {
|
|
6553
|
+
if (e.target.closest("[data-menu-dropdown]") || e.target.closest("button")) {
|
|
6554
|
+
return;
|
|
6555
|
+
}
|
|
6556
|
+
onClick();
|
|
6557
|
+
},
|
|
6558
|
+
onMouseEnter: () => setHovered(true),
|
|
6559
|
+
onMouseLeave: () => setHovered(false),
|
|
6560
|
+
children: /* @__PURE__ */ jsxs(
|
|
6561
|
+
"div",
|
|
6562
|
+
{
|
|
6563
|
+
style: {
|
|
6564
|
+
display: "grid",
|
|
6565
|
+
gridTemplateColumns: "10px 80px 1fr 1fr 90px 90px 32px",
|
|
6566
|
+
alignItems: "center",
|
|
6567
|
+
gap: "var(--mantine-spacing-sm)"
|
|
6568
|
+
},
|
|
6569
|
+
children: [
|
|
6570
|
+
/* @__PURE__ */ jsx(Tooltip, { label: `P${task.priority} \u2014 ${getPriorityLabel(task.priority)}`, children: /* @__PURE__ */ jsx(
|
|
6571
|
+
"div",
|
|
6572
|
+
{
|
|
6573
|
+
style: {
|
|
6574
|
+
width: 10,
|
|
6575
|
+
height: 10,
|
|
6576
|
+
borderRadius: "50%",
|
|
6577
|
+
flexShrink: 0,
|
|
6578
|
+
backgroundColor: getPriorityDotColor(task.priority)
|
|
6579
|
+
}
|
|
6580
|
+
}
|
|
6581
|
+
) }),
|
|
6582
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, c: getPriorityColor(task.priority), children: getPriorityLabel(task.priority).toUpperCase() }),
|
|
6583
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, truncate: true, title: task.description || "Task approval required", children: task.description || "Task approval required" }),
|
|
6584
|
+
/* @__PURE__ */ jsxs(Group, { gap: 5, wrap: "nowrap", style: { minWidth: 0 }, children: [
|
|
6585
|
+
/* @__PURE__ */ jsx(OriginIcon, { size: 13, color: "var(--color-text-subtle)", style: { flexShrink: 0 } }),
|
|
6586
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, ff: "monospace", style: { minWidth: 0 }, children: task.originResourceId })
|
|
6587
|
+
] }),
|
|
6588
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor3(task.status), radius: "sm", children: task.status.charAt(0).toUpperCase() + task.status.slice(1) }),
|
|
6589
|
+
/* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
6590
|
+
/* @__PURE__ */ jsx(IconClock, { size: 11, color: "var(--color-text-subtle)", style: { flexShrink: 0 } }),
|
|
6591
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: "nowrap" }, children: formatRelativeTime(task.createdAt) })
|
|
6592
|
+
] }),
|
|
6593
|
+
/* @__PURE__ */ jsxs(Menu, { position: "bottom-end", withinPortal: true, children: [
|
|
6594
|
+
/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", color: "gray", children: /* @__PURE__ */ jsx(IconDotsVertical, { size: 16 }) }) }),
|
|
6595
|
+
/* @__PURE__ */ jsx(Menu.Dropdown, { children: /* @__PURE__ */ jsx(Menu.Item, { leftSection: /* @__PURE__ */ jsx(IconTrash, { size: 14 }), color: "red", onClick: () => onDelete(task.id), children: "Delete" }) })
|
|
6596
|
+
] })
|
|
6597
|
+
]
|
|
6598
|
+
}
|
|
6599
|
+
)
|
|
6600
|
+
}
|
|
6601
|
+
);
|
|
6602
|
+
}
|
|
6603
|
+
function CheckpointGroup({ name, count, isActive, onClick }) {
|
|
6604
|
+
const theme = useMantineTheme();
|
|
6605
|
+
const activeColor = theme.colors[theme.primaryColor][6];
|
|
6606
|
+
const defaultTextColor = "var(--color-text)";
|
|
6607
|
+
const textColor = isActive ? activeColor : defaultTextColor;
|
|
6608
|
+
const fontWeight = isActive ? 600 : 500;
|
|
6609
|
+
const activeBg = `color-mix(in srgb, ${activeColor} 10%, transparent)`;
|
|
6610
|
+
return /* @__PURE__ */ jsx(
|
|
6611
|
+
UnstyledButton,
|
|
6612
|
+
{
|
|
6613
|
+
onClick,
|
|
6614
|
+
style: {
|
|
6615
|
+
display: "flex",
|
|
6616
|
+
alignItems: "center",
|
|
6617
|
+
width: "100%",
|
|
6618
|
+
padding: theme.spacing.xs,
|
|
6619
|
+
borderRadius: theme.radius.sm,
|
|
6620
|
+
backgroundColor: isActive ? activeBg : "transparent",
|
|
6621
|
+
transition: `all var(--duration-fast) var(--easing)`,
|
|
6622
|
+
cursor: "pointer"
|
|
6623
|
+
},
|
|
6624
|
+
onMouseEnter: (e) => {
|
|
6625
|
+
if (!isActive) {
|
|
6626
|
+
e.currentTarget.style.backgroundColor = "var(--color-surface-hover)";
|
|
6627
|
+
}
|
|
6628
|
+
},
|
|
6629
|
+
onMouseLeave: (e) => {
|
|
6630
|
+
if (!isActive) {
|
|
6631
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
6632
|
+
}
|
|
6633
|
+
},
|
|
6634
|
+
children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", style: { width: "100%" }, children: [
|
|
6635
|
+
/* @__PURE__ */ jsx(
|
|
6636
|
+
Text,
|
|
6637
|
+
{
|
|
6638
|
+
size: "sm",
|
|
6639
|
+
fw: fontWeight,
|
|
6640
|
+
style: {
|
|
6641
|
+
color: textColor,
|
|
6642
|
+
fontFamily: "var(--elevasis-font-family-subtitle)",
|
|
6643
|
+
transition: `color var(--duration-fast) var(--easing)`
|
|
6644
|
+
},
|
|
6645
|
+
children: name
|
|
6646
|
+
}
|
|
6647
|
+
),
|
|
6648
|
+
/* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", children: count })
|
|
6649
|
+
] })
|
|
6650
|
+
}
|
|
6651
|
+
);
|
|
6652
|
+
}
|
|
6653
|
+
var CommandQueueSidebarTop = ({
|
|
6654
|
+
status,
|
|
6655
|
+
onStatusChange,
|
|
6656
|
+
priorityRange,
|
|
6657
|
+
onPriorityRangeChange
|
|
6658
|
+
}) => {
|
|
6659
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6660
|
+
/* @__PURE__ */ jsx(SubshellSidebarSection, { icon: IconFilter, label: "Filters" }),
|
|
6661
|
+
/* @__PURE__ */ jsxs(Stack, { gap: "xs", p: "sm", children: [
|
|
6662
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Status" }),
|
|
6663
|
+
/* @__PURE__ */ jsx(
|
|
6664
|
+
Select,
|
|
6665
|
+
{
|
|
6666
|
+
size: "sm",
|
|
6667
|
+
value: status,
|
|
6668
|
+
onChange: (value) => value && onStatusChange(value),
|
|
6669
|
+
data: [
|
|
6670
|
+
{ value: "all", label: "All" },
|
|
6671
|
+
{ value: "pending", label: "Pending" },
|
|
6672
|
+
{ value: "completed", label: "Completed" },
|
|
6673
|
+
{ value: "expired", label: "Expired" }
|
|
6674
|
+
],
|
|
6675
|
+
leftSection: /* @__PURE__ */ jsx(IconCircleCheck, { size: 14 })
|
|
6676
|
+
}
|
|
6677
|
+
),
|
|
6678
|
+
/* @__PURE__ */ jsx(Group, { justify: "space-between", children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Priority" }) }),
|
|
6679
|
+
/* @__PURE__ */ jsx(
|
|
6680
|
+
RangeSlider,
|
|
6681
|
+
{
|
|
6682
|
+
size: "sm",
|
|
6683
|
+
min: 1,
|
|
6684
|
+
max: 10,
|
|
6685
|
+
step: 1,
|
|
6686
|
+
minRange: 0,
|
|
6687
|
+
defaultValue: priorityRange,
|
|
6688
|
+
onChangeEnd: onPriorityRangeChange,
|
|
6689
|
+
marks: [
|
|
6690
|
+
{ value: 1, label: "1" },
|
|
6691
|
+
{ value: 5, label: "5" },
|
|
6692
|
+
{ value: 10, label: "10" }
|
|
6693
|
+
],
|
|
6694
|
+
styles: { markLabel: { fontSize: 10 } }
|
|
6695
|
+
},
|
|
6696
|
+
`${priorityRange[0]}-${priorityRange[1]}`
|
|
6697
|
+
),
|
|
6698
|
+
/* @__PURE__ */ jsx(Space, { h: 8 })
|
|
6699
|
+
] })
|
|
6700
|
+
] });
|
|
6701
|
+
};
|
|
6702
|
+
function CommandQueueSidebarMiddle({
|
|
6703
|
+
selectedCheckpoint,
|
|
6704
|
+
onSelectCheckpoint,
|
|
6705
|
+
priorityRange,
|
|
6706
|
+
status,
|
|
6707
|
+
timeRange
|
|
6708
|
+
}) {
|
|
6709
|
+
const { data, isLoading } = useCommandQueueTotals({
|
|
6710
|
+
timeRange,
|
|
6711
|
+
priorityMin: priorityRange[0],
|
|
6712
|
+
priorityMax: priorityRange[1],
|
|
6713
|
+
status: status === "all" ? void 0 : status
|
|
6714
|
+
});
|
|
6715
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6716
|
+
/* @__PURE__ */ jsx(SubshellSidebarSection, { icon: IconCategory, label: "Checkpoint Groups", withTopBorder: true }),
|
|
6717
|
+
/* @__PURE__ */ jsx(Stack, { gap: "xs", p: "sm", style: { flex: 1, overflowY: "auto" }, children: isLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6718
|
+
/* @__PURE__ */ jsx(
|
|
6719
|
+
CheckpointGroup,
|
|
6720
|
+
{
|
|
6721
|
+
id: void 0,
|
|
6722
|
+
name: "All Tasks",
|
|
6723
|
+
count: data?.total ?? 0,
|
|
6724
|
+
isActive: selectedCheckpoint === void 0,
|
|
6725
|
+
onClick: () => onSelectCheckpoint(void 0)
|
|
6726
|
+
}
|
|
6727
|
+
),
|
|
6728
|
+
data?.checkpoints.map((checkpoint) => /* @__PURE__ */ jsx(
|
|
6729
|
+
CheckpointGroup,
|
|
6730
|
+
{
|
|
6731
|
+
id: checkpoint.id,
|
|
6732
|
+
name: checkpoint.name,
|
|
6733
|
+
count: checkpoint.count,
|
|
6734
|
+
isActive: selectedCheckpoint === checkpoint.id,
|
|
6735
|
+
onClick: () => onSelectCheckpoint(checkpoint.id)
|
|
6736
|
+
},
|
|
6737
|
+
checkpoint.id
|
|
6738
|
+
))
|
|
6739
|
+
] }) })
|
|
6740
|
+
] });
|
|
6741
|
+
}
|
|
6742
|
+
var CommandQueueSidebar = ({
|
|
6743
|
+
selectedCheckpoint,
|
|
6744
|
+
onSelectCheckpoint,
|
|
6745
|
+
status,
|
|
6746
|
+
onStatusChange,
|
|
6747
|
+
priorityRange,
|
|
6748
|
+
onPriorityRangeChange,
|
|
6749
|
+
timeRange
|
|
6750
|
+
}) => {
|
|
6751
|
+
const colors = useCyberColors();
|
|
6752
|
+
const statusFilter = status === "all" ? void 0 : status;
|
|
6753
|
+
const { data: checkpointData, isLoading: isDonutLoading } = useCommandQueueTotals({
|
|
6754
|
+
timeRange,
|
|
6755
|
+
priorityMin: priorityRange[0],
|
|
6756
|
+
priorityMax: priorityRange[1],
|
|
6757
|
+
status: statusFilter
|
|
6758
|
+
});
|
|
6759
|
+
const {
|
|
6760
|
+
pending: pendingCount,
|
|
6761
|
+
completed: completedCount,
|
|
6762
|
+
expired: expiredCount
|
|
6763
|
+
} = checkpointData?.statusCounts ?? { pending: 0, completed: 0, expired: 0 };
|
|
6764
|
+
const {
|
|
6765
|
+
critical: criticalCount,
|
|
6766
|
+
high: highCount,
|
|
6767
|
+
medium: mediumCount,
|
|
6768
|
+
low: lowCount
|
|
6769
|
+
} = checkpointData?.priorityCounts ?? { critical: 0, high: 0, medium: 0, low: 0 };
|
|
6770
|
+
const totalTasks = checkpointData?.total ?? 0;
|
|
6771
|
+
const statusSegments = [
|
|
6772
|
+
{ name: "Pending", value: pendingCount, color: colors.cyan },
|
|
6773
|
+
{ name: "Completed", value: completedCount, color: colors.green },
|
|
6774
|
+
{ name: "Expired", value: expiredCount, color: colors.red }
|
|
6775
|
+
];
|
|
6776
|
+
const prioritySegments = [
|
|
6777
|
+
{ name: "Critical", value: criticalCount, color: colors.red },
|
|
6778
|
+
{ name: "High", value: highCount, color: colors.yellow },
|
|
6779
|
+
{ name: "Medium", value: mediumCount, color: colors.blue },
|
|
6780
|
+
{ name: "Low", value: lowCount, color: colors.cyanDim }
|
|
6781
|
+
];
|
|
6782
|
+
return /* @__PURE__ */ jsxs(Stack, { gap: 0, style: { height: "100%", display: "flex", flexDirection: "column" }, children: [
|
|
6783
|
+
/* @__PURE__ */ jsx(Box, { p: "sm", style: { borderBottom: "1px solid var(--color-border)" }, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
6784
|
+
status === "all" && /* @__PURE__ */ jsx(
|
|
6785
|
+
CyberDonut,
|
|
6786
|
+
{
|
|
6787
|
+
title: "Status",
|
|
6788
|
+
segments: statusSegments,
|
|
6789
|
+
centerValue: totalTasks,
|
|
6790
|
+
centerLabel: "total",
|
|
6791
|
+
glowId: "sbStatusGlow",
|
|
6792
|
+
colors,
|
|
6793
|
+
isLoading: isDonutLoading
|
|
6794
|
+
}
|
|
6795
|
+
),
|
|
6796
|
+
/* @__PURE__ */ jsx(
|
|
6797
|
+
CyberDonut,
|
|
6798
|
+
{
|
|
6799
|
+
title: "Priority",
|
|
6800
|
+
segments: prioritySegments,
|
|
6801
|
+
centerValue: criticalCount + highCount + mediumCount + lowCount,
|
|
6802
|
+
centerLabel: status === "all" ? "total" : status,
|
|
6803
|
+
glowId: "sbPrioGlow",
|
|
6804
|
+
colors,
|
|
6805
|
+
isLoading: isDonutLoading
|
|
6806
|
+
}
|
|
6807
|
+
)
|
|
6808
|
+
] }) }),
|
|
6809
|
+
/* @__PURE__ */ jsx(
|
|
6810
|
+
CommandQueueSidebarTop,
|
|
6811
|
+
{
|
|
6812
|
+
status,
|
|
6813
|
+
onStatusChange,
|
|
6814
|
+
priorityRange,
|
|
6815
|
+
onPriorityRangeChange
|
|
6816
|
+
}
|
|
6817
|
+
),
|
|
6818
|
+
/* @__PURE__ */ jsx(
|
|
6819
|
+
CommandQueueSidebarMiddle,
|
|
6820
|
+
{
|
|
6821
|
+
selectedCheckpoint,
|
|
6822
|
+
onSelectCheckpoint,
|
|
6823
|
+
priorityRange,
|
|
6824
|
+
status,
|
|
6825
|
+
timeRange
|
|
6826
|
+
}
|
|
6827
|
+
)
|
|
6828
|
+
] });
|
|
6829
|
+
};
|
|
6830
|
+
function ContextUsageBadge({ currentTokens, maxTokens }) {
|
|
6831
|
+
const percentage = currentTokens / maxTokens * 100;
|
|
6832
|
+
const color = percentage > 90 ? "red" : percentage > 70 ? "yellow" : "green";
|
|
6833
|
+
return /* @__PURE__ */ jsx(
|
|
6834
|
+
Tooltip,
|
|
6835
|
+
{
|
|
6836
|
+
label: `${currentTokens.toLocaleString()} of ${maxTokens.toLocaleString()} tokens used (${percentage.toFixed(1)}%)`,
|
|
6837
|
+
position: "bottom",
|
|
6838
|
+
children: /* @__PURE__ */ jsxs(Group, { gap: 6, style: { cursor: "help" }, children: [
|
|
6839
|
+
/* @__PURE__ */ jsx(IconBrain, { size: 16, color: `var(--mantine-color-${color}-6)` }),
|
|
6840
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: color, fw: 500, children: [
|
|
6841
|
+
currentTokens.toLocaleString(),
|
|
6842
|
+
" / ",
|
|
6843
|
+
maxTokens.toLocaleString()
|
|
6844
|
+
] }),
|
|
6845
|
+
/* @__PURE__ */ jsx(Progress, { value: percentage, color, size: "sm", w: 80, radius: "xl" })
|
|
6846
|
+
] })
|
|
6847
|
+
}
|
|
6848
|
+
);
|
|
6849
|
+
}
|
|
6850
|
+
function parseMemoryContent(memory) {
|
|
6851
|
+
const parsedSessionMemory = {};
|
|
6852
|
+
for (const [key, entry] of Object.entries(memory.sessionMemory || {})) {
|
|
6853
|
+
try {
|
|
6854
|
+
if (typeof entry.content === "string") {
|
|
6855
|
+
parsedSessionMemory[key] = {
|
|
6856
|
+
...entry,
|
|
6857
|
+
content: JSON.parse(entry.content)
|
|
6858
|
+
};
|
|
6859
|
+
} else {
|
|
6860
|
+
parsedSessionMemory[key] = entry;
|
|
6861
|
+
}
|
|
6862
|
+
} catch {
|
|
6863
|
+
parsedSessionMemory[key] = entry;
|
|
6864
|
+
}
|
|
6865
|
+
}
|
|
6866
|
+
const parsedHistory = (memory.history || []).map((entry) => {
|
|
6867
|
+
try {
|
|
6868
|
+
if (typeof entry.content === "string") {
|
|
6869
|
+
return {
|
|
6870
|
+
...entry,
|
|
6871
|
+
content: JSON.parse(entry.content)
|
|
6872
|
+
};
|
|
6873
|
+
}
|
|
6874
|
+
return entry;
|
|
6875
|
+
} catch {
|
|
6876
|
+
return entry;
|
|
6877
|
+
}
|
|
6878
|
+
});
|
|
6879
|
+
return {
|
|
6880
|
+
sessionMemory: parsedSessionMemory,
|
|
6881
|
+
history: parsedHistory
|
|
6882
|
+
};
|
|
6883
|
+
}
|
|
6884
|
+
function SessionMemory({ memory }) {
|
|
6885
|
+
if (!memory) {
|
|
6886
|
+
return /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6887
|
+
/* @__PURE__ */ jsx(IconDatabase, { size: 18 }),
|
|
6888
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No memory data available" })
|
|
6889
|
+
] });
|
|
6890
|
+
}
|
|
6891
|
+
const sessionMemoryKeys = Object.keys(memory.sessionMemory || {});
|
|
6892
|
+
const historyCount = memory.history?.length || 0;
|
|
6893
|
+
const parsedMemory = parseMemoryContent(memory);
|
|
6894
|
+
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
6895
|
+
/* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
|
|
6896
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6897
|
+
/* @__PURE__ */ jsx(IconDatabase, { size: 20 }),
|
|
6898
|
+
/* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: "Session Memory" })
|
|
6899
|
+
] }),
|
|
6900
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6901
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", children: [
|
|
6902
|
+
sessionMemoryKeys.length,
|
|
6903
|
+
" keys"
|
|
6904
|
+
] }),
|
|
6905
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", children: [
|
|
6906
|
+
historyCount,
|
|
6907
|
+
" history items"
|
|
6908
|
+
] })
|
|
6909
|
+
] })
|
|
6910
|
+
] }),
|
|
6911
|
+
/* @__PURE__ */ jsxs(Stack, { children: [
|
|
6912
|
+
/* @__PURE__ */ jsx(
|
|
6913
|
+
CollapsibleSection,
|
|
6914
|
+
{
|
|
6915
|
+
title: "Session Memory",
|
|
6916
|
+
count: sessionMemoryKeys.length,
|
|
6917
|
+
countLabel: "keys",
|
|
6918
|
+
emptyMessage: "No session memory stored",
|
|
6919
|
+
defaultExpanded: false,
|
|
6920
|
+
children: /* @__PURE__ */ jsx(JsonViewer, { data: parsedMemory.sessionMemory, maxHeight: 300 })
|
|
6921
|
+
}
|
|
6922
|
+
),
|
|
6923
|
+
/* @__PURE__ */ jsx(
|
|
6924
|
+
CollapsibleSection,
|
|
6925
|
+
{
|
|
6926
|
+
title: "Conversation History",
|
|
6927
|
+
count: historyCount,
|
|
6928
|
+
countLabel: "items",
|
|
6929
|
+
emptyMessage: "No history available",
|
|
6930
|
+
defaultExpanded: false,
|
|
6931
|
+
children: /* @__PURE__ */ jsx(JsonViewer, { data: parsedMemory.history, maxHeight: 300 })
|
|
6932
|
+
}
|
|
6933
|
+
)
|
|
6934
|
+
] })
|
|
6935
|
+
] });
|
|
6936
|
+
}
|
|
6937
|
+
var triggerTypeIcons = {
|
|
6938
|
+
webhook: IconWebhook,
|
|
6939
|
+
schedule: IconClock,
|
|
6940
|
+
manual: IconHandClick,
|
|
6941
|
+
event: IconBolt
|
|
6942
|
+
};
|
|
6943
|
+
var connectionStatusIcons = {
|
|
6944
|
+
connected: IconCircleCheck,
|
|
6945
|
+
disconnected: IconCircleX,
|
|
6946
|
+
error: IconAlertCircle
|
|
6947
|
+
};
|
|
6948
|
+
var statBubbleBase = {
|
|
6949
|
+
minWidth: 20,
|
|
6950
|
+
height: 20,
|
|
6951
|
+
borderRadius: 10,
|
|
6952
|
+
display: "flex",
|
|
6953
|
+
alignItems: "center",
|
|
6954
|
+
justifyContent: "center",
|
|
6955
|
+
fontSize: 11,
|
|
6956
|
+
fontWeight: 600,
|
|
6957
|
+
padding: "0 6px",
|
|
6958
|
+
color: "white",
|
|
6959
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
|
|
6960
|
+
};
|
|
6961
|
+
var CommandViewNode = memo(function CommandViewNode2({ data, selected }) {
|
|
6962
|
+
const Icon = getResourceIcon(data.type);
|
|
6963
|
+
const color = getResourceColor(data.type);
|
|
6964
|
+
const successCount = (data.type === "agent" || data.type === "workflow") && data.stats ? data.stats.successCount : 0;
|
|
6965
|
+
const failureCount = (data.type === "agent" || data.type === "workflow") && data.stats ? data.stats.failureCount : 0;
|
|
6966
|
+
const warningCount = (data.type === "agent" || data.type === "workflow") && data.stats ? data.stats.warningCount : 0;
|
|
6967
|
+
const pendingCount = data.type === "human" && data.stats ? data.stats.pendingCount : 0;
|
|
6968
|
+
const showBubbles = successCount > 0 || failureCount > 0 || warningCount > 0 || pendingCount > 0;
|
|
6969
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
6970
|
+
showBubbles && /* @__PURE__ */ jsxs(
|
|
6971
|
+
"div",
|
|
6972
|
+
{
|
|
6973
|
+
style: {
|
|
6974
|
+
position: "absolute",
|
|
6975
|
+
top: -8,
|
|
6976
|
+
right: -8,
|
|
6977
|
+
display: "flex",
|
|
6978
|
+
gap: 4,
|
|
6979
|
+
zIndex: 10
|
|
6980
|
+
},
|
|
6981
|
+
children: [
|
|
6982
|
+
successCount > 0 && /* @__PURE__ */ jsx(
|
|
6983
|
+
"div",
|
|
6984
|
+
{
|
|
6985
|
+
style: {
|
|
6986
|
+
...statBubbleBase,
|
|
6987
|
+
background: "linear-gradient(135deg, var(--mantine-color-green-5), var(--mantine-color-green-7))"
|
|
6988
|
+
},
|
|
6989
|
+
children: successCount
|
|
6990
|
+
}
|
|
6991
|
+
),
|
|
6992
|
+
warningCount > 0 && /* @__PURE__ */ jsx(
|
|
6993
|
+
"div",
|
|
6994
|
+
{
|
|
6995
|
+
style: {
|
|
6996
|
+
...statBubbleBase,
|
|
6997
|
+
background: "linear-gradient(135deg, var(--mantine-color-yellow-5), var(--mantine-color-yellow-7))"
|
|
6998
|
+
},
|
|
6999
|
+
children: warningCount
|
|
7000
|
+
}
|
|
7001
|
+
),
|
|
7002
|
+
failureCount > 0 && /* @__PURE__ */ jsx(
|
|
7003
|
+
"div",
|
|
7004
|
+
{
|
|
7005
|
+
style: {
|
|
7006
|
+
...statBubbleBase,
|
|
7007
|
+
background: "linear-gradient(135deg, var(--mantine-color-red-5), var(--mantine-color-red-7))"
|
|
7008
|
+
},
|
|
7009
|
+
children: failureCount
|
|
7010
|
+
}
|
|
7011
|
+
),
|
|
7012
|
+
pendingCount > 0 && /* @__PURE__ */ jsx(
|
|
7013
|
+
"div",
|
|
7014
|
+
{
|
|
7015
|
+
style: {
|
|
7016
|
+
...statBubbleBase,
|
|
7017
|
+
background: "linear-gradient(135deg, var(--mantine-color-orange-5), var(--mantine-color-orange-7))"
|
|
7018
|
+
},
|
|
7019
|
+
children: pendingCount
|
|
7020
|
+
}
|
|
7021
|
+
)
|
|
7022
|
+
]
|
|
7023
|
+
}
|
|
7024
|
+
),
|
|
7025
|
+
/* @__PURE__ */ jsx(BaseNode, { color, selected, highlighted: Boolean(data.highlighted), children: /* @__PURE__ */ jsxs(Stack, { gap: 8, children: [
|
|
7026
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
7027
|
+
/* @__PURE__ */ jsx(
|
|
7028
|
+
ThemeIcon,
|
|
7029
|
+
{
|
|
7030
|
+
size: "md",
|
|
7031
|
+
variant: "gradient",
|
|
7032
|
+
gradient: { from: `${color}.4`, to: `${color}.6`, deg: 135 },
|
|
7033
|
+
className: Graph_module_css_default.nodeIcon,
|
|
7034
|
+
children: /* @__PURE__ */ jsx(Icon, { size: 16 })
|
|
7035
|
+
}
|
|
7036
|
+
),
|
|
7037
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, truncate: true, style: { flex: 1, fontFamily: "var(--elevasis-font-family-subtitle)" }, children: data.name })
|
|
7038
|
+
] }),
|
|
7039
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", lineClamp: 2, children: data.description }),
|
|
7040
|
+
/* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "wrap", children: [
|
|
7041
|
+
/* @__PURE__ */ jsx(
|
|
7042
|
+
Badge,
|
|
7043
|
+
{
|
|
7044
|
+
size: "xs",
|
|
7045
|
+
variant: "gradient",
|
|
7046
|
+
gradient: data.status === "prod" ? { from: "green.5", to: "green.7", deg: 135 } : { from: "blue.5", to: "blue.7", deg: 135 },
|
|
7047
|
+
className: data.status === "prod" ? Graph_module_css_default.badgeProd : "",
|
|
7048
|
+
style: {
|
|
7049
|
+
textTransform: "uppercase",
|
|
7050
|
+
letterSpacing: "0.5px"
|
|
7051
|
+
},
|
|
7052
|
+
children: data.status
|
|
7053
|
+
}
|
|
7054
|
+
),
|
|
7055
|
+
data.type === "agent" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7056
|
+
/* @__PURE__ */ jsxs(
|
|
7057
|
+
Badge,
|
|
7058
|
+
{
|
|
7059
|
+
size: "xs",
|
|
7060
|
+
variant: "outline",
|
|
7061
|
+
color: "gray",
|
|
7062
|
+
className: Graph_module_css_default.badge,
|
|
7063
|
+
style: { backdropFilter: "blur(4px)" },
|
|
7064
|
+
children: [
|
|
7065
|
+
data.toolCount,
|
|
7066
|
+
" tools"
|
|
7067
|
+
]
|
|
7068
|
+
}
|
|
7069
|
+
),
|
|
7070
|
+
data.hasKnowledgeMap && /* @__PURE__ */ jsx(
|
|
7071
|
+
Badge,
|
|
7072
|
+
{
|
|
7073
|
+
size: "xs",
|
|
7074
|
+
variant: "gradient",
|
|
7075
|
+
gradient: { from: "grape.5", to: "grape.7", deg: 135 },
|
|
7076
|
+
leftSection: /* @__PURE__ */ jsx(IconBrain, { size: 10 }),
|
|
7077
|
+
className: Graph_module_css_default.badge,
|
|
7078
|
+
children: "KM"
|
|
7079
|
+
}
|
|
7080
|
+
),
|
|
7081
|
+
data.hasMemory && /* @__PURE__ */ jsx(
|
|
7082
|
+
Badge,
|
|
7083
|
+
{
|
|
7084
|
+
size: "xs",
|
|
7085
|
+
variant: "gradient",
|
|
7086
|
+
gradient: { from: "cyan.5", to: "cyan.7", deg: 135 },
|
|
7087
|
+
leftSection: /* @__PURE__ */ jsx(IconDatabase, { size: 10 }),
|
|
7088
|
+
className: Graph_module_css_default.badge,
|
|
7089
|
+
children: "Mem"
|
|
7090
|
+
}
|
|
7091
|
+
),
|
|
7092
|
+
data.sessionCapable && /* @__PURE__ */ jsx(
|
|
7093
|
+
Badge,
|
|
7094
|
+
{
|
|
7095
|
+
size: "xs",
|
|
7096
|
+
variant: "gradient",
|
|
7097
|
+
gradient: { from: "blue.5", to: "blue.7", deg: 135 },
|
|
7098
|
+
leftSection: /* @__PURE__ */ jsx(IconMessage, { size: 10 }),
|
|
7099
|
+
className: Graph_module_css_default.badge,
|
|
7100
|
+
children: "Session"
|
|
7101
|
+
}
|
|
7102
|
+
)
|
|
7103
|
+
] }),
|
|
7104
|
+
data.type === "workflow" && /* @__PURE__ */ jsxs(
|
|
7105
|
+
Badge,
|
|
7106
|
+
{
|
|
7107
|
+
size: "xs",
|
|
7108
|
+
variant: "outline",
|
|
7109
|
+
color: "gray",
|
|
7110
|
+
className: Graph_module_css_default.badge,
|
|
7111
|
+
style: { backdropFilter: "blur(4px)" },
|
|
7112
|
+
children: [
|
|
7113
|
+
data.stepCount,
|
|
7114
|
+
" steps"
|
|
7115
|
+
]
|
|
7116
|
+
}
|
|
7117
|
+
),
|
|
7118
|
+
data.type === "integration" && /* @__PURE__ */ jsx(
|
|
7119
|
+
Badge,
|
|
7120
|
+
{
|
|
7121
|
+
size: "xs",
|
|
7122
|
+
variant: "gradient",
|
|
7123
|
+
gradient: data.connectionStatus === "connected" ? { from: "green.5", to: "green.7", deg: 135 } : data.connectionStatus === "error" ? { from: "red.5", to: "red.7", deg: 135 } : { from: "gray.5", to: "gray.7", deg: 135 },
|
|
7124
|
+
leftSection: (() => {
|
|
7125
|
+
const StatusIcon = connectionStatusIcons[data.connectionStatus];
|
|
7126
|
+
return /* @__PURE__ */ jsx(StatusIcon, { size: 10 });
|
|
7127
|
+
})(),
|
|
7128
|
+
className: Graph_module_css_default.badge,
|
|
7129
|
+
children: data.connectionStatus
|
|
7130
|
+
}
|
|
7131
|
+
),
|
|
7132
|
+
data.type === "trigger" && /* @__PURE__ */ jsx(
|
|
7133
|
+
Badge,
|
|
7134
|
+
{
|
|
7135
|
+
size: "xs",
|
|
7136
|
+
variant: "outline",
|
|
7137
|
+
color: "gray",
|
|
7138
|
+
leftSection: (() => {
|
|
7139
|
+
const TriggerIcon = triggerTypeIcons[data.triggerType] || IconBolt;
|
|
7140
|
+
return /* @__PURE__ */ jsx(TriggerIcon, { size: 10 });
|
|
7141
|
+
})(),
|
|
7142
|
+
className: Graph_module_css_default.badge,
|
|
7143
|
+
style: { backdropFilter: "blur(4px)" },
|
|
7144
|
+
children: data.triggerType
|
|
7145
|
+
}
|
|
7146
|
+
),
|
|
7147
|
+
data.type === "external" && /* @__PURE__ */ jsx(
|
|
7148
|
+
Badge,
|
|
7149
|
+
{
|
|
7150
|
+
size: "xs",
|
|
7151
|
+
variant: "outline",
|
|
7152
|
+
color: "gray",
|
|
7153
|
+
leftSection: /* @__PURE__ */ jsx(IconExternalLink, { size: 10 }),
|
|
7154
|
+
className: Graph_module_css_default.badge,
|
|
7155
|
+
style: { backdropFilter: "blur(4px)" },
|
|
7156
|
+
children: data.platform
|
|
7157
|
+
}
|
|
7158
|
+
),
|
|
7159
|
+
data.type === "human" && /* @__PURE__ */ jsx(
|
|
7160
|
+
Badge,
|
|
7161
|
+
{
|
|
7162
|
+
size: "xs",
|
|
7163
|
+
variant: "gradient",
|
|
7164
|
+
gradient: { from: "yellow.5", to: "orange.6", deg: 135 },
|
|
7165
|
+
leftSection: /* @__PURE__ */ jsx(IconHandClick, { size: 10 }),
|
|
7166
|
+
className: Graph_module_css_default.badge,
|
|
7167
|
+
children: "Approval Required"
|
|
7168
|
+
}
|
|
7169
|
+
)
|
|
7170
|
+
] })
|
|
7171
|
+
] }) })
|
|
7172
|
+
] });
|
|
7173
|
+
});
|
|
7174
|
+
var relationshipColorMap = {
|
|
7175
|
+
triggers: { color: "edgeTriggers", glow: "edgeTriggersGlow" },
|
|
7176
|
+
uses: { color: "edgeUses", glow: "edgeUsesGlow" },
|
|
7177
|
+
approval: { color: "edgeApproval", glow: "edgeApprovalGlow" }
|
|
7178
|
+
};
|
|
7179
|
+
function getEdgeColors(relationship, colors) {
|
|
7180
|
+
const mapping = relationshipColorMap[relationship] ?? relationshipColorMap.approval;
|
|
7181
|
+
return {
|
|
7182
|
+
edgeColor: colors[mapping.color],
|
|
7183
|
+
glowColor: colors[mapping.glow]
|
|
7184
|
+
};
|
|
7185
|
+
}
|
|
7186
|
+
var CommandViewEdge = memo(function CommandViewEdge2({
|
|
7187
|
+
id,
|
|
7188
|
+
sourceX,
|
|
7189
|
+
sourceY,
|
|
7190
|
+
targetX,
|
|
7191
|
+
targetY,
|
|
7192
|
+
sourcePosition,
|
|
7193
|
+
targetPosition,
|
|
7194
|
+
data,
|
|
7195
|
+
selected
|
|
7196
|
+
}) {
|
|
7197
|
+
const colors = useGraphTheme();
|
|
7198
|
+
const relationship = data?.relationship || "uses";
|
|
7199
|
+
const { edgeColor, glowColor } = getEdgeColors(relationship, colors);
|
|
7200
|
+
return /* @__PURE__ */ jsx(
|
|
7201
|
+
BaseEdge,
|
|
7202
|
+
{
|
|
7203
|
+
id,
|
|
7204
|
+
sourceX,
|
|
7205
|
+
sourceY,
|
|
7206
|
+
targetX,
|
|
7207
|
+
targetY,
|
|
7208
|
+
sourcePosition,
|
|
7209
|
+
targetPosition,
|
|
7210
|
+
color: edgeColor,
|
|
7211
|
+
glowColor,
|
|
7212
|
+
label: data?.label || relationship,
|
|
7213
|
+
animated: data?.animated ?? false,
|
|
7214
|
+
selected,
|
|
7215
|
+
dimmed: data?.dimmed,
|
|
7216
|
+
edgeIndex: data?.edgeIndex,
|
|
7217
|
+
totalEdges: data?.totalEdges
|
|
7218
|
+
}
|
|
7219
|
+
);
|
|
7220
|
+
});
|
|
7221
|
+
var nodeTypes4 = {
|
|
7222
|
+
commandView: CommandViewNode
|
|
7223
|
+
};
|
|
7224
|
+
var edgeTypes4 = {
|
|
7225
|
+
commandView: CommandViewEdge
|
|
7226
|
+
};
|
|
7227
|
+
var CommandViewGraphInner = forwardRef(function CommandViewGraphInner2({ graph, height, selectedNodeId, onNodeSelect }, ref) {
|
|
7228
|
+
const { fitView } = useReactFlow();
|
|
7229
|
+
const { nodes: layoutNodes, edges: layoutEdges } = useCommandViewLayout(graph);
|
|
7230
|
+
const { nodes, edges, handleNodeMouseEnter, handleNodeMouseLeave } = useDirectedChainHighlighting(
|
|
7231
|
+
layoutNodes,
|
|
7232
|
+
layoutEdges,
|
|
7233
|
+
{ selectedNodeId }
|
|
7234
|
+
);
|
|
7235
|
+
const { handleNodeClick, handlePaneClick } = useNodeSelection(selectedNodeId ?? null, onNodeSelect ?? (() => {
|
|
7236
|
+
}));
|
|
7237
|
+
const nodesWithSelection = useMemo(
|
|
7238
|
+
() => nodes.map((node) => ({
|
|
7239
|
+
...node,
|
|
7240
|
+
selected: node.id === selectedNodeId
|
|
7241
|
+
})),
|
|
7242
|
+
[nodes, selectedNodeId]
|
|
7243
|
+
);
|
|
7244
|
+
useImperativeHandle(ref, () => ({
|
|
7245
|
+
fitView: () => fitView({ padding: 0.15, duration: 300 })
|
|
7246
|
+
}));
|
|
7247
|
+
return /* @__PURE__ */ jsx(
|
|
7248
|
+
Box,
|
|
7249
|
+
{
|
|
7250
|
+
className: Graph_module_css_default.graphContainer,
|
|
7251
|
+
style: {
|
|
7252
|
+
width: "100%",
|
|
7253
|
+
height,
|
|
7254
|
+
border: "1px solid var(--color-border)",
|
|
7255
|
+
borderRadius: "var(--mantine-radius-default)",
|
|
7256
|
+
overflow: "hidden"
|
|
7257
|
+
},
|
|
7258
|
+
children: /* @__PURE__ */ jsxs(
|
|
7259
|
+
ReactFlow,
|
|
7260
|
+
{
|
|
7261
|
+
nodes: nodesWithSelection,
|
|
7262
|
+
edges,
|
|
7263
|
+
nodeTypes: nodeTypes4,
|
|
7264
|
+
edgeTypes: edgeTypes4,
|
|
7265
|
+
onNodeMouseEnter: handleNodeMouseEnter,
|
|
7266
|
+
onNodeMouseLeave: handleNodeMouseLeave,
|
|
7267
|
+
onNodeClick: onNodeSelect ? handleNodeClick : void 0,
|
|
7268
|
+
onPaneClick: onNodeSelect ? handlePaneClick : void 0,
|
|
7269
|
+
fitView: true,
|
|
7270
|
+
fitViewOptions: { padding: 0.15 },
|
|
7271
|
+
proOptions: { hideAttribution: true },
|
|
7272
|
+
minZoom: GRAPH_CONSTANTS.MIN_ZOOM,
|
|
7273
|
+
maxZoom: GRAPH_CONSTANTS.MAX_ZOOM,
|
|
7274
|
+
nodesDraggable: false,
|
|
7275
|
+
nodesConnectable: false,
|
|
7276
|
+
elementsSelectable: !!onNodeSelect,
|
|
7277
|
+
selectNodesOnDrag: false,
|
|
7278
|
+
panOnDrag: true,
|
|
7279
|
+
zoomOnScroll: true,
|
|
7280
|
+
zoomOnPinch: true,
|
|
7281
|
+
panOnScroll: false,
|
|
7282
|
+
children: [
|
|
7283
|
+
/* @__PURE__ */ jsx(GraphBackground, {}),
|
|
7284
|
+
/* @__PURE__ */ jsx(
|
|
7285
|
+
GraphLegend,
|
|
7286
|
+
{
|
|
7287
|
+
title: "",
|
|
7288
|
+
position: "bottom-right",
|
|
7289
|
+
items: [
|
|
7290
|
+
{ color: "orange", label: "Triggers" },
|
|
7291
|
+
{ color: "violet", label: "Agents" },
|
|
7292
|
+
{ color: "blue", label: "Workflows" },
|
|
7293
|
+
{ color: "teal", label: "Integrations" },
|
|
7294
|
+
{ color: "yellow", label: "Human" },
|
|
7295
|
+
{ color: "gray", label: "External" }
|
|
7296
|
+
]
|
|
7297
|
+
}
|
|
7298
|
+
),
|
|
7299
|
+
/* @__PURE__ */ jsx(
|
|
7300
|
+
GraphLegend,
|
|
7301
|
+
{
|
|
7302
|
+
title: "",
|
|
7303
|
+
position: "bottom-left",
|
|
7304
|
+
items: [
|
|
7305
|
+
{ color: "blue", label: "Triggers", type: "line" },
|
|
7306
|
+
{ color: "teal", label: "Uses", type: "line" },
|
|
7307
|
+
{ color: "yellow", label: "Requires Approval", type: "line" }
|
|
7308
|
+
]
|
|
7309
|
+
}
|
|
7310
|
+
),
|
|
7311
|
+
/* @__PURE__ */ jsx(GraphFitViewButton, { padding: 0.15, variant: "mantine", duration: 300 })
|
|
7312
|
+
]
|
|
7313
|
+
}
|
|
7314
|
+
)
|
|
7315
|
+
}
|
|
7316
|
+
);
|
|
7317
|
+
});
|
|
7318
|
+
var CommandViewGraph = forwardRef(
|
|
7319
|
+
function CommandViewGraph2(props, ref) {
|
|
7320
|
+
return /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(CommandViewGraphInner, { ref, ...props }) });
|
|
7321
|
+
}
|
|
7322
|
+
);
|
|
7323
|
+
|
|
7324
|
+
export { AbsoluteScheduleForm, ActionModal, ActivityCard, ActivityFilters as ActivityFiltersBar, ActivityTable, AgentDefinitionDisplay, AgentExecutionLogs, AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, BaseEdge, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates, BaseNode, BusinessImpactCard, CheckpointGroup, CollapsibleJsonSection, CommandQueueSidebar, CommandQueueSidebarMiddle, CommandQueueSidebarTop, CommandQueueTaskRow, CommandViewEdge, CommandViewGraph, CommandViewNode, ConfigCard, ConfirmationInputModal, ConfirmationModal, ContentSections, ContextUsageBadge, ContractDisplay, CostBreakdownCard, CostByModelTable, CostMetricsCard, CreateScheduleModal, CustomModal, DeleteScheduleModal, DocTreeNav, EmptyVisualizer, ErrorAnalysisCard, ErrorBreakdownTable, ExecutionBreakdownTable, ExecutionErrorSection, ExecutionHealthCard, ExecutionLogsFilters as ExecutionLogsFilterBar, ExecutionLogsTable, ExecutionStats, ExecutionStatusBadge, FilterBar, FormFieldRenderer, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, KnowledgeBasePage, LogEntry, LogGroup, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, NotificationBell, NotificationItem, NotificationList, NotificationPanel, RecurringScheduleForm, RelativeScheduleForm, ResourceDefinitionSection, ResourceDetailPage, ResourceErrorState, ResourceFilter, ResourceHeader, ResourceHealthChart, ResourceHealthPanel, ResourceNotFoundState, ScheduleCard, ScheduleDetailModal, ScheduleTypeSelector, SessionMemory, SortableHeader, TableSelectionToolbar, TaskCard, TaskScheduler, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, ToolsListDisplay, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, VisualizerContainer, WorkflowDefinitionDisplay, WorkflowExecutionLogs, WorkflowExecutionTimeline, getExecutionStatusConfig, getGraphBackgroundStyles, getHealthColor, getIcon, getLogLevelConfig, iconMap, useGraphBackgroundStyles, useGraphTheme, useNewKnowledgeMapLayout };
|