@elevasis/ui 2.73.0 → 2.75.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.
- package/dist/api/index.js +3 -3
- package/dist/app/index.d.ts +58 -0
- package/dist/app/index.js +9 -10
- package/dist/auth/index.js +5 -6
- package/dist/charts/index.js +5 -6
- package/dist/chunk-2GIJBHZT.js +60 -0
- package/dist/{chunk-Z4ICFQXG.js → chunk-2ZRY3ARL.js} +1 -1
- package/dist/{chunk-5B2ZFO44.js → chunk-3H5DIJN7.js} +1 -1
- package/dist/{chunk-LZT2H2MA.js → chunk-47YJVIZE.js} +36 -43
- package/dist/{chunk-3TS5U5BL.js → chunk-5RH6NYZH.js} +1 -1
- package/dist/chunk-5SLRGUC4.js +224 -0
- package/dist/{chunk-JYBJMVNY.js → chunk-5VF5LPYS.js} +1 -1
- package/dist/{chunk-SWKAH2YM.js → chunk-6BJ5HMMC.js} +282 -553
- package/dist/{chunk-NI37YNRP.js → chunk-7OOFMEX6.js} +11 -5
- package/dist/{chunk-IBCEAVB2.js → chunk-A2SB32YV.js} +65 -5
- package/dist/{chunk-CJ2232PQ.js → chunk-CRPH5AAB.js} +1 -1
- package/dist/chunk-D3XXPCCK.js +69 -0
- package/dist/chunk-DMSTDZCJ.js +305 -0
- package/dist/chunk-DTEGVSJ6.js +645 -0
- package/dist/chunk-DVAOCHIF.js +165 -0
- package/dist/chunk-G7O4CBMC.js +231 -0
- package/dist/{chunk-IGBPWD6S.js → chunk-GDTK33QT.js} +5 -3
- package/dist/chunk-ICHDIVQO.js +54 -0
- package/dist/{chunk-U2H3TIHD.js → chunk-IYATYH5I.js} +2 -52
- package/dist/chunk-L3NBMLRN.js +49 -0
- package/dist/{chunk-LEPYXLJ2.js → chunk-LFLM723H.js} +1 -1
- package/dist/chunk-M6VAZAQW.js +45 -0
- package/dist/{chunk-AJOVWB47.js → chunk-MLHZUN2X.js} +6 -3
- package/dist/chunk-N6K2Q5BM.js +393 -0
- package/dist/chunk-NMHQAYZU.js +439 -0
- package/dist/chunk-NYIIRZSA.js +286 -0
- package/dist/{chunk-ETN3TTRT.js → chunk-OGHTJKBV.js} +115 -8
- package/dist/{chunk-M7WWRZ5Z.js → chunk-QFGNRKIE.js} +1 -78
- package/dist/chunk-QFS2GZMV.js +515 -0
- package/dist/{chunk-OCVSPAKM.js → chunk-SB3IHM5Y.js} +1150 -4346
- package/dist/{chunk-4CW2C5BD.js → chunk-SEYOVNS5.js} +1 -1
- package/dist/chunk-SN7X5N2A.js +116 -0
- package/dist/{chunk-PQ4B62HH.js → chunk-TX3UHDL5.js} +2 -2
- package/dist/chunk-VM2OWOXL.js +24 -0
- package/dist/{chunk-ZDKPHFTH.js → chunk-VWGCURZF.js} +5 -3
- package/dist/chunk-WDBNW44Z.js +49 -0
- package/dist/chunk-YQQ5GRUR.js +21 -0
- package/dist/{chunk-NHNTX6ZL.js → chunk-ZG6YJUT4.js} +3 -2
- package/dist/components/index.d.ts +228 -6
- package/dist/components/index.js +321 -35
- package/dist/components/navigation/index.js +6 -7
- package/dist/features/auth/index.d.ts +78 -2
- package/dist/features/auth/index.js +18 -9
- package/dist/features/clients/index.js +7 -7
- package/dist/features/content/index.d.ts +226 -5
- package/dist/features/content/index.js +270 -19
- package/dist/features/crm/index.d.ts +58 -0
- package/dist/features/crm/index.js +10 -8
- package/dist/features/dashboard/index.js +9 -8
- package/dist/features/delivery/index.d.ts +58 -0
- package/dist/features/delivery/index.js +23 -7
- package/dist/features/knowledge/index.js +5 -6
- package/dist/features/lead-gen/index.d.ts +9 -15
- package/dist/features/lead-gen/index.js +12 -8
- package/dist/features/monitoring/index.js +11 -9
- package/dist/features/monitoring/requests/index.js +8 -7
- package/dist/features/operations/index.js +15 -11
- package/dist/features/public-agent-chat/index.js +3 -1
- package/dist/features/settings/index.d.ts +66 -3
- package/dist/features/settings/index.js +9 -8
- package/dist/hooks/access/index.js +5 -6
- package/dist/hooks/delivery/index.d.ts +58 -0
- package/dist/hooks/delivery/index.js +3 -2
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +1 -1
- package/dist/hooks/published.d.ts +181 -5
- package/dist/hooks/published.js +22 -6
- package/dist/initialization/index.d.ts +58 -0
- package/dist/knowledge/index.js +167 -11
- package/dist/{knowledge-search-index-RZLIVWPJ.js → knowledge-search-index-6GQK55IQ.js} +1 -1
- package/dist/layout/index.js +8 -9
- package/dist/profile/index.d.ts +58 -0
- package/dist/provider/index.d.ts +77 -1
- package/dist/provider/index.js +5 -6
- package/dist/provider/published.d.ts +105 -1
- package/dist/provider/published.js +5 -6
- package/dist/test-utils/index.d.ts +16 -5
- package/dist/test-utils/index.js +17 -18
- package/dist/types/index.d.ts +73 -1
- package/dist/utils/index.d.ts +83 -3
- package/dist/utils/index.js +1 -1
- package/package.json +10 -5
- package/dist/chunk-6M6OLGQY.js +0 -36
- package/dist/chunk-MKH2KOAO.js +0 -39
- package/dist/hooks/index.css +0 -659
- package/dist/hooks/index.d.ts +0 -14073
- package/dist/hooks/index.js +0 -27
- package/dist/supabase/index.d.ts +0 -7118
- package/dist/supabase/index.js +0 -3
- package/dist/typeform/index.d.ts +0 -462
- package/dist/typeform/index.js +0 -2051
- package/dist/typeform/schemas.d.ts +0 -67
- package/dist/typeform/schemas.js +0 -2
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import { createLiveTempMessageIdentity } from './chunk-QFGNRKIE.js';
|
|
2
|
+
import { sessionsKeys } from './chunk-SB3IHM5Y.js';
|
|
3
|
+
import { SessionIdParamSchema, WebSocketSessionTurnSchema, ExecutionIdParamsSchema } from './chunk-2GIJBHZT.js';
|
|
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';
|
|
7
|
+
import { useElevasisServices } from './chunk-BI5VDO2K.js';
|
|
8
|
+
import { useAuthContext } from './chunk-BRJ3QZ4E.js';
|
|
9
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
10
|
+
import { create } from 'zustand';
|
|
11
|
+
import { persist } from 'zustand/middleware';
|
|
12
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
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();
|
|
27
|
+
return useQuery({
|
|
28
|
+
queryKey: ["checkpoint-tasks", workOSOrganizationId, checkpointId],
|
|
29
|
+
queryFn: async () => {
|
|
30
|
+
return apiRequest(
|
|
31
|
+
`/command-queue?humanCheckpoint=${checkpointId}&status=pending&limit=10`
|
|
32
|
+
);
|
|
33
|
+
},
|
|
34
|
+
// Only fetch when: org ready, checkpoint selected, and enabled
|
|
35
|
+
enabled: isReady && !!checkpointId && enabled,
|
|
36
|
+
staleTime: STALE_TIME_MONITORING
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function useResourceExecutions({
|
|
40
|
+
resourceId,
|
|
41
|
+
timeRange,
|
|
42
|
+
page = 1,
|
|
43
|
+
limit = 10,
|
|
44
|
+
enabled = true
|
|
45
|
+
}) {
|
|
46
|
+
const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
|
|
47
|
+
return useQuery({
|
|
48
|
+
queryKey: ["resource-executions", workOSOrganizationId, resourceId, timeRange, page, limit],
|
|
49
|
+
queryFn: async () => {
|
|
50
|
+
return apiRequest(
|
|
51
|
+
`/command-view/resource-executions?resourceId=${resourceId}&timeRange=${timeRange}&page=${page}&limit=${limit}`
|
|
52
|
+
);
|
|
53
|
+
},
|
|
54
|
+
// Only fetch when: org ready, resource selected, and enabled
|
|
55
|
+
enabled: isReady && !!resourceId && enabled,
|
|
56
|
+
staleTime: STALE_TIME_MONITORING
|
|
57
|
+
});
|
|
58
|
+
}
|
|
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
|
+
function useSessionMessages(sessionId) {
|
|
147
|
+
const { apiRequest, isReady } = useElevasisServices();
|
|
148
|
+
const { currentSupabaseOrganizationId } = useOrganization();
|
|
149
|
+
return useQuery({
|
|
150
|
+
queryKey: sessionsKeys.messages(currentSupabaseOrganizationId, sessionId),
|
|
151
|
+
queryFn: async () => {
|
|
152
|
+
SessionIdParamSchema.parse({ sessionId });
|
|
153
|
+
const response = await apiRequest(`/sessions/${sessionId}/messages`, {
|
|
154
|
+
method: "GET"
|
|
155
|
+
});
|
|
156
|
+
const messages = response.messages.map((msg) => ({
|
|
157
|
+
...msg,
|
|
158
|
+
createdAt: new Date(msg.createdAt)
|
|
159
|
+
}));
|
|
160
|
+
return messages;
|
|
161
|
+
},
|
|
162
|
+
enabled: isReady && !!sessionId,
|
|
163
|
+
staleTime: 0
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function formatMessageEvent(event) {
|
|
167
|
+
switch (event.type) {
|
|
168
|
+
case "user_message":
|
|
169
|
+
return event.text;
|
|
170
|
+
case "assistant_message":
|
|
171
|
+
return event.text;
|
|
172
|
+
case "agent:started":
|
|
173
|
+
return "\u{1F916} Agent started reasoning";
|
|
174
|
+
case "agent:reasoning":
|
|
175
|
+
return `\u{1F4AD} Reasoning (Iteration ${event.iteration})`;
|
|
176
|
+
case "agent:tool_call":
|
|
177
|
+
return `\u{1F527} Tool: ${event.toolName}`;
|
|
178
|
+
case "agent:tool_result":
|
|
179
|
+
return event.success ? "\u2705 Tool Result" : "\u26A0\uFE0F Tool Result (Failed)";
|
|
180
|
+
case "agent:completed":
|
|
181
|
+
return "\u2705 Agent completed";
|
|
182
|
+
case "agent:error":
|
|
183
|
+
return `\u274C Agent error: ${event.error}`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function getWsUrl(apiUrl) {
|
|
187
|
+
const url = new URL(apiUrl);
|
|
188
|
+
const protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
189
|
+
return `${protocol}//${url.host}`;
|
|
190
|
+
}
|
|
191
|
+
function useSessionWebSocket(sessionId, apiUrl) {
|
|
192
|
+
const [messages, setMessages] = useState([]);
|
|
193
|
+
const [state, setState] = useState({
|
|
194
|
+
isConnected: false,
|
|
195
|
+
isProcessing: false,
|
|
196
|
+
error: null
|
|
197
|
+
});
|
|
198
|
+
const [lastTokenUsage, setLastTokenUsage] = useState(null);
|
|
199
|
+
const wsRef = useRef(null);
|
|
200
|
+
const retryCountRef = useRef(0);
|
|
201
|
+
const reconnectTimeoutRef = useRef(null);
|
|
202
|
+
const connectionEpochRef = useRef(0);
|
|
203
|
+
const { getAccessToken } = useAuthContext();
|
|
204
|
+
const { currentWorkOSOrganizationId, currentSupabaseOrganizationId } = useOrganization();
|
|
205
|
+
const queryClient = useQueryClient();
|
|
206
|
+
const getAccessTokenRef = useRef(getAccessToken);
|
|
207
|
+
getAccessTokenRef.current = getAccessToken;
|
|
208
|
+
const currentWorkOSOrgIdRef = useRef(currentWorkOSOrganizationId);
|
|
209
|
+
currentWorkOSOrgIdRef.current = currentWorkOSOrganizationId;
|
|
210
|
+
const queryClientRef = useRef(queryClient);
|
|
211
|
+
queryClientRef.current = queryClient;
|
|
212
|
+
const currentSupabaseOrgIdRef = useRef(currentSupabaseOrganizationId);
|
|
213
|
+
currentSupabaseOrgIdRef.current = currentSupabaseOrganizationId;
|
|
214
|
+
const connect = useCallback(async () => {
|
|
215
|
+
if (!sessionId) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!currentWorkOSOrgIdRef.current) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (wsRef.current?.readyState === WebSocket.OPEN || wsRef.current?.readyState === WebSocket.CONNECTING) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const epoch = connectionEpochRef.current;
|
|
225
|
+
const token = await getAccessTokenRef.current();
|
|
226
|
+
if (!token) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (epoch !== connectionEpochRef.current) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const orgId = currentWorkOSOrgIdRef.current;
|
|
233
|
+
const wsUrl = `${getWsUrl(apiUrl)}/ws/sessions/${sessionId}?token=${token}&orgId=${orgId}`;
|
|
234
|
+
const ws = new WebSocket(wsUrl);
|
|
235
|
+
ws.onopen = () => {
|
|
236
|
+
setState((prev) => ({ ...prev, isConnected: true, error: null }));
|
|
237
|
+
retryCountRef.current = 0;
|
|
238
|
+
const supabaseOrgId = currentSupabaseOrgIdRef.current;
|
|
239
|
+
if (supabaseOrgId) {
|
|
240
|
+
queryClientRef.current.invalidateQueries({
|
|
241
|
+
queryKey: sessionsKeys.messages(supabaseOrgId, sessionId)
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
ws.onmessage = (event) => {
|
|
246
|
+
try {
|
|
247
|
+
const data = JSON.parse(event.data);
|
|
248
|
+
if (data.type && data.type !== "turn:complete" && data.type !== "error") {
|
|
249
|
+
const liveIdentity = createLiveTempMessageIdentity();
|
|
250
|
+
const tempMessage = {
|
|
251
|
+
id: liveIdentity.id,
|
|
252
|
+
role: data.type === "user_message" ? "user" : "assistant",
|
|
253
|
+
messageType: data.type,
|
|
254
|
+
text: formatMessageEvent(data),
|
|
255
|
+
// Format based on type
|
|
256
|
+
metadata: data.type.startsWith("agent:") ? data : void 0,
|
|
257
|
+
turnNumber: 999999,
|
|
258
|
+
// High placeholder so temp messages sort to bottom
|
|
259
|
+
messageIndex: liveIdentity.messageIndex,
|
|
260
|
+
createdAt: liveIdentity.createdAt
|
|
261
|
+
};
|
|
262
|
+
setMessages((prev) => [...prev, tempMessage]);
|
|
263
|
+
} else if (data.type === "turn:complete") {
|
|
264
|
+
if (data.tokenUsage) {
|
|
265
|
+
setLastTokenUsage(data.tokenUsage);
|
|
266
|
+
}
|
|
267
|
+
setState((prev) => ({ ...prev, isProcessing: false }));
|
|
268
|
+
const supabaseOrgId = currentSupabaseOrgIdRef.current;
|
|
269
|
+
if (supabaseOrgId) {
|
|
270
|
+
queryClientRef.current.invalidateQueries({
|
|
271
|
+
queryKey: sessionsKeys.messages(supabaseOrgId, sessionId)
|
|
272
|
+
});
|
|
273
|
+
queryClientRef.current.invalidateQueries({
|
|
274
|
+
queryKey: sessionsKeys.executions(supabaseOrgId, sessionId)
|
|
275
|
+
});
|
|
276
|
+
queryClientRef.current.invalidateQueries({
|
|
277
|
+
queryKey: sessionsKeys.session(supabaseOrgId, sessionId)
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
} else if (data.type === "error") {
|
|
281
|
+
setState((prev) => ({
|
|
282
|
+
...prev,
|
|
283
|
+
error: data.error,
|
|
284
|
+
isProcessing: false
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.error("Failed to parse WebSocket message:", error);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
ws.onerror = () => {
|
|
292
|
+
};
|
|
293
|
+
ws.onclose = (event) => {
|
|
294
|
+
setState((prev) => ({ ...prev, isConnected: false }));
|
|
295
|
+
if (!event.wasClean && retryCountRef.current >= WS_MAX_RETRIES_BEFORE_ERROR) {
|
|
296
|
+
setState((prev) => ({
|
|
297
|
+
...prev,
|
|
298
|
+
error: "Unable to connect to session. Retrying..."
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
301
|
+
const terminalCodes = [1003, 1008];
|
|
302
|
+
if (terminalCodes.includes(event.code) || event.code >= 4e3) {
|
|
303
|
+
setState((prev) => ({
|
|
304
|
+
...prev,
|
|
305
|
+
error: `Connection rejected (code ${event.code})`
|
|
306
|
+
}));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const delay = Math.min(WS_RECONNECT_BASE_DELAY * Math.pow(2, retryCountRef.current), WS_RECONNECT_MAX_DELAY);
|
|
310
|
+
retryCountRef.current += 1;
|
|
311
|
+
reconnectTimeoutRef.current = setTimeout(() => {
|
|
312
|
+
connect();
|
|
313
|
+
}, delay);
|
|
314
|
+
};
|
|
315
|
+
wsRef.current = ws;
|
|
316
|
+
}, [sessionId, apiUrl]);
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
retryCountRef.current = 0;
|
|
319
|
+
if (currentWorkOSOrgIdRef.current) {
|
|
320
|
+
connect();
|
|
321
|
+
}
|
|
322
|
+
return () => {
|
|
323
|
+
connectionEpochRef.current += 1;
|
|
324
|
+
if (reconnectTimeoutRef.current) {
|
|
325
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
326
|
+
reconnectTimeoutRef.current = null;
|
|
327
|
+
}
|
|
328
|
+
const ws = wsRef.current;
|
|
329
|
+
if (ws) {
|
|
330
|
+
ws.onopen = null;
|
|
331
|
+
ws.onmessage = null;
|
|
332
|
+
ws.onerror = null;
|
|
333
|
+
ws.onclose = null;
|
|
334
|
+
ws.close();
|
|
335
|
+
wsRef.current = null;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
}, [sessionId, currentWorkOSOrganizationId, connect]);
|
|
339
|
+
const sendMessage = useCallback(
|
|
340
|
+
(text, pageContext) => {
|
|
341
|
+
const trimmed = text.trim();
|
|
342
|
+
if (!trimmed) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (!wsRef.current || state.isProcessing) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (wsRef.current.readyState !== WebSocket.OPEN) {
|
|
349
|
+
setState((prev) => ({
|
|
350
|
+
...prev,
|
|
351
|
+
error: "WebSocket not connected"
|
|
352
|
+
}));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const liveIdentity = createLiveTempMessageIdentity();
|
|
356
|
+
const userMessage = {
|
|
357
|
+
id: liveIdentity.id,
|
|
358
|
+
role: "user",
|
|
359
|
+
messageType: "user_message",
|
|
360
|
+
text: trimmed,
|
|
361
|
+
turnNumber: 999999,
|
|
362
|
+
// High placeholder so temp messages sort to bottom
|
|
363
|
+
messageIndex: liveIdentity.messageIndex,
|
|
364
|
+
createdAt: liveIdentity.createdAt
|
|
365
|
+
};
|
|
366
|
+
setMessages((prev) => [...prev, userMessage]);
|
|
367
|
+
const input = { message: trimmed };
|
|
368
|
+
if (pageContext) {
|
|
369
|
+
input.pageContext = pageContext;
|
|
370
|
+
}
|
|
371
|
+
const message = WebSocketSessionTurnSchema.parse({
|
|
372
|
+
type: "session:turn",
|
|
373
|
+
input
|
|
374
|
+
});
|
|
375
|
+
wsRef.current.send(JSON.stringify(message));
|
|
376
|
+
setState((prev) => ({ ...prev, isProcessing: true, error: null }));
|
|
377
|
+
},
|
|
378
|
+
[state.isProcessing, sessionId]
|
|
379
|
+
);
|
|
380
|
+
const clearError = useCallback(() => {
|
|
381
|
+
setState((prev) => ({ ...prev, error: null }));
|
|
382
|
+
}, []);
|
|
383
|
+
return {
|
|
384
|
+
messages,
|
|
385
|
+
state,
|
|
386
|
+
sendMessage,
|
|
387
|
+
clearError,
|
|
388
|
+
lastTokenUsage
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function useSessionExecutions(sessionId) {
|
|
392
|
+
const { apiRequest, isReady } = useElevasisServices();
|
|
393
|
+
const { currentSupabaseOrganizationId } = useOrganization();
|
|
394
|
+
return useQuery({
|
|
395
|
+
queryKey: sessionsKeys.executions(currentSupabaseOrganizationId, sessionId),
|
|
396
|
+
queryFn: async () => {
|
|
397
|
+
SessionIdParamSchema.parse({ sessionId });
|
|
398
|
+
return apiRequest(`/sessions/${sessionId}/executions`, {
|
|
399
|
+
method: "GET"
|
|
400
|
+
});
|
|
401
|
+
},
|
|
402
|
+
enabled: isReady && !!sessionId,
|
|
403
|
+
staleTime: 0
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
function useSessionExecution(sessionId, executionId) {
|
|
407
|
+
const { apiRequest, isReady } = useElevasisServices();
|
|
408
|
+
const { currentSupabaseOrganizationId } = useOrganization();
|
|
409
|
+
return useQuery({
|
|
410
|
+
queryKey: sessionsKeys.execution(currentSupabaseOrganizationId, sessionId, executionId),
|
|
411
|
+
queryFn: async () => {
|
|
412
|
+
ExecutionIdParamsSchema.parse({ sessionId, executionId });
|
|
413
|
+
return apiRequest(`/sessions/${sessionId}/executions/${executionId}`, {
|
|
414
|
+
method: "GET"
|
|
415
|
+
});
|
|
416
|
+
},
|
|
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
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/hooks/operations/command-view/useCommandViewData.ts
|
|
427
|
+
function useCommandViewData() {
|
|
428
|
+
const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
|
|
429
|
+
return useQuery({
|
|
430
|
+
queryKey: ["command-view", workOSOrganizationId],
|
|
431
|
+
queryFn: async () => {
|
|
432
|
+
return apiRequest("/command-view");
|
|
433
|
+
},
|
|
434
|
+
enabled: isReady,
|
|
435
|
+
staleTime: STALE_TIME_DEFAULT
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export { useCheckpointTasks, useCommandViewData, useCommandViewStats, useCommandViewStore, useResourceExecutions, useSessionExecution, useSessionExecutions, useSessionMessages, useSessionWebSocket };
|