@elevasis/ui 2.49.0 → 2.50.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 (56) hide show
  1. package/dist/api/index.js +4 -3
  2. package/dist/app/index.d.ts +132 -0
  3. package/dist/app/index.js +8 -6
  4. package/dist/auth/index.js +8 -6
  5. package/dist/charts/index.js +8 -6
  6. package/dist/{chunk-SOGPJFO6.js → chunk-4UA62IDF.js} +1 -1
  7. package/dist/{chunk-OFLWSKSC.js → chunk-7Q5THR43.js} +1 -1
  8. package/dist/chunk-EJL4U7OZ.js +79 -0
  9. package/dist/chunk-FVOMKZ7S.js +118 -0
  10. package/dist/{chunk-Y3HPUATG.js → chunk-SBNC3FRX.js} +117 -118
  11. package/dist/{chunk-CDZB24OR.js → chunk-XOPLS4S6.js} +1 -85
  12. package/dist/components/index.d.ts +132 -0
  13. package/dist/components/index.js +8 -6
  14. package/dist/components/navigation/index.js +8 -6
  15. package/dist/features/auth/index.d.ts +132 -0
  16. package/dist/features/auth/index.js +9 -7
  17. package/dist/features/clients/index.js +8 -6
  18. package/dist/features/crm/index.d.ts +132 -0
  19. package/dist/features/crm/index.js +8 -6
  20. package/dist/features/dashboard/index.js +8 -6
  21. package/dist/features/delivery/index.d.ts +132 -0
  22. package/dist/features/delivery/index.js +8 -6
  23. package/dist/features/knowledge/index.js +8 -6
  24. package/dist/features/lead-gen/index.js +8 -6
  25. package/dist/features/monitoring/index.js +8 -6
  26. package/dist/features/monitoring/requests/index.js +9 -7
  27. package/dist/features/operations/index.d.ts +2 -2
  28. package/dist/features/operations/index.js +8 -6
  29. package/dist/features/public-agent-chat/index.d.ts +161 -0
  30. package/dist/features/public-agent-chat/index.js +413 -0
  31. package/dist/features/settings/index.d.ts +132 -0
  32. package/dist/features/settings/index.js +8 -6
  33. package/dist/hooks/access/index.js +8 -6
  34. package/dist/hooks/delivery/index.d.ts +132 -0
  35. package/dist/hooks/delivery/index.js +8 -6
  36. package/dist/hooks/index.d.ts +135 -1
  37. package/dist/hooks/index.js +8 -6
  38. package/dist/hooks/published.d.ts +135 -1
  39. package/dist/hooks/published.js +8 -6
  40. package/dist/index.d.ts +135 -1
  41. package/dist/index.js +9 -7
  42. package/dist/initialization/index.d.ts +132 -0
  43. package/dist/knowledge/index.js +263 -29
  44. package/dist/{knowledge-search-index-MHOBQTT3.js → knowledge-search-index-JOPRYZN6.js} +600 -561
  45. package/dist/layout/index.js +8 -6
  46. package/dist/organization/index.js +8 -6
  47. package/dist/profile/index.d.ts +132 -0
  48. package/dist/provider/index.d.ts +132 -0
  49. package/dist/provider/index.js +8 -6
  50. package/dist/provider/published.d.ts +132 -0
  51. package/dist/provider/published.js +8 -6
  52. package/dist/supabase/index.d.ts +258 -0
  53. package/dist/test-utils/index.js +4 -3
  54. package/dist/types/index.d.ts +135 -3
  55. package/dist/utils/index.js +2 -1
  56. package/package.json +9 -4
@@ -0,0 +1,161 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as _tanstack_react_query from '@tanstack/react-query';
3
+
4
+ type MessageType = MessageEvent['type'];
5
+ interface ChatMessage {
6
+ id: string;
7
+ role: 'user' | 'assistant';
8
+ messageType: MessageType;
9
+ text: string;
10
+ metadata?: MessageEvent;
11
+ turnNumber: number;
12
+ messageIndex?: number;
13
+ createdAt: Date;
14
+ }
15
+ /** Token usage data sent with turn:complete WebSocket events */
16
+ interface SessionTokenUsage {
17
+ /** Tokens consumed by this turn's input */
18
+ turnInputTokens: number;
19
+ /** Tokens generated by this turn's output */
20
+ turnOutputTokens: number;
21
+ /** Total tokens for this turn (turnInputTokens + turnOutputTokens) */
22
+ turnTotalTokens: number;
23
+ /** Cumulative input tokens across all turns in this session */
24
+ cumulativeInputTokens: number;
25
+ /** Cumulative output tokens across all turns in this session */
26
+ cumulativeOutputTokens: number;
27
+ /** The model's context window size for this session (e.g., 200K) */
28
+ contextWindowSize: number;
29
+ }
30
+
31
+ /**
32
+ * Base Execution Engine type definitions
33
+ * Core types shared across all Execution Engine resources
34
+ */
35
+
36
+ /**
37
+ * Unified message event type - covers all message types in sessions
38
+ * Replaces separate SessionTurnMessages and AgentActivityEvent mechanisms
39
+ */
40
+ /**
41
+ * Structured action metadata attached to assistant messages.
42
+ * Frontend reads this instead of parsing text prefixes.
43
+ */
44
+ type AssistantAction = {
45
+ kind: 'navigate';
46
+ path: string;
47
+ reason: string;
48
+ } | {
49
+ kind: 'update_filters';
50
+ timeRange: string | null;
51
+ statusFilter: string | null;
52
+ searchQuery: string | null;
53
+ };
54
+ type MessageEvent = {
55
+ type: 'user_message';
56
+ text: string;
57
+ } | {
58
+ type: 'assistant_message';
59
+ text: string;
60
+ _action?: AssistantAction;
61
+ } | {
62
+ type: 'agent:started';
63
+ } | {
64
+ type: 'agent:completed';
65
+ } | {
66
+ type: 'agent:error';
67
+ error: string;
68
+ } | {
69
+ type: 'agent:reasoning';
70
+ iteration: number;
71
+ reasoning: string;
72
+ } | {
73
+ type: 'agent:tool_call';
74
+ toolName: string;
75
+ args: Record<string, unknown>;
76
+ } | {
77
+ type: 'agent:tool_result';
78
+ toolName: string;
79
+ success: boolean;
80
+ result?: unknown;
81
+ error?: string;
82
+ };
83
+
84
+ interface PublicAgentChatGrant {
85
+ slug: string;
86
+ resourceId: string;
87
+ mode: 'public' | 'code' | string;
88
+ requiresCode: boolean;
89
+ branding?: unknown;
90
+ captureFields?: unknown;
91
+ maxTurnsPerSession?: number;
92
+ }
93
+ interface PublicAgentChatMetadataResponse {
94
+ grant: PublicAgentChatGrant;
95
+ }
96
+ interface PublicAgentChatAuthorizeResponse {
97
+ capabilityToken: string;
98
+ expiresAt: string;
99
+ grant: PublicAgentChatGrant;
100
+ }
101
+ interface PublicAgentChatSessionResponse {
102
+ sessionId: string;
103
+ resourceId: string;
104
+ turnCount: number;
105
+ isEnded: boolean;
106
+ title: string | null;
107
+ createdAt?: string;
108
+ updatedAt?: string;
109
+ }
110
+ interface PublicAgentChatMessagesResponse {
111
+ sessionId: string;
112
+ messages: Array<Omit<ChatMessage, 'createdAt'> & {
113
+ createdAt?: string;
114
+ }>;
115
+ limit: number;
116
+ cursor: number | null;
117
+ nextCursor: number | null;
118
+ total: number;
119
+ hasMore: boolean;
120
+ }
121
+ interface PublicAgentChatConnectionState {
122
+ isConnected: boolean;
123
+ isProcessing: boolean;
124
+ error: string | null;
125
+ }
126
+
127
+ interface PublicAgentChatProps {
128
+ apiUrl: string;
129
+ slug: string;
130
+ visitorId?: string;
131
+ metadata?: Record<string, unknown>;
132
+ title?: string;
133
+ className?: string;
134
+ style?: React.CSSProperties;
135
+ onSessionReady?: (session: PublicAgentChatSessionResponse) => void;
136
+ }
137
+ declare function PublicAgentChat({ apiUrl, slug, visitorId, metadata, title, className, style, onSessionReady }: PublicAgentChatProps): react_jsx_runtime.JSX.Element;
138
+
139
+ declare function usePublicAgentChatMessages(apiUrl: string, sessionId: string | null, capabilityToken: string | null): _tanstack_react_query.UseQueryResult<ChatMessage[], Error>;
140
+
141
+ interface WebSocketState {
142
+ isConnected: boolean;
143
+ isProcessing: boolean;
144
+ error: string | null;
145
+ }
146
+
147
+ declare function usePublicAgentChatWebSocket(sessionId: string | null, apiUrl: string, capabilityToken: string | null): {
148
+ messages: ChatMessage[];
149
+ state: WebSocketState;
150
+ sendMessage: (text: string) => void;
151
+ clearError: () => void;
152
+ lastTokenUsage: SessionTokenUsage | null;
153
+ };
154
+
155
+ declare const publicAgentChatKeys: {
156
+ all: readonly ["public-agent-chat"];
157
+ messages: (sessionId: string) => readonly ["public-agent-chat", "messages", string];
158
+ };
159
+
160
+ export { PublicAgentChat, publicAgentChatKeys, usePublicAgentChatMessages, usePublicAgentChatWebSocket };
161
+ export type { PublicAgentChatAuthorizeResponse, PublicAgentChatConnectionState, PublicAgentChatGrant, PublicAgentChatMessagesResponse, PublicAgentChatMetadataResponse, PublicAgentChatProps, PublicAgentChatSessionResponse };
@@ -0,0 +1,413 @@
1
+ import { WebSocketSessionTurnSchema } from '../../chunk-EJL4U7OZ.js';
2
+ import { ChatInterface } from '../../chunk-GUKY77FJ.js';
3
+ import { WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, validateTokenLimit, TOKEN_LIMITS } from '../../chunk-FVOMKZ7S.js';
4
+ import '../../chunk-TVTSASST.js';
5
+ import '../../chunk-I2KLQ2HA.js';
6
+ import { Center, Loader, Paper, Stack, Group, Title, Alert, PasswordInput, Button, Text } from '@mantine/core';
7
+ import { IconLock, IconAlertCircle, IconSend } from '@tabler/icons-react';
8
+ import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
9
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
10
+ import { jsx, jsxs } from 'react/jsx-runtime';
11
+
12
+ // src/features/public-agent-chat/queryKeys.ts
13
+ var publicAgentChatKeys = {
14
+ all: ["public-agent-chat"],
15
+ messages: (sessionId) => [...publicAgentChatKeys.all, "messages", sessionId]
16
+ };
17
+
18
+ // src/features/public-agent-chat/usePublicAgentChatMessages.ts
19
+ function usePublicAgentChatMessages(apiUrl, sessionId, capabilityToken) {
20
+ return useQuery({
21
+ queryKey: [...publicAgentChatKeys.messages(sessionId ?? "pending"), apiUrl, capabilityToken],
22
+ queryFn: async () => {
23
+ if (!sessionId || !capabilityToken) return [];
24
+ const response = await fetch(`${apiUrl}/api/public/agent-chat/sessions/${sessionId}/messages`, {
25
+ method: "GET",
26
+ headers: {
27
+ Authorization: `Bearer ${capabilityToken}`
28
+ }
29
+ });
30
+ if (!response.ok) {
31
+ throw new Error("Failed to load public agent chat messages");
32
+ }
33
+ const payload = await response.json();
34
+ return payload.messages.map(
35
+ (message) => ({
36
+ ...message,
37
+ createdAt: message.createdAt ? new Date(message.createdAt) : /* @__PURE__ */ new Date()
38
+ })
39
+ );
40
+ },
41
+ enabled: !!apiUrl && !!sessionId && !!capabilityToken,
42
+ staleTime: 0
43
+ });
44
+ }
45
+
46
+ // src/hooks/sessions/sessionWebSocketUtils.ts
47
+ function formatMessageEvent(event) {
48
+ switch (event.type) {
49
+ case "user_message":
50
+ return event.text;
51
+ case "assistant_message":
52
+ return event.text;
53
+ case "agent:started":
54
+ return "Agent started reasoning";
55
+ case "agent:reasoning":
56
+ return `Reasoning (Iteration ${event.iteration})`;
57
+ case "agent:tool_call":
58
+ return `Tool: ${event.toolName}`;
59
+ case "agent:tool_result":
60
+ return event.success ? "Tool Result" : "Tool Result (Failed)";
61
+ case "agent:completed":
62
+ return "Agent completed";
63
+ case "agent:error":
64
+ return `Agent error: ${event.error}`;
65
+ }
66
+ }
67
+ function getWebSocketBaseUrl(apiUrl) {
68
+ const url = new URL(apiUrl);
69
+ const protocol = url.protocol === "https:" ? "wss:" : "ws:";
70
+ return `${protocol}//${url.host}`;
71
+ }
72
+
73
+ // src/features/public-agent-chat/usePublicAgentChatWebSocket.ts
74
+ function usePublicAgentChatWebSocket(sessionId, apiUrl, capabilityToken) {
75
+ const [messages, setMessages] = useState([]);
76
+ const [state, setState] = useState({
77
+ isConnected: false,
78
+ isProcessing: false,
79
+ error: null
80
+ });
81
+ const [lastTokenUsage, setLastTokenUsage] = useState(null);
82
+ const wsRef = useRef(null);
83
+ const retryCountRef = useRef(0);
84
+ const reconnectTimeoutRef = useRef(null);
85
+ const queryClient = useQueryClient();
86
+ const sessionIdRef = useRef(sessionId);
87
+ sessionIdRef.current = sessionId;
88
+ const capabilityTokenRef = useRef(capabilityToken);
89
+ capabilityTokenRef.current = capabilityToken;
90
+ const queryClientRef = useRef(queryClient);
91
+ queryClientRef.current = queryClient;
92
+ const connect = useCallback(() => {
93
+ const currentSessionId = sessionIdRef.current;
94
+ const currentCapabilityToken = capabilityTokenRef.current;
95
+ if (!currentSessionId || !currentCapabilityToken) {
96
+ return;
97
+ }
98
+ if (wsRef.current?.readyState === WebSocket.OPEN || wsRef.current?.readyState === WebSocket.CONNECTING) {
99
+ return;
100
+ }
101
+ const wsUrl = `${getWebSocketBaseUrl(apiUrl)}/api/public/ws/agent-chat/${currentSessionId}?token=${encodeURIComponent(currentCapabilityToken)}`;
102
+ const ws = new WebSocket(wsUrl);
103
+ ws.onopen = () => {
104
+ setState((prev) => ({ ...prev, isConnected: true, error: null }));
105
+ retryCountRef.current = 0;
106
+ queryClientRef.current.invalidateQueries({
107
+ queryKey: publicAgentChatKeys.messages(currentSessionId)
108
+ });
109
+ };
110
+ ws.onmessage = (event) => {
111
+ try {
112
+ const data = JSON.parse(event.data);
113
+ if (data.type && data.type !== "turn:complete" && data.type !== "error") {
114
+ const tempMessage = {
115
+ id: `temp-${Date.now()}`,
116
+ role: data.type === "user_message" ? "user" : "assistant",
117
+ messageType: data.type,
118
+ text: formatMessageEvent(data),
119
+ metadata: data.type.startsWith("agent:") ? data : void 0,
120
+ turnNumber: 999999,
121
+ messageIndex: Date.now(),
122
+ createdAt: /* @__PURE__ */ new Date()
123
+ };
124
+ setMessages((prev) => [...prev, tempMessage]);
125
+ } else if (data.type === "turn:complete") {
126
+ if (data.tokenUsage) {
127
+ setLastTokenUsage(data.tokenUsage);
128
+ }
129
+ setState((prev) => ({ ...prev, isProcessing: false }));
130
+ queryClientRef.current.invalidateQueries({
131
+ queryKey: publicAgentChatKeys.messages(currentSessionId)
132
+ });
133
+ } else if (data.type === "error") {
134
+ setState((prev) => ({
135
+ ...prev,
136
+ error: data.error,
137
+ isProcessing: false
138
+ }));
139
+ }
140
+ } catch {
141
+ setState((prev) => ({ ...prev, error: "Failed to parse agent chat message" }));
142
+ }
143
+ };
144
+ ws.onerror = () => {
145
+ };
146
+ ws.onclose = (event) => {
147
+ setState((prev) => ({ ...prev, isConnected: false }));
148
+ if (!event.wasClean && retryCountRef.current >= WS_MAX_RETRIES_BEFORE_ERROR) {
149
+ setState((prev) => ({ ...prev, error: "Unable to connect to agent chat. Retrying..." }));
150
+ }
151
+ const terminalCodes = [1003, 1008];
152
+ if (terminalCodes.includes(event.code) || event.code >= 4e3) {
153
+ setState((prev) => ({
154
+ ...prev,
155
+ error: `Connection rejected (code ${event.code})`
156
+ }));
157
+ return;
158
+ }
159
+ const delay = Math.min(WS_RECONNECT_BASE_DELAY * Math.pow(2, retryCountRef.current), WS_RECONNECT_MAX_DELAY);
160
+ retryCountRef.current += 1;
161
+ reconnectTimeoutRef.current = setTimeout(connect, delay);
162
+ };
163
+ wsRef.current = ws;
164
+ }, [apiUrl]);
165
+ useEffect(() => {
166
+ retryCountRef.current = 0;
167
+ if (sessionId && capabilityToken) {
168
+ connect();
169
+ }
170
+ return () => {
171
+ if (reconnectTimeoutRef.current) {
172
+ clearTimeout(reconnectTimeoutRef.current);
173
+ }
174
+ if (wsRef.current) {
175
+ wsRef.current.close();
176
+ wsRef.current = null;
177
+ }
178
+ };
179
+ }, [sessionId, capabilityToken, connect]);
180
+ const sendMessage = useCallback(
181
+ (text) => {
182
+ const trimmed = text.trim();
183
+ if (!trimmed || state.isProcessing) {
184
+ return;
185
+ }
186
+ if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
187
+ setState((prev) => ({ ...prev, error: "WebSocket not connected" }));
188
+ return;
189
+ }
190
+ const tokenValidation = validateTokenLimit(trimmed, {
191
+ maxTokens: TOKEN_LIMITS.USER_MESSAGE
192
+ });
193
+ if (!tokenValidation.withinLimit) {
194
+ setState((prev) => ({ ...prev, error: "Input too large" }));
195
+ return;
196
+ }
197
+ const userMessage = {
198
+ id: `temp-${Date.now()}`,
199
+ role: "user",
200
+ messageType: "user_message",
201
+ text: trimmed,
202
+ turnNumber: 999999,
203
+ messageIndex: Date.now(),
204
+ createdAt: /* @__PURE__ */ new Date()
205
+ };
206
+ setMessages((prev) => [...prev, userMessage]);
207
+ const message = WebSocketSessionTurnSchema.parse({
208
+ type: "session:turn",
209
+ input: { message: trimmed }
210
+ });
211
+ wsRef.current.send(JSON.stringify(message));
212
+ setState((prev) => ({ ...prev, isProcessing: true, error: null }));
213
+ },
214
+ [state.isProcessing]
215
+ );
216
+ const clearError = useCallback(() => {
217
+ setState((prev) => ({ ...prev, error: null }));
218
+ }, []);
219
+ return {
220
+ messages,
221
+ state,
222
+ sendMessage,
223
+ clearError,
224
+ lastTokenUsage
225
+ };
226
+ }
227
+ async function fetchJson(url, init) {
228
+ const response = await fetch(url, init);
229
+ if (!response.ok) {
230
+ throw new Error(`Request failed with status ${response.status}`);
231
+ }
232
+ return await response.json();
233
+ }
234
+ function mergeMessages(historyMessages, liveMessages) {
235
+ const messageMap = /* @__PURE__ */ new Map();
236
+ for (const message of historyMessages) {
237
+ messageMap.set(message.id, message);
238
+ }
239
+ for (const message of liveMessages) {
240
+ if (!message.id.startsWith("temp-")) {
241
+ messageMap.set(message.id, message);
242
+ continue;
243
+ }
244
+ const exists = Array.from(messageMap.values()).some((existing) => {
245
+ if (existing.role !== message.role) return false;
246
+ if (existing.text !== message.text) return false;
247
+ if (message.metadata && existing.metadata) {
248
+ return JSON.stringify(existing.metadata) === JSON.stringify(message.metadata);
249
+ }
250
+ return true;
251
+ });
252
+ if (!exists) {
253
+ messageMap.set(message.id, message);
254
+ }
255
+ }
256
+ return Array.from(messageMap.values()).sort((a, b) => {
257
+ if (a.turnNumber !== b.turnNumber) return a.turnNumber - b.turnNumber;
258
+ return (a.messageIndex ?? 0) - (b.messageIndex ?? 0);
259
+ });
260
+ }
261
+ function PublicAgentChat({
262
+ apiUrl,
263
+ slug,
264
+ visitorId,
265
+ metadata,
266
+ title,
267
+ className,
268
+ style,
269
+ onSessionReady
270
+ }) {
271
+ const [grant, setGrant] = useState(null);
272
+ const [capabilityToken, setCapabilityToken] = useState(null);
273
+ const [session, setSession] = useState(null);
274
+ const [status, setStatus] = useState("loading");
275
+ const [error, setError] = useState(null);
276
+ const [accessCode, setAccessCode] = useState("");
277
+ const [input, setInput] = useState("");
278
+ const autoStartedRef = useRef(false);
279
+ const { data: historyMessages = [] } = usePublicAgentChatMessages(apiUrl, session?.sessionId ?? null, capabilityToken);
280
+ const { messages: liveMessages, state, sendMessage, clearError } = usePublicAgentChatWebSocket(
281
+ session?.sessionId ?? null,
282
+ apiUrl,
283
+ capabilityToken
284
+ );
285
+ useEffect(() => {
286
+ let cancelled = false;
287
+ autoStartedRef.current = false;
288
+ setGrant(null);
289
+ setCapabilityToken(null);
290
+ setSession(null);
291
+ setError(null);
292
+ setStatus("loading");
293
+ fetchJson(`${apiUrl}/api/public/agent-chat/${encodeURIComponent(slug)}`).then((payload) => {
294
+ if (cancelled) return;
295
+ setGrant(payload.grant);
296
+ setStatus(payload.grant.requiresCode ? "code-required" : "authorizing");
297
+ }).catch((requestError) => {
298
+ if (cancelled) return;
299
+ setError(requestError instanceof Error ? requestError.message : "Unable to load agent chat");
300
+ setStatus("error");
301
+ });
302
+ return () => {
303
+ cancelled = true;
304
+ };
305
+ }, [apiUrl, slug]);
306
+ const startSession = useCallback(
307
+ async (code) => {
308
+ if (!grant) return;
309
+ try {
310
+ setError(null);
311
+ setStatus("authorizing");
312
+ const authorization = await fetchJson(
313
+ `${apiUrl}/api/public/agent-chat/${encodeURIComponent(slug)}/authorize`,
314
+ {
315
+ method: "POST",
316
+ headers: { "Content-Type": "application/json" },
317
+ body: JSON.stringify({
318
+ ...code ? { code } : {},
319
+ ...visitorId ? { visitorId } : {}
320
+ })
321
+ }
322
+ );
323
+ setCapabilityToken(authorization.capabilityToken);
324
+ const createdSession = await fetchJson(
325
+ `${apiUrl}/api/public/agent-chat/${encodeURIComponent(slug)}/sessions`,
326
+ {
327
+ method: "POST",
328
+ headers: { "Content-Type": "application/json" },
329
+ body: JSON.stringify({
330
+ capabilityToken: authorization.capabilityToken,
331
+ ...metadata ? { metadata } : {}
332
+ })
333
+ }
334
+ );
335
+ setSession(createdSession);
336
+ setStatus("ready");
337
+ onSessionReady?.(createdSession);
338
+ } catch (requestError) {
339
+ setError(requestError instanceof Error ? requestError.message : "Unable to start agent chat");
340
+ setStatus(grant.requiresCode ? "code-required" : "error");
341
+ }
342
+ },
343
+ [apiUrl, grant, metadata, onSessionReady, slug, visitorId]
344
+ );
345
+ useEffect(() => {
346
+ if (!grant || grant.requiresCode || autoStartedRef.current) {
347
+ return;
348
+ }
349
+ autoStartedRef.current = true;
350
+ void startSession();
351
+ }, [grant, startSession]);
352
+ const allMessages = useMemo(() => mergeMessages(historyMessages, liveMessages), [historyMessages, liveMessages]);
353
+ const handleSend = () => {
354
+ const trimmed = input.trim();
355
+ if (!trimmed || state.isProcessing) return;
356
+ sendMessage(trimmed);
357
+ setInput("");
358
+ };
359
+ if (status === "loading" || status === "authorizing") {
360
+ return /* @__PURE__ */ jsx(Center, { className, style: { minHeight: 360, ...style }, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) });
361
+ }
362
+ if (status === "code-required") {
363
+ return /* @__PURE__ */ jsx(Center, { className, style: { minHeight: 360, padding: 16, ...style }, children: /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "lg", radius: "md", style: { width: "min(100%, 420px)" }, children: /* @__PURE__ */ jsx(
364
+ "form",
365
+ {
366
+ onSubmit: (event) => {
367
+ event.preventDefault();
368
+ void startSession(accessCode);
369
+ },
370
+ children: /* @__PURE__ */ jsxs(Stack, { children: [
371
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
372
+ /* @__PURE__ */ jsx(IconLock, { size: 18 }),
373
+ /* @__PURE__ */ jsx(Title, { order: 2, size: "h4", children: title ?? "Agent Chat" })
374
+ ] }),
375
+ error && /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), children: error }),
376
+ /* @__PURE__ */ jsx(
377
+ PasswordInput,
378
+ {
379
+ label: "Access code",
380
+ value: accessCode,
381
+ onChange: (event) => setAccessCode(event.currentTarget.value),
382
+ autoComplete: "one-time-code",
383
+ required: true
384
+ }
385
+ ),
386
+ /* @__PURE__ */ jsx(Button, { type: "submit", leftSection: /* @__PURE__ */ jsx(IconSend, { size: 16 }), disabled: !accessCode.trim(), children: "Continue" })
387
+ ] })
388
+ }
389
+ ) }) });
390
+ }
391
+ if (status === "error") {
392
+ return /* @__PURE__ */ jsx(Center, { className, style: { minHeight: 360, padding: 16, ...style }, children: /* @__PURE__ */ jsx(Alert, { color: "red", icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), title: title ?? "Agent Chat", children: /* @__PURE__ */ jsx(Text, { size: "sm", children: error ?? "Unable to load agent chat" }) }) });
393
+ }
394
+ return /* @__PURE__ */ jsx("div", { className, style: { height: "100%", minHeight: 480, display: "flex", flexDirection: "column", ...style }, children: /* @__PURE__ */ jsx(
395
+ ChatInterface,
396
+ {
397
+ messages: allMessages,
398
+ input,
399
+ onInputChange: setInput,
400
+ onSendMessage: handleSend,
401
+ isProcessing: state.isProcessing,
402
+ isConnected: state.isConnected,
403
+ error: state.error,
404
+ onClearError: clearError,
405
+ emptyStateText: "No messages yet",
406
+ emptyStateSubtext: "Send a message to start the conversation",
407
+ placeholder: "Message the agent...",
408
+ messageAreaVariant: "plain"
409
+ }
410
+ ) });
411
+ }
412
+
413
+ export { PublicAgentChat, publicAgentChatKeys, usePublicAgentChatMessages, usePublicAgentChatWebSocket };