@elevasis/ui 1.7.5 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/api/index.js +2 -3
  2. package/dist/auth/index.js +3 -4
  3. package/dist/charts/index.js +6 -8
  4. package/dist/{chunk-SFF5MJEI.js → chunk-2YBPRE6H.js} +1 -2
  5. package/dist/{chunk-U34YGJQB.js → chunk-3I2LOKQU.js} +1 -1
  6. package/dist/{chunk-PVVQTENF.js → chunk-3PURTICE.js} +1 -1
  7. package/dist/{chunk-2JBWPFHF.js → chunk-6TMW6VQ2.js} +1 -1
  8. package/dist/{chunk-6HZAMY6T.js → chunk-ARZM3OTI.js} +6 -2
  9. package/dist/{chunk-OK3XFSJJ.js → chunk-BWZMI4KP.js} +963 -10
  10. package/dist/{chunk-4KPI7YCY.js → chunk-EHXOR5LA.js} +2 -3
  11. package/dist/{chunk-Y7UY3HI4.js → chunk-ESOQEOOX.js} +2 -2
  12. package/dist/{chunk-L2CM2CUA.js → chunk-GZVH423C.js} +26 -3
  13. package/dist/{chunk-Y6DNK5ZD.js → chunk-JRJW2H57.js} +35 -9
  14. package/dist/{chunk-LBPALY25.js → chunk-JUPCUF77.js} +2 -2
  15. package/dist/chunk-QWYJHM3S.js +1068 -0
  16. package/dist/{chunk-NEK6JKPW.js → chunk-WUQWCUCB.js} +1 -1
  17. package/dist/chunk-Z4TPHMRD.js +231 -0
  18. package/dist/components/index.css +65 -0
  19. package/dist/components/index.d.ts +261 -2
  20. package/dist/components/index.js +1136 -80
  21. package/dist/hooks/index.css +452 -0
  22. package/dist/hooks/index.d.ts +1831 -13
  23. package/dist/hooks/index.js +15 -6
  24. package/dist/hooks/published.css +452 -0
  25. package/dist/hooks/published.d.ts +866 -6
  26. package/dist/hooks/published.js +15 -370
  27. package/dist/index.css +3 -0
  28. package/dist/index.d.ts +1665 -2
  29. package/dist/index.js +14 -17
  30. package/dist/initialization/index.js +3 -4
  31. package/dist/organization/index.js +3 -4
  32. package/dist/profile/index.js +1 -2
  33. package/dist/provider/index.css +3 -0
  34. package/dist/provider/index.js +7 -10
  35. package/dist/provider/published.js +6 -9
  36. package/dist/utils/index.d.ts +92 -1
  37. package/dist/utils/index.js +1 -2
  38. package/package.json +7 -3
  39. package/dist/chunk-4VGWQ5AN.js +0 -91
  40. package/dist/chunk-KA7LO7U5.js +0 -28
  41. package/dist/chunk-LFYO3MDC.js +0 -58
  42. package/dist/chunk-TIRMFDM4.js +0 -33
  43. package/dist/chunk-TYV5NJV2.js +0 -1
@@ -1,11 +1,20 @@
1
- import { getTimeRangeDates, observabilityKeys } from './chunk-6HZAMY6T.js';
1
+ import { getTimeRangeDates, observabilityKeys } from './chunk-ARZM3OTI.js';
2
2
  import { useSupabase } from './chunk-JGJSZ3UE.js';
3
- import { useNotificationAdapter } from './chunk-TIRMFDM4.js';
3
+ import { GRAPH_CONSTANTS } from './chunk-F6RBK7NJ.js';
4
+ import { useNotificationAdapter } from './chunk-JRJW2H57.js';
5
+ import { HTTP_HEADERS } from './chunk-JUPCUF77.js';
6
+ import { STALE_TIME_MONITORING, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_RUNNING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, STALE_TIME_DEFAULT, STALE_TIME_ADMIN } from './chunk-Z4TPHMRD.js';
4
7
  import { useStableAccessToken } from './chunk-FWZJH3TL.js';
5
- import { useElevasisServices } from './chunk-KA7LO7U5.js';
8
+ import { useElevasisServices } from './chunk-GZVH423C.js';
9
+ import { useOrganization } from './chunk-DD3CCMCZ.js';
10
+ import { useAuthContext } from './chunk-7PLEQFHO.js';
6
11
  import { useQuery, useQueryClient, useMutation, useQueries } from '@tanstack/react-query';
7
12
  import { z } from 'zod';
8
- import { useCallback, useMemo, useState, useEffect, useId, useRef } from 'react';
13
+ import { useCallback, useMemo, useState, useRef, useEffect, useId } from 'react';
14
+ import { useNavigate, useSearch } from '@tanstack/react-router';
15
+ import { create } from 'zustand';
16
+ import { persist } from 'zustand/middleware';
17
+ import dagre from '@dagrejs/dagre';
9
18
 
10
19
  function useCommandQueue({
11
20
  status,
@@ -202,7 +211,7 @@ function useExecutions(resourceId, resourceStatus, limit) {
202
211
  enabled: isReady && !!resourceId
203
212
  });
204
213
  }
205
- var REFETCH_INTERVAL_RUNNING = 2e3;
214
+ var REFETCH_INTERVAL_RUNNING2 = 2e3;
206
215
  function useExecution(resourceId, executionId) {
207
216
  const { apiRequest, organizationId, isReady } = useElevasisServices();
208
217
  return useQuery({
@@ -211,7 +220,7 @@ function useExecution(resourceId, executionId) {
211
220
  enabled: isReady && !!resourceId && !!executionId,
212
221
  refetchInterval: (query) => {
213
222
  const data = query.state.data;
214
- return data?.status === "running" ? REFETCH_INTERVAL_RUNNING : false;
223
+ return data?.status === "running" ? REFETCH_INTERVAL_RUNNING2 : false;
215
224
  }
216
225
  });
217
226
  }
@@ -323,7 +332,7 @@ var UuidSchema = z.string().uuid();
323
332
  var NonEmptyStringSchema = z.string().trim().min(1).max(1e3);
324
333
  var ResourceTypeSchema = z.enum(["agent", "workflow"]);
325
334
  var OriginResourceTypeSchema = z.enum(["agent", "workflow", "scheduler", "api"]);
326
- z.string().trim().toLowerCase().min(1, "Credential name required").max(100, "Credential name too long (max 100 chars)").regex(
335
+ var CredentialNameSchema = z.string().trim().toLowerCase().min(1, "Credential name required").max(100, "Credential name too long (max 100 chars)").regex(
327
336
  /^[a-z0-9]+(-[a-z0-9]+)+$/,
328
337
  "Credential name must be lowercase letters, numbers, and hyphens in format: service-environment (e.g., gmail-prod, attio-dev)"
329
338
  );
@@ -946,6 +955,24 @@ function useBatchDelete(tableName, invalidateQueryKeys) {
946
955
  }
947
956
  });
948
957
  }
958
+ function useTestNotification() {
959
+ const queryClient = useQueryClient();
960
+ const { apiRequest } = useElevasisServices();
961
+ const adapter = useNotificationAdapter();
962
+ return useMutation({
963
+ mutationFn: async () => {
964
+ await apiRequest("/notifications/test", {
965
+ method: "POST"
966
+ });
967
+ },
968
+ onSuccess: () => {
969
+ queryClient.invalidateQueries({ queryKey: ["notifications"] });
970
+ },
971
+ onError: (error) => {
972
+ adapter.apiError(error);
973
+ }
974
+ });
975
+ }
949
976
  function useErrorAnalysis(timeRange) {
950
977
  const { apiRequest, isReady, organizationId } = useElevasisServices();
951
978
  return useQuery({
@@ -1206,6 +1233,62 @@ function useBatchedResourcesHealth(params) {
1206
1233
  }, [queryResults]);
1207
1234
  return { healthLookup };
1208
1235
  }
1236
+ function useUnresolvedErrors({ startDate, endDate }) {
1237
+ const { apiRequest, isReady, organizationId } = useElevasisServices();
1238
+ return useQuery({
1239
+ queryKey: observabilityKeys.unresolvedErrors(organizationId, startDate, endDate),
1240
+ queryFn: async () => {
1241
+ const params = new URLSearchParams({
1242
+ resolved: "false",
1243
+ limit: "5",
1244
+ page: "1",
1245
+ startDate,
1246
+ endDate
1247
+ });
1248
+ return apiRequest(`/observability/error-details?${params.toString()}`);
1249
+ },
1250
+ enabled: isReady,
1251
+ refetchInterval: REFETCH_INTERVAL_DASHBOARD,
1252
+ staleTime: STALE_TIME_MONITORING
1253
+ });
1254
+ }
1255
+ function useRecentExecutionsByResource({ timeRange, limit }) {
1256
+ const { apiRequest, isReady, organizationId } = useElevasisServices();
1257
+ return useQuery({
1258
+ queryKey: observabilityKeys.recentExecutionsByResource(organizationId, timeRange, limit),
1259
+ queryFn: async () => {
1260
+ const { startDate, endDate } = getTimeRangeDates(timeRange);
1261
+ const params = new URLSearchParams({
1262
+ startDate,
1263
+ endDate,
1264
+ ...limit !== void 0 && { limit: String(limit) }
1265
+ });
1266
+ return apiRequest(
1267
+ `/observability/recent-executions-by-resource?${params.toString()}`
1268
+ );
1269
+ },
1270
+ enabled: isReady,
1271
+ refetchInterval: REFETCH_INTERVAL_DASHBOARD
1272
+ });
1273
+ }
1274
+ function useScheduledTasks(options = {}) {
1275
+ const { apiRequest, organizationId, isReady } = useElevasisServices();
1276
+ return useQuery({
1277
+ queryKey: ["schedules", "dashboard", organizationId, options.status, options.targetResourceType],
1278
+ queryFn: async () => {
1279
+ const params = new URLSearchParams();
1280
+ if (options.status) params.append("status", options.status);
1281
+ if (options.targetResourceType) params.append("targetResourceType", options.targetResourceType);
1282
+ const queryString = params.toString();
1283
+ const response = await apiRequest(
1284
+ `/task-scheduler/schedules${queryString ? `?${queryString}` : ""}`
1285
+ );
1286
+ return response.schedules;
1287
+ },
1288
+ enabled: isReady,
1289
+ refetchInterval: REFETCH_INTERVAL_DASHBOARD
1290
+ });
1291
+ }
1209
1292
 
1210
1293
  // src/hooks/scheduling/queryKeys.ts
1211
1294
  var scheduleKeys = {
@@ -1384,6 +1467,358 @@ function useDeleteSchedule() {
1384
1467
  }
1385
1468
  });
1386
1469
  }
1470
+
1471
+ // src/hooks/sessions/queryKeys.ts
1472
+ var sessionsKeys = {
1473
+ all: ["sessions"],
1474
+ sessions: (org, params) => [...sessionsKeys.all, "list", org, params],
1475
+ session: (org, sessionId) => [...sessionsKeys.all, "detail", org, sessionId],
1476
+ executions: (org, sessionId) => [...sessionsKeys.all, org, sessionId, "executions"],
1477
+ execution: (org, sessionId, executionId) => [...sessionsKeys.all, org, sessionId, "executions", executionId],
1478
+ messages: (org, sessionId) => [...sessionsKeys.all, org, sessionId, "messages"]
1479
+ };
1480
+ function useSessions(params, options) {
1481
+ const { apiRequest, isReady } = useElevasisServices();
1482
+ const { currentMembership } = useOrganization();
1483
+ const organizationName = currentMembership?.organization?.name;
1484
+ return useQuery({
1485
+ queryKey: sessionsKeys.sessions(organizationName || "", params),
1486
+ queryFn: async () => {
1487
+ const service = new OperationsService(apiRequest);
1488
+ return service.listSessions(params);
1489
+ },
1490
+ enabled: isReady && (options?.enabled ?? true)
1491
+ });
1492
+ }
1493
+ function useSession(sessionId) {
1494
+ const { apiRequest, isReady } = useElevasisServices();
1495
+ const { currentMembership } = useOrganization();
1496
+ const organizationName = currentMembership?.organization?.name;
1497
+ return useQuery({
1498
+ queryKey: sessionsKeys.session(organizationName || "", sessionId),
1499
+ queryFn: () => {
1500
+ const service = new OperationsService(apiRequest);
1501
+ return service.getSession(sessionId);
1502
+ },
1503
+ enabled: isReady && !!sessionId
1504
+ });
1505
+ }
1506
+ function useCreateSession() {
1507
+ const { apiRequest } = useElevasisServices();
1508
+ const { currentMembership } = useOrganization();
1509
+ const organizationName = currentMembership?.organization?.name;
1510
+ const queryClient = useQueryClient();
1511
+ return useMutation({
1512
+ mutationFn: async (resourceId) => {
1513
+ const service = new OperationsService(apiRequest);
1514
+ return service.createSession(resourceId);
1515
+ },
1516
+ onSuccess: () => {
1517
+ queryClient.invalidateQueries({ queryKey: sessionsKeys.sessions(organizationName || "") });
1518
+ }
1519
+ });
1520
+ }
1521
+ function useDeleteSession() {
1522
+ const { apiRequest } = useElevasisServices();
1523
+ const { currentMembership } = useOrganization();
1524
+ const organizationName = currentMembership?.organization?.name;
1525
+ const queryClient = useQueryClient();
1526
+ return useMutation({
1527
+ mutationFn: async (sessionId) => {
1528
+ SessionIdParamSchema.parse({ sessionId });
1529
+ await apiRequest(`/sessions/${sessionId}`, {
1530
+ method: "DELETE"
1531
+ });
1532
+ },
1533
+ onSuccess: (_, sessionId) => {
1534
+ queryClient.removeQueries({
1535
+ queryKey: sessionsKeys.session(organizationName || "", sessionId)
1536
+ });
1537
+ queryClient.invalidateQueries({
1538
+ queryKey: sessionsKeys.sessions(organizationName || "")
1539
+ });
1540
+ }
1541
+ });
1542
+ }
1543
+ function useArchiveSession() {
1544
+ const { apiRequest } = useElevasisServices();
1545
+ const { currentMembership } = useOrganization();
1546
+ const organizationName = currentMembership?.organization?.name;
1547
+ const queryClient = useQueryClient();
1548
+ return useMutation({
1549
+ mutationFn: (sessionId) => {
1550
+ const service = new OperationsService(apiRequest);
1551
+ return service.archiveSession(sessionId);
1552
+ },
1553
+ onSuccess: () => {
1554
+ queryClient.invalidateQueries({ queryKey: sessionsKeys.sessions(organizationName || "") });
1555
+ }
1556
+ });
1557
+ }
1558
+ function useSessionExecutions(sessionId) {
1559
+ const { apiRequest, isReady } = useElevasisServices();
1560
+ const { currentSupabaseOrganizationId } = useOrganization();
1561
+ return useQuery({
1562
+ queryKey: sessionsKeys.executions(currentSupabaseOrganizationId || "", sessionId),
1563
+ queryFn: async () => {
1564
+ SessionIdParamSchema.parse({ sessionId });
1565
+ return apiRequest(`/sessions/${sessionId}/executions`, {
1566
+ method: "GET"
1567
+ });
1568
+ },
1569
+ enabled: isReady && !!sessionId,
1570
+ staleTime: 0
1571
+ });
1572
+ }
1573
+ function useSessionExecution(sessionId, executionId) {
1574
+ const { apiRequest, isReady } = useElevasisServices();
1575
+ const { currentSupabaseOrganizationId } = useOrganization();
1576
+ return useQuery({
1577
+ queryKey: sessionsKeys.execution(currentSupabaseOrganizationId || "", sessionId, executionId),
1578
+ queryFn: async () => {
1579
+ ExecutionIdParamsSchema.parse({ sessionId, executionId });
1580
+ return apiRequest(`/sessions/${sessionId}/executions/${executionId}`, {
1581
+ method: "GET"
1582
+ });
1583
+ },
1584
+ enabled: isReady && !!sessionId && !!executionId,
1585
+ refetchInterval: (query) => {
1586
+ const data = query.state.data;
1587
+ const shouldRefetch = data?.status === "running";
1588
+ return shouldRefetch ? REFETCH_INTERVAL_RUNNING : false;
1589
+ }
1590
+ });
1591
+ }
1592
+ function useSessionMessages(sessionId) {
1593
+ const { apiRequest, isReady } = useElevasisServices();
1594
+ const { currentSupabaseOrganizationId } = useOrganization();
1595
+ return useQuery({
1596
+ queryKey: sessionsKeys.messages(currentSupabaseOrganizationId || "", sessionId),
1597
+ queryFn: async () => {
1598
+ SessionIdParamSchema.parse({ sessionId });
1599
+ const response = await apiRequest(`/sessions/${sessionId}/messages`, {
1600
+ method: "GET"
1601
+ });
1602
+ const messages = response.messages.map((msg) => ({
1603
+ ...msg,
1604
+ createdAt: new Date(msg.createdAt)
1605
+ }));
1606
+ return messages;
1607
+ },
1608
+ enabled: isReady && !!sessionId,
1609
+ staleTime: 0
1610
+ });
1611
+ }
1612
+ function formatMessageEvent(event) {
1613
+ switch (event.type) {
1614
+ case "user_message":
1615
+ return event.text;
1616
+ case "assistant_message":
1617
+ return event.text;
1618
+ case "agent:started":
1619
+ return "\u{1F916} Agent started reasoning";
1620
+ case "agent:reasoning":
1621
+ return `\u{1F4AD} Reasoning (Iteration ${event.iteration})`;
1622
+ case "agent:tool_call":
1623
+ return `\u{1F527} Tool: ${event.toolName}`;
1624
+ case "agent:tool_result":
1625
+ return event.success ? "\u2705 Tool Result" : "\u26A0\uFE0F Tool Result (Failed)";
1626
+ case "agent:completed":
1627
+ return "\u2705 Agent completed";
1628
+ case "agent:error":
1629
+ return `\u274C Agent error: ${event.error}`;
1630
+ }
1631
+ }
1632
+ function getWsUrl(apiUrl) {
1633
+ const url = new URL(apiUrl);
1634
+ const protocol = url.protocol === "https:" ? "wss:" : "ws:";
1635
+ return `${protocol}//${url.host}`;
1636
+ }
1637
+ function useSessionWebSocket(sessionId, apiUrl) {
1638
+ const [messages, setMessages] = useState([]);
1639
+ const [state, setState] = useState({
1640
+ isConnected: false,
1641
+ isProcessing: false,
1642
+ error: null
1643
+ });
1644
+ const [lastTokenUsage, setLastTokenUsage] = useState(null);
1645
+ const wsRef = useRef(null);
1646
+ const retryCountRef = useRef(0);
1647
+ const reconnectTimeoutRef = useRef(null);
1648
+ const { getAccessToken } = useAuthContext();
1649
+ const { currentWorkOSOrganizationId, currentSupabaseOrganizationId } = useOrganization();
1650
+ const queryClient = useQueryClient();
1651
+ const getAccessTokenRef = useRef(getAccessToken);
1652
+ getAccessTokenRef.current = getAccessToken;
1653
+ const currentWorkOSOrgIdRef = useRef(currentWorkOSOrganizationId);
1654
+ currentWorkOSOrgIdRef.current = currentWorkOSOrganizationId;
1655
+ const queryClientRef = useRef(queryClient);
1656
+ queryClientRef.current = queryClient;
1657
+ const currentSupabaseOrgIdRef = useRef(currentSupabaseOrganizationId);
1658
+ currentSupabaseOrgIdRef.current = currentSupabaseOrganizationId;
1659
+ const connect = useCallback(async () => {
1660
+ if (!currentWorkOSOrgIdRef.current) {
1661
+ return;
1662
+ }
1663
+ if (wsRef.current?.readyState === WebSocket.OPEN || wsRef.current?.readyState === WebSocket.CONNECTING) {
1664
+ return;
1665
+ }
1666
+ const token = await getAccessTokenRef.current();
1667
+ if (!token) {
1668
+ return;
1669
+ }
1670
+ const orgId = currentWorkOSOrgIdRef.current;
1671
+ const wsUrl = `${getWsUrl(apiUrl)}/ws/sessions/${sessionId}?token=${token}&orgId=${orgId}`;
1672
+ const ws = new WebSocket(wsUrl);
1673
+ ws.onopen = () => {
1674
+ setState((prev) => ({ ...prev, isConnected: true, error: null }));
1675
+ retryCountRef.current = 0;
1676
+ const supabaseOrgId = currentSupabaseOrgIdRef.current;
1677
+ if (supabaseOrgId) {
1678
+ queryClientRef.current.invalidateQueries({
1679
+ queryKey: sessionsKeys.messages(supabaseOrgId, sessionId)
1680
+ });
1681
+ }
1682
+ };
1683
+ ws.onmessage = (event) => {
1684
+ try {
1685
+ const data = JSON.parse(event.data);
1686
+ if (data.type && data.type !== "turn:complete" && data.type !== "error") {
1687
+ const tempMessage = {
1688
+ id: `temp-${Date.now()}`,
1689
+ role: data.type === "user_message" ? "user" : "assistant",
1690
+ messageType: data.type,
1691
+ text: formatMessageEvent(data),
1692
+ // Format based on type
1693
+ metadata: data.type.startsWith("agent:") ? data : void 0,
1694
+ turnNumber: 999999,
1695
+ // High placeholder so temp messages sort to bottom
1696
+ messageIndex: Date.now(),
1697
+ // Use timestamp for unique ordering
1698
+ createdAt: /* @__PURE__ */ new Date()
1699
+ };
1700
+ setMessages((prev) => [...prev, tempMessage]);
1701
+ } else if (data.type === "turn:complete") {
1702
+ if (data.tokenUsage) {
1703
+ setLastTokenUsage(data.tokenUsage);
1704
+ }
1705
+ setState((prev) => ({ ...prev, isProcessing: false }));
1706
+ const supabaseOrgId = currentSupabaseOrgIdRef.current;
1707
+ if (supabaseOrgId) {
1708
+ queryClientRef.current.invalidateQueries({
1709
+ queryKey: sessionsKeys.messages(supabaseOrgId, sessionId)
1710
+ });
1711
+ queryClientRef.current.invalidateQueries({
1712
+ queryKey: sessionsKeys.executions(supabaseOrgId, sessionId)
1713
+ });
1714
+ queryClientRef.current.invalidateQueries({
1715
+ queryKey: sessionsKeys.session(supabaseOrgId, sessionId)
1716
+ });
1717
+ }
1718
+ } else if (data.type === "error") {
1719
+ setState((prev) => ({
1720
+ ...prev,
1721
+ error: data.error,
1722
+ isProcessing: false
1723
+ }));
1724
+ }
1725
+ } catch (error) {
1726
+ console.error("Failed to parse WebSocket message:", error);
1727
+ }
1728
+ };
1729
+ ws.onerror = () => {
1730
+ };
1731
+ ws.onclose = (event) => {
1732
+ setState((prev) => ({ ...prev, isConnected: false }));
1733
+ if (!event.wasClean && retryCountRef.current >= WS_MAX_RETRIES_BEFORE_ERROR) {
1734
+ setState((prev) => ({
1735
+ ...prev,
1736
+ error: "Unable to connect to session. Retrying..."
1737
+ }));
1738
+ }
1739
+ const terminalCodes = [1003, 1008];
1740
+ if (terminalCodes.includes(event.code) || event.code >= 4e3) {
1741
+ setState((prev) => ({
1742
+ ...prev,
1743
+ error: `Connection rejected (code ${event.code})`
1744
+ }));
1745
+ return;
1746
+ }
1747
+ const delay = Math.min(WS_RECONNECT_BASE_DELAY * Math.pow(2, retryCountRef.current), WS_RECONNECT_MAX_DELAY);
1748
+ retryCountRef.current += 1;
1749
+ reconnectTimeoutRef.current = setTimeout(() => {
1750
+ connect();
1751
+ }, delay);
1752
+ };
1753
+ wsRef.current = ws;
1754
+ }, [sessionId, apiUrl]);
1755
+ useEffect(() => {
1756
+ retryCountRef.current = 0;
1757
+ if (currentWorkOSOrgIdRef.current) {
1758
+ connect();
1759
+ }
1760
+ return () => {
1761
+ if (reconnectTimeoutRef.current) {
1762
+ clearTimeout(reconnectTimeoutRef.current);
1763
+ }
1764
+ if (wsRef.current) {
1765
+ wsRef.current.close();
1766
+ wsRef.current = null;
1767
+ }
1768
+ };
1769
+ }, [sessionId, currentWorkOSOrganizationId, connect]);
1770
+ const sendMessage = useCallback(
1771
+ (text, pageContext) => {
1772
+ const trimmed = text.trim();
1773
+ if (!trimmed) {
1774
+ return;
1775
+ }
1776
+ if (!wsRef.current || state.isProcessing) {
1777
+ return;
1778
+ }
1779
+ if (wsRef.current.readyState !== WebSocket.OPEN) {
1780
+ setState((prev) => ({
1781
+ ...prev,
1782
+ error: "WebSocket not connected"
1783
+ }));
1784
+ return;
1785
+ }
1786
+ const userMessage = {
1787
+ id: `temp-${Date.now()}`,
1788
+ role: "user",
1789
+ messageType: "user_message",
1790
+ text: trimmed,
1791
+ turnNumber: 999999,
1792
+ // High placeholder so temp messages sort to bottom
1793
+ messageIndex: Date.now(),
1794
+ // Use timestamp for unique ordering
1795
+ createdAt: /* @__PURE__ */ new Date()
1796
+ };
1797
+ setMessages((prev) => [...prev, userMessage]);
1798
+ const input = { message: trimmed };
1799
+ if (pageContext) {
1800
+ input.pageContext = pageContext;
1801
+ }
1802
+ const message = WebSocketSessionTurnSchema.parse({
1803
+ type: "session:turn",
1804
+ input
1805
+ });
1806
+ wsRef.current.send(JSON.stringify(message));
1807
+ setState((prev) => ({ ...prev, isProcessing: true, error: null }));
1808
+ },
1809
+ [state.isProcessing, sessionId]
1810
+ );
1811
+ const clearError = useCallback(() => {
1812
+ setState((prev) => ({ ...prev, error: null }));
1813
+ }, []);
1814
+ return {
1815
+ messages,
1816
+ state,
1817
+ sendMessage,
1818
+ clearError,
1819
+ lastTokenUsage
1820
+ };
1821
+ }
1387
1822
  function usePaginationState(pageSize, resetDeps, total) {
1388
1823
  const [page, setPage] = useState(1);
1389
1824
  useEffect(() => {
@@ -1491,12 +1926,12 @@ function useSortedData(data, defaultColumn, accessors, defaultDirection = "desc"
1491
1926
  }
1492
1927
  function createUseFeatureAccess({
1493
1928
  useInitialization,
1494
- useOrganization,
1929
+ useOrganization: useOrganization2,
1495
1930
  optInFeatures = []
1496
1931
  }) {
1497
1932
  return function useFeatureAccess() {
1498
1933
  const { profile, organizationReady } = useInitialization();
1499
- const { currentMembership } = useOrganization();
1934
+ const { currentMembership } = useOrganization2();
1500
1935
  const { orgConfig, membershipConfig } = useMemo(() => {
1501
1936
  const organizationConfig = currentMembership?.organization?.config;
1502
1937
  const memberConfig = currentMembership?.config;
@@ -1593,4 +2028,522 @@ function useSSEConnection({
1593
2028
  return { connected, error };
1594
2029
  }
1595
2030
 
1596
- export { ExecutionIdParamsSchema, OperationsService, SessionIdParamSchema, WebSocketSessionTurnSchema, createUseFeatureAccess, executionsKeys, scheduleKeys, sortData, useActivities, useActivityTrend, useBatchDelete, useBatchedResourcesHealth, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCommandQueue, useCommandQueueTotals, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useDeleteTask, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutions, useGetExecutionHistory, useGetSchedule, useListSchedules, useMarkAllAsRead, useMarkAsRead, useNotificationCount, useNotifications, usePaginationState, usePatchTask, usePauseSchedule, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResourcesHealth, useResumeSchedule, useRetryExecution, useSSEConnection, useSortedData, useSubmitAction, useSuccessNotification, useTableSelection, useTableSort, useTopFailingResources, useUnresolveError, useUpdateAnchor, useUpdateSchedule, useWarningNotification };
2031
+ // src/hooks/operations/shared/queryKeys.ts
2032
+ var operationsKeys = {
2033
+ all: ["operations"],
2034
+ // Individual resource types (kept for CC-specific features)
2035
+ workflows: (org) => [...operationsKeys.all, "workflows", org],
2036
+ workflowDetails: (org) => [...operationsKeys.workflows(org), "details"],
2037
+ workflow: (id, org) => [...operationsKeys.workflows(org), id],
2038
+ agents: (org) => [...operationsKeys.all, "agents", org],
2039
+ agentDetails: (org) => [...operationsKeys.agents(org), "details"],
2040
+ agent: (id, org) => [...operationsKeys.agents(org), id],
2041
+ sessions: (org, params) => [...operationsKeys.all, "sessions", org, params],
2042
+ session: (org, sessionId) => [...operationsKeys.all, "session", org, sessionId]
2043
+ };
2044
+ function useExecutionLogSSE(resourceId, manager) {
2045
+ const queryClient = useQueryClient();
2046
+ const [liveExecutions, setLiveExecutions] = useState(/* @__PURE__ */ new Set());
2047
+ const [streamingLogs, setStreamingLogs] = useState(/* @__PURE__ */ new Map());
2048
+ const { isReady: isOrganizationReady, organizationId } = useElevasisServices();
2049
+ const { currentMembership } = useOrganization();
2050
+ const currentWorkOSOrganizationId = currentMembership?.organization?.id;
2051
+ const apiUrl = import.meta.env?.VITE_API_SERVER ?? "http://localhost:5170";
2052
+ const sseUrl = `${apiUrl}/api/execution-engine/sse/${resourceId}`;
2053
+ const headers = useMemo(() => {
2054
+ const h = {};
2055
+ if (currentWorkOSOrganizationId) h[HTTP_HEADERS.WORKOS_ORGANIZATION_ID] = currentWorkOSOrganizationId;
2056
+ return h;
2057
+ }, [currentWorkOSOrganizationId]);
2058
+ const handleMessage = useCallback(
2059
+ (data) => {
2060
+ try {
2061
+ const event = JSON.parse(data);
2062
+ switch (event.type) {
2063
+ case "connected":
2064
+ break;
2065
+ case "new-execution":
2066
+ if (event.executionId) {
2067
+ setLiveExecutions((prev) => {
2068
+ const updated = new Set(prev);
2069
+ updated.add(event.executionId);
2070
+ return updated;
2071
+ });
2072
+ queryClient.invalidateQueries({
2073
+ queryKey: executionsKeys.executions(organizationId, resourceId)
2074
+ });
2075
+ }
2076
+ break;
2077
+ case "execution-complete":
2078
+ if (event.executionId) {
2079
+ setLiveExecutions((prev) => {
2080
+ const updated = new Set(prev);
2081
+ updated.delete(event.executionId);
2082
+ return updated;
2083
+ });
2084
+ setStreamingLogs((prev) => {
2085
+ const updated = new Map(prev);
2086
+ updated.delete(event.executionId);
2087
+ return updated;
2088
+ });
2089
+ queryClient.invalidateQueries({
2090
+ queryKey: executionsKeys.executions(organizationId, resourceId)
2091
+ });
2092
+ queryClient.invalidateQueries({
2093
+ queryKey: executionsKeys.execution(organizationId, resourceId, event.executionId)
2094
+ });
2095
+ }
2096
+ break;
2097
+ case "log":
2098
+ if (event.executionId) {
2099
+ if (event.data?.log) {
2100
+ setStreamingLogs((prev) => {
2101
+ const updated = new Map(prev);
2102
+ const existing = updated.get(event.executionId) || [];
2103
+ updated.set(event.executionId, [...existing, event.data.log]);
2104
+ return updated;
2105
+ });
2106
+ }
2107
+ queryClient.invalidateQueries({
2108
+ queryKey: executionsKeys.execution(organizationId, resourceId, event.executionId)
2109
+ });
2110
+ }
2111
+ break;
2112
+ }
2113
+ } catch {
2114
+ }
2115
+ },
2116
+ [organizationId, resourceId, queryClient]
2117
+ );
2118
+ const { connected, error } = useSSEConnection({
2119
+ manager,
2120
+ connectionKey: `resource-${resourceId}`,
2121
+ url: sseUrl,
2122
+ enabled: !!resourceId && !!organizationId && isOrganizationReady,
2123
+ headers,
2124
+ onmessage: handleMessage,
2125
+ onopen: (response) => response.status === 403 ? "Organization access denied" : void 0
2126
+ });
2127
+ useEffect(() => {
2128
+ return () => {
2129
+ setLiveExecutions(/* @__PURE__ */ new Set());
2130
+ setStreamingLogs(/* @__PURE__ */ new Map());
2131
+ };
2132
+ }, [resourceId, organizationId, isOrganizationReady]);
2133
+ return {
2134
+ liveExecutions,
2135
+ connected,
2136
+ error,
2137
+ runningCount: liveExecutions.size,
2138
+ isLive: (executionId) => liveExecutions.has(executionId),
2139
+ streamingLogs
2140
+ };
2141
+ }
2142
+ function useExecutionPanelState({
2143
+ resourceId,
2144
+ manager,
2145
+ limit,
2146
+ onConnectionStatus
2147
+ }) {
2148
+ const queryClient = useQueryClient();
2149
+ const navigate = useNavigate();
2150
+ const { organizationId } = useElevasisServices();
2151
+ const [resourceStatusFilter, setResourceStatusFilter] = useState("all");
2152
+ const { data: executionsData, isLoading, isFetched } = useExecutions(resourceId, resourceStatusFilter, limit);
2153
+ const { liveExecutions, connected, runningCount, streamingLogs } = useExecutionLogSSE(resourceId, manager);
2154
+ const search = useSearch({ strict: false });
2155
+ const selectedId = search.exec;
2156
+ const setSelectedId = useCallback(
2157
+ (id) => {
2158
+ void navigate({
2159
+ to: ".",
2160
+ search: { exec: id },
2161
+ replace: true
2162
+ });
2163
+ },
2164
+ [navigate]
2165
+ );
2166
+ const executions = executionsData?.executions || [];
2167
+ const prevExecutionCountRef = useRef(0);
2168
+ const prevNewestIdRef = useRef(void 0);
2169
+ const prevResourceIdRef = useRef(resourceId);
2170
+ const hasInitializedRef = useRef(false);
2171
+ useEffect(() => {
2172
+ if (prevResourceIdRef.current !== resourceId) {
2173
+ setSelectedId(void 0);
2174
+ prevResourceIdRef.current = resourceId;
2175
+ hasInitializedRef.current = false;
2176
+ }
2177
+ }, [resourceId, setSelectedId]);
2178
+ useEffect(() => {
2179
+ if (organizationId) {
2180
+ queryClient.invalidateQueries({
2181
+ queryKey: [...executionsKeys.all, "execution"]
2182
+ });
2183
+ }
2184
+ }, [resourceId, queryClient, organizationId]);
2185
+ useEffect(() => {
2186
+ const sortedExecutions = [...executions].sort((a, b) => b.startTime - a.startTime);
2187
+ const newestExecution = sortedExecutions[0];
2188
+ if (!newestExecution) return;
2189
+ if (!hasInitializedRef.current) {
2190
+ hasInitializedRef.current = true;
2191
+ prevExecutionCountRef.current = executions.length;
2192
+ prevNewestIdRef.current = newestExecution.id;
2193
+ return;
2194
+ }
2195
+ const executionCountIncreased = executions.length > prevExecutionCountRef.current;
2196
+ const newestIdChanged = newestExecution.id !== prevNewestIdRef.current;
2197
+ if (executionCountIncreased && newestIdChanged && newestExecution.id !== selectedId) {
2198
+ setSelectedId(newestExecution.id);
2199
+ }
2200
+ prevExecutionCountRef.current = executions.length;
2201
+ prevNewestIdRef.current = newestExecution.id;
2202
+ }, [executions, selectedId, setSelectedId]);
2203
+ useEffect(() => {
2204
+ if (!isFetched) return;
2205
+ if (executions.length === 0) {
2206
+ setSelectedId(void 0);
2207
+ } else if (!selectedId && executions.length > 0) {
2208
+ const latest = [...executions].sort((a, b) => b.startTime - a.startTime)[0];
2209
+ setSelectedId(latest.id);
2210
+ }
2211
+ }, [executions, selectedId, setSelectedId, isFetched]);
2212
+ useEffect(() => {
2213
+ if (onConnectionStatus) {
2214
+ onConnectionStatus(connected, runningCount);
2215
+ }
2216
+ }, [connected, runningCount, onConnectionStatus]);
2217
+ return {
2218
+ executions,
2219
+ isLoading,
2220
+ isFetched,
2221
+ selectedId,
2222
+ setSelectedId,
2223
+ resourceStatusFilter,
2224
+ setResourceStatusFilter,
2225
+ liveExecutions,
2226
+ connected,
2227
+ runningCount,
2228
+ streamingLogs
2229
+ };
2230
+ }
2231
+
2232
+ // src/hooks/operations/shared/resourceDefinitionUtils.ts
2233
+ function isSessionCapable(type, resourceDefinition) {
2234
+ if (type !== "agent" || !resourceDefinition) {
2235
+ return false;
2236
+ }
2237
+ const config = resourceDefinition.config;
2238
+ return config.sessionCapable === true;
2239
+ }
2240
+ function useDeploymentDocs(selectedDeploymentId) {
2241
+ const { apiRequest, isReady: isOrganizationReady, organizationId } = useElevasisServices();
2242
+ const deploymentsQuery = useQuery({
2243
+ queryKey: ["deployments", organizationId],
2244
+ queryFn: async () => {
2245
+ const response = await apiRequest("/deployments");
2246
+ return response.deployments;
2247
+ },
2248
+ enabled: isOrganizationReady,
2249
+ staleTime: STALE_TIME_DEFAULT
2250
+ });
2251
+ const activeDeployments = useMemo(() => {
2252
+ if (!deploymentsQuery.data) return [];
2253
+ return deploymentsQuery.data.filter((d) => d.status === "active").sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
2254
+ }, [deploymentsQuery.data]);
2255
+ const activeDeployment = useMemo(() => {
2256
+ if (selectedDeploymentId) {
2257
+ return activeDeployments.find((d) => d.id === selectedDeploymentId) ?? activeDeployments[0] ?? null;
2258
+ }
2259
+ return activeDeployments[0] ?? null;
2260
+ }, [activeDeployments, selectedDeploymentId]);
2261
+ const deploymentId = activeDeployment?.id;
2262
+ const docsQuery = useQuery({
2263
+ queryKey: ["deployment-docs", deploymentId],
2264
+ queryFn: async () => {
2265
+ const response = await apiRequest(`/deployments/${deploymentId}/docs`);
2266
+ return response.files;
2267
+ },
2268
+ enabled: isOrganizationReady && !!deploymentId,
2269
+ staleTime: STALE_TIME_DEFAULT
2270
+ });
2271
+ return {
2272
+ files: docsQuery.data ?? [],
2273
+ isLoading: deploymentsQuery.isLoading || !!deploymentId && docsQuery.isLoading,
2274
+ error: deploymentsQuery.error || docsQuery.error,
2275
+ activeDeployment,
2276
+ activeDeployments
2277
+ };
2278
+ }
2279
+ function useCommandViewData() {
2280
+ const { apiRequest, organizationId, isReady } = useElevasisServices();
2281
+ return useQuery({
2282
+ queryKey: ["command-view", organizationId],
2283
+ queryFn: async () => {
2284
+ return apiRequest("/command-view");
2285
+ },
2286
+ enabled: isReady,
2287
+ staleTime: STALE_TIME_DEFAULT
2288
+ });
2289
+ }
2290
+ function useCommandViewStats(timeRange = "24h") {
2291
+ const { apiRequest, organizationId, isReady } = useElevasisServices();
2292
+ return useQuery({
2293
+ queryKey: ["command-view-stats", organizationId, timeRange],
2294
+ queryFn: async () => {
2295
+ return apiRequest(`/command-view/stats?timeRange=${timeRange}`);
2296
+ },
2297
+ enabled: isReady,
2298
+ staleTime: STALE_TIME_MONITORING
2299
+ });
2300
+ }
2301
+ var useCommandViewStore = create()(
2302
+ persist(
2303
+ (set) => ({
2304
+ statusFilter: "all",
2305
+ setStatusFilter: (statusFilter) => set({ statusFilter }),
2306
+ showIntegrations: true,
2307
+ setShowIntegrations: (showIntegrations) => set({ showIntegrations }),
2308
+ fitViewOnFilter: true,
2309
+ setFitViewOnFilter: (fitViewOnFilter) => set({ fitViewOnFilter }),
2310
+ selectedNodeId: null,
2311
+ setSelectedNodeId: (selectedNodeId) => set({ selectedNodeId })
2312
+ }),
2313
+ {
2314
+ name: "command-view-store",
2315
+ partialize: (s) => ({
2316
+ showIntegrations: s.showIntegrations,
2317
+ fitViewOnFilter: s.fitViewOnFilter
2318
+ })
2319
+ }
2320
+ )
2321
+ );
2322
+ function useCommandViewLayout(graph) {
2323
+ return useMemo(() => {
2324
+ const dagreGraph = new dagre.graphlib.Graph();
2325
+ dagreGraph.setDefaultEdgeLabel(() => ({}));
2326
+ dagreGraph.setGraph({
2327
+ rankdir: "LR",
2328
+ ranksep: GRAPH_CONSTANTS.RANK_SEP,
2329
+ nodesep: GRAPH_CONSTANTS.NODE_SEP,
2330
+ marginx: 50,
2331
+ marginy: 50,
2332
+ ranker: "longest-path"
2333
+ });
2334
+ graph.nodes.forEach((node) => {
2335
+ dagreGraph.setNode(node.id, {
2336
+ width: GRAPH_CONSTANTS.NODE_WIDTH,
2337
+ height: GRAPH_CONSTANTS.NODE_HEIGHT
2338
+ });
2339
+ });
2340
+ graph.edges.forEach((edge) => {
2341
+ dagreGraph.setEdge(edge.source, edge.target);
2342
+ });
2343
+ dagre.layout(dagreGraph);
2344
+ const nodePositions = /* @__PURE__ */ new Map();
2345
+ const nodeNames = /* @__PURE__ */ new Map();
2346
+ graph.nodes.forEach((node) => {
2347
+ const dagreNode = dagreGraph.node(node.id);
2348
+ nodePositions.set(node.id, { x: dagreNode.x, y: dagreNode.y });
2349
+ nodeNames.set(node.id, node.name);
2350
+ });
2351
+ const parent = /* @__PURE__ */ new Map();
2352
+ graph.nodes.forEach((node) => parent.set(node.id, node.id));
2353
+ const find = (id) => {
2354
+ if (parent.get(id) !== id) {
2355
+ parent.set(id, find(parent.get(id)));
2356
+ }
2357
+ return parent.get(id);
2358
+ };
2359
+ const union = (a, b) => {
2360
+ const rootA = find(a);
2361
+ const rootB = find(b);
2362
+ if (rootA !== rootB) {
2363
+ parent.set(rootA, rootB);
2364
+ }
2365
+ };
2366
+ graph.edges.forEach((edge) => {
2367
+ if (edge.relationship === "triggers" || edge.relationship === "approval") {
2368
+ union(edge.source, edge.target);
2369
+ }
2370
+ });
2371
+ const components = /* @__PURE__ */ new Map();
2372
+ graph.nodes.forEach((node) => {
2373
+ const root = find(node.id);
2374
+ const existing = components.get(root) || [];
2375
+ existing.push(node.id);
2376
+ components.set(root, existing);
2377
+ });
2378
+ const getMinPrefix = (nodeIds) => {
2379
+ let minPrefix = "";
2380
+ for (const id of nodeIds) {
2381
+ const name = nodeNames.get(id) || "";
2382
+ const prefix = name.match(/^([A-Z]+-\d+)/)?.[1];
2383
+ if (prefix && (!minPrefix || prefix.localeCompare(minPrefix) < 0)) {
2384
+ minPrefix = prefix;
2385
+ }
2386
+ }
2387
+ return minPrefix || nodeNames.get(nodeIds[0]) || "";
2388
+ };
2389
+ const sortedComponents = Array.from(components.values()).sort((a, b) => {
2390
+ return getMinPrefix(a).localeCompare(getMinPrefix(b));
2391
+ });
2392
+ const chains = sortedComponents.filter((c) => c.length > 1);
2393
+ const orphans = sortedComponents.filter((c) => c.length === 1);
2394
+ const componentYOffsets = /* @__PURE__ */ new Map();
2395
+ let currentY = 0;
2396
+ for (const nodeIds of chains) {
2397
+ let minY = Infinity;
2398
+ let maxY = -Infinity;
2399
+ for (const id of nodeIds) {
2400
+ const pos = nodePositions.get(id);
2401
+ minY = Math.min(minY, pos.y);
2402
+ maxY = Math.max(maxY, pos.y);
2403
+ }
2404
+ const offset = currentY - minY + 50;
2405
+ for (const id of nodeIds) {
2406
+ componentYOffsets.set(id, offset);
2407
+ }
2408
+ currentY = currentY + (maxY - minY) + GRAPH_CONSTANTS.NODE_HEIGHT + 80;
2409
+ }
2410
+ if (orphans.length > 0) {
2411
+ const longestChainDepth = chains.length > 0 ? Math.max(
2412
+ ...chains.map((chain) => {
2413
+ const xValues = new Set(chain.map((id) => Math.round(nodePositions.get(id).x)));
2414
+ return xValues.size;
2415
+ })
2416
+ ) : 0;
2417
+ const ORPHAN_COLS = Math.max(5, longestChainDepth + Math.floor(longestChainDepth / 4));
2418
+ const cellW = GRAPH_CONSTANTS.NODE_WIDTH + GRAPH_CONSTANTS.NODE_SEP;
2419
+ const cellH = GRAPH_CONSTANTS.NODE_HEIGHT + GRAPH_CONSTANTS.NODE_SEP;
2420
+ const gridStartY = currentY + 50;
2421
+ orphans.forEach((nodeIds, i) => {
2422
+ const id = nodeIds[0];
2423
+ const col = i % ORPHAN_COLS;
2424
+ const row = Math.floor(i / ORPHAN_COLS);
2425
+ nodePositions.set(id, {
2426
+ x: col * cellW + GRAPH_CONSTANTS.NODE_WIDTH / 2,
2427
+ y: gridStartY + row * cellH + GRAPH_CONSTANTS.NODE_HEIGHT / 2
2428
+ });
2429
+ componentYOffsets.set(id, 0);
2430
+ });
2431
+ }
2432
+ const nodes = graph.nodes.map((node) => {
2433
+ const pos = nodePositions.get(node.id);
2434
+ const yOffset = componentYOffsets.get(node.id) || 0;
2435
+ return {
2436
+ id: node.id,
2437
+ type: "commandView",
2438
+ position: {
2439
+ x: pos.x - GRAPH_CONSTANTS.NODE_WIDTH / 2,
2440
+ y: pos.y + yOffset - GRAPH_CONSTANTS.NODE_HEIGHT / 2
2441
+ },
2442
+ data: node
2443
+ };
2444
+ });
2445
+ const edgesBySource = /* @__PURE__ */ new Map();
2446
+ graph.edges.forEach((edge) => {
2447
+ const existing = edgesBySource.get(edge.source) || [];
2448
+ existing.push(edge);
2449
+ edgesBySource.set(edge.source, existing);
2450
+ });
2451
+ const edges = graph.edges.map((edge) => {
2452
+ const sourceEdges = edgesBySource.get(edge.source) || [];
2453
+ const edgeIndex = sourceEdges.indexOf(edge);
2454
+ const totalEdges = sourceEdges.length;
2455
+ return {
2456
+ id: edge.id,
2457
+ source: edge.source,
2458
+ target: edge.target,
2459
+ type: "commandView",
2460
+ data: {
2461
+ relationship: edge.relationship,
2462
+ label: edge.label,
2463
+ edgeIndex,
2464
+ totalEdges
2465
+ }
2466
+ };
2467
+ });
2468
+ return { nodes, edges };
2469
+ }, [graph]);
2470
+ }
2471
+ function useGraphStats(graph) {
2472
+ return useMemo(() => {
2473
+ const stats = {
2474
+ agents: 0,
2475
+ workflows: 0,
2476
+ integrations: 0,
2477
+ triggers: 0,
2478
+ prodResources: 0,
2479
+ devResources: 0,
2480
+ connectedIntegrations: 0,
2481
+ errorIntegrations: 0
2482
+ };
2483
+ for (const node of graph.nodes) {
2484
+ switch (node.type) {
2485
+ case "agent":
2486
+ stats.agents++;
2487
+ break;
2488
+ case "workflow":
2489
+ stats.workflows++;
2490
+ break;
2491
+ case "integration":
2492
+ stats.integrations++;
2493
+ if (node.connectionStatus === "connected") stats.connectedIntegrations++;
2494
+ if (node.connectionStatus === "error") stats.errorIntegrations++;
2495
+ break;
2496
+ case "trigger":
2497
+ stats.triggers++;
2498
+ break;
2499
+ }
2500
+ if (node.status === "prod") stats.prodResources++;
2501
+ if (node.status === "dev") stats.devResources++;
2502
+ }
2503
+ return stats;
2504
+ }, [graph]);
2505
+ }
2506
+ function useCheckpointTasks({ checkpointId, enabled = true }) {
2507
+ const { apiRequest, organizationId, isReady } = useElevasisServices();
2508
+ return useQuery({
2509
+ queryKey: ["checkpoint-tasks", organizationId, checkpointId],
2510
+ queryFn: async () => {
2511
+ return apiRequest(
2512
+ `/command-queue?humanCheckpoint=${checkpointId}&status=pending&limit=10`
2513
+ );
2514
+ },
2515
+ // Only fetch when: org ready, checkpoint selected, and enabled
2516
+ enabled: isReady && !!checkpointId && enabled,
2517
+ staleTime: STALE_TIME_MONITORING
2518
+ });
2519
+ }
2520
+ function useResourceErrors({ resourceId, timeRange, hasFailures }) {
2521
+ const { apiRequest, organizationId, isReady } = useElevasisServices();
2522
+ return useQuery({
2523
+ queryKey: ["resource-errors", organizationId, resourceId, timeRange],
2524
+ queryFn: async () => {
2525
+ return apiRequest(
2526
+ `/command-view/resource-errors?resourceId=${resourceId}&timeRange=${timeRange}`
2527
+ );
2528
+ },
2529
+ // Only fetch when: org ready, resource selected, and resource has failures
2530
+ enabled: isReady && !!resourceId && hasFailures,
2531
+ staleTime: STALE_TIME_ADMIN
2532
+ });
2533
+ }
2534
+ function useResourceExecutions({ resourceId, timeRange, enabled = true }) {
2535
+ const { apiRequest, organizationId, isReady } = useElevasisServices();
2536
+ return useQuery({
2537
+ queryKey: ["resource-executions", organizationId, resourceId, timeRange],
2538
+ queryFn: async () => {
2539
+ return apiRequest(
2540
+ `/command-view/resource-executions?resourceId=${resourceId}&timeRange=${timeRange}`
2541
+ );
2542
+ },
2543
+ // Only fetch when: org ready, resource selected, and enabled
2544
+ enabled: isReady && !!resourceId && enabled,
2545
+ staleTime: STALE_TIME_MONITORING
2546
+ });
2547
+ }
2548
+
2549
+ export { CredentialNameSchema, OperationsService, UuidSchema, createUseFeatureAccess, executionsKeys, isSessionCapable, operationsKeys, scheduleKeys, sessionsKeys, sortData, useActivities, useActivityTrend, useArchiveSession, useBatchDelete, useBatchedResourcesHealth, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCheckpointTasks, useCommandQueue, useCommandQueueTotals, useCommandViewData, useCommandViewLayout, useCommandViewStats, useCommandViewStore, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useCreateSession, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useDeleteSession, useDeleteTask, useDeploymentDocs, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogSSE, useExecutionLogs, useExecutionPanelState, useExecutions, useGetExecutionHistory, useGetSchedule, useGraphStats, useListSchedules, useMarkAllAsRead, useMarkAsRead, useNotificationCount, useNotifications, usePaginationState, usePatchTask, usePauseSchedule, useRecentExecutionsByResource, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResourceErrors, useResourceExecutions, useResources, useResourcesHealth, useResumeSchedule, useRetryExecution, useSSEConnection, useScheduledTasks, useSession, useSessionExecution, useSessionExecutions, useSessionMessages, useSessionWebSocket, useSessions, useSortedData, useSubmitAction, useSuccessNotification, useTableSelection, useTableSort, useTestNotification, useTopFailingResources, useUnresolveError, useUnresolvedErrors, useUpdateAnchor, useUpdateSchedule, useWarningNotification };