@elevasis/ui 2.75.0 → 2.77.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 (110) hide show
  1. package/dist/api/index.js +3 -3
  2. package/dist/app/index.d.ts +277 -249
  3. package/dist/app/index.js +12 -11
  4. package/dist/auth/context.d.ts +1 -2
  5. package/dist/auth/index.d.ts +1 -2
  6. package/dist/auth/index.js +6 -7
  7. package/dist/charts/index.js +6 -7
  8. package/dist/{chunk-CRPH5AAB.js → chunk-2GIHWU5O.js} +4 -3
  9. package/dist/chunk-2Y6AKWGU.js +42 -0
  10. package/dist/chunk-3QYRZSHP.js +854 -0
  11. package/dist/{chunk-L3NBMLRN.js → chunk-3RK2NNJX.js} +1 -1
  12. package/dist/{chunk-R6NMRXNO.js → chunk-4WLAVUPS.js} +1 -1
  13. package/dist/{chunk-DTEGVSJ6.js → chunk-5R4I2PAN.js} +9 -43
  14. package/dist/chunk-6B4ZPBQJ.js +7 -0
  15. package/dist/{chunk-QFS2GZMV.js → chunk-73G3I5HJ.js} +160 -160
  16. package/dist/{chunk-7OOFMEX6.js → chunk-BFLYDVEN.js} +28 -41
  17. package/dist/{chunk-VWGCURZF.js → chunk-BG6PWDJ3.js} +381 -381
  18. package/dist/{chunk-5VF5LPYS.js → chunk-BV2RNLPP.js} +1 -1
  19. package/dist/{chunk-NMHQAYZU.js → chunk-CTT4RDXE.js} +150 -151
  20. package/dist/chunk-E2LJ3FRA.js +237 -0
  21. package/dist/{chunk-5RH6NYZH.js → chunk-EFQLXRYT.js} +1 -2
  22. package/dist/{chunk-M6VAZAQW.js → chunk-EVNLJHDD.js} +3 -3
  23. package/dist/{chunk-NYIIRZSA.js → chunk-GDQQX5SL.js} +4 -42
  24. package/dist/{chunk-IYATYH5I.js → chunk-GFSOQH3N.js} +1 -1
  25. package/dist/{chunk-G7O4CBMC.js → chunk-H5AEYSVX.js} +164 -3
  26. package/dist/{chunk-ZFISGKYW.js → chunk-IIEZXXDD.js} +1 -1
  27. package/dist/{chunk-5SLRGUC4.js → chunk-INCEZAM3.js} +1 -1
  28. package/dist/{chunk-ZG6YJUT4.js → chunk-JZQNUQE4.js} +1 -1
  29. package/dist/{chunk-SB3IHM5Y.js → chunk-K55TU6CC.js} +2023 -1700
  30. package/dist/chunk-KB5CAN5D.js +33 -0
  31. package/dist/{chunk-OGHTJKBV.js → chunk-KMA4FOSV.js} +5682 -5675
  32. package/dist/{chunk-ICHDIVQO.js → chunk-KXNRTJAE.js} +1 -1
  33. package/dist/{chunk-MLHZUN2X.js → chunk-MGAELVTZ.js} +12 -12
  34. package/dist/chunk-MKH2KOAO.js +39 -0
  35. package/dist/{chunk-6BJ5HMMC.js → chunk-NAPXMYFW.js} +35 -362
  36. package/dist/{chunk-GDTK33QT.js → chunk-OGG3QJYW.js} +14 -5
  37. package/dist/{chunk-SN7X5N2A.js → chunk-P6HHXMLJ.js} +1 -1
  38. package/dist/{chunk-SEYOVNS5.js → chunk-QAILYRC2.js} +1 -1
  39. package/dist/{chunk-RBGVNPA6.js → chunk-RXZ3XDBM.js} +1 -1
  40. package/dist/{chunk-2ZRY3ARL.js → chunk-SPW6UA6B.js} +1 -1
  41. package/dist/{chunk-3H5DIJN7.js → chunk-SVZR4GYA.js} +1 -1
  42. package/dist/{chunk-47YJVIZE.js → chunk-UEY4AB3R.js} +789 -66
  43. package/dist/{chunk-LFLM723H.js → chunk-UL6MPMKY.js} +1 -1
  44. package/dist/{chunk-TX3UHDL5.js → chunk-WELN7DDV.js} +2 -2
  45. package/dist/{chunk-D3XXPCCK.js → chunk-WJN2VVVJ.js} +1 -1
  46. package/dist/{chunk-DMSTDZCJ.js → chunk-XODQUPFW.js} +11 -11
  47. package/dist/components/index.d.ts +135 -25
  48. package/dist/components/index.js +2165 -1996
  49. package/dist/components/navigation/index.js +7 -8
  50. package/dist/features/auth/index.d.ts +35 -3716
  51. package/dist/features/auth/index.js +9 -10
  52. package/dist/features/clients/index.js +18 -12
  53. package/dist/features/content/index.js +27 -27
  54. package/dist/features/crm/index.css +59 -59
  55. package/dist/features/crm/index.d.ts +17 -1
  56. package/dist/features/crm/index.js +13 -11
  57. package/dist/features/dashboard/index.css +59 -59
  58. package/dist/features/dashboard/index.js +8 -9
  59. package/dist/features/delivery/index.d.ts +3 -0
  60. package/dist/features/delivery/index.js +21 -20
  61. package/dist/features/knowledge/index.js +6 -7
  62. package/dist/features/lead-gen/index.css +59 -59
  63. package/dist/features/lead-gen/index.d.ts +3921 -4
  64. package/dist/features/lead-gen/index.js +15 -13
  65. package/dist/features/monitoring/index.js +10 -11
  66. package/dist/features/monitoring/requests/index.css +59 -59
  67. package/dist/features/monitoring/requests/index.js +8 -9
  68. package/dist/features/notes/index.js +4 -4
  69. package/dist/features/operations/index.css +59 -59
  70. package/dist/features/operations/index.js +13 -15
  71. package/dist/features/seo/index.css +659 -0
  72. package/dist/features/seo/index.d.ts +3979 -1
  73. package/dist/features/seo/index.js +31 -2
  74. package/dist/features/settings/index.css +59 -59
  75. package/dist/features/settings/index.d.ts +96 -3742
  76. package/dist/features/settings/index.js +10 -12
  77. package/dist/hooks/access/index.js +6 -7
  78. package/dist/hooks/delivery/index.css +59 -59
  79. package/dist/hooks/delivery/index.d.ts +12 -4
  80. package/dist/hooks/delivery/index.js +3 -3
  81. package/dist/hooks/published.d.ts +83 -29
  82. package/dist/hooks/published.js +19 -19
  83. package/dist/initialization/index.d.ts +35 -3716
  84. package/dist/knowledge/index.js +11 -11
  85. package/dist/layout/index.d.ts +55 -2
  86. package/dist/layout/index.js +10 -10
  87. package/dist/organization/index.css +59 -59
  88. package/dist/organization/index.d.ts +20 -4
  89. package/dist/profile/index.d.ts +81 -3716
  90. package/dist/provider/ElevasisServiceContext.d.ts +1 -2
  91. package/dist/provider/index.d.ts +4 -2
  92. package/dist/provider/index.js +6 -7
  93. package/dist/provider/published.d.ts +4 -2
  94. package/dist/provider/published.js +6 -7
  95. package/dist/test-utils/index.d.ts +1 -2
  96. package/dist/test-utils/index.js +3 -3
  97. package/dist/theme/index.js +3 -3
  98. package/dist/theme/presets/index.js +1 -1
  99. package/dist/types/index.d.ts +298 -251
  100. package/dist/utils/index.d.ts +1 -1
  101. package/dist/utils/index.js +1 -1
  102. package/package.json +4 -8
  103. package/src/hooks/README.md +22 -23
  104. package/dist/chunk-6ZAP3FOA.js +0 -93
  105. package/dist/chunk-AH52XQB7.js +0 -1
  106. package/dist/chunk-DVAOCHIF.js +0 -165
  107. package/dist/chunk-MISHPEJX.js +0 -244
  108. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +0 -879
  109. package/dist/hooks/operations/command-view/utils/transformCommandViewData.js +0 -2
  110. /package/dist/{chunk-A2SB32YV.js → chunk-5ZK7K7YP.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { useOptionalElevasisSystems } from './chunk-SB3IHM5Y.js';
1
+ import { useOptionalElevasisSystems } from './chunk-K55TU6CC.js';
2
2
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
3
3
  import { useMemo } from 'react';
4
4
 
@@ -1,148 +1,49 @@
1
1
  import { createLiveTempMessageIdentity } from './chunk-QFGNRKIE.js';
2
- import { sessionsKeys } from './chunk-SB3IHM5Y.js';
3
- import { SessionIdParamSchema, WebSocketSessionTurnSchema, ExecutionIdParamsSchema } from './chunk-2GIJBHZT.js';
2
+ import { sessionsKeys, isExecutionInFlight } from './chunk-K55TU6CC.js';
3
+ import { SessionIdParamSchema, ExecutionIdParamsSchema, WebSocketSessionTurnSchema } from './chunk-2GIJBHZT.js';
4
4
  import { useOrganization } from './chunk-DD3CCMCZ.js';
5
- import { STALE_TIME_MONITORING, STALE_TIME_DEFAULT } from './chunk-A2SB32YV.js';
6
- import { WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, REFETCH_INTERVAL_RUNNING } from './chunk-Y6I3IC45.js';
5
+ import { STALE_TIME_MONITORING, STALE_TIME_DEFAULT } from './chunk-5ZK7K7YP.js';
6
+ import { REFETCH_INTERVAL_RUNNING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY } from './chunk-Y6I3IC45.js';
7
7
  import { useElevasisServices } from './chunk-BI5VDO2K.js';
8
8
  import { useAuthContext } from './chunk-BRJ3QZ4E.js';
9
9
  import { useQuery, useQueryClient } from '@tanstack/react-query';
10
+ import { useState, useRef, useCallback, useEffect } from 'react';
10
11
  import { create } from 'zustand';
11
12
  import { persist } from 'zustand/middleware';
12
- import { useState, useRef, useCallback, useEffect } from 'react';
13
13
 
14
- function useCommandViewStats(timeRange = "30d", options) {
15
- const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
16
- return useQuery({
17
- queryKey: ["command-view-stats", workOSOrganizationId, timeRange],
18
- queryFn: async () => {
19
- return apiRequest(`/command-view/stats?timeRange=${timeRange}`);
20
- },
21
- enabled: isReady && (options?.enabled ?? true),
22
- staleTime: STALE_TIME_MONITORING
23
- });
24
- }
25
- function useCheckpointTasks({ checkpointId, enabled = true }) {
26
- const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
14
+ function useSessionExecutions(sessionId) {
15
+ const { apiRequest, isReady } = useElevasisServices();
16
+ const { currentSupabaseOrganizationId } = useOrganization();
27
17
  return useQuery({
28
- queryKey: ["checkpoint-tasks", workOSOrganizationId, checkpointId],
18
+ queryKey: sessionsKeys.executions(currentSupabaseOrganizationId, sessionId),
29
19
  queryFn: async () => {
30
- return apiRequest(
31
- `/command-queue?humanCheckpoint=${checkpointId}&status=pending&limit=10`
32
- );
20
+ SessionIdParamSchema.parse({ sessionId });
21
+ return apiRequest(`/sessions/${sessionId}/executions`, {
22
+ method: "GET"
23
+ });
33
24
  },
34
- // Only fetch when: org ready, checkpoint selected, and enabled
35
- enabled: isReady && !!checkpointId && enabled,
36
- staleTime: STALE_TIME_MONITORING
25
+ enabled: isReady && !!sessionId,
26
+ staleTime: 0
37
27
  });
38
28
  }
39
- function useResourceExecutions({
40
- resourceId,
41
- timeRange,
42
- page = 1,
43
- limit = 10,
44
- enabled = true
45
- }) {
46
- const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
29
+ function useSessionExecution(sessionId, executionId) {
30
+ const { apiRequest, isReady } = useElevasisServices();
31
+ const { currentSupabaseOrganizationId } = useOrganization();
47
32
  return useQuery({
48
- queryKey: ["resource-executions", workOSOrganizationId, resourceId, timeRange, page, limit],
33
+ queryKey: sessionsKeys.execution(currentSupabaseOrganizationId, sessionId, executionId),
49
34
  queryFn: async () => {
50
- return apiRequest(
51
- `/command-view/resource-executions?resourceId=${resourceId}&timeRange=${timeRange}&page=${page}&limit=${limit}`
52
- );
35
+ ExecutionIdParamsSchema.parse({ sessionId, executionId });
36
+ return apiRequest(`/sessions/${sessionId}/executions/${executionId}`, {
37
+ method: "GET"
38
+ });
53
39
  },
54
- // Only fetch when: org ready, resource selected, and enabled
55
- enabled: isReady && !!resourceId && enabled,
56
- staleTime: STALE_TIME_MONITORING
40
+ enabled: isReady && !!sessionId && !!executionId,
41
+ refetchInterval: (query) => {
42
+ const data = query.state.data;
43
+ return isExecutionInFlight(data?.status) ? REFETCH_INTERVAL_RUNNING : false;
44
+ }
57
45
  });
58
46
  }
59
- var NEW_SESSION_VISUALIZATION_MODE = "explore";
60
- var LEGACY_VISUALIZATION_MODES = /* @__PURE__ */ new Set(["overview", "cluster", "swimlane", "focus", "network", "force"]);
61
- function normalizePersistedVisualizationMode(value) {
62
- if (value === "explore") return "explore";
63
- if (LEGACY_VISUALIZATION_MODES.has(String(value))) return NEW_SESSION_VISUALIZATION_MODE;
64
- return NEW_SESSION_VISUALIZATION_MODE;
65
- }
66
- var DEFAULT_DIAGNOSTIC_CATEGORIES = ["diagnostic", "testing"];
67
- var useCommandViewStore = create()(
68
- persist(
69
- (set) => ({
70
- statusFilter: "all",
71
- setStatusFilter: (statusFilter) => set({ statusFilter }),
72
- showIntegrations: true,
73
- setShowIntegrations: (showIntegrations) => set({ showIntegrations }),
74
- fitViewOnFilter: true,
75
- setFitViewOnFilter: (fitViewOnFilter) => set({ fitViewOnFilter }),
76
- // New sessions default to 'explore'; returning sessions get their stored mode via persist.
77
- visualizationMode: NEW_SESSION_VISUALIZATION_MODE,
78
- setVisualizationMode: (visualizationMode) => set({ visualizationMode, lastUsedVisualizationMode: visualizationMode }),
79
- lastUsedVisualizationMode: null,
80
- lastOpenBottomTab: null,
81
- setLastOpenBottomTab: (lastOpenBottomTab) => set({ lastOpenBottomTab }),
82
- selectedNodeId: null,
83
- setSelectedNodeId: (selectedNodeId) => set({ selectedNodeId }),
84
- resourcesHidden: true,
85
- setResourcesHidden: (resourcesHidden) => set({ resourcesHidden, hasVisibilityInteraction: true }),
86
- diagnosticsHidden: true,
87
- setDiagnosticsHidden: (diagnosticsHidden) => set({ diagnosticsHidden, hasVisibilityInteraction: true }),
88
- diagnosticCategories: DEFAULT_DIAGNOSTIC_CATEGORIES,
89
- revealedIds: /* @__PURE__ */ new Set(),
90
- setRevealedIds: (ids) => set({ revealedIds: new Set(ids) }),
91
- clearRevealedIds: () => set({ revealedIds: /* @__PURE__ */ new Set() }),
92
- hasVisibilityInteraction: false,
93
- markVisibilityInteraction: () => set({ hasVisibilityInteraction: true }),
94
- resetVisibilityInteraction: () => set({ hasVisibilityInteraction: false }),
95
- expandedClusterDomains: [],
96
- toggleClusterDomain: (domain) => set((s) => ({
97
- expandedClusterDomains: s.expandedClusterDomains.includes(domain) ? s.expandedClusterDomains.filter((d) => d !== domain) : [...s.expandedClusterDomains, domain]
98
- })),
99
- setExpandedClusterDomains: (expandedClusterDomains) => set({ expandedClusterDomains }),
100
- expandedNodeIdsArray: [],
101
- expandedNodeIds: /* @__PURE__ */ new Set(),
102
- toggleNodeExpansion: (nodeId) => set((s) => {
103
- const currentSet = s.expandedNodeIds;
104
- const isCurrentlyExpanded = currentSet.has(nodeId);
105
- if (isCurrentlyExpanded) {
106
- const next2 = new Set(currentSet);
107
- next2.delete(nodeId);
108
- const nextArray2 = [...next2];
109
- return { expandedNodeIdsArray: nextArray2, expandedNodeIds: next2 };
110
- }
111
- const next = new Set(currentSet);
112
- next.add(nodeId);
113
- const nextArray = [...next];
114
- return { expandedNodeIdsArray: nextArray, expandedNodeIds: next };
115
- }),
116
- clearExpandedNodes: () => set({ expandedNodeIdsArray: [], expandedNodeIds: /* @__PURE__ */ new Set() })
117
- }),
118
- {
119
- name: "command-view-store",
120
- partialize: (s) => ({
121
- showIntegrations: s.showIntegrations,
122
- fitViewOnFilter: s.fitViewOnFilter,
123
- visualizationMode: s.visualizationMode,
124
- lastUsedVisualizationMode: s.lastUsedVisualizationMode,
125
- resourcesHidden: s.resourcesHidden,
126
- diagnosticsHidden: s.diagnosticsHidden,
127
- lastOpenBottomTab: s.lastOpenBottomTab,
128
- expandedClusterDomains: s.expandedClusterDomains
129
- }),
130
- // Guard against stale localStorage with an invalid mode name (e.g. old 'overview' → 'explore' rename).
131
- merge: (persisted, current) => {
132
- const stored = persisted;
133
- const storedMode = stored.visualizationMode;
134
- const storedLastUsed = stored.lastUsedVisualizationMode;
135
- const { expandedZonesArray: _dropped, ...restStored } = stored;
136
- return {
137
- ...current,
138
- ...restStored,
139
- visualizationMode: normalizePersistedVisualizationMode(storedMode),
140
- lastUsedVisualizationMode: storedLastUsed === null || storedLastUsed === void 0 ? current.lastUsedVisualizationMode : normalizePersistedVisualizationMode(storedLastUsed)
141
- };
142
- }
143
- }
144
- )
145
- );
146
47
  function useSessionMessages(sessionId) {
147
48
  const { apiRequest, isReady } = useElevasisServices();
148
49
  const { currentSupabaseOrganizationId } = useOrganization();
@@ -388,38 +289,136 @@ function useSessionWebSocket(sessionId, apiUrl) {
388
289
  lastTokenUsage
389
290
  };
390
291
  }
391
- function useSessionExecutions(sessionId) {
392
- const { apiRequest, isReady } = useElevasisServices();
393
- const { currentSupabaseOrganizationId } = useOrganization();
292
+ var NEW_SESSION_VISUALIZATION_MODE = "explore";
293
+ var LEGACY_VISUALIZATION_MODES = /* @__PURE__ */ new Set(["overview", "cluster", "swimlane", "focus", "network", "force"]);
294
+ function normalizePersistedVisualizationMode(value) {
295
+ if (value === "explore") return "explore";
296
+ if (LEGACY_VISUALIZATION_MODES.has(String(value))) return NEW_SESSION_VISUALIZATION_MODE;
297
+ return NEW_SESSION_VISUALIZATION_MODE;
298
+ }
299
+ var DEFAULT_DIAGNOSTIC_CATEGORIES = ["diagnostic", "testing"];
300
+ var useCommandViewStore = create()(
301
+ persist(
302
+ (set) => ({
303
+ statusFilter: "all",
304
+ setStatusFilter: (statusFilter) => set({ statusFilter }),
305
+ showIntegrations: true,
306
+ setShowIntegrations: (showIntegrations) => set({ showIntegrations }),
307
+ fitViewOnFilter: true,
308
+ setFitViewOnFilter: (fitViewOnFilter) => set({ fitViewOnFilter }),
309
+ // New sessions default to 'explore'; returning sessions get their stored mode via persist.
310
+ visualizationMode: NEW_SESSION_VISUALIZATION_MODE,
311
+ setVisualizationMode: (visualizationMode) => set({ visualizationMode, lastUsedVisualizationMode: visualizationMode }),
312
+ lastUsedVisualizationMode: null,
313
+ lastOpenBottomTab: null,
314
+ setLastOpenBottomTab: (lastOpenBottomTab) => set({ lastOpenBottomTab }),
315
+ selectedNodeId: null,
316
+ setSelectedNodeId: (selectedNodeId) => set({ selectedNodeId }),
317
+ resourcesHidden: true,
318
+ setResourcesHidden: (resourcesHidden) => set({ resourcesHidden, hasVisibilityInteraction: true }),
319
+ diagnosticsHidden: true,
320
+ setDiagnosticsHidden: (diagnosticsHidden) => set({ diagnosticsHidden, hasVisibilityInteraction: true }),
321
+ diagnosticCategories: DEFAULT_DIAGNOSTIC_CATEGORIES,
322
+ revealedIds: /* @__PURE__ */ new Set(),
323
+ setRevealedIds: (ids) => set({ revealedIds: new Set(ids) }),
324
+ clearRevealedIds: () => set({ revealedIds: /* @__PURE__ */ new Set() }),
325
+ hasVisibilityInteraction: false,
326
+ markVisibilityInteraction: () => set({ hasVisibilityInteraction: true }),
327
+ resetVisibilityInteraction: () => set({ hasVisibilityInteraction: false }),
328
+ expandedClusterDomains: [],
329
+ toggleClusterDomain: (domain) => set((s) => ({
330
+ expandedClusterDomains: s.expandedClusterDomains.includes(domain) ? s.expandedClusterDomains.filter((d) => d !== domain) : [...s.expandedClusterDomains, domain]
331
+ })),
332
+ setExpandedClusterDomains: (expandedClusterDomains) => set({ expandedClusterDomains }),
333
+ expandedNodeIdsArray: [],
334
+ expandedNodeIds: /* @__PURE__ */ new Set(),
335
+ toggleNodeExpansion: (nodeId) => set((s) => {
336
+ const currentSet = s.expandedNodeIds;
337
+ const isCurrentlyExpanded = currentSet.has(nodeId);
338
+ if (isCurrentlyExpanded) {
339
+ const next2 = new Set(currentSet);
340
+ next2.delete(nodeId);
341
+ const nextArray2 = [...next2];
342
+ return { expandedNodeIdsArray: nextArray2, expandedNodeIds: next2 };
343
+ }
344
+ const next = new Set(currentSet);
345
+ next.add(nodeId);
346
+ const nextArray = [...next];
347
+ return { expandedNodeIdsArray: nextArray, expandedNodeIds: next };
348
+ }),
349
+ clearExpandedNodes: () => set({ expandedNodeIdsArray: [], expandedNodeIds: /* @__PURE__ */ new Set() })
350
+ }),
351
+ {
352
+ name: "command-view-store",
353
+ partialize: (s) => ({
354
+ showIntegrations: s.showIntegrations,
355
+ fitViewOnFilter: s.fitViewOnFilter,
356
+ visualizationMode: s.visualizationMode,
357
+ lastUsedVisualizationMode: s.lastUsedVisualizationMode,
358
+ resourcesHidden: s.resourcesHidden,
359
+ diagnosticsHidden: s.diagnosticsHidden,
360
+ lastOpenBottomTab: s.lastOpenBottomTab,
361
+ expandedClusterDomains: s.expandedClusterDomains
362
+ }),
363
+ // Guard against stale localStorage with an invalid mode name (e.g. old 'overview' → 'explore' rename).
364
+ merge: (persisted, current) => {
365
+ const stored = persisted;
366
+ const storedMode = stored.visualizationMode;
367
+ const storedLastUsed = stored.lastUsedVisualizationMode;
368
+ const { expandedZonesArray: _dropped, ...restStored } = stored;
369
+ return {
370
+ ...current,
371
+ ...restStored,
372
+ visualizationMode: normalizePersistedVisualizationMode(storedMode),
373
+ lastUsedVisualizationMode: storedLastUsed === null || storedLastUsed === void 0 ? current.lastUsedVisualizationMode : normalizePersistedVisualizationMode(storedLastUsed)
374
+ };
375
+ }
376
+ }
377
+ )
378
+ );
379
+ function useCommandViewStats(timeRange = "30d", options) {
380
+ const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
394
381
  return useQuery({
395
- queryKey: sessionsKeys.executions(currentSupabaseOrganizationId, sessionId),
382
+ queryKey: ["command-view-stats", workOSOrganizationId, timeRange],
396
383
  queryFn: async () => {
397
- SessionIdParamSchema.parse({ sessionId });
398
- return apiRequest(`/sessions/${sessionId}/executions`, {
399
- method: "GET"
400
- });
384
+ return apiRequest(`/command-view/stats?timeRange=${timeRange}`);
401
385
  },
402
- enabled: isReady && !!sessionId,
403
- staleTime: 0
386
+ enabled: isReady && (options?.enabled ?? true),
387
+ staleTime: STALE_TIME_MONITORING
404
388
  });
405
389
  }
406
- function useSessionExecution(sessionId, executionId) {
407
- const { apiRequest, isReady } = useElevasisServices();
408
- const { currentSupabaseOrganizationId } = useOrganization();
390
+ function useCheckpointTasks({ checkpointId, enabled = true }) {
391
+ const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
409
392
  return useQuery({
410
- queryKey: sessionsKeys.execution(currentSupabaseOrganizationId, sessionId, executionId),
393
+ queryKey: ["checkpoint-tasks", workOSOrganizationId, checkpointId],
411
394
  queryFn: async () => {
412
- ExecutionIdParamsSchema.parse({ sessionId, executionId });
413
- return apiRequest(`/sessions/${sessionId}/executions/${executionId}`, {
414
- method: "GET"
415
- });
395
+ return apiRequest(
396
+ `/command-queue?humanCheckpoint=${checkpointId}&status=pending&limit=10`
397
+ );
416
398
  },
417
- enabled: isReady && !!sessionId && !!executionId,
418
- refetchInterval: (query) => {
419
- const data = query.state.data;
420
- const shouldRefetch = data?.status === "running";
421
- return shouldRefetch ? REFETCH_INTERVAL_RUNNING : false;
422
- }
399
+ // Only fetch when: org ready, checkpoint selected, and enabled
400
+ enabled: isReady && !!checkpointId && enabled,
401
+ staleTime: STALE_TIME_MONITORING
402
+ });
403
+ }
404
+ function useResourceExecutions({
405
+ resourceId,
406
+ timeRange,
407
+ page = 1,
408
+ limit = 10,
409
+ enabled = true
410
+ }) {
411
+ const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
412
+ return useQuery({
413
+ queryKey: ["resource-executions", workOSOrganizationId, resourceId, timeRange, page, limit],
414
+ queryFn: async () => {
415
+ return apiRequest(
416
+ `/command-view/resource-executions?resourceId=${resourceId}&timeRange=${timeRange}&page=${page}&limit=${limit}`
417
+ );
418
+ },
419
+ // Only fetch when: org ready, resource selected, and enabled
420
+ enabled: isReady && !!resourceId && enabled,
421
+ staleTime: STALE_TIME_MONITORING
423
422
  });
424
423
  }
425
424
 
@@ -0,0 +1,237 @@
1
+ import { AppearanceContext } from './chunk-K55TU6CC.js';
2
+ import { ElevasisServiceContext } from './chunk-BI5VDO2K.js';
3
+ import { useContext, useState, useRef, useCallback, useEffect } from 'react';
4
+ import { Paper, Stack, Title, Text, Group, Button, Anchor, Collapse, Badge, Code } from '@mantine/core';
5
+ import { IconAlertTriangle, IconLockOff, IconServerBolt, IconPlugConnectedX, IconWifiOff, IconRefresh, IconChevronDown, IconChevronRight } from '@tabler/icons-react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ // src/components/error/classifyConnectionError.ts
9
+ function isApiErrorLike(error) {
10
+ return error instanceof Error && "statusCode" in error && typeof error.statusCode === "number";
11
+ }
12
+ function isBrowserOffline() {
13
+ return typeof navigator !== "undefined" && navigator.onLine === false;
14
+ }
15
+ function describeTechnically(error, fallbackMessage) {
16
+ if (error instanceof Error) {
17
+ return error.name && error.name !== "Error" ? `${error.name}: ${error.message}` : error.message;
18
+ }
19
+ if (typeof error === "string" && error.length > 0) return error;
20
+ return fallbackMessage;
21
+ }
22
+ function classifyConnectionError(error, fallbackMessage = "Something went wrong") {
23
+ const technical = describeTechnically(error, fallbackMessage);
24
+ if (isBrowserOffline()) {
25
+ return {
26
+ kind: "offline",
27
+ title: "You're offline",
28
+ description: "This device has no network connection. The app reconnects on its own as soon as the connection is back.",
29
+ autoRecoverable: true,
30
+ technical
31
+ };
32
+ }
33
+ if (isApiErrorLike(error)) {
34
+ const { statusCode, requestId } = error;
35
+ if (statusCode === 401 || statusCode === 403) {
36
+ return {
37
+ kind: "unauthorized",
38
+ title: "Your session is no longer valid",
39
+ description: "The server rejected this session. Signing in again should clear it.",
40
+ autoRecoverable: false,
41
+ statusCode,
42
+ requestId,
43
+ technical
44
+ };
45
+ }
46
+ if (statusCode >= 500) {
47
+ return {
48
+ kind: "server",
49
+ title: "The server had a problem",
50
+ description: statusCode === 502 || statusCode === 503 || statusCode === 504 ? "The API is restarting or temporarily unavailable. This page keeps retrying and loads as soon as it answers." : "The API returned an error while loading your account. This page keeps retrying while the issue clears.",
51
+ autoRecoverable: true,
52
+ statusCode,
53
+ requestId,
54
+ technical
55
+ };
56
+ }
57
+ return {
58
+ kind: "unknown",
59
+ title: "Your account couldn't be loaded",
60
+ description: "The server rejected the request that loads your account. Retrying may help.",
61
+ autoRecoverable: false,
62
+ statusCode,
63
+ requestId,
64
+ technical
65
+ };
66
+ }
67
+ if (error instanceof Error) {
68
+ const name = error.name;
69
+ const message = error.message.toLowerCase();
70
+ if (name === "TimeoutError" || name === "AbortError" || message.includes("timed out") || message.includes("timeout")) {
71
+ return {
72
+ kind: "timeout",
73
+ title: "The server took too long to respond",
74
+ description: "The request timed out before the API answered. This page keeps retrying.",
75
+ autoRecoverable: true,
76
+ technical
77
+ };
78
+ }
79
+ if (name === "TypeError" || message.includes("failed to fetch") || message.includes("networkerror")) {
80
+ return {
81
+ kind: "unreachable",
82
+ title: "Can't reach the server",
83
+ description: "The API is not responding \u2014 it may be restarting or temporarily down. This page keeps retrying and loads as soon as it comes back.",
84
+ autoRecoverable: true,
85
+ technical
86
+ };
87
+ }
88
+ }
89
+ return {
90
+ kind: "unknown",
91
+ title: "Your account couldn't be loaded",
92
+ description: "Something went wrong while starting the app. Retrying may help.",
93
+ autoRecoverable: false,
94
+ technical
95
+ };
96
+ }
97
+ var RETRY_DELAYS_SECONDS = [5, 10, 20, 30, 60];
98
+ var ICONS = {
99
+ offline: IconWifiOff,
100
+ unreachable: IconPlugConnectedX,
101
+ timeout: IconServerBolt,
102
+ server: IconServerBolt,
103
+ unauthorized: IconLockOff,
104
+ unknown: IconAlertTriangle
105
+ };
106
+ function ServiceUnavailableScreen({ message, error, retry, appVersion }) {
107
+ const appearance = useContext(AppearanceContext);
108
+ const serviceContext = useContext(ElevasisServiceContext);
109
+ const failure = classifyConnectionError(error, message);
110
+ const Icon = ICONS[failure.kind];
111
+ const [isRetrying, setIsRetrying] = useState(false);
112
+ const [secondsRemaining, setSecondsRemaining] = useState(null);
113
+ const [detailsOpen, setDetailsOpen] = useState(false);
114
+ const attemptRef = useRef(0);
115
+ const retryRef = useRef(retry);
116
+ retryRef.current = retry;
117
+ const runRetry = useCallback(async () => {
118
+ if (!retryRef.current) return;
119
+ setIsRetrying(true);
120
+ setSecondsRemaining(null);
121
+ try {
122
+ await retryRef.current();
123
+ } catch {
124
+ } finally {
125
+ setIsRetrying(false);
126
+ }
127
+ }, []);
128
+ const handleManualRetry = useCallback(() => {
129
+ attemptRef.current = 0;
130
+ void runRetry();
131
+ }, [runRetry]);
132
+ const canAutoRetry = failure.autoRecoverable && !!retry;
133
+ useEffect(() => {
134
+ if (!canAutoRetry || isRetrying || secondsRemaining !== null) return;
135
+ const delay = RETRY_DELAYS_SECONDS[Math.min(attemptRef.current, RETRY_DELAYS_SECONDS.length - 1)];
136
+ attemptRef.current += 1;
137
+ setSecondsRemaining(delay);
138
+ }, [canAutoRetry, isRetrying, secondsRemaining]);
139
+ useEffect(() => {
140
+ if (secondsRemaining === null) return;
141
+ if (secondsRemaining <= 0) {
142
+ void runRetry();
143
+ return;
144
+ }
145
+ const timer = setTimeout(() => setSecondsRemaining((current) => current === null ? null : current - 1), 1e3);
146
+ return () => clearTimeout(timer);
147
+ }, [secondsRemaining, runRetry]);
148
+ useEffect(() => {
149
+ if (typeof window === "undefined") return;
150
+ const onOnline = () => {
151
+ attemptRef.current = 0;
152
+ void runRetry();
153
+ };
154
+ window.addEventListener("online", onOnline);
155
+ return () => window.removeEventListener("online", onOnline);
156
+ }, [runRetry]);
157
+ const statusLine = isRetrying ? "Reconnecting\u2026" : secondsRemaining !== null ? `Retrying automatically in ${secondsRemaining}s` : null;
158
+ return /* @__PURE__ */ jsxs(
159
+ "div",
160
+ {
161
+ style: {
162
+ position: "fixed",
163
+ inset: 0,
164
+ overflow: "auto",
165
+ background: "var(--color-background)",
166
+ display: "flex",
167
+ alignItems: "center",
168
+ justifyContent: "center",
169
+ padding: 24,
170
+ zIndex: 1e4
171
+ },
172
+ children: [
173
+ appearance?.background,
174
+ /* @__PURE__ */ jsx(
175
+ Paper,
176
+ {
177
+ withBorder: true,
178
+ radius: "md",
179
+ p: "xl",
180
+ style: { position: "relative", zIndex: 1, width: "100%", maxWidth: 520 },
181
+ "data-testid": "service-unavailable",
182
+ children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "md", children: [
183
+ /* @__PURE__ */ jsx(Icon, { size: 48, color: failure.kind === "offline" ? "var(--color-text-dimmed)" : "var(--color-error)" }),
184
+ /* @__PURE__ */ jsxs(Stack, { align: "center", gap: 6, children: [
185
+ /* @__PURE__ */ jsx(Title, { order: 3, ta: "center", children: failure.title }),
186
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", children: failure.description })
187
+ ] }),
188
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
189
+ /* @__PURE__ */ jsx(Button, { leftSection: /* @__PURE__ */ jsx(IconRefresh, { size: 16 }), onClick: handleManualRetry, loading: isRetrying, children: "Try again" }),
190
+ /* @__PURE__ */ jsx(Button, { variant: "default", onClick: () => window.location.reload(), children: "Reload page" })
191
+ ] }),
192
+ statusLine && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", "data-testid": "service-unavailable-status", children: statusLine }),
193
+ /* @__PURE__ */ jsxs(Stack, { gap: 6, w: "100%", children: [
194
+ /* @__PURE__ */ jsxs(
195
+ Anchor,
196
+ {
197
+ component: "button",
198
+ type: "button",
199
+ size: "xs",
200
+ c: "dimmed",
201
+ onClick: () => setDetailsOpen((open) => !open),
202
+ style: { alignSelf: "center", display: "flex", alignItems: "center", gap: 4 },
203
+ children: [
204
+ detailsOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 12 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 12 }),
205
+ "Technical details"
206
+ ]
207
+ }
208
+ ),
209
+ /* @__PURE__ */ jsx(Collapse, { in: detailsOpen, children: /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
210
+ /* @__PURE__ */ jsxs(Group, { gap: 6, justify: "center", children: [
211
+ /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "default", children: failure.kind }),
212
+ failure.statusCode !== void 0 && /* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "default", children: [
213
+ "HTTP ",
214
+ failure.statusCode
215
+ ] }),
216
+ appVersion && /* @__PURE__ */ jsxs(Badge, { size: "xs", variant: "default", children: [
217
+ "v",
218
+ appVersion
219
+ ] })
220
+ ] }),
221
+ /* @__PURE__ */ jsx(Code, { block: true, style: { fontSize: 11, whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: [
222
+ failure.technical,
223
+ serviceContext?.apiUrl ? `api: ${serviceContext.apiUrl}` : null,
224
+ failure.requestId ? `request id: ${failure.requestId}` : null,
225
+ `layer message: ${message}`
226
+ ].filter(Boolean).join("\n") })
227
+ ] }) })
228
+ ] })
229
+ ] })
230
+ }
231
+ )
232
+ ]
233
+ }
234
+ );
235
+ }
236
+
237
+ export { ServiceUnavailableScreen, classifyConnectionError };
@@ -1,5 +1,4 @@
1
- import { useAppearance } from './chunk-SB3IHM5Y.js';
2
- import { topbarHeight } from './chunk-MISHPEJX.js';
1
+ import { topbarHeight, useAppearance } from './chunk-K55TU6CC.js';
3
2
  import { Stack, Title, Button } from '@mantine/core';
4
3
  import { IconAlertCircle } from '@tabler/icons-react';
5
4
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,6 +1,6 @@
1
- import { dealKeys } from './chunk-SB3IHM5Y.js';
2
- import { showApiErrorNotification } from './chunk-ICHDIVQO.js';
3
- import { APIClientError } from './chunk-A2SB32YV.js';
1
+ import { dealKeys } from './chunk-K55TU6CC.js';
2
+ import { showApiErrorNotification } from './chunk-KXNRTJAE.js';
3
+ import { APIClientError } from './chunk-5ZK7K7YP.js';
4
4
  import { useElevasisServices } from './chunk-BI5VDO2K.js';
5
5
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
6
6
 
@@ -1,10 +1,9 @@
1
- import { acquisitionListKeys } from './chunk-SB3IHM5Y.js';
2
- import { showApiErrorNotification, showSuccessNotification } from './chunk-ICHDIVQO.js';
3
- import { APIClientError } from './chunk-A2SB32YV.js';
1
+ import { acquisitionListKeys } from './chunk-K55TU6CC.js';
2
+ import { showApiErrorNotification, showSuccessNotification } from './chunk-KXNRTJAE.js';
3
+ import { APIClientError } from './chunk-5ZK7K7YP.js';
4
4
  import { useElevasisServices } from './chunk-BI5VDO2K.js';
5
5
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
6
6
  import { z } from 'zod';
7
- import { useState, useCallback, useMemo } from 'react';
8
7
 
9
8
  z.object({
10
9
  replyBody: z.string().trim().min(1).max(1e4)
@@ -12,43 +11,6 @@ z.object({
12
11
  function deriveActions(deal, actions = []) {
13
12
  return actions.filter((a) => a.isAvailableFor(deal)).map(({ key, label, payloadSchema }) => ({ key, label, payloadSchema }));
14
13
  }
15
- function useTableSort(defaultColumn, defaultDirection = "desc") {
16
- const [sort, setSort] = useState({ column: defaultColumn, direction: defaultDirection });
17
- const toggleSort = useCallback((column) => {
18
- setSort((prev) => {
19
- if (prev.column === column) {
20
- return { column, direction: prev.direction === "asc" ? "desc" : "asc" };
21
- }
22
- return { column, direction: "desc" };
23
- });
24
- }, []);
25
- return { sort, toggleSort };
26
- }
27
- function sortData(data, sort, accessors) {
28
- const accessor = accessors[sort.column];
29
- if (!accessor) return data;
30
- return [...data].sort((a, b) => {
31
- const aVal = accessor(a);
32
- const bVal = accessor(b);
33
- if (aVal == null && bVal == null) return 0;
34
- if (aVal == null) return 1;
35
- if (bVal == null) return -1;
36
- let comparison = 0;
37
- if (typeof aVal === "string" && typeof bVal === "string") {
38
- comparison = aVal.localeCompare(bVal);
39
- } else if (typeof aVal === "number" && typeof bVal === "number") {
40
- comparison = aVal - bVal;
41
- } else {
42
- comparison = String(aVal).localeCompare(String(bVal));
43
- }
44
- return sort.direction === "asc" ? comparison : -comparison;
45
- });
46
- }
47
- function useSortedData(data, defaultColumn, accessors, defaultDirection = "desc") {
48
- const { sort, toggleSort } = useTableSort(defaultColumn, defaultDirection);
49
- const sorted = useMemo(() => sortData(data, sort, accessors), [data, sort, accessors]);
50
- return { sorted, sort, toggleSort };
51
- }
52
14
  var contactKeys = {
53
15
  all: ["acquisition-contacts"],
54
16
  list: (organizationId, filters) => [...contactKeys.all, "list", organizationId, filters],
@@ -283,4 +245,4 @@ function useDeleteCompanies() {
283
245
  });
284
246
  }
285
247
 
286
- export { companyKeys, contactKeys, deriveActions, sortData, useCompanies, useCompany, useCompanyFacets, useContact, useContacts, useCreateCompany, useCreateContact, useDeleteCompanies, useDeleteContacts, useSortedData, useTableSort, useUpdateCompany, useUpdateContact };
248
+ export { companyKeys, contactKeys, deriveActions, useCompanies, useCompany, useCompanyFacets, useContact, useContacts, useCreateCompany, useCreateContact, useDeleteCompanies, useDeleteContacts, useUpdateCompany, useUpdateContact };