@standardagents/react 0.8.3 → 0.9.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/index.d.ts CHANGED
@@ -152,6 +152,10 @@ declare function AgentBuilderProvider({ config, children }: AgentBuilderProvider
152
152
  * Event listener callback type
153
153
  */
154
154
  type EventListener<T = unknown> = (data: T) => void;
155
+ /**
156
+ * WebSocket connection status
157
+ */
158
+ type ConnectionStatus = 'connecting' | 'connected' | 'disconnected';
155
159
  /**
156
160
  * Thread context value
157
161
  */
@@ -164,6 +168,8 @@ interface ThreadContextValue {
164
168
  loading: boolean;
165
169
  /** Any error that occurred */
166
170
  error: Error | null;
171
+ /** WebSocket connection status */
172
+ connectionStatus: ConnectionStatus;
167
173
  /** Subscribe to a specific event type */
168
174
  subscribeToEvent: <T = unknown>(eventType: string, listener: EventListener<T>) => () => void;
169
175
  /** Options passed to the provider */
@@ -454,4 +460,4 @@ interface StopThreadOptions {
454
460
  */
455
461
  declare function stopThread(id: string, options?: StopThreadOptions): Promise<void>;
456
462
 
457
- export { type AgentBuilderConfig, AgentBuilderProvider, type CustomEvent, type ErrorEvent, type GetMessagesOptions, type LogDataEvent, type LogStreamEvent, type LogWebSocketCallbacks, type Message, type MessageChunkEvent, type MessageDataEvent, type MessageStreamEvent, type MessageWebSocketCallbacks, type SendMessagePayload, type StoppedByUserEvent, type Thread, type ThreadEvent, type ThreadMessage, ThreadProvider, type ThreadProviderOptions, type UseThreadOptions, type WorkItem, type WorkMessage, onThreadEvent, sendMessage, stopThread, useSendMessage, useStopThread, useThread, useThreadContext, useThreadEvent, useThreadId };
463
+ export { type AgentBuilderConfig, AgentBuilderProvider, type ConnectionStatus, type CustomEvent, type ErrorEvent, type GetMessagesOptions, type LogDataEvent, type LogStreamEvent, type LogWebSocketCallbacks, type Message, type MessageChunkEvent, type MessageDataEvent, type MessageStreamEvent, type MessageWebSocketCallbacks, type SendMessagePayload, type StoppedByUserEvent, type Thread, type ThreadEvent, type ThreadMessage, ThreadProvider, type ThreadProviderOptions, type UseThreadOptions, type WorkItem, type WorkMessage, onThreadEvent, sendMessage, stopThread, useSendMessage, useStopThread, useThread, useThreadContext, useThreadEvent, useThreadId };
package/dist/index.js CHANGED
@@ -92,6 +92,9 @@ var AgentBuilderClient = class {
92
92
  };
93
93
  ws.onmessage = (event) => {
94
94
  try {
95
+ if (typeof event.data === "string" && event.data === "pong") {
96
+ return;
97
+ }
95
98
  const data = JSON.parse(event.data);
96
99
  switch (data.type) {
97
100
  case "message_data":
@@ -113,8 +116,10 @@ var AgentBuilderClient = class {
113
116
  };
114
117
  ws.onerror = (event) => {
115
118
  console.error("WebSocket error:", event);
119
+ callbacks.onError?.({ type: "error", error: "WebSocket connection error" });
116
120
  };
117
- ws.onclose = () => {
121
+ ws.onclose = (event) => {
122
+ console.log(`[AgentBuilderClient] Message WebSocket closed - code: ${event.code}, reason: ${event.reason || "none"}, wasClean: ${event.wasClean}`);
118
123
  callbacks.onClose?.();
119
124
  };
120
125
  return ws;
@@ -134,6 +139,9 @@ var AgentBuilderClient = class {
134
139
  };
135
140
  ws.onmessage = (event) => {
136
141
  try {
142
+ if (typeof event.data === "string" && event.data === "pong") {
143
+ return;
144
+ }
137
145
  const data = JSON.parse(event.data);
138
146
  switch (data.type) {
139
147
  case "log_data":
@@ -285,23 +293,34 @@ function ThreadProvider({
285
293
  const [messages, setMessages] = useState([]);
286
294
  const [loading, setLoading] = useState(preload);
287
295
  const [error, setError] = useState(null);
296
+ const [connectionStatus, setConnectionStatus] = useState(
297
+ live ? "connecting" : "disconnected"
298
+ );
288
299
  const eventListenersRef = useRef(/* @__PURE__ */ new Map());
289
300
  const wsRef = useRef(null);
290
- const subscribeToEvent = useCallback((eventType, listener) => {
291
- if (!eventListenersRef.current.has(eventType)) {
292
- eventListenersRef.current.set(eventType, /* @__PURE__ */ new Set());
293
- }
294
- eventListenersRef.current.get(eventType).add(listener);
295
- return () => {
296
- const listeners = eventListenersRef.current.get(eventType);
297
- if (listeners) {
298
- listeners.delete(listener);
299
- if (listeners.size === 0) {
300
- eventListenersRef.current.delete(eventType);
301
- }
301
+ const reconnectAttempts = useRef(0);
302
+ const reconnectTimeoutRef = useRef(null);
303
+ const heartbeatIntervalRef = useRef(null);
304
+ const isReconnectingRef = useRef(false);
305
+ const isMountedRef = useRef(true);
306
+ const subscribeToEvent = useCallback(
307
+ (eventType, listener) => {
308
+ if (!eventListenersRef.current.has(eventType)) {
309
+ eventListenersRef.current.set(eventType, /* @__PURE__ */ new Set());
302
310
  }
303
- };
304
- }, []);
311
+ eventListenersRef.current.get(eventType).add(listener);
312
+ return () => {
313
+ const listeners = eventListenersRef.current.get(eventType);
314
+ if (listeners) {
315
+ listeners.delete(listener);
316
+ if (listeners.size === 0) {
317
+ eventListenersRef.current.delete(eventType);
318
+ }
319
+ }
320
+ };
321
+ },
322
+ []
323
+ );
305
324
  const dispatchEvent = useCallback((eventType, data) => {
306
325
  const listeners = eventListenersRef.current.get(eventType);
307
326
  if (listeners) {
@@ -314,32 +333,61 @@ function ThreadProvider({
314
333
  });
315
334
  }
316
335
  }, []);
317
- useEffect(() => {
318
- if (!preload || !threadId) return;
319
- const fetchMessages = async () => {
320
- setLoading(true);
321
- setError(null);
322
- try {
323
- const fetchedMessages = await clientRef.current.getMessages(threadId, {
324
- depth,
325
- includeSilent
326
- });
327
- setMessages(fetchedMessages);
328
- } catch (err) {
329
- console.error("Failed to fetch messages:", err);
330
- setError(err instanceof Error ? err : new Error("Failed to fetch messages"));
331
- setMessages([]);
332
- } finally {
333
- setLoading(false);
336
+ const clearTimers = useCallback(() => {
337
+ if (reconnectTimeoutRef.current) {
338
+ clearTimeout(reconnectTimeoutRef.current);
339
+ reconnectTimeoutRef.current = null;
340
+ }
341
+ if (heartbeatIntervalRef.current) {
342
+ clearInterval(heartbeatIntervalRef.current);
343
+ heartbeatIntervalRef.current = null;
344
+ }
345
+ }, []);
346
+ const startHeartbeat = useCallback((ws) => {
347
+ if (heartbeatIntervalRef.current) {
348
+ clearInterval(heartbeatIntervalRef.current);
349
+ }
350
+ heartbeatIntervalRef.current = setInterval(() => {
351
+ if (ws.readyState === WebSocket.OPEN) {
352
+ ws.send("ping");
334
353
  }
335
- };
336
- fetchMessages();
337
- }, [threadId, preload, depth, includeSilent]);
354
+ }, 3e4);
355
+ }, []);
338
356
  useEffect(() => {
339
357
  if (!live || !threadId) return;
358
+ console.log(
359
+ `[ThreadProvider] useEffect running - threadId: ${threadId}, live: ${live}`
360
+ );
361
+ connectWebSocket();
362
+ return () => {
363
+ console.log(
364
+ `[ThreadProvider] useEffect cleanup - threadId: ${threadId}, live: ${live}`
365
+ );
366
+ clearTimers();
367
+ if (wsRef.current) {
368
+ wsRef.current.close();
369
+ wsRef.current = null;
370
+ }
371
+ reconnectAttempts.current = 0;
372
+ isReconnectingRef.current = false;
373
+ };
374
+ }, [threadId, live]);
375
+ const connectWebSocket = useCallback(() => {
376
+ if (!live || !threadId || !isMountedRef.current) return;
377
+ console.log(`[ThreadProvider] Connecting WebSocket for thread ${threadId}`);
378
+ setConnectionStatus("connecting");
340
379
  const ws = clientRef.current.connectMessageWebSocket(
341
380
  threadId,
342
381
  {
382
+ onOpen: () => {
383
+ console.log(
384
+ `[ThreadProvider] WebSocket connected for thread ${threadId}`
385
+ );
386
+ setConnectionStatus("connected");
387
+ reconnectAttempts.current = 0;
388
+ isReconnectingRef.current = false;
389
+ startHeartbeat(ws);
390
+ },
343
391
  onMessage: (event) => {
344
392
  setMessages((prev) => {
345
393
  const exists = prev.some((m) => m.id === event.data.id);
@@ -367,8 +415,32 @@ function ThreadProvider({
367
415
  dispatchEvent(event.eventType, event.data);
368
416
  },
369
417
  onError: (event) => {
370
- console.error("WebSocket error:", event.error);
418
+ console.error("[ThreadProvider] WebSocket error:", event.error);
371
419
  setError(new Error(event.error));
420
+ setConnectionStatus("disconnected");
421
+ },
422
+ onClose: () => {
423
+ console.log("[ThreadProvider] WebSocket closed");
424
+ clearTimers();
425
+ if (isMountedRef.current && !isReconnectingRef.current) {
426
+ isReconnectingRef.current = true;
427
+ setConnectionStatus("connecting");
428
+ const delay = Math.min(
429
+ 1e3 * Math.pow(2, reconnectAttempts.current),
430
+ 3e4
431
+ );
432
+ reconnectAttempts.current++;
433
+ console.log(
434
+ `[ThreadProvider] Reconnecting in ${delay}ms (attempt ${reconnectAttempts.current})`
435
+ );
436
+ reconnectTimeoutRef.current = setTimeout(() => {
437
+ if (isMountedRef.current) {
438
+ connectWebSocket();
439
+ }
440
+ }, delay);
441
+ } else {
442
+ setConnectionStatus("disconnected");
443
+ }
372
444
  }
373
445
  },
374
446
  {
@@ -377,17 +449,51 @@ function ThreadProvider({
377
449
  }
378
450
  );
379
451
  wsRef.current = ws;
452
+ }, [
453
+ threadId,
454
+ live,
455
+ depth,
456
+ includeSilent,
457
+ dispatchEvent,
458
+ startHeartbeat,
459
+ clearTimers
460
+ ]);
461
+ useEffect(() => {
462
+ if (!preload || !threadId) return;
463
+ const fetchMessages = async () => {
464
+ setLoading(true);
465
+ setError(null);
466
+ try {
467
+ const fetchedMessages = await clientRef.current.getMessages(threadId, {
468
+ depth,
469
+ includeSilent
470
+ });
471
+ setMessages(fetchedMessages);
472
+ } catch (err) {
473
+ console.error("Failed to fetch messages:", err);
474
+ setError(
475
+ err instanceof Error ? err : new Error("Failed to fetch messages")
476
+ );
477
+ setMessages([]);
478
+ } finally {
479
+ setLoading(false);
480
+ }
481
+ };
482
+ fetchMessages();
483
+ }, [threadId, preload, depth, includeSilent]);
484
+ useEffect(() => {
485
+ isMountedRef.current = true;
380
486
  return () => {
381
- ws.close();
382
- wsRef.current = null;
487
+ isMountedRef.current = false;
383
488
  };
384
- }, [threadId, live, depth, includeSilent, dispatchEvent]);
489
+ }, []);
385
490
  const contextValue = useMemo(
386
491
  () => ({
387
492
  threadId,
388
493
  messages,
389
494
  loading,
390
495
  error,
496
+ connectionStatus,
391
497
  subscribeToEvent,
392
498
  options: {
393
499
  depth,
@@ -395,7 +501,17 @@ function ThreadProvider({
395
501
  ...options
396
502
  }
397
503
  }),
398
- [threadId, messages, loading, error, subscribeToEvent, depth, includeSilent, options]
504
+ [
505
+ threadId,
506
+ messages,
507
+ loading,
508
+ error,
509
+ connectionStatus,
510
+ subscribeToEvent,
511
+ depth,
512
+ includeSilent,
513
+ options
514
+ ]
399
515
  );
400
516
  return /* @__PURE__ */ jsx(ThreadContext.Provider, { value: contextValue, children });
401
517
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/client.ts","../src/services/sendMessage.ts","../src/services/stopThread.ts","../src/context/AgentBuilderProvider.tsx","../src/context/ThreadProvider.tsx","../src/utils/workblocks.ts","../src/hooks/useThread.ts","../src/hooks/onThreadEvent.ts","../src/hooks/useSendMessage.ts","../src/hooks/useStopThread.ts"],"names":["globalEndpoint","createContext","useEffect","useMemo","jsx","useContext","useState","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n Message,\n Thread,\n SendMessagePayload,\n GetMessagesOptions,\n MessageWebSocketCallbacks,\n LogWebSocketCallbacks,\n MessageStreamEvent,\n LogStreamEvent,\n ThreadEvent,\n} from '../types'\n\nexport class AgentBuilderClient {\n private endpoint: string\n private token: string | null\n\n constructor(endpoint: string) {\n // Normalize endpoint by removing trailing slash\n this.endpoint = endpoint.replace(/\\/$/, '')\n\n // Read auth token from localStorage\n this.token = typeof localStorage !== 'undefined'\n ? localStorage.getItem('agentbuilder_auth_token')\n : null\n }\n\n /**\n * Get thread metadata\n */\n async getThread(id: string): Promise<Thread> {\n const response = await fetch(`${this.endpoint}/threads/${id}`, {\n method: 'GET',\n headers: this.getHeaders(),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to get thread: ${response.statusText}`)\n }\n\n return response.json()\n }\n\n /**\n * Get messages from a thread with optional pagination and filtering\n */\n async getMessages(\n id: string,\n options: GetMessagesOptions = {}\n ): Promise<Message[]> {\n const params = new URLSearchParams()\n\n if (options.limit !== undefined) params.set('limit', String(options.limit))\n if (options.offset !== undefined) params.set('offset', String(options.offset))\n if (options.depth !== undefined) params.set('depth', String(options.depth))\n if (options.includeSilent !== undefined) params.set('includeSilent', String(options.includeSilent))\n\n const queryString = params.toString()\n const url = `${this.endpoint}/threads/${id}/messages${queryString ? `?${queryString}` : ''}`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to get messages: ${response.statusText}`)\n }\n\n const data = await response.json()\n return data.messages || []\n }\n\n /**\n * Send a message to a thread\n */\n async sendMessage(\n id: string,\n payload: SendMessagePayload\n ): Promise<Message> {\n const response = await fetch(`${this.endpoint}/threads/${id}/message`, {\n method: 'POST',\n headers: {\n ...this.getHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to send message: ${response.statusText}`)\n }\n\n return response.json()\n }\n\n /**\n * Stop execution of a thread\n */\n async stopExecution(id: string): Promise<void> {\n const response = await fetch(`${this.endpoint}/threads/${id}/stop`, {\n method: 'POST',\n headers: this.getHeaders(),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to stop execution: ${response.statusText}`)\n }\n\n await response.json()\n }\n\n /**\n * Connect to message WebSocket for real-time message updates\n */\n connectMessageWebSocket(\n id: string,\n callbacks: MessageWebSocketCallbacks = {},\n options: { includeSilent?: boolean; depth?: number } = {}\n ): WebSocket {\n const params = new URLSearchParams()\n\n if (this.token) params.set('token', this.token)\n if (options.includeSilent !== undefined) params.set('includeSilent', String(options.includeSilent))\n if (options.depth !== undefined) params.set('depth', String(options.depth))\n\n const wsProtocol = this.endpoint.startsWith('https') ? 'wss' : 'ws'\n const wsEndpoint = this.endpoint.replace(/^https?/, wsProtocol)\n const url = `${wsEndpoint}/threads/${id}/stream?${params.toString()}`\n\n const ws = new WebSocket(url)\n\n ws.onopen = () => {\n callbacks.onOpen?.()\n }\n\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data) as MessageStreamEvent\n\n switch (data.type) {\n case 'message_data':\n callbacks.onMessage?.(data)\n break\n case 'message_chunk':\n callbacks.onChunk?.(data)\n break\n case 'event':\n callbacks.onEvent?.(data as ThreadEvent)\n break\n case 'error':\n callbacks.onError?.(data)\n break\n }\n } catch (error) {\n console.error('Failed to parse WebSocket message:', error)\n }\n }\n\n ws.onerror = (event) => {\n console.error('WebSocket error:', event)\n }\n\n ws.onclose = () => {\n callbacks.onClose?.()\n }\n\n return ws\n }\n\n /**\n * Connect to log WebSocket for custom events\n */\n connectLogWebSocket(\n id: string,\n callbacks: LogWebSocketCallbacks = {}\n ): WebSocket {\n const params = new URLSearchParams()\n\n if (this.token) params.set('token', this.token)\n\n const wsProtocol = this.endpoint.startsWith('https') ? 'wss' : 'ws'\n const wsEndpoint = this.endpoint.replace(/^https?/, wsProtocol)\n const url = `${wsEndpoint}/threads/${id}?${params.toString()}`\n\n const ws = new WebSocket(url)\n\n ws.onopen = () => {\n callbacks.onOpen?.()\n }\n\n ws.onmessage = (event) => {\n try {\n const data = JSON.parse(event.data) as LogStreamEvent\n\n switch (data.type) {\n case 'log_data':\n callbacks.onLog?.(data)\n break\n case 'custom':\n callbacks.onCustom?.(data)\n break\n case 'stopped_by_user':\n callbacks.onStopped?.(data)\n break\n }\n } catch (error) {\n console.error('Failed to parse WebSocket message:', error)\n }\n }\n\n ws.onerror = (event) => {\n console.error('WebSocket error:', event)\n }\n\n ws.onclose = () => {\n callbacks.onClose?.()\n }\n\n return ws\n }\n\n /**\n * Get headers for HTTP requests\n */\n private getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {}\n\n if (this.token) {\n headers['Authorization'] = `Bearer ${this.token}`\n }\n\n return headers\n }\n}\n","import type { SendMessagePayload, Message } from '../types'\n\n// Global client instance (set by AgentBuilderProvider)\nlet globalEndpoint: string | null = null\n\n/**\n * Internal function to set the global endpoint.\n * Called by AgentBuilderProvider when it mounts.\n * @internal\n */\nexport function __setGlobalEndpoint(endpoint: string) {\n globalEndpoint = endpoint\n}\n\n/**\n * Send a message to a specific thread.\n *\n * This is a standalone function that sends messages to threads.\n * It requires that an AgentBuilderProvider is mounted somewhere in your app\n * to set the global endpoint configuration.\n *\n * @param id - The thread ID to send the message to\n * @param payload - The message payload containing role, content, and optional silent flag\n * @returns Promise resolving to the created message\n *\n * @throws Error if called before AgentBuilderProvider is mounted\n *\n * @example\n * ```tsx\n * import { sendMessage } from '@standardagents/react'\n *\n * await sendMessage('thread-123', {\n * role: 'user',\n * content: 'Hello, agent!',\n * })\n *\n * // Send a silent message\n * await sendMessage('thread-123', {\n * role: 'user',\n * content: 'Silent message',\n * silent: true,\n * })\n * ```\n */\nexport async function sendMessage(\n id: string,\n payload: SendMessagePayload\n): Promise<Message> {\n if (!globalEndpoint) {\n throw new Error(\n 'sendMessage requires AgentBuilderProvider to be mounted in your app'\n )\n }\n\n // Read auth token from localStorage\n const token =\n typeof localStorage !== 'undefined'\n ? localStorage.getItem('agentbuilder_auth_token')\n : null\n\n // Build headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n // Make the request\n const response = await fetch(`${globalEndpoint}/threads/${id}/message`, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to send message: ${response.statusText}`)\n }\n\n return response.json()\n}\n","// Global endpoint instance (set by AgentBuilderProvider)\nlet globalEndpoint: string | null = null\n\n/**\n * Internal function to set the global endpoint.\n * Called by AgentBuilderProvider when it mounts.\n * @internal\n */\nexport function __setGlobalEndpointForStop(endpoint: string) {\n globalEndpoint = endpoint\n}\n\nexport interface StopThreadOptions {\n /**\n * Override the endpoint URL for this request.\n * If not provided, uses the endpoint from AgentBuilderProvider.\n */\n endpoint?: string\n}\n\n/**\n * Stop execution of a thread.\n *\n * This is a standalone function that stops a running thread execution.\n * It requires that an AgentBuilderProvider is mounted somewhere in your app\n * to set the global endpoint configuration, or you can provide a custom endpoint.\n *\n * @param id - The thread ID to stop\n * @param options - Optional configuration including custom endpoint\n * @returns Promise that resolves when the thread is stopped\n *\n * @throws Error if called before AgentBuilderProvider is mounted and no endpoint is provided\n *\n * @example\n * ```tsx\n * import { stopThread } from '@standardagents/react'\n *\n * // Using global endpoint from AgentBuilderProvider\n * await stopThread('thread-123')\n *\n * // Using custom endpoint\n * await stopThread('thread-123', {\n * endpoint: 'https://custom.example.com/api'\n * })\n * ```\n */\nexport async function stopThread(\n id: string,\n options?: StopThreadOptions\n): Promise<void> {\n const endpoint = options?.endpoint ?? globalEndpoint\n\n if (!endpoint) {\n throw new Error(\n 'stopThread requires AgentBuilderProvider to be mounted or endpoint option to be provided'\n )\n }\n\n // Normalize endpoint by removing trailing slash\n const normalizedEndpoint = endpoint.replace(/\\/$/, '')\n\n // Read auth token from localStorage\n const token =\n typeof localStorage !== 'undefined'\n ? localStorage.getItem('agentbuilder_auth_token')\n : null\n\n // Build headers\n const headers: Record<string, string> = {}\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n // Make the request\n const response = await fetch(`${normalizedEndpoint}/threads/${id}/stop`, {\n method: 'POST',\n headers,\n })\n\n if (!response.ok) {\n throw new Error(`Failed to stop thread: ${response.statusText}`)\n }\n\n await response.json()\n}\n","import React, { createContext, useContext, useMemo, useEffect, type ReactNode } from 'react'\nimport { AgentBuilderClient } from '../services/client'\nimport { __setGlobalEndpoint } from '../services/sendMessage'\nimport { __setGlobalEndpointForStop } from '../services/stopThread'\nimport type { AgentBuilderConfig } from '../types'\n\ninterface AgentBuilderContextValue {\n client: AgentBuilderClient\n config: AgentBuilderConfig\n}\n\nexport const AgentBuilderContext = createContext<AgentBuilderContextValue | null>(null)\n\nexport interface AgentBuilderProviderProps {\n config: AgentBuilderConfig\n children: ReactNode\n}\n\n/**\n * AgentBuilderProvider provides the AgentBuilder client instance to all child components.\n * This should wrap the part of your app where you want to use AgentBuilder functionality.\n *\n * @example\n * ```tsx\n * <AgentBuilderProvider config={{ endpoint: 'https://api.example.com' }}>\n * <YourApp />\n * </AgentBuilderProvider>\n * ```\n */\nexport function AgentBuilderProvider({ config, children }: AgentBuilderProviderProps) {\n // Create client instance only once using useMemo\n const client = useMemo(() => {\n return new AgentBuilderClient(config.endpoint)\n }, [config.endpoint])\n\n const value = useMemo(\n () => ({\n client,\n config,\n }),\n [client, config]\n )\n\n // Set global endpoint for standalone functions like sendMessage and stopThread\n useEffect(() => {\n __setGlobalEndpoint(config.endpoint)\n __setGlobalEndpointForStop(config.endpoint)\n }, [config.endpoint])\n\n return <AgentBuilderContext.Provider value={value}>{children}</AgentBuilderContext.Provider>\n}\n\n/**\n * Hook to access the AgentBuilder client instance.\n * Must be used within an AgentBuilderProvider.\n *\n * @throws Error if used outside of AgentBuilderProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useAgentBuilderClient()\n * // Use client.getThread(), client.sendMessage(), etc.\n * }\n * ```\n */\nexport function useAgentBuilderClient(): AgentBuilderClient {\n const context = useContext(AgentBuilderContext)\n\n if (!context) {\n throw new Error('useAgentBuilderClient must be used within AgentBuilderProvider')\n }\n\n return context.client\n}\n\n/**\n * Hook to access the AgentBuilder config.\n * Must be used within an AgentBuilderProvider.\n *\n * @throws Error if used outside of AgentBuilderProvider\n */\nexport function useAgentBuilderConfig(): AgentBuilderConfig {\n const context = useContext(AgentBuilderContext)\n\n if (!context) {\n throw new Error('useAgentBuilderConfig must be used within AgentBuilderProvider')\n }\n\n return context.config\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n useCallback,\n useMemo,\n type ReactNode,\n} from 'react'\nimport { useAgentBuilderClient, useAgentBuilderConfig } from './AgentBuilderProvider'\nimport { AgentBuilderClient } from '../services/client'\nimport type { Message, ThreadEvent, ThreadProviderOptions } from '../types'\n\n/**\n * Event listener callback type\n */\ntype EventListener<T = unknown> = (data: T) => void\n\n/**\n * Thread context value\n */\ninterface ThreadContextValue {\n /** The thread ID */\n threadId: string\n /** Current messages in the thread */\n messages: Message[]\n /** Whether messages are currently loading */\n loading: boolean\n /** Any error that occurred */\n error: Error | null\n /** Subscribe to a specific event type */\n subscribeToEvent: <T = unknown>(eventType: string, listener: EventListener<T>) => () => void\n /** Options passed to the provider */\n options: ThreadProviderOptions\n}\n\nexport const ThreadContext = createContext<ThreadContextValue | null>(null)\n\nexport interface ThreadProviderProps {\n /** The thread ID to connect to */\n threadId: string\n /** Provider options */\n options?: ThreadProviderOptions\n /** Whether to preload messages on mount (default: true) */\n preload?: boolean\n /** Whether to enable live updates via WebSocket (default: true) */\n live?: boolean\n /** Maximum message depth to fetch/stream (default: 0 for top-level only) */\n depth?: number\n /** Whether to include silent messages (default: false) */\n includeSilent?: boolean\n /** Optional endpoint override */\n endpoint?: string\n children: ReactNode\n}\n\n/**\n * ThreadProvider establishes a WebSocket connection to a thread and provides\n * context for child components to access messages and events.\n *\n * Must be nested inside AgentBuilderProvider.\n *\n * @example\n * ```tsx\n * <AgentBuilderProvider config={{ endpoint: 'https://api.example.com' }}>\n * <ThreadProvider threadId=\"thread-123\">\n * <ChatMessages />\n * </ThreadProvider>\n * </AgentBuilderProvider>\n * ```\n */\nexport function ThreadProvider({\n threadId,\n options = {},\n preload = true,\n live = true,\n depth = 0,\n includeSilent = false,\n endpoint: endpointOverride,\n children,\n}: ThreadProviderProps) {\n const contextClient = useAgentBuilderClient()\n const contextConfig = useAgentBuilderConfig()\n\n // Use override endpoint if provided, otherwise use context endpoint\n const effectiveEndpoint = endpointOverride || contextConfig.endpoint\n\n // Create a client instance\n const clientRef = useRef<AgentBuilderClient>(\n endpointOverride ? new AgentBuilderClient(endpointOverride) : contextClient\n )\n\n // Update client if endpoint override changes\n useEffect(() => {\n if (endpointOverride) {\n clientRef.current = new AgentBuilderClient(endpointOverride)\n } else {\n clientRef.current = contextClient\n }\n }, [endpointOverride, contextClient])\n\n // State\n const [messages, setMessages] = useState<Message[]>([])\n const [loading, setLoading] = useState(preload)\n const [error, setError] = useState<Error | null>(null)\n\n // Event listeners registry\n const eventListenersRef = useRef<Map<string, Set<EventListener>>>(new Map())\n\n // WebSocket ref\n const wsRef = useRef<WebSocket | null>(null)\n\n /**\n * Subscribe to a specific event type\n */\n const subscribeToEvent = useCallback(<T = unknown>(\n eventType: string,\n listener: EventListener<T>\n ): (() => void) => {\n if (!eventListenersRef.current.has(eventType)) {\n eventListenersRef.current.set(eventType, new Set())\n }\n eventListenersRef.current.get(eventType)!.add(listener as EventListener)\n\n // Return unsubscribe function\n return () => {\n const listeners = eventListenersRef.current.get(eventType)\n if (listeners) {\n listeners.delete(listener as EventListener)\n if (listeners.size === 0) {\n eventListenersRef.current.delete(eventType)\n }\n }\n }\n }, [])\n\n /**\n * Dispatch event to all registered listeners\n */\n const dispatchEvent = useCallback((eventType: string, data: unknown) => {\n const listeners = eventListenersRef.current.get(eventType)\n if (listeners) {\n listeners.forEach((listener) => {\n try {\n listener(data)\n } catch (err) {\n console.error(`Error in event listener for \"${eventType}\":`, err)\n }\n })\n }\n }, [])\n\n // Fetch initial messages\n useEffect(() => {\n if (!preload || !threadId) return\n\n const fetchMessages = async () => {\n setLoading(true)\n setError(null)\n\n try {\n const fetchedMessages = await clientRef.current.getMessages(threadId, {\n depth,\n includeSilent,\n })\n setMessages(fetchedMessages)\n } catch (err) {\n console.error('Failed to fetch messages:', err)\n setError(err instanceof Error ? err : new Error('Failed to fetch messages'))\n setMessages([])\n } finally {\n setLoading(false)\n }\n }\n\n fetchMessages()\n }, [threadId, preload, depth, includeSilent])\n\n // Set up WebSocket connection\n useEffect(() => {\n if (!live || !threadId) return\n\n const ws = clientRef.current.connectMessageWebSocket(\n threadId,\n {\n onMessage: (event) => {\n setMessages((prev) => {\n // Check if message already exists\n const exists = prev.some((m) => m.id === event.data.id)\n if (exists) {\n // Update existing message\n return prev.map((m) => (m.id === event.data.id ? event.data : m))\n } else {\n // Add new message\n return [...prev, event.data]\n }\n })\n },\n onChunk: (event) => {\n // Handle streaming chunks\n setMessages((prev) => {\n return prev.map((m) => {\n if (m.id === event.message_id) {\n return {\n ...m,\n content: (m.content || '') + event.chunk,\n }\n }\n return m\n })\n })\n },\n onEvent: (event) => {\n // Dispatch custom events to subscribers\n dispatchEvent(event.eventType, event.data)\n },\n onError: (event) => {\n console.error('WebSocket error:', event.error)\n setError(new Error(event.error))\n },\n },\n {\n depth,\n includeSilent,\n }\n )\n\n wsRef.current = ws\n\n return () => {\n ws.close()\n wsRef.current = null\n }\n }, [threadId, live, depth, includeSilent, dispatchEvent])\n\n // Memoize context value\n const contextValue = useMemo(\n (): ThreadContextValue => ({\n threadId,\n messages,\n loading,\n error,\n subscribeToEvent,\n options: {\n depth,\n includeSilent,\n ...options,\n },\n }),\n [threadId, messages, loading, error, subscribeToEvent, depth, includeSilent, options]\n )\n\n return (\n <ThreadContext.Provider value={contextValue}>\n {children}\n </ThreadContext.Provider>\n )\n}\n\n/**\n * Hook to access the thread context.\n * Must be used within a ThreadProvider.\n *\n * @throws Error if used outside of ThreadProvider\n */\nexport function useThreadContext(): ThreadContextValue {\n const context = useContext(ThreadContext)\n\n if (!context) {\n throw new Error('useThreadContext must be used within a ThreadProvider')\n }\n\n return context\n}\n\n/**\n * Hook to get the current thread ID from context.\n * Must be used within a ThreadProvider.\n */\nexport function useThreadId(): string {\n return useThreadContext().threadId\n}\n","import type { Message, WorkMessage, WorkItem, ThreadMessage } from '../types'\n\n/**\n * Transform a flat list of messages into a list with workblocks.\n * Groups consecutive assistant tool_calls and their tool results into WorkMessage objects.\n *\n * A workblock starts when an assistant message has tool_calls,\n * and includes all subsequent tool messages until:\n * - A non-tool message appears\n * - Another assistant message without tool_calls appears\n */\nexport function transformToWorkblocks(messages: Message[]): ThreadMessage[] {\n if (messages.length === 0) {\n return []\n }\n\n const result: ThreadMessage[] = []\n let i = 0\n\n while (i < messages.length) {\n const message = messages[i]\n\n // Check if this is an assistant message with tool_calls\n if (message.role === 'assistant' && message.tool_calls) {\n // Try to parse tool_calls\n let toolCalls: any[]\n try {\n toolCalls = JSON.parse(message.tool_calls)\n } catch (error) {\n // If we can't parse tool_calls, treat it as a regular message\n result.push(message)\n i++\n continue\n }\n\n // Start building a workblock\n const workItems: WorkItem[] = []\n\n // Add tool calls as work items (status determined after collecting results)\n for (const toolCall of toolCalls) {\n workItems.push({\n id: toolCall.id || message.id,\n type: 'tool_call',\n name: toolCall.function?.name,\n content: toolCall.function?.arguments || null,\n status: null, // Will be updated below based on matching results\n tool_call_id: toolCall.id,\n })\n }\n\n // Collect subsequent tool result messages\n let j = i + 1\n while (j < messages.length && messages[j].role === 'tool') {\n const toolMessage = messages[j]\n // A tool result is pending if it has no tool_status set\n // (tool_status is set to 'success' or 'error' when execution completes)\n const resultStatus = toolMessage.tool_status || 'pending'\n\n workItems.push({\n id: toolMessage.id,\n type: 'tool_result',\n name: toolMessage.name || undefined,\n content: toolMessage.content,\n status: resultStatus,\n tool_call_id: toolMessage.tool_call_id || undefined,\n })\n j++\n }\n\n // Update tool call statuses based on their matching results\n for (const item of workItems) {\n if (item.type === 'tool_call' && item.tool_call_id) {\n // Find matching result\n const matchingResult = workItems.find(\n wi => wi.type === 'tool_result' && wi.tool_call_id === item.tool_call_id\n )\n if (matchingResult) {\n // Tool call inherits status from its result\n item.status = matchingResult.status\n } else {\n // No result yet - tool call is pending\n item.status = 'pending'\n }\n }\n }\n\n // Determine workblock status based on the assistant message status only\n // Individual tool errors are reflected in the work item's status, not the workblock\n let status: 'pending' | 'completed' | 'failed' = 'completed'\n if (message.status === 'pending') {\n status = 'pending'\n } else if (message.status === 'failed') {\n status = 'failed'\n }\n\n // Create the workblock\n const workblock: WorkMessage = {\n id: message.id,\n type: 'workblock',\n content: message.content,\n reasoning_content: message.reasoning_content,\n workItems,\n status,\n created_at: message.created_at,\n depth: message.depth,\n }\n\n result.push(workblock)\n\n // Move index past all consumed messages\n i = j\n } else {\n // Not a workblock, pass through unchanged\n result.push(message)\n i++\n }\n }\n\n return result\n}\n","import { useContext, useMemo } from 'react'\nimport { ThreadContext } from '../context/ThreadProvider'\nimport { transformToWorkblocks } from '../utils/workblocks'\nimport type { ThreadMessage, UseThreadOptions } from '../types'\n\n/**\n * Hook to get messages from a thread.\n *\n * Must be used within a ThreadProvider. The thread ID and WebSocket connection\n * are managed by the ThreadProvider, so this hook simply returns the messages.\n *\n * @param options - Configuration options\n * @returns Array of messages (raw or transformed to workblocks)\n *\n * @example\n * ```tsx\n * function ChatMessages() {\n * // Basic usage - returns messages from context\n * const messages = useThread()\n *\n * return (\n * <div>\n * {messages.map(msg => <Message key={msg.id} message={msg} />)}\n * </div>\n * )\n * }\n *\n * // Wrap with ThreadProvider\n * <ThreadProvider threadId=\"thread-123\">\n * <ChatMessages />\n * </ThreadProvider>\n * ```\n *\n * @example\n * ```tsx\n * // Disable workblocks transformation\n * const messages = useThread({ useWorkblocks: false })\n * ```\n */\nexport function useThread(options: UseThreadOptions = {}): ThreadMessage[] {\n const {\n useWorkblocks = true,\n } = options\n\n const context = useContext(ThreadContext)\n\n if (!context) {\n throw new Error(\n 'useThread must be used within a ThreadProvider. ' +\n 'Wrap your component with <ThreadProvider threadId=\"...\">.'\n )\n }\n\n const { messages } = context\n\n // Transform to workblocks if requested\n const transformedMessages = useMemo(() => {\n return useWorkblocks ? transformToWorkblocks(messages) : messages\n }, [messages, useWorkblocks])\n\n return transformedMessages\n}\n","import { useContext, useEffect, useState } from 'react'\nimport { ThreadContext } from '../context/ThreadProvider'\n\n/**\n * Hook to listen for custom events emitted from a thread via the stream WebSocket.\n * Calls the provided callback whenever an event of the specified type is received.\n *\n * Must be used within a ThreadProvider. Events are emitted from the backend\n * using `emitThreadEvent(flow, 'event-type', data)`.\n *\n * @param type - The custom event type to filter for\n * @param callback - Function to call when an event of this type is received\n *\n * @example\n * ```tsx\n * function GamePreview() {\n * const [gameHtml, setGameHtml] = useState<string | null>(null)\n *\n * onThreadEvent('game_built', (data: { success: boolean }) => {\n * if (data.success) {\n * fetchGameHtml()\n * }\n * })\n *\n * return <iframe srcDoc={gameHtml} />\n * }\n * ```\n *\n * @example\n * ```tsx\n * function ProgressIndicator() {\n * const [progress, setProgress] = useState(0)\n *\n * onThreadEvent('progress', (data: { step: number; total: number }) => {\n * setProgress(data.step / data.total * 100)\n * })\n *\n * return <ProgressBar value={progress} />\n * }\n * ```\n */\nexport function onThreadEvent<T = unknown>(\n type: string,\n callback: (data: T) => void\n): void {\n const context = useContext(ThreadContext)\n\n if (!context) {\n throw new Error(\n 'onThreadEvent must be used within a ThreadProvider. ' +\n 'Wrap your component with <ThreadProvider threadId=\"...\">.'\n )\n }\n\n const { subscribeToEvent } = context\n\n useEffect(() => {\n // Subscribe to events of the specified type\n const unsubscribe = subscribeToEvent<T>(type, callback)\n\n // Cleanup subscription on unmount\n return unsubscribe\n }, [subscribeToEvent, type, callback])\n}\n\n/**\n * Hook to get the latest event data for a specific event type as React state.\n * Returns the most recent event data, or null if no event has been received.\n *\n * Must be used within a ThreadProvider. Events are emitted from the backend\n * using `emitThreadEvent(flow, 'event-type', data)`.\n *\n * @param type - The custom event type to filter for\n * @returns The latest event data matching the specified type, or null if none received\n *\n * @example\n * ```tsx\n * function ProgressIndicator() {\n * const progress = useThreadEvent<{ step: number; total: number }>('progress')\n *\n * if (!progress) return null\n *\n * return (\n * <div>\n * Step {progress.step} of {progress.total}\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * function StatusDisplay() {\n * const status = useThreadEvent<{ message: string }>('status')\n *\n * useEffect(() => {\n * if (status) {\n * console.log('Status updated:', status.message)\n * }\n * }, [status])\n *\n * return <div>{status?.message ?? 'No status'}</div>\n * }\n * ```\n */\nexport function useThreadEvent<T = unknown>(type: string): T | null {\n const context = useContext(ThreadContext)\n const [eventData, setEventData] = useState<T | null>(null)\n\n if (!context) {\n throw new Error(\n 'useThreadEvent must be used within a ThreadProvider. ' +\n 'Wrap your component with <ThreadProvider threadId=\"...\">.'\n )\n }\n\n const { subscribeToEvent } = context\n\n useEffect(() => {\n // Subscribe to events of the specified type\n const unsubscribe = subscribeToEvent<T>(type, (data) => {\n setEventData(data)\n })\n\n // Cleanup subscription on unmount\n return unsubscribe\n }, [subscribeToEvent, type])\n\n return eventData\n}\n","import { useCallback } from 'react'\nimport { useThreadContext } from '../context/ThreadProvider'\nimport { sendMessage as sendMessageService } from '../services/sendMessage'\nimport type { SendMessagePayload, Message } from '../types'\n\n/**\n * Hook that returns a function to send messages to the current thread.\n * Must be used within a ThreadProvider.\n *\n * This hook automatically uses the thread ID from the ThreadProvider context,\n * so you don't need to pass it manually.\n *\n * @returns A function that sends a message to the current thread\n *\n * @throws Error if used outside of ThreadProvider\n *\n * @example\n * ```tsx\n * function ChatInput() {\n * const sendMessage = useSendMessage()\n *\n * const handleSubmit = async (content: string) => {\n * await sendMessage({\n * role: 'user',\n * content,\n * })\n * }\n *\n * return <input onSubmit={handleSubmit} />\n * }\n * ```\n */\nexport function useSendMessage(): (payload: SendMessagePayload) => Promise<Message> {\n let context: ReturnType<typeof useThreadContext>\n\n try {\n context = useThreadContext()\n } catch {\n throw new Error('useSendMessage must be used within a ThreadProvider')\n }\n\n const { threadId } = context\n\n return useCallback(\n (payload: SendMessagePayload) => {\n return sendMessageService(threadId, payload)\n },\n [threadId]\n )\n}\n","import { useCallback } from 'react'\nimport { useThreadContext } from '../context/ThreadProvider'\nimport { stopThread as stopThreadService } from '../services/stopThread'\n\n/**\n * Hook that returns a function to stop the current thread's execution.\n * Must be used within a ThreadProvider.\n *\n * This hook automatically uses the thread ID from the ThreadProvider context,\n * so you don't need to pass it manually.\n *\n * @returns A function that stops the current thread's execution\n *\n * @throws Error if used outside of ThreadProvider\n *\n * @example\n * ```tsx\n * function StopButton() {\n * const stopThread = useStopThread()\n *\n * return (\n * <button onClick={() => stopThread()}>\n * Stop\n * </button>\n * )\n * }\n * ```\n */\nexport function useStopThread(): () => Promise<void> {\n let context: ReturnType<typeof useThreadContext>\n\n try {\n context = useThreadContext()\n } catch {\n throw new Error('useStopThread must be used within a ThreadProvider')\n }\n\n const { threadId } = context\n\n return useCallback(\n () => {\n return stopThreadService(threadId)\n },\n [threadId]\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/services/client.ts","../src/services/sendMessage.ts","../src/services/stopThread.ts","../src/context/AgentBuilderProvider.tsx","../src/context/ThreadProvider.tsx","../src/utils/workblocks.ts","../src/hooks/useThread.ts","../src/hooks/onThreadEvent.ts","../src/hooks/useSendMessage.ts","../src/hooks/useStopThread.ts"],"names":["globalEndpoint","createContext","useEffect","useMemo","jsx","useContext","useState","useCallback"],"mappings":";;;;;;AAYO,IAAM,qBAAN,MAAyB;AAAA,EACtB,QAAA;AAAA,EACA,KAAA;AAAA,EAER,YAAY,QAAA,EAAkB;AAE5B,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAG1C,IAAA,IAAA,CAAK,QAAQ,OAAO,YAAA,KAAiB,cACjC,YAAA,CAAa,OAAA,CAAQ,yBAAyB,CAAA,GAC9C,IAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,EAAA,EAA6B;AAC3C,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,QAAQ,CAAA,SAAA,EAAY,EAAE,CAAA,CAAA,EAAI;AAAA,MAC7D,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,KAAK,UAAA;AAAW,KAC1B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IAChE;AAEA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,CACJ,EAAA,EACA,OAAA,GAA8B,EAAC,EACX;AACpB,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AAEnC,IAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC1E,IAAA,IAAI,OAAA,CAAQ,WAAW,MAAA,EAAW,MAAA,CAAO,IAAI,QAAA,EAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AAC7E,IAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC1E,IAAA,IAAI,OAAA,CAAQ,kBAAkB,MAAA,EAAW,MAAA,CAAO,IAAI,eAAA,EAAiB,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAC,CAAA;AAElG,IAAA,MAAM,WAAA,GAAc,OAAO,QAAA,EAAS;AACpC,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA,SAAA,EAAY,EAAE,CAAA,SAAA,EAAY,WAAA,GAAc,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAE1F,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAChC,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,KAAK,UAAA;AAAW,KAC1B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IAClE;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,OAAO,IAAA,CAAK,YAAY,EAAC;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,CACJ,EAAA,EACA,OAAA,EACkB;AAClB,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,QAAQ,CAAA,SAAA,EAAY,EAAE,CAAA,QAAA,CAAA,EAAY;AAAA,MACrE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,GAAG,KAAK,UAAA,EAAW;AAAA,QACnB,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC7B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IAClE;AAEA,IAAA,OAAO,SAAS,IAAA,EAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,EAAA,EAA2B;AAC7C,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,QAAQ,CAAA,SAAA,EAAY,EAAE,CAAA,KAAA,CAAA,EAAS;AAAA,MAClE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,KAAK,UAAA;AAAW,KAC1B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IACpE;AAEA,IAAA,MAAM,SAAS,IAAA,EAAK;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,wBACE,EAAA,EACA,SAAA,GAAuC,EAAC,EACxC,OAAA,GAAuD,EAAC,EAC7C;AACX,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AAEnC,IAAA,IAAI,KAAK,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,KAAK,KAAK,CAAA;AAC9C,IAAA,IAAI,OAAA,CAAQ,kBAAkB,MAAA,EAAW,MAAA,CAAO,IAAI,eAAA,EAAiB,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAC,CAAA;AAClG,IAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAC,CAAA;AAE1E,IAAA,MAAM,aAAa,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,OAAO,IAAI,KAAA,GAAQ,IAAA;AAC/D,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,WAAW,UAAU,CAAA;AAC9D,IAAA,MAAM,GAAA,GAAM,GAAG,UAAU,CAAA,SAAA,EAAY,EAAE,CAAA,QAAA,EAAW,MAAA,CAAO,UAAU,CAAA,CAAA;AAEnE,IAAA,MAAM,EAAA,GAAK,IAAI,SAAA,CAAU,GAAG,CAAA;AAE5B,IAAA,EAAA,CAAG,SAAS,MAAM;AAChB,MAAA,SAAA,CAAU,MAAA,IAAS;AAAA,IACrB,CAAA;AAEA,IAAA,EAAA,CAAG,SAAA,GAAY,CAAC,KAAA,KAAU;AACxB,MAAA,IAAI;AAEF,QAAA,IAAI,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,SAAS,MAAA,EAAQ;AAC3D,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAElC,QAAA,QAAQ,KAAK,IAAA;AAAM,UACjB,KAAK,cAAA;AACH,YAAA,SAAA,CAAU,YAAY,IAAI,CAAA;AAC1B,YAAA;AAAA,UACF,KAAK,eAAA;AACH,YAAA,SAAA,CAAU,UAAU,IAAI,CAAA;AACxB,YAAA;AAAA,UACF,KAAK,OAAA;AACH,YAAA,SAAA,CAAU,UAAU,IAAmB,CAAA;AACvC,YAAA;AAAA,UACF,KAAK,OAAA;AACH,YAAA,SAAA,CAAU,UAAU,IAAI,CAAA;AACxB,YAAA;AAAA;AACJ,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,sCAAsC,KAAK,CAAA;AAAA,MAC3D;AAAA,IACF,CAAA;AAEA,IAAA,EAAA,CAAG,OAAA,GAAU,CAAC,KAAA,KAAU;AACtB,MAAA,OAAA,CAAQ,KAAA,CAAM,oBAAoB,KAAK,CAAA;AACvC,MAAA,SAAA,CAAU,UAAU,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,8BAA8B,CAAA;AAAA,IAC5E,CAAA;AAEA,IAAA,EAAA,CAAG,OAAA,GAAU,CAAC,KAAA,KAAU;AACtB,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,sDAAA,EAAyD,KAAA,CAAM,IAAI,CAAA,UAAA,EAAa,KAAA,CAAM,MAAA,IAAU,MAAM,CAAA,YAAA,EAAe,KAAA,CAAM,QAAQ,CAAA,CAAE,CAAA;AACjJ,MAAA,SAAA,CAAU,OAAA,IAAU;AAAA,IACtB,CAAA;AAEA,IAAA,OAAO,EAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAA,CACE,EAAA,EACA,SAAA,GAAmC,EAAC,EACzB;AACX,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AAEnC,IAAA,IAAI,KAAK,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,KAAK,KAAK,CAAA;AAE9C,IAAA,MAAM,aAAa,IAAA,CAAK,QAAA,CAAS,UAAA,CAAW,OAAO,IAAI,KAAA,GAAQ,IAAA;AAC/D,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,WAAW,UAAU,CAAA;AAC9D,IAAA,MAAM,GAAA,GAAM,GAAG,UAAU,CAAA,SAAA,EAAY,EAAE,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,CAAA,CAAA;AAE5D,IAAA,MAAM,EAAA,GAAK,IAAI,SAAA,CAAU,GAAG,CAAA;AAE5B,IAAA,EAAA,CAAG,SAAS,MAAM;AAChB,MAAA,SAAA,CAAU,MAAA,IAAS;AAAA,IACrB,CAAA;AAEA,IAAA,EAAA,CAAG,SAAA,GAAY,CAAC,KAAA,KAAU;AACxB,MAAA,IAAI;AAEF,QAAA,IAAI,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,SAAS,MAAA,EAAQ;AAC3D,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAElC,QAAA,QAAQ,KAAK,IAAA;AAAM,UACjB,KAAK,UAAA;AACH,YAAA,SAAA,CAAU,QAAQ,IAAI,CAAA;AACtB,YAAA;AAAA,UACF,KAAK,QAAA;AACH,YAAA,SAAA,CAAU,WAAW,IAAI,CAAA;AACzB,YAAA;AAAA,UACF,KAAK,iBAAA;AACH,YAAA,SAAA,CAAU,YAAY,IAAI,CAAA;AAC1B,YAAA;AAAA;AACJ,MACF,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,sCAAsC,KAAK,CAAA;AAAA,MAC3D;AAAA,IACF,CAAA;AAEA,IAAA,EAAA,CAAG,OAAA,GAAU,CAAC,KAAA,KAAU;AACtB,MAAA,OAAA,CAAQ,KAAA,CAAM,oBAAoB,KAAK,CAAA;AAAA,IACzC,CAAA;AAEA,IAAA,EAAA,CAAG,UAAU,MAAM;AACjB,MAAA,SAAA,CAAU,OAAA,IAAU;AAAA,IACtB,CAAA;AAEA,IAAA,OAAO,EAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAA,GAAqC;AAC3C,IAAA,MAAM,UAAkC,EAAC;AAEzC,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AAAA,IACjD;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AACF,CAAA;;;AClPA,IAAI,cAAA,GAAgC,IAAA;AAO7B,SAAS,oBAAoB,QAAA,EAAkB;AACpD,EAAA,cAAA,GAAiB,QAAA;AACnB;AAgCA,eAAsB,WAAA,CACpB,IACA,OAAA,EACkB;AAClB,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,QACJ,OAAO,YAAA,KAAiB,cACpB,YAAA,CAAa,OAAA,CAAQ,yBAAyB,CAAA,GAC9C,IAAA;AAGN,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,cAAA,EAAgB;AAAA,GAClB;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA;AAAA,EAC5C;AAGA,EAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,cAAc,CAAA,SAAA,EAAY,EAAE,CAAA,QAAA,CAAA,EAAY;AAAA,IACtE,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,GAC7B,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACvB;;;AChFA,IAAIA,eAAAA,GAAgC,IAAA;AAO7B,SAAS,2BAA2B,QAAA,EAAkB;AAC3D,EAAAA,eAAAA,GAAiB,QAAA;AACnB;AAoCA,eAAsB,UAAA,CACpB,IACA,OAAA,EACe;AACf,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAYA,eAAAA;AAEtC,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,kBAAA,GAAqB,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAGrD,EAAA,MAAM,QACJ,OAAO,YAAA,KAAiB,cACpB,YAAA,CAAa,OAAA,CAAQ,yBAAyB,CAAA,GAC9C,IAAA;AAGN,EAAA,MAAM,UAAkC,EAAC;AAEzC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA;AAAA,EAC5C;AAGA,EAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,kBAAkB,CAAA,SAAA,EAAY,EAAE,CAAA,KAAA,CAAA,EAAS;AAAA,IACvE,MAAA,EAAQ,MAAA;AAAA,IACR;AAAA,GACD,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,EACjE;AAEA,EAAA,MAAM,SAAS,IAAA,EAAK;AACtB;AC1EO,IAAM,mBAAA,GAAsB,cAA+C,IAAI,CAAA;AAkB/E,SAAS,oBAAA,CAAqB,EAAE,MAAA,EAAQ,QAAA,EAAS,EAA8B;AAEpF,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAM;AAC3B,IAAA,OAAO,IAAI,kBAAA,CAAmB,MAAA,CAAO,QAAQ,CAAA;AAAA,EAC/C,CAAA,EAAG,CAAC,MAAA,CAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,OAAO;AAAA,MACL,MAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,QAAQ,MAAM;AAAA,GACjB;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,mBAAA,CAAoB,OAAO,QAAQ,CAAA;AACnC,IAAA,0BAAA,CAA2B,OAAO,QAAQ,CAAA;AAAA,EAC5C,CAAA,EAAG,CAAC,MAAA,CAAO,QAAQ,CAAC,CAAA;AAEpB,EAAA,uBAAO,GAAA,CAAC,mBAAA,CAAoB,QAAA,EAApB,EAA6B,OAAe,QAAA,EAAS,CAAA;AAC/D;AAgBO,SAAS,qBAAA,GAA4C;AAC1D,EAAA,MAAM,OAAA,GAAU,WAAW,mBAAmB,CAAA;AAE9C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAAA,EAClF;AAEA,EAAA,OAAO,OAAA,CAAQ,MAAA;AACjB;AAQO,SAAS,qBAAA,GAA4C;AAC1D,EAAA,MAAM,OAAA,GAAU,WAAW,mBAAmB,CAAA;AAE9C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAAA,EAClF;AAEA,EAAA,OAAO,OAAA,CAAQ,MAAA;AACjB;ACxCO,IAAM,aAAA,GAAgBC,cAAyC,IAAI,CAAA;AAmCnE,SAAS,cAAA,CAAe;AAAA,EAC7B,QAAA;AAAA,EACA,UAAU,EAAC;AAAA,EACX,OAAA,GAAU,IAAA;AAAA,EACV,IAAA,GAAO,IAAA;AAAA,EACP,KAAA,GAAQ,CAAA;AAAA,EACR,aAAA,GAAgB,KAAA;AAAA,EAChB,QAAA,EAAU,gBAAA;AAAA,EACV;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,gBAAgB,qBAAA,EAAsB;AAC5C,EAAA,MAAM,gBAAgB,qBAAA,EAAsB;AAG5C,EAA0B,oBAAoB,aAAA,CAAc;AAG5D,EAAA,MAAM,SAAA,GAAY,MAAA;AAAA,IAChB,gBAAA,GAAmB,IAAI,kBAAA,CAAmB,gBAAgB,CAAA,GAAI;AAAA,GAChE;AAGA,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,SAAA,CAAU,OAAA,GAAU,IAAI,kBAAA,CAAmB,gBAAgB,CAAA;AAAA,IAC7D,CAAA,MAAO;AACL,MAAA,SAAA,CAAU,OAAA,GAAU,aAAA;AAAA,IACtB;AAAA,EACF,CAAA,EAAG,CAAC,gBAAA,EAAkB,aAAa,CAAC,CAAA;AAGpC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAA,CAAoB,EAAE,CAAA;AACtD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,OAAO,CAAA;AAC9C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,QAAA;AAAA,IAC9C,OAAO,YAAA,GAAe;AAAA,GACxB;AAGA,EAAA,MAAM,iBAAA,GAAoB,MAAA,iBAAwC,IAAI,GAAA,EAAK,CAAA;AAG3E,EAAA,MAAM,KAAA,GAAQ,OAAyB,IAAI,CAAA;AAG3C,EAAA,MAAM,iBAAA,GAAoB,OAAe,CAAC,CAAA;AAC1C,EAAA,MAAM,mBAAA,GAAsB,OAA8B,IAAI,CAAA;AAC9D,EAAA,MAAM,oBAAA,GAAuB,OAA8B,IAAI,CAAA;AAC/D,EAAA,MAAM,iBAAA,GAAoB,OAAgB,KAAK,CAAA;AAC/C,EAAA,MAAM,YAAA,GAAe,OAAgB,IAAI,CAAA;AAKzC,EAAA,MAAM,gBAAA,GAAmB,WAAA;AAAA,IACvB,CACE,WACA,QAAA,KACiB;AACjB,MAAA,IAAI,CAAC,iBAAA,CAAkB,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,EAAG;AAC7C,QAAA,iBAAA,CAAkB,OAAA,CAAQ,GAAA,CAAI,SAAA,kBAAW,IAAI,KAAK,CAAA;AAAA,MACpD;AACA,MAAA,iBAAA,CAAkB,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,CAAG,IAAI,QAAyB,CAAA;AAGvE,MAAA,OAAO,MAAM;AACX,QAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA;AACzD,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,SAAA,CAAU,OAAO,QAAyB,CAAA;AAC1C,UAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,YAAA,iBAAA,CAAkB,OAAA,CAAQ,OAAO,SAAS,CAAA;AAAA,UAC5C;AAAA,QACF;AAAA,MACF,CAAA;AAAA,IACF,CAAA;AAAA,IACA;AAAC,GACH;AAKA,EAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,CAAC,SAAA,EAAmB,IAAA,KAAkB;AACtE,IAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA;AACzD,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,SAAA,CAAU,OAAA,CAAQ,CAAC,QAAA,KAAa;AAC9B,QAAA,IAAI;AACF,UAAA,QAAA,CAAS,IAAI,CAAA;AAAA,QACf,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,6BAAA,EAAgC,SAAS,CAAA,EAAA,CAAA,EAAM,GAAG,CAAA;AAAA,QAClE;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,IAAI,oBAAoB,OAAA,EAAS;AAC/B,MAAA,YAAA,CAAa,oBAAoB,OAAO,CAAA;AACxC,MAAA,mBAAA,CAAoB,OAAA,GAAU,IAAA;AAAA,IAChC;AACA,IAAA,IAAI,qBAAqB,OAAA,EAAS;AAChC,MAAA,aAAA,CAAc,qBAAqB,OAAO,CAAA;AAC1C,MAAA,oBAAA,CAAqB,OAAA,GAAU,IAAA;AAAA,IACjC;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,CAAC,EAAA,KAAkB;AAEpD,IAAA,IAAI,qBAAqB,OAAA,EAAS;AAChC,MAAA,aAAA,CAAc,qBAAqB,OAAO,CAAA;AAAA,IAC5C;AAGA,IAAA,oBAAA,CAAqB,OAAA,GAAU,YAAY,MAAM;AAC/C,MAAA,IAAI,EAAA,CAAG,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AACpC,QAAA,EAAA,CAAG,KAAK,MAAM,CAAA;AAAA,MAChB;AAAA,IACF,GAAG,GAAK,CAAA;AAAA,EACV,CAAA,EAAG,EAAE,CAAA;AAGL,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,QAAA,EAAU;AAExB,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN,CAAA,+CAAA,EAAkD,QAAQ,CAAA,QAAA,EAAW,IAAI,CAAA;AAAA,KAC3E;AACA,IAAA,gBAAA,EAAiB;AAEjB,IAAA,OAAO,MAAM;AAEX,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,+CAAA,EAAkD,QAAQ,CAAA,QAAA,EAAW,IAAI,CAAA;AAAA,OAC3E;AACA,MAAA,WAAA,EAAY;AACZ,MAAA,IAAI,MAAM,OAAA,EAAS;AACjB,QAAA,KAAA,CAAM,QAAQ,KAAA,EAAM;AACpB,QAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAAA,MAClB;AACA,MAAA,iBAAA,CAAkB,OAAA,GAAU,CAAA;AAC5B,MAAA,iBAAA,CAAkB,OAAA,GAAU,KAAA;AAAA,IAC9B,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,IAAI,CAAC,CAAA;AAKnB,EAAA,MAAM,gBAAA,GAAmB,YAAY,MAAM;AACzC,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,QAAA,IAAY,CAAC,aAAa,OAAA,EAAS;AAEjD,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,iDAAA,EAAoD,QAAQ,CAAA,CAAE,CAAA;AAC1E,IAAA,mBAAA,CAAoB,YAAY,CAAA;AAEhC,IAAA,MAAM,EAAA,GAAK,UAAU,OAAA,CAAQ,uBAAA;AAAA,MAC3B,QAAA;AAAA,MACA;AAAA,QACE,QAAQ,MAAM;AACZ,UAAA,OAAA,CAAQ,GAAA;AAAA,YACN,mDAAmD,QAAQ,CAAA;AAAA,WAC7D;AACA,UAAA,mBAAA,CAAoB,WAAW,CAAA;AAC/B,UAAA,iBAAA,CAAkB,OAAA,GAAU,CAAA;AAC5B,UAAA,iBAAA,CAAkB,OAAA,GAAU,KAAA;AAC5B,UAAA,cAAA,CAAe,EAAE,CAAA;AAAA,QACnB,CAAA;AAAA,QACA,SAAA,EAAW,CAAC,KAAA,KAAU;AACpB,UAAA,WAAA,CAAY,CAAC,IAAA,KAAS;AAEpB,YAAA,MAAM,MAAA,GAAS,KAAK,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA;AACtD,YAAA,IAAI,MAAA,EAAQ;AAEV,cAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAO,CAAA,CAAE,EAAA,KAAO,KAAA,CAAM,IAAA,CAAK,EAAA,GAAK,KAAA,CAAM,IAAA,GAAO,CAAE,CAAA;AAAA,YAClE,CAAA,MAAO;AAEL,cAAA,OAAO,CAAC,GAAG,IAAA,EAAM,KAAA,CAAM,IAAI,CAAA;AAAA,YAC7B;AAAA,UACF,CAAC,CAAA;AAAA,QACH,CAAA;AAAA,QACA,OAAA,EAAS,CAAC,KAAA,KAAU;AAElB,UAAA,WAAA,CAAY,CAAC,IAAA,KAAS;AACpB,YAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM;AACrB,cAAA,IAAI,CAAA,CAAE,EAAA,KAAO,KAAA,CAAM,UAAA,EAAY;AAC7B,gBAAA,OAAO;AAAA,kBACL,GAAG,CAAA;AAAA,kBACH,OAAA,EAAA,CAAU,CAAA,CAAE,OAAA,IAAW,EAAA,IAAM,KAAA,CAAM;AAAA,iBACrC;AAAA,cACF;AACA,cAAA,OAAO,CAAA;AAAA,YACT,CAAC,CAAA;AAAA,UACH,CAAC,CAAA;AAAA,QACH,CAAA;AAAA,QACA,OAAA,EAAS,CAAC,KAAA,KAAU;AAElB,UAAA,aAAA,CAAc,KAAA,CAAM,SAAA,EAAW,KAAA,CAAM,IAAI,CAAA;AAAA,QAC3C,CAAA;AAAA,QACA,OAAA,EAAS,CAAC,KAAA,KAAU;AAClB,UAAA,OAAA,CAAQ,KAAA,CAAM,mCAAA,EAAqC,KAAA,CAAM,KAAK,CAAA;AAC9D,UAAA,QAAA,CAAS,IAAI,KAAA,CAAM,KAAA,CAAM,KAAK,CAAC,CAAA;AAC/B,UAAA,mBAAA,CAAoB,cAAc,CAAA;AAAA,QACpC,CAAA;AAAA,QACA,SAAS,MAAM;AACb,UAAA,OAAA,CAAQ,IAAI,mCAAmC,CAAA;AAC/C,UAAA,WAAA,EAAY;AAGZ,UAAA,IAAI,YAAA,CAAa,OAAA,IAAW,CAAC,iBAAA,CAAkB,OAAA,EAAS;AACtD,YAAA,iBAAA,CAAkB,OAAA,GAAU,IAAA;AAC5B,YAAA,mBAAA,CAAoB,YAAY,CAAA;AAChC,YAAA,MAAM,QAAQ,IAAA,CAAK,GAAA;AAAA,cACjB,GAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,kBAAkB,OAAO,CAAA;AAAA,cAC5C;AAAA,aACF;AACA,YAAA,iBAAA,CAAkB,OAAA,EAAA;AAElB,YAAA,OAAA,CAAQ,GAAA;AAAA,cACN,CAAA,iCAAA,EAAoC,KAAK,CAAA,YAAA,EAAe,iBAAA,CAAkB,OAAO,CAAA,CAAA;AAAA,aACnF;AAEA,YAAA,mBAAA,CAAoB,OAAA,GAAU,WAAW,MAAM;AAC7C,cAAA,IAAI,aAAa,OAAA,EAAS;AACxB,gBAAA,gBAAA,EAAiB;AAAA,cACnB;AAAA,YACF,GAAG,KAAK,CAAA;AAAA,UACV,CAAA,MAAO;AACL,YAAA,mBAAA,CAAoB,cAAc,CAAA;AAAA,UACpC;AAAA,QACF;AAAA,OACF;AAAA,MACA;AAAA,QACE,KAAA;AAAA,QACA;AAAA;AACF,KACF;AAEA,IAAA,KAAA,CAAM,OAAA,GAAU,EAAA;AAAA,EAClB,CAAA,EAAG;AAAA,IACD,QAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACD,CAAA;AAGD,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,EAAU;AAE3B,IAAA,MAAM,gBAAgB,YAAY;AAChC,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,IAAI,CAAA;AAEb,MAAA,IAAI;AACF,QAAA,MAAM,eAAA,GAAkB,MAAM,SAAA,CAAU,OAAA,CAAQ,YAAY,QAAA,EAAU;AAAA,UACpE,KAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,WAAA,CAAY,eAAe,CAAA;AAAA,MAC7B,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,6BAA6B,GAAG,CAAA;AAC9C,QAAA,QAAA;AAAA,UACE,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,MAAM,0BAA0B;AAAA,SACnE;AACA,QAAA,WAAA,CAAY,EAAE,CAAA;AAAA,MAChB,CAAA,SAAE;AACA,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB;AAAA,IACF,CAAA;AAEA,IAAA,aAAA,EAAc;AAAA,EAChB,GAAG,CAAC,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,aAAa,CAAC,CAAA;AAG5C,EAAAA,UAAU,MAAM;AACd,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,IAAA,OAAO,MAAM;AACX,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AAAA,IACzB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,YAAA,GAAeC,OAAAA;AAAA,IACnB,OAA2B;AAAA,MACzB,QAAA;AAAA,MACA,QAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,gBAAA;AAAA,MACA,gBAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,KAAA;AAAA,QACA,aAAA;AAAA,QACA,GAAG;AAAA;AACL,KACF,CAAA;AAAA,IACA;AAAA,MACE,QAAA;AAAA,MACA,QAAA;AAAA,MACA,OAAA;AAAA,MACA,KAAA;AAAA,MACA,gBAAA;AAAA,MACA,gBAAA;AAAA,MACA,KAAA;AAAA,MACA,aAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,uBACEC,GAAAA,CAAC,aAAA,CAAc,UAAd,EAAuB,KAAA,EAAO,cAC5B,QAAA,EACH,CAAA;AAEJ;AAQO,SAAS,gBAAA,GAAuC;AACrD,EAAA,MAAM,OAAA,GAAUC,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,EACzE;AAEA,EAAA,OAAO,OAAA;AACT;AAMO,SAAS,WAAA,GAAsB;AACpC,EAAA,OAAO,kBAAiB,CAAE,QAAA;AAC5B;;;AClaO,SAAS,sBAAsB,QAAA,EAAsC;AAC1E,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,SAA0B,EAAC;AACjC,EAAA,IAAI,CAAA,GAAI,CAAA;AAER,EAAA,OAAO,CAAA,GAAI,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,OAAA,GAAU,SAAS,CAAC,CAAA;AAG1B,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,WAAA,IAAe,OAAA,CAAQ,UAAA,EAAY;AAEtD,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI;AACF,QAAA,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA;AAAA,MAC3C,SAAS,KAAA,EAAO;AAEd,QAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,QAAA,CAAA,EAAA;AACA,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,YAAwB,EAAC;AAG/B,MAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,QAAA,SAAA,CAAU,IAAA,CAAK;AAAA,UACb,EAAA,EAAI,QAAA,CAAS,EAAA,IAAM,OAAA,CAAQ,EAAA;AAAA,UAC3B,IAAA,EAAM,WAAA;AAAA,UACN,IAAA,EAAM,SAAS,QAAA,EAAU,IAAA;AAAA,UACzB,OAAA,EAAS,QAAA,CAAS,QAAA,EAAU,SAAA,IAAa,IAAA;AAAA,UACzC,MAAA,EAAQ,IAAA;AAAA;AAAA,UACR,cAAc,QAAA,CAAS;AAAA,SACxB,CAAA;AAAA,MACH;AAGA,MAAA,IAAI,IAAI,CAAA,GAAI,CAAA;AACZ,MAAA,OAAO,IAAI,QAAA,CAAS,MAAA,IAAU,SAAS,CAAC,CAAA,CAAE,SAAS,MAAA,EAAQ;AACzD,QAAA,MAAM,WAAA,GAAc,SAAS,CAAC,CAAA;AAG9B,QAAA,MAAM,YAAA,GAAe,YAAY,WAAA,IAAe,SAAA;AAEhD,QAAA,SAAA,CAAU,IAAA,CAAK;AAAA,UACb,IAAI,WAAA,CAAY,EAAA;AAAA,UAChB,IAAA,EAAM,aAAA;AAAA,UACN,IAAA,EAAM,YAAY,IAAA,IAAQ,MAAA;AAAA,UAC1B,SAAS,WAAA,CAAY,OAAA;AAAA,UACrB,MAAA,EAAQ,YAAA;AAAA,UACR,YAAA,EAAc,YAAY,YAAA,IAAgB;AAAA,SAC3C,CAAA;AACD,QAAA,CAAA,EAAA;AAAA,MACF;AAGA,MAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC5B,QAAA,IAAI,IAAA,CAAK,IAAA,KAAS,WAAA,IAAe,IAAA,CAAK,YAAA,EAAc;AAElD,UAAA,MAAM,iBAAiB,SAAA,CAAU,IAAA;AAAA,YAC/B,QAAM,EAAA,CAAG,IAAA,KAAS,aAAA,IAAiB,EAAA,CAAG,iBAAiB,IAAA,CAAK;AAAA,WAC9D;AACA,UAAA,IAAI,cAAA,EAAgB;AAElB,YAAA,IAAA,CAAK,SAAS,cAAA,CAAe,MAAA;AAAA,UAC/B,CAAA,MAAO;AAEL,YAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAIA,MAAA,IAAI,MAAA,GAA6C,WAAA;AACjD,MAAA,IAAI,OAAA,CAAQ,WAAW,SAAA,EAAW;AAChC,QAAA,MAAA,GAAS,SAAA;AAAA,MACX,CAAA,MAAA,IAAW,OAAA,CAAQ,MAAA,KAAW,QAAA,EAAU;AACtC,QAAA,MAAA,GAAS,QAAA;AAAA,MACX;AAGA,MAAA,MAAM,SAAA,GAAyB;AAAA,QAC7B,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,IAAA,EAAM,WAAA;AAAA,QACN,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,QAC3B,SAAA;AAAA,QACA,MAAA;AAAA,QACA,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,OAAO,OAAA,CAAQ;AAAA,OACjB;AAEA,MAAA,MAAA,CAAO,KAAK,SAAS,CAAA;AAGrB,MAAA,CAAA,GAAI,CAAA;AAAA,IACN,CAAA,MAAO;AAEL,MAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,MAAA,CAAA,EAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;;;AChFO,SAAS,SAAA,CAAU,OAAA,GAA4B,EAAC,EAAoB;AACzE,EAAA,MAAM;AAAA,IACJ,aAAA,GAAgB;AAAA,GAClB,GAAI,OAAA;AAEJ,EAAA,MAAM,OAAA,GAAUA,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AAGrB,EAAA,MAAM,mBAAA,GAAsBF,QAAQ,MAAM;AACxC,IAAA,OAAO,aAAA,GAAgB,qBAAA,CAAsB,QAAQ,CAAA,GAAI,QAAA;AAAA,EAC3D,CAAA,EAAG,CAAC,QAAA,EAAU,aAAa,CAAC,CAAA;AAE5B,EAAA,OAAO,mBAAA;AACT;ACpBO,SAAS,aAAA,CACd,MACA,QAAA,EACM;AACN,EAAA,MAAM,OAAA,GAAUE,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,kBAAiB,GAAI,OAAA;AAE7B,EAAAH,UAAU,MAAM;AAEd,IAAA,MAAM,WAAA,GAAc,gBAAA,CAAoB,IAAA,EAAM,QAAQ,CAAA;AAGtD,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,gBAAA,EAAkB,IAAA,EAAM,QAAQ,CAAC,CAAA;AACvC;AA0CO,SAAS,eAA4B,IAAA,EAAwB;AAClE,EAAA,MAAM,OAAA,GAAUG,WAAW,aAAa,CAAA;AACxC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIC,SAAmB,IAAI,CAAA;AAEzD,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,kBAAiB,GAAI,OAAA;AAE7B,EAAAJ,UAAU,MAAM;AAEd,IAAA,MAAM,WAAA,GAAc,gBAAA,CAAoB,IAAA,EAAM,CAAC,IAAA,KAAS;AACtD,MAAA,YAAA,CAAa,IAAI,CAAA;AAAA,IACnB,CAAC,CAAA;AAGD,IAAA,OAAO,WAAA;AAAA,EACT,CAAA,EAAG,CAAC,gBAAA,EAAkB,IAAI,CAAC,CAAA;AAE3B,EAAA,OAAO,SAAA;AACT;ACjGO,SAAS,cAAA,GAAoE;AAClF,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,gBAAA,EAAiB;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,EACvE;AAEA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AAErB,EAAA,OAAOK,WAAAA;AAAA,IACL,CAAC,OAAA,KAAgC;AAC/B,MAAA,OAAO,WAAA,CAAmB,UAAU,OAAO,CAAA;AAAA,IAC7C,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AACF;ACrBO,SAAS,aAAA,GAAqC;AACnD,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,gBAAA,EAAiB;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AAEA,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AAErB,EAAA,OAAOA,WAAAA;AAAA,IACL,MAAM;AACJ,MAAA,OAAO,WAAkB,QAAQ,CAAA;AAAA,IACnC,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AACF","file":"index.js","sourcesContent":["import type {\n Message,\n Thread,\n SendMessagePayload,\n GetMessagesOptions,\n MessageWebSocketCallbacks,\n LogWebSocketCallbacks,\n MessageStreamEvent,\n LogStreamEvent,\n ThreadEvent,\n} from '../types'\n\nexport class AgentBuilderClient {\n private endpoint: string\n private token: string | null\n\n constructor(endpoint: string) {\n // Normalize endpoint by removing trailing slash\n this.endpoint = endpoint.replace(/\\/$/, '')\n\n // Read auth token from localStorage\n this.token = typeof localStorage !== 'undefined'\n ? localStorage.getItem('agentbuilder_auth_token')\n : null\n }\n\n /**\n * Get thread metadata\n */\n async getThread(id: string): Promise<Thread> {\n const response = await fetch(`${this.endpoint}/threads/${id}`, {\n method: 'GET',\n headers: this.getHeaders(),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to get thread: ${response.statusText}`)\n }\n\n return response.json()\n }\n\n /**\n * Get messages from a thread with optional pagination and filtering\n */\n async getMessages(\n id: string,\n options: GetMessagesOptions = {}\n ): Promise<Message[]> {\n const params = new URLSearchParams()\n\n if (options.limit !== undefined) params.set('limit', String(options.limit))\n if (options.offset !== undefined) params.set('offset', String(options.offset))\n if (options.depth !== undefined) params.set('depth', String(options.depth))\n if (options.includeSilent !== undefined) params.set('includeSilent', String(options.includeSilent))\n\n const queryString = params.toString()\n const url = `${this.endpoint}/threads/${id}/messages${queryString ? `?${queryString}` : ''}`\n\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to get messages: ${response.statusText}`)\n }\n\n const data = await response.json()\n return data.messages || []\n }\n\n /**\n * Send a message to a thread\n */\n async sendMessage(\n id: string,\n payload: SendMessagePayload\n ): Promise<Message> {\n const response = await fetch(`${this.endpoint}/threads/${id}/message`, {\n method: 'POST',\n headers: {\n ...this.getHeaders(),\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to send message: ${response.statusText}`)\n }\n\n return response.json()\n }\n\n /**\n * Stop execution of a thread\n */\n async stopExecution(id: string): Promise<void> {\n const response = await fetch(`${this.endpoint}/threads/${id}/stop`, {\n method: 'POST',\n headers: this.getHeaders(),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to stop execution: ${response.statusText}`)\n }\n\n await response.json()\n }\n\n /**\n * Connect to message WebSocket for real-time message updates\n */\n connectMessageWebSocket(\n id: string,\n callbacks: MessageWebSocketCallbacks = {},\n options: { includeSilent?: boolean; depth?: number } = {}\n ): WebSocket {\n const params = new URLSearchParams()\n\n if (this.token) params.set('token', this.token)\n if (options.includeSilent !== undefined) params.set('includeSilent', String(options.includeSilent))\n if (options.depth !== undefined) params.set('depth', String(options.depth))\n\n const wsProtocol = this.endpoint.startsWith('https') ? 'wss' : 'ws'\n const wsEndpoint = this.endpoint.replace(/^https?/, wsProtocol)\n const url = `${wsEndpoint}/threads/${id}/stream?${params.toString()}`\n\n const ws = new WebSocket(url)\n\n ws.onopen = () => {\n callbacks.onOpen?.()\n }\n\n ws.onmessage = (event) => {\n try {\n // Handle pong response from heartbeat ping\n if (typeof event.data === 'string' && event.data === 'pong') {\n return\n }\n\n const data = JSON.parse(event.data) as MessageStreamEvent\n\n switch (data.type) {\n case 'message_data':\n callbacks.onMessage?.(data)\n break\n case 'message_chunk':\n callbacks.onChunk?.(data)\n break\n case 'event':\n callbacks.onEvent?.(data as ThreadEvent)\n break\n case 'error':\n callbacks.onError?.(data)\n break\n }\n } catch (error) {\n console.error('Failed to parse WebSocket message:', error)\n }\n }\n\n ws.onerror = (event) => {\n console.error('WebSocket error:', event)\n callbacks.onError?.({ type: 'error', error: 'WebSocket connection error' })\n }\n\n ws.onclose = (event) => {\n console.log(`[AgentBuilderClient] Message WebSocket closed - code: ${event.code}, reason: ${event.reason || 'none'}, wasClean: ${event.wasClean}`)\n callbacks.onClose?.()\n }\n\n return ws\n }\n\n /**\n * Connect to log WebSocket for custom events\n */\n connectLogWebSocket(\n id: string,\n callbacks: LogWebSocketCallbacks = {}\n ): WebSocket {\n const params = new URLSearchParams()\n\n if (this.token) params.set('token', this.token)\n\n const wsProtocol = this.endpoint.startsWith('https') ? 'wss' : 'ws'\n const wsEndpoint = this.endpoint.replace(/^https?/, wsProtocol)\n const url = `${wsEndpoint}/threads/${id}?${params.toString()}`\n\n const ws = new WebSocket(url)\n\n ws.onopen = () => {\n callbacks.onOpen?.()\n }\n\n ws.onmessage = (event) => {\n try {\n // Handle pong response from heartbeat ping\n if (typeof event.data === 'string' && event.data === 'pong') {\n return\n }\n\n const data = JSON.parse(event.data) as LogStreamEvent\n\n switch (data.type) {\n case 'log_data':\n callbacks.onLog?.(data)\n break\n case 'custom':\n callbacks.onCustom?.(data)\n break\n case 'stopped_by_user':\n callbacks.onStopped?.(data)\n break\n }\n } catch (error) {\n console.error('Failed to parse WebSocket message:', error)\n }\n }\n\n ws.onerror = (event) => {\n console.error('WebSocket error:', event)\n }\n\n ws.onclose = () => {\n callbacks.onClose?.()\n }\n\n return ws\n }\n\n /**\n * Get headers for HTTP requests\n */\n private getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {}\n\n if (this.token) {\n headers['Authorization'] = `Bearer ${this.token}`\n }\n\n return headers\n }\n}\n","import type { SendMessagePayload, Message } from '../types'\n\n// Global client instance (set by AgentBuilderProvider)\nlet globalEndpoint: string | null = null\n\n/**\n * Internal function to set the global endpoint.\n * Called by AgentBuilderProvider when it mounts.\n * @internal\n */\nexport function __setGlobalEndpoint(endpoint: string) {\n globalEndpoint = endpoint\n}\n\n/**\n * Send a message to a specific thread.\n *\n * This is a standalone function that sends messages to threads.\n * It requires that an AgentBuilderProvider is mounted somewhere in your app\n * to set the global endpoint configuration.\n *\n * @param id - The thread ID to send the message to\n * @param payload - The message payload containing role, content, and optional silent flag\n * @returns Promise resolving to the created message\n *\n * @throws Error if called before AgentBuilderProvider is mounted\n *\n * @example\n * ```tsx\n * import { sendMessage } from '@standardagents/react'\n *\n * await sendMessage('thread-123', {\n * role: 'user',\n * content: 'Hello, agent!',\n * })\n *\n * // Send a silent message\n * await sendMessage('thread-123', {\n * role: 'user',\n * content: 'Silent message',\n * silent: true,\n * })\n * ```\n */\nexport async function sendMessage(\n id: string,\n payload: SendMessagePayload\n): Promise<Message> {\n if (!globalEndpoint) {\n throw new Error(\n 'sendMessage requires AgentBuilderProvider to be mounted in your app'\n )\n }\n\n // Read auth token from localStorage\n const token =\n typeof localStorage !== 'undefined'\n ? localStorage.getItem('agentbuilder_auth_token')\n : null\n\n // Build headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n // Make the request\n const response = await fetch(`${globalEndpoint}/threads/${id}/message`, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n throw new Error(`Failed to send message: ${response.statusText}`)\n }\n\n return response.json()\n}\n","// Global endpoint instance (set by AgentBuilderProvider)\nlet globalEndpoint: string | null = null\n\n/**\n * Internal function to set the global endpoint.\n * Called by AgentBuilderProvider when it mounts.\n * @internal\n */\nexport function __setGlobalEndpointForStop(endpoint: string) {\n globalEndpoint = endpoint\n}\n\nexport interface StopThreadOptions {\n /**\n * Override the endpoint URL for this request.\n * If not provided, uses the endpoint from AgentBuilderProvider.\n */\n endpoint?: string\n}\n\n/**\n * Stop execution of a thread.\n *\n * This is a standalone function that stops a running thread execution.\n * It requires that an AgentBuilderProvider is mounted somewhere in your app\n * to set the global endpoint configuration, or you can provide a custom endpoint.\n *\n * @param id - The thread ID to stop\n * @param options - Optional configuration including custom endpoint\n * @returns Promise that resolves when the thread is stopped\n *\n * @throws Error if called before AgentBuilderProvider is mounted and no endpoint is provided\n *\n * @example\n * ```tsx\n * import { stopThread } from '@standardagents/react'\n *\n * // Using global endpoint from AgentBuilderProvider\n * await stopThread('thread-123')\n *\n * // Using custom endpoint\n * await stopThread('thread-123', {\n * endpoint: 'https://custom.example.com/api'\n * })\n * ```\n */\nexport async function stopThread(\n id: string,\n options?: StopThreadOptions\n): Promise<void> {\n const endpoint = options?.endpoint ?? globalEndpoint\n\n if (!endpoint) {\n throw new Error(\n 'stopThread requires AgentBuilderProvider to be mounted or endpoint option to be provided'\n )\n }\n\n // Normalize endpoint by removing trailing slash\n const normalizedEndpoint = endpoint.replace(/\\/$/, '')\n\n // Read auth token from localStorage\n const token =\n typeof localStorage !== 'undefined'\n ? localStorage.getItem('agentbuilder_auth_token')\n : null\n\n // Build headers\n const headers: Record<string, string> = {}\n\n if (token) {\n headers['Authorization'] = `Bearer ${token}`\n }\n\n // Make the request\n const response = await fetch(`${normalizedEndpoint}/threads/${id}/stop`, {\n method: 'POST',\n headers,\n })\n\n if (!response.ok) {\n throw new Error(`Failed to stop thread: ${response.statusText}`)\n }\n\n await response.json()\n}\n","import React, { createContext, useContext, useMemo, useEffect, type ReactNode } from 'react'\nimport { AgentBuilderClient } from '../services/client'\nimport { __setGlobalEndpoint } from '../services/sendMessage'\nimport { __setGlobalEndpointForStop } from '../services/stopThread'\nimport type { AgentBuilderConfig } from '../types'\n\ninterface AgentBuilderContextValue {\n client: AgentBuilderClient\n config: AgentBuilderConfig\n}\n\nexport const AgentBuilderContext = createContext<AgentBuilderContextValue | null>(null)\n\nexport interface AgentBuilderProviderProps {\n config: AgentBuilderConfig\n children: ReactNode\n}\n\n/**\n * AgentBuilderProvider provides the AgentBuilder client instance to all child components.\n * This should wrap the part of your app where you want to use AgentBuilder functionality.\n *\n * @example\n * ```tsx\n * <AgentBuilderProvider config={{ endpoint: 'https://api.example.com' }}>\n * <YourApp />\n * </AgentBuilderProvider>\n * ```\n */\nexport function AgentBuilderProvider({ config, children }: AgentBuilderProviderProps) {\n // Create client instance only once using useMemo\n const client = useMemo(() => {\n return new AgentBuilderClient(config.endpoint)\n }, [config.endpoint])\n\n const value = useMemo(\n () => ({\n client,\n config,\n }),\n [client, config]\n )\n\n // Set global endpoint for standalone functions like sendMessage and stopThread\n useEffect(() => {\n __setGlobalEndpoint(config.endpoint)\n __setGlobalEndpointForStop(config.endpoint)\n }, [config.endpoint])\n\n return <AgentBuilderContext.Provider value={value}>{children}</AgentBuilderContext.Provider>\n}\n\n/**\n * Hook to access the AgentBuilder client instance.\n * Must be used within an AgentBuilderProvider.\n *\n * @throws Error if used outside of AgentBuilderProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const client = useAgentBuilderClient()\n * // Use client.getThread(), client.sendMessage(), etc.\n * }\n * ```\n */\nexport function useAgentBuilderClient(): AgentBuilderClient {\n const context = useContext(AgentBuilderContext)\n\n if (!context) {\n throw new Error('useAgentBuilderClient must be used within AgentBuilderProvider')\n }\n\n return context.client\n}\n\n/**\n * Hook to access the AgentBuilder config.\n * Must be used within an AgentBuilderProvider.\n *\n * @throws Error if used outside of AgentBuilderProvider\n */\nexport function useAgentBuilderConfig(): AgentBuilderConfig {\n const context = useContext(AgentBuilderContext)\n\n if (!context) {\n throw new Error('useAgentBuilderConfig must be used within AgentBuilderProvider')\n }\n\n return context.config\n}\n","import React, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n useCallback,\n useMemo,\n type ReactNode,\n} from \"react\"\nimport {\n useAgentBuilderClient,\n useAgentBuilderConfig,\n} from \"./AgentBuilderProvider\"\nimport { AgentBuilderClient } from \"../services/client\"\nimport type { Message, ThreadEvent, ThreadProviderOptions } from \"../types\"\n\n/**\n * Event listener callback type\n */\ntype EventListener<T = unknown> = (data: T) => void\n\n/**\n * WebSocket connection status\n */\nexport type ConnectionStatus = 'connecting' | 'connected' | 'disconnected'\n\n/**\n * Thread context value\n */\ninterface ThreadContextValue {\n /** The thread ID */\n threadId: string\n /** Current messages in the thread */\n messages: Message[]\n /** Whether messages are currently loading */\n loading: boolean\n /** Any error that occurred */\n error: Error | null\n /** WebSocket connection status */\n connectionStatus: ConnectionStatus\n /** Subscribe to a specific event type */\n subscribeToEvent: <T = unknown>(\n eventType: string,\n listener: EventListener<T>\n ) => () => void\n /** Options passed to the provider */\n options: ThreadProviderOptions\n}\n\nexport const ThreadContext = createContext<ThreadContextValue | null>(null)\n\nexport interface ThreadProviderProps {\n /** The thread ID to connect to */\n threadId: string\n /** Provider options */\n options?: ThreadProviderOptions\n /** Whether to preload messages on mount (default: true) */\n preload?: boolean\n /** Whether to enable live updates via WebSocket (default: true) */\n live?: boolean\n /** Maximum message depth to fetch/stream (default: 0 for top-level only) */\n depth?: number\n /** Whether to include silent messages (default: false) */\n includeSilent?: boolean\n /** Optional endpoint override */\n endpoint?: string\n children: ReactNode\n}\n\n/**\n * ThreadProvider establishes a WebSocket connection to a thread and provides\n * context for child components to access messages and events.\n *\n * Must be nested inside AgentBuilderProvider.\n *\n * @example\n * ```tsx\n * <AgentBuilderProvider config={{ endpoint: 'https://api.example.com' }}>\n * <ThreadProvider threadId=\"thread-123\">\n * <ChatMessages />\n * </ThreadProvider>\n * </AgentBuilderProvider>\n * ```\n */\nexport function ThreadProvider({\n threadId,\n options = {},\n preload = true,\n live = true,\n depth = 0,\n includeSilent = false,\n endpoint: endpointOverride,\n children,\n}: ThreadProviderProps) {\n const contextClient = useAgentBuilderClient()\n const contextConfig = useAgentBuilderConfig()\n\n // Use override endpoint if provided, otherwise use context endpoint\n const effectiveEndpoint = endpointOverride || contextConfig.endpoint\n\n // Create a client instance\n const clientRef = useRef<AgentBuilderClient>(\n endpointOverride ? new AgentBuilderClient(endpointOverride) : contextClient\n )\n\n // Update client if endpoint override changes\n useEffect(() => {\n if (endpointOverride) {\n clientRef.current = new AgentBuilderClient(endpointOverride)\n } else {\n clientRef.current = contextClient\n }\n }, [endpointOverride, contextClient])\n\n // State\n const [messages, setMessages] = useState<Message[]>([])\n const [loading, setLoading] = useState(preload)\n const [error, setError] = useState<Error | null>(null)\n const [connectionStatus, setConnectionStatus] = useState<ConnectionStatus>(\n live ? 'connecting' : 'disconnected'\n )\n\n // Event listeners registry\n const eventListenersRef = useRef<Map<string, Set<EventListener>>>(new Map())\n\n // WebSocket ref\n const wsRef = useRef<WebSocket | null>(null)\n\n // Reconnection state\n const reconnectAttempts = useRef<number>(0)\n const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const heartbeatIntervalRef = useRef<NodeJS.Timeout | null>(null)\n const isReconnectingRef = useRef<boolean>(false)\n const isMountedRef = useRef<boolean>(true)\n\n /**\n * Subscribe to a specific event type\n */\n const subscribeToEvent = useCallback(\n <T = unknown,>(\n eventType: string,\n listener: EventListener<T>\n ): (() => void) => {\n if (!eventListenersRef.current.has(eventType)) {\n eventListenersRef.current.set(eventType, new Set())\n }\n eventListenersRef.current.get(eventType)!.add(listener as EventListener)\n\n // Return unsubscribe function\n return () => {\n const listeners = eventListenersRef.current.get(eventType)\n if (listeners) {\n listeners.delete(listener as EventListener)\n if (listeners.size === 0) {\n eventListenersRef.current.delete(eventType)\n }\n }\n }\n },\n []\n )\n\n /**\n * Dispatch event to all registered listeners\n */\n const dispatchEvent = useCallback((eventType: string, data: unknown) => {\n const listeners = eventListenersRef.current.get(eventType)\n if (listeners) {\n listeners.forEach((listener) => {\n try {\n listener(data)\n } catch (err) {\n console.error(`Error in event listener for \"${eventType}\":`, err)\n }\n })\n }\n }, [])\n\n /**\n * Clear all timers and cleanup\n */\n const clearTimers = useCallback(() => {\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n if (heartbeatIntervalRef.current) {\n clearInterval(heartbeatIntervalRef.current)\n heartbeatIntervalRef.current = null\n }\n }, [])\n\n /**\n * Start heartbeat to keep connection alive\n */\n const startHeartbeat = useCallback((ws: WebSocket) => {\n // Clear any existing heartbeat\n if (heartbeatIntervalRef.current) {\n clearInterval(heartbeatIntervalRef.current)\n }\n\n // Send ping every 30 seconds\n heartbeatIntervalRef.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(\"ping\")\n }\n }, 30000)\n }, [])\n\n // Set up WebSocket connection\n useEffect(() => {\n if (!live || !threadId) return\n\n console.log(\n `[ThreadProvider] useEffect running - threadId: ${threadId}, live: ${live}`\n )\n connectWebSocket()\n\n return () => {\n // Clean up on unmount or thread change\n console.log(\n `[ThreadProvider] useEffect cleanup - threadId: ${threadId}, live: ${live}`\n )\n clearTimers()\n if (wsRef.current) {\n wsRef.current.close()\n wsRef.current = null\n }\n reconnectAttempts.current = 0\n isReconnectingRef.current = false\n }\n }, [threadId, live]) // Only reconnect when threadId or live changes, not when callbacks change\n\n /**\n * Connect to WebSocket with error handling\n */\n const connectWebSocket = useCallback(() => {\n if (!live || !threadId || !isMountedRef.current) return\n\n console.log(`[ThreadProvider] Connecting WebSocket for thread ${threadId}`)\n setConnectionStatus('connecting')\n\n const ws = clientRef.current.connectMessageWebSocket(\n threadId,\n {\n onOpen: () => {\n console.log(\n `[ThreadProvider] WebSocket connected for thread ${threadId}`\n )\n setConnectionStatus('connected')\n reconnectAttempts.current = 0\n isReconnectingRef.current = false\n startHeartbeat(ws)\n },\n onMessage: (event) => {\n setMessages((prev) => {\n // Check if message already exists\n const exists = prev.some((m) => m.id === event.data.id)\n if (exists) {\n // Update existing message\n return prev.map((m) => (m.id === event.data.id ? event.data : m))\n } else {\n // Add new message\n return [...prev, event.data]\n }\n })\n },\n onChunk: (event) => {\n // Handle streaming chunks\n setMessages((prev) => {\n return prev.map((m) => {\n if (m.id === event.message_id) {\n return {\n ...m,\n content: (m.content || \"\") + event.chunk,\n }\n }\n return m\n })\n })\n },\n onEvent: (event) => {\n // Dispatch custom events to subscribers\n dispatchEvent(event.eventType, event.data)\n },\n onError: (event) => {\n console.error(\"[ThreadProvider] WebSocket error:\", event.error)\n setError(new Error(event.error))\n setConnectionStatus('disconnected')\n },\n onClose: () => {\n console.log(\"[ThreadProvider] WebSocket closed\")\n clearTimers()\n\n // Only attempt to reconnect if still mounted and not already reconnecting\n if (isMountedRef.current && !isReconnectingRef.current) {\n isReconnectingRef.current = true\n setConnectionStatus('connecting')\n const delay = Math.min(\n 1000 * Math.pow(2, reconnectAttempts.current),\n 30000\n )\n reconnectAttempts.current++\n\n console.log(\n `[ThreadProvider] Reconnecting in ${delay}ms (attempt ${reconnectAttempts.current})`\n )\n\n reconnectTimeoutRef.current = setTimeout(() => {\n if (isMountedRef.current) {\n connectWebSocket()\n }\n }, delay)\n } else {\n setConnectionStatus('disconnected')\n }\n },\n },\n {\n depth,\n includeSilent,\n }\n )\n\n wsRef.current = ws\n }, [\n threadId,\n live,\n depth,\n includeSilent,\n dispatchEvent,\n startHeartbeat,\n clearTimers,\n ])\n\n // Fetch initial messages\n useEffect(() => {\n if (!preload || !threadId) return\n\n const fetchMessages = async () => {\n setLoading(true)\n setError(null)\n\n try {\n const fetchedMessages = await clientRef.current.getMessages(threadId, {\n depth,\n includeSilent,\n })\n setMessages(fetchedMessages)\n } catch (err) {\n console.error(\"Failed to fetch messages:\", err)\n setError(\n err instanceof Error ? err : new Error(\"Failed to fetch messages\")\n )\n setMessages([])\n } finally {\n setLoading(false)\n }\n }\n\n fetchMessages()\n }, [threadId, preload, depth, includeSilent])\n\n // Track component mount state\n useEffect(() => {\n isMountedRef.current = true\n return () => {\n isMountedRef.current = false\n }\n }, [])\n\n // Memoize context value\n const contextValue = useMemo(\n (): ThreadContextValue => ({\n threadId,\n messages,\n loading,\n error,\n connectionStatus,\n subscribeToEvent,\n options: {\n depth,\n includeSilent,\n ...options,\n },\n }),\n [\n threadId,\n messages,\n loading,\n error,\n connectionStatus,\n subscribeToEvent,\n depth,\n includeSilent,\n options,\n ]\n )\n\n return (\n <ThreadContext.Provider value={contextValue}>\n {children}\n </ThreadContext.Provider>\n )\n}\n\n/**\n * Hook to access the thread context.\n * Must be used within a ThreadProvider.\n *\n * @throws Error if used outside of ThreadProvider\n */\nexport function useThreadContext(): ThreadContextValue {\n const context = useContext(ThreadContext)\n\n if (!context) {\n throw new Error(\"useThreadContext must be used within a ThreadProvider\")\n }\n\n return context\n}\n\n/**\n * Hook to get the current thread ID from context.\n * Must be used within a ThreadProvider.\n */\nexport function useThreadId(): string {\n return useThreadContext().threadId\n}\n","import type { Message, WorkMessage, WorkItem, ThreadMessage } from '../types'\n\n/**\n * Transform a flat list of messages into a list with workblocks.\n * Groups consecutive assistant tool_calls and their tool results into WorkMessage objects.\n *\n * A workblock starts when an assistant message has tool_calls,\n * and includes all subsequent tool messages until:\n * - A non-tool message appears\n * - Another assistant message without tool_calls appears\n */\nexport function transformToWorkblocks(messages: Message[]): ThreadMessage[] {\n if (messages.length === 0) {\n return []\n }\n\n const result: ThreadMessage[] = []\n let i = 0\n\n while (i < messages.length) {\n const message = messages[i]\n\n // Check if this is an assistant message with tool_calls\n if (message.role === 'assistant' && message.tool_calls) {\n // Try to parse tool_calls\n let toolCalls: any[]\n try {\n toolCalls = JSON.parse(message.tool_calls)\n } catch (error) {\n // If we can't parse tool_calls, treat it as a regular message\n result.push(message)\n i++\n continue\n }\n\n // Start building a workblock\n const workItems: WorkItem[] = []\n\n // Add tool calls as work items (status determined after collecting results)\n for (const toolCall of toolCalls) {\n workItems.push({\n id: toolCall.id || message.id,\n type: 'tool_call',\n name: toolCall.function?.name,\n content: toolCall.function?.arguments || null,\n status: null, // Will be updated below based on matching results\n tool_call_id: toolCall.id,\n })\n }\n\n // Collect subsequent tool result messages\n let j = i + 1\n while (j < messages.length && messages[j].role === 'tool') {\n const toolMessage = messages[j]\n // A tool result is pending if it has no tool_status set\n // (tool_status is set to 'success' or 'error' when execution completes)\n const resultStatus = toolMessage.tool_status || 'pending'\n\n workItems.push({\n id: toolMessage.id,\n type: 'tool_result',\n name: toolMessage.name || undefined,\n content: toolMessage.content,\n status: resultStatus,\n tool_call_id: toolMessage.tool_call_id || undefined,\n })\n j++\n }\n\n // Update tool call statuses based on their matching results\n for (const item of workItems) {\n if (item.type === 'tool_call' && item.tool_call_id) {\n // Find matching result\n const matchingResult = workItems.find(\n wi => wi.type === 'tool_result' && wi.tool_call_id === item.tool_call_id\n )\n if (matchingResult) {\n // Tool call inherits status from its result\n item.status = matchingResult.status\n } else {\n // No result yet - tool call is pending\n item.status = 'pending'\n }\n }\n }\n\n // Determine workblock status based on the assistant message status only\n // Individual tool errors are reflected in the work item's status, not the workblock\n let status: 'pending' | 'completed' | 'failed' = 'completed'\n if (message.status === 'pending') {\n status = 'pending'\n } else if (message.status === 'failed') {\n status = 'failed'\n }\n\n // Create the workblock\n const workblock: WorkMessage = {\n id: message.id,\n type: 'workblock',\n content: message.content,\n reasoning_content: message.reasoning_content,\n workItems,\n status,\n created_at: message.created_at,\n depth: message.depth,\n }\n\n result.push(workblock)\n\n // Move index past all consumed messages\n i = j\n } else {\n // Not a workblock, pass through unchanged\n result.push(message)\n i++\n }\n }\n\n return result\n}\n","import { useContext, useMemo } from 'react'\nimport { ThreadContext } from '../context/ThreadProvider'\nimport { transformToWorkblocks } from '../utils/workblocks'\nimport type { ThreadMessage, UseThreadOptions } from '../types'\n\n/**\n * Hook to get messages from a thread.\n *\n * Must be used within a ThreadProvider. The thread ID and WebSocket connection\n * are managed by the ThreadProvider, so this hook simply returns the messages.\n *\n * @param options - Configuration options\n * @returns Array of messages (raw or transformed to workblocks)\n *\n * @example\n * ```tsx\n * function ChatMessages() {\n * // Basic usage - returns messages from context\n * const messages = useThread()\n *\n * return (\n * <div>\n * {messages.map(msg => <Message key={msg.id} message={msg} />)}\n * </div>\n * )\n * }\n *\n * // Wrap with ThreadProvider\n * <ThreadProvider threadId=\"thread-123\">\n * <ChatMessages />\n * </ThreadProvider>\n * ```\n *\n * @example\n * ```tsx\n * // Disable workblocks transformation\n * const messages = useThread({ useWorkblocks: false })\n * ```\n */\nexport function useThread(options: UseThreadOptions = {}): ThreadMessage[] {\n const {\n useWorkblocks = true,\n } = options\n\n const context = useContext(ThreadContext)\n\n if (!context) {\n throw new Error(\n 'useThread must be used within a ThreadProvider. ' +\n 'Wrap your component with <ThreadProvider threadId=\"...\">.'\n )\n }\n\n const { messages } = context\n\n // Transform to workblocks if requested\n const transformedMessages = useMemo(() => {\n return useWorkblocks ? transformToWorkblocks(messages) : messages\n }, [messages, useWorkblocks])\n\n return transformedMessages\n}\n","import { useContext, useEffect, useState } from 'react'\nimport { ThreadContext } from '../context/ThreadProvider'\n\n/**\n * Hook to listen for custom events emitted from a thread via the stream WebSocket.\n * Calls the provided callback whenever an event of the specified type is received.\n *\n * Must be used within a ThreadProvider. Events are emitted from the backend\n * using `emitThreadEvent(flow, 'event-type', data)`.\n *\n * @param type - The custom event type to filter for\n * @param callback - Function to call when an event of this type is received\n *\n * @example\n * ```tsx\n * function GamePreview() {\n * const [gameHtml, setGameHtml] = useState<string | null>(null)\n *\n * onThreadEvent('game_built', (data: { success: boolean }) => {\n * if (data.success) {\n * fetchGameHtml()\n * }\n * })\n *\n * return <iframe srcDoc={gameHtml} />\n * }\n * ```\n *\n * @example\n * ```tsx\n * function ProgressIndicator() {\n * const [progress, setProgress] = useState(0)\n *\n * onThreadEvent('progress', (data: { step: number; total: number }) => {\n * setProgress(data.step / data.total * 100)\n * })\n *\n * return <ProgressBar value={progress} />\n * }\n * ```\n */\nexport function onThreadEvent<T = unknown>(\n type: string,\n callback: (data: T) => void\n): void {\n const context = useContext(ThreadContext)\n\n if (!context) {\n throw new Error(\n 'onThreadEvent must be used within a ThreadProvider. ' +\n 'Wrap your component with <ThreadProvider threadId=\"...\">.'\n )\n }\n\n const { subscribeToEvent } = context\n\n useEffect(() => {\n // Subscribe to events of the specified type\n const unsubscribe = subscribeToEvent<T>(type, callback)\n\n // Cleanup subscription on unmount\n return unsubscribe\n }, [subscribeToEvent, type, callback])\n}\n\n/**\n * Hook to get the latest event data for a specific event type as React state.\n * Returns the most recent event data, or null if no event has been received.\n *\n * Must be used within a ThreadProvider. Events are emitted from the backend\n * using `emitThreadEvent(flow, 'event-type', data)`.\n *\n * @param type - The custom event type to filter for\n * @returns The latest event data matching the specified type, or null if none received\n *\n * @example\n * ```tsx\n * function ProgressIndicator() {\n * const progress = useThreadEvent<{ step: number; total: number }>('progress')\n *\n * if (!progress) return null\n *\n * return (\n * <div>\n * Step {progress.step} of {progress.total}\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * function StatusDisplay() {\n * const status = useThreadEvent<{ message: string }>('status')\n *\n * useEffect(() => {\n * if (status) {\n * console.log('Status updated:', status.message)\n * }\n * }, [status])\n *\n * return <div>{status?.message ?? 'No status'}</div>\n * }\n * ```\n */\nexport function useThreadEvent<T = unknown>(type: string): T | null {\n const context = useContext(ThreadContext)\n const [eventData, setEventData] = useState<T | null>(null)\n\n if (!context) {\n throw new Error(\n 'useThreadEvent must be used within a ThreadProvider. ' +\n 'Wrap your component with <ThreadProvider threadId=\"...\">.'\n )\n }\n\n const { subscribeToEvent } = context\n\n useEffect(() => {\n // Subscribe to events of the specified type\n const unsubscribe = subscribeToEvent<T>(type, (data) => {\n setEventData(data)\n })\n\n // Cleanup subscription on unmount\n return unsubscribe\n }, [subscribeToEvent, type])\n\n return eventData\n}\n","import { useCallback } from 'react'\nimport { useThreadContext } from '../context/ThreadProvider'\nimport { sendMessage as sendMessageService } from '../services/sendMessage'\nimport type { SendMessagePayload, Message } from '../types'\n\n/**\n * Hook that returns a function to send messages to the current thread.\n * Must be used within a ThreadProvider.\n *\n * This hook automatically uses the thread ID from the ThreadProvider context,\n * so you don't need to pass it manually.\n *\n * @returns A function that sends a message to the current thread\n *\n * @throws Error if used outside of ThreadProvider\n *\n * @example\n * ```tsx\n * function ChatInput() {\n * const sendMessage = useSendMessage()\n *\n * const handleSubmit = async (content: string) => {\n * await sendMessage({\n * role: 'user',\n * content,\n * })\n * }\n *\n * return <input onSubmit={handleSubmit} />\n * }\n * ```\n */\nexport function useSendMessage(): (payload: SendMessagePayload) => Promise<Message> {\n let context: ReturnType<typeof useThreadContext>\n\n try {\n context = useThreadContext()\n } catch {\n throw new Error('useSendMessage must be used within a ThreadProvider')\n }\n\n const { threadId } = context\n\n return useCallback(\n (payload: SendMessagePayload) => {\n return sendMessageService(threadId, payload)\n },\n [threadId]\n )\n}\n","import { useCallback } from 'react'\nimport { useThreadContext } from '../context/ThreadProvider'\nimport { stopThread as stopThreadService } from '../services/stopThread'\n\n/**\n * Hook that returns a function to stop the current thread's execution.\n * Must be used within a ThreadProvider.\n *\n * This hook automatically uses the thread ID from the ThreadProvider context,\n * so you don't need to pass it manually.\n *\n * @returns A function that stops the current thread's execution\n *\n * @throws Error if used outside of ThreadProvider\n *\n * @example\n * ```tsx\n * function StopButton() {\n * const stopThread = useStopThread()\n *\n * return (\n * <button onClick={() => stopThread()}>\n * Stop\n * </button>\n * )\n * }\n * ```\n */\nexport function useStopThread(): () => Promise<void> {\n let context: ReturnType<typeof useThreadContext>\n\n try {\n context = useThreadContext()\n } catch {\n throw new Error('useStopThread must be used within a ThreadProvider')\n }\n\n const { threadId } = context\n\n return useCallback(\n () => {\n return stopThreadService(threadId)\n },\n [threadId]\n )\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standardagents/react",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },