bs-agent 0.0.10 → 0.0.12

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/agent-context.tsx","../../src/react/use-agent.ts","../../src/react/constants.ts","../../src/react/session-utils.ts","../../src/react/debug-handlers.ts","../../src/react/client-tools.ts","../../src/react/utils/schema.ts","../../src/core/stream.ts","../../src/react/utils/message.ts","../../src/react/stream-callbacks.ts","../../src/react/utils/use-synced-local-storage.ts","../../src/react/use-client-tool.ts"],"sourcesContent":["import {\n createContext,\n useContext,\n useCallback,\n useRef,\n useState,\n useEffect,\n useMemo,\n ReactNode,\n} from \"react\";\nimport useAgent from \"./use-agent\";\nimport type { Message, Session, DebugDataType } from \"./types\";\nimport type { ClientToolConfig } from \"./use-client-tool\";\nimport { useSyncedLocalStorage } from \"./utils/use-synced-local-storage\";\nimport { AGENT_SESSIONS_KEY, AGENT_DEBUG_DATA_KEY } from \"./constants\";\n\nexport interface AgentRunner {\n messages: Message[];\n inProgress: boolean;\n sessionId: string;\n sessions: Session[];\n debugData: Record<string, DebugDataType>;\n handleSend: (\n input: string,\n options?: {\n context?: Record<string, unknown>;\n skipUserMessage?: boolean;\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n /** @deprecated Use `useClientTool` hook instead. */\n clientTools?: Array<{\n name: string;\n description: string;\n parameters: unknown;\n await?: boolean;\n }>;\n },\n ) => Promise<void>;\n resumeTool: (callId: string, result: any) => Promise<void>;\n switchSession: (sessionId?: string) => void;\n deleteSession: (sessionId: string) => void;\n addOptimisticMessage: (input: string) => void;\n abort: () => void;\n}\n\n// ─── Tool Registry Context ──────────────────────────────────────────────────\n\nexport interface AgentToolContextValue {\n registerTool: (agentId: string, config: ClientToolConfig) => void;\n unregisterTool: (agentId: string, toolName: string) => void;\n getTool: (agentId: string, toolName: string) => ClientToolConfig | undefined;\n getToolsForAgent: (agentId: string) => ClientToolConfig[];\n resumeTool: (agentId: string, callId: string, result: any) => void;\n}\n\nexport const AgentToolContext = createContext<AgentToolContextValue | null>(null);\n\n// ─── Agent Context ──────────────────────────────────────────────────────────\n\ninterface AgentContextValue {\n initializeAgent: (agentId: string, agentUrl: string, accessKey?: string) => void;\n registerRunner: (agentId: string, runner: AgentRunner) => void;\n getRunner: (agentId: string) => AgentRunner | null;\n // Global state provided to useAgent hooks\n allSessions: Record<string, Record<string, Session>>;\n setAllSessions: (\n value:\n | Record<string, Record<string, Session>>\n | ((\n prev: Record<string, Record<string, Session>>,\n ) => Record<string, Record<string, Session>>),\n ) => void;\n debugData: Record<string, DebugDataType>;\n setDebugData: (\n value:\n | Record<string, DebugDataType>\n | ((prev: Record<string, DebugDataType>) => Record<string, DebugDataType>),\n ) => void;\n}\n\nconst AgentContext = createContext<AgentContextValue | null>(null);\n\nexport function AgentContextProvider({ children }: { children: ReactNode }) {\n const activeAgentsRef = useRef<Map<string, { agentUrl: string; accessKey?: string }>>(new Map());\n const runnersRef = useRef<Map<string, AgentRunner>>(new Map());\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Tool registry: agentId -> Map<toolName, ClientToolConfig>\n const toolRegistryRef = useRef<Map<string, Map<string, ClientToolConfig>>>(new Map());\n\n const [, forceUpdate] = useState({});\n\n // Global Sync State managed here to be shared\n const [allSessions, setAllSessions] = useSyncedLocalStorage<\n Record<string, Record<string, Session>>\n >(AGENT_SESSIONS_KEY, {});\n\n const [debugData, setDebugData] = useSyncedLocalStorage<Record<string, DebugDataType>>(\n AGENT_DEBUG_DATA_KEY,\n {},\n );\n\n const initializeAgent = useCallback((agentId: string, agentUrl: string, accessKey?: string) => {\n const existing = activeAgentsRef.current.get(agentId);\n\n if (!existing) {\n activeAgentsRef.current.set(agentId, { agentUrl, accessKey });\n forceUpdate({});\n } else if (existing.agentUrl !== agentUrl || existing.accessKey !== accessKey) {\n activeAgentsRef.current.set(agentId, { agentUrl, accessKey });\n forceUpdate({});\n }\n }, []);\n\n const registerRunner = useCallback((agentId: string, runner: AgentRunner) => {\n runnersRef.current.set(agentId, runner);\n // Notify listeners for this agentId\n const listeners = listenersRef.current.get(agentId);\n if (listeners) {\n listeners.forEach((callback) => callback());\n }\n }, []);\n\n const getRunner = useCallback((agentId: string) => {\n return runnersRef.current.get(agentId) || null;\n }, []);\n\n // ─── Tool registry methods ─────────────────────────────────────────\n\n const registerTool = useCallback((agentId: string, config: ClientToolConfig) => {\n if (!toolRegistryRef.current.has(agentId)) {\n toolRegistryRef.current.set(agentId, new Map());\n }\n toolRegistryRef.current.get(agentId)!.set(config.name, config);\n }, []);\n\n const unregisterTool = useCallback((agentId: string, toolName: string) => {\n toolRegistryRef.current.get(agentId)?.delete(toolName);\n }, []);\n\n const getTool = useCallback((agentId: string, toolName: string) => {\n return toolRegistryRef.current.get(agentId)?.get(toolName);\n }, []);\n\n const getToolsForAgent = useCallback((agentId: string) => {\n const toolMap = toolRegistryRef.current.get(agentId);\n return toolMap ? Array.from(toolMap.values()) : [];\n }, []);\n\n const resumeToolFromContext = useCallback((agentId: string, callId: string, result: any) => {\n const runner = runnersRef.current.get(agentId);\n if (runner) {\n runner.resumeTool(callId, result);\n } else {\n console.warn(`Cannot resume tool: no runner found for agent \"${agentId}\"`);\n }\n }, []);\n\n // ─── Context values ────────────────────────────────────────────────\n\n const agentContextValue = useMemo(\n () => ({\n initializeAgent,\n registerRunner,\n getRunner,\n allSessions,\n setAllSessions,\n debugData,\n setDebugData,\n runnersRef,\n listenersRef,\n }),\n [\n initializeAgent,\n registerRunner,\n getRunner,\n allSessions,\n setAllSessions,\n debugData,\n setDebugData,\n ],\n );\n\n const toolContextValue = useMemo(\n () => ({\n registerTool,\n unregisterTool,\n getTool,\n getToolsForAgent,\n resumeTool: resumeToolFromContext,\n }),\n [registerTool, unregisterTool, getTool, getToolsForAgent, resumeToolFromContext],\n );\n\n return (\n <AgentContext.Provider value={agentContextValue}>\n <AgentToolContext.Provider value={toolContextValue}>\n {children}\n {Array.from(activeAgentsRef.current.entries()).map(([agentId, { agentUrl, accessKey }]) => (\n <AgentRunnerInstance\n key={agentId}\n agentId={agentId}\n agentUrl={agentUrl}\n accessKey={accessKey}\n />\n ))}\n </AgentToolContext.Provider>\n </AgentContext.Provider>\n );\n}\n\nfunction AgentRunnerInstance({\n agentId,\n agentUrl,\n accessKey,\n}: {\n agentId: string;\n agentUrl: string;\n accessKey?: string;\n}) {\n const agent = useAgent(agentId, agentUrl, accessKey);\n const context = useContext(AgentContext);\n\n useEffect(() => {\n if (context) {\n context.registerRunner(agentId, agent);\n }\n }, [agentId, agent, context]);\n\n if (!context) return null;\n\n return null;\n}\n\nexport function useAgentContext(\n agentId: string,\n agentUrl: string,\n accessKey?: string,\n): AgentRunner {\n const context = useContext(AgentContext);\n\n if (!context) {\n throw new Error(\"useAgentContext must be used within AgentContextProvider\");\n }\n\n const { initializeAgent, getRunner, listenersRef } = context as AgentContextValue & {\n listenersRef: React.MutableRefObject<Map<string, Set<() => void>>>;\n };\n\n useEffect(() => {\n initializeAgent(agentId, agentUrl, accessKey);\n }, [agentId, agentUrl, initializeAgent]);\n\n // Reactive subscription to runner updates\n const [runner, setRunner] = useState<AgentRunner | null>(() => getRunner(agentId));\n\n useEffect(() => {\n // Current runner state\n const currentRunner = getRunner(agentId);\n if (currentRunner !== runner) {\n setRunner(currentRunner);\n }\n\n // Subscribe to future updates\n const callback = () => {\n setRunner(getRunner(agentId));\n };\n\n if (!listenersRef.current.has(agentId)) {\n listenersRef.current.set(agentId, new Set());\n }\n listenersRef.current.get(agentId)?.add(callback);\n\n return () => {\n listenersRef.current.get(agentId)?.delete(callback);\n };\n }, [agentId, getRunner]);\n\n const placeholder = useMemo(\n () => ({\n messages: [],\n inProgress: false,\n sessionId: \"\",\n sessions: [],\n debugData: {},\n handleSend: async () => {},\n resumeTool: async () => {},\n switchSession: () => {},\n deleteSession: () => {},\n addOptimisticMessage: () => {},\n abort: () => {},\n }),\n [],\n );\n\n return runner || placeholder;\n}\n\n// Hook to access the global state for use-agent\nexport function useAgentGlobalState() {\n const context = useContext(AgentContext);\n if (!context) {\n throw new Error(\"useAgentGlobalState must be used within AgentContextProvider\");\n }\n return {\n allSessions: context.allSessions,\n setAllSessions: context.setAllSessions,\n debugData: context.debugData,\n setDebugData: context.setDebugData,\n };\n}\n","import { useCallback, useRef, useState, useEffect, useContext, useMemo } from \"react\";\n\nimport type { ExecuteRequestBody, StreamEvent } from \"../core/types\";\n\nimport { DEFAULT_SESSION_NAME, TEMPORARY_SESSION_ID } from \"./constants\";\nimport { useSessionUtils } from \"./session-utils\";\nimport { createDebugHandlers } from \"./debug-handlers\";\nimport { useAgentGlobalState, AgentToolContext } from \"./agent-context\";\nimport type { Message } from \"./types\";\nimport { useClientToolHelpers } from \"./client-tools\";\nimport { buildStreamCallbacks, executeAgentStream } from \"./stream-callbacks\";\nimport type { RunOptions } from \"./stream-callbacks\";\n\nexport default function useAgent(agentId: string, agentUrl: string, accessKey?: string) {\n const { allSessions, setAllSessions, debugData, setDebugData } = useAgentGlobalState();\n const toolContext = useContext(AgentToolContext);\n\n const [inProgress, setInProgress] = useState(false);\n const [messages, setMessages] = useState<Array<Message>>([]);\n const messagesRef = useRef<Array<Message>>([]);\n\n const [currentSessionId, setCurrentSessionId] = useState<string>(TEMPORARY_SESSION_ID);\n\n const sessionUtils = useSessionUtils(\n agentId,\n allSessions,\n setAllSessions,\n currentSessionId,\n setCurrentSessionId,\n messagesRef,\n );\n\n useEffect(() => {\n const initialSessionId = sessionUtils.getInitialSessionId();\n setCurrentSessionId(initialSessionId);\n }, []);\n\n const debugHandlers = useMemo(() => createDebugHandlers(setDebugData), [setDebugData]);\n\n useEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n\n // Reload messages from session storage only on session/agent switch\n useEffect(() => {\n if (inProgress) return;\n const session = sessionUtils.agentSessions[currentSessionId];\n if (session) {\n setMessages(session.messages);\n } else {\n setMessages([]);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentSessionId, agentId]);\n\n useEffect(() => {\n return () => {\n if (messagesRef.current.length > 0 && sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current();\n }\n };\n }, []);\n\n const controller = useRef<AbortController>();\n\n // Persist additionalHeaders + additionalBody + sessionId for resume calls\n const lastRequestContextRef = useRef<{\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n sessionId?: string;\n }>({});\n\n const { getClientToolsMap, getClientToolDefs } = useClientToolHelpers(agentId, toolContext);\n\n // Ref for recursive auto-resume calls\n const runAgentRef = useRef<\n ((input: string | undefined, options?: RunOptions) => Promise<void>) | undefined\n >();\n\n const runAgent = useCallback(\n async (input: string | undefined, runOptions?: RunOptions) => {\n // Resolve session ID (exclude temp placeholder)\n const realSessionId =\n currentSessionId && currentSessionId !== TEMPORARY_SESSION_ID\n ? currentSessionId\n : lastRequestContextRef.current.sessionId;\n\n // Persist context for resume calls\n lastRequestContextRef.current = {\n additionalHeaders:\n runOptions?.additionalHeaders ?? lastRequestContextRef.current.additionalHeaders,\n additionalBody: runOptions?.additionalBody ?? lastRequestContextRef.current.additionalBody,\n sessionId: realSessionId,\n };\n\n setInProgress(true);\n // Only abort a previous in-flight stream if this is NOT a resume.\n if (!runOptions?.resumeToolCallId && controller.current) {\n controller.current.abort();\n }\n controller.current = new AbortController();\n\n // ── Build request ────────────────────────────────────────────\n const headers: Record<string, string> = {\n ...(lastRequestContextRef.current.additionalHeaders || {}),\n ...(accessKey ? { Authorization: `Bearer ${accessKey}` } : {}),\n };\n\n if (realSessionId) {\n headers[\"x-buildship-agent-session-id\"] = realSessionId;\n }\n\n const body: ExecuteRequestBody = {\n stream: true,\n ...(lastRequestContextRef.current.additionalBody || {}),\n };\n\n if (input !== undefined) {\n body.input = input;\n }\n\n if (runOptions?.context) {\n Object.assign(body, { context: runOptions.context });\n }\n\n if (runOptions?.resumeToolCallId) {\n body.toolCallResult = {\n callId: runOptions.resumeToolCallId,\n result: runOptions.resumeToolResult,\n };\n }\n\n // Client tool definitions\n const registeredToolDefs = getClientToolDefs() || [];\n const legacyToolDefs = (runOptions?.clientTools || []) as NonNullable<\n ExecuteRequestBody[\"clientTools\"]\n >;\n const allToolDefs = [...registeredToolDefs, ...legacyToolDefs];\n if (allToolDefs.length > 0) {\n body.clientTools = allToolDefs;\n }\n\n // ── Debug key ────────────────────────────────────────────────\n const debugKey =\n runOptions?.optimisticExecutionId ||\n messagesRef.current.findLast((m) => m.role === \"user\")?.executionId;\n\n // ── Build callbacks & execute ────────────────────────────────\n const deps = {\n agentUrl,\n agentId,\n accessKey,\n currentSessionId,\n messagesRef,\n setMessages,\n setInProgress,\n setCurrentSessionId,\n syncSessionRef: sessionUtils.syncSessionRef,\n createSessionFromResponse: sessionUtils.createSessionFromResponse,\n debugHandlers,\n toolContext,\n lastRequestContextRef,\n getClientToolsMap,\n signal: controller.current.signal,\n runAgentRef,\n };\n\n const callbacks = buildStreamCallbacks(deps, debugKey);\n\n try {\n await executeAgentStream(deps, body, headers, callbacks, debugKey);\n } catch (error) {\n console.log(\"Agent execution failed\", error);\n setInProgress(false);\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(messagesRef.current);\n }\n throw error;\n }\n },\n [\n agentUrl,\n accessKey,\n currentSessionId,\n sessionUtils.syncSessionRef,\n sessionUtils.createSessionFromResponse,\n debugHandlers,\n getClientToolsMap,\n getClientToolDefs,\n agentId,\n toolContext,\n ],\n );\n\n // Keep the ref in sync so onAutoResume can call runAgent\n useEffect(() => {\n runAgentRef.current = runAgent;\n }, [runAgent]);\n\n const handleSend = useCallback(\n async (\n input: string,\n options?: {\n context?: object;\n skipUserMessage?: boolean;\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n /** @deprecated Use `useClientTool` hook instead. */\n clientTools?: Array<{\n name: string;\n description: string;\n parameters: unknown;\n await?: boolean;\n }>;\n },\n ) => {\n const userMessage = {\n role: \"user\" as const,\n content: input,\n executionId: Date.now().toString(),\n };\n\n if (!options?.skipUserMessage) {\n setMessages((prev) => {\n const updatedMessages = [...prev, userMessage];\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n }\n\n // When skipUserMessage is true, the user message was already added\n // externally (e.g. via addOptimisticMessage) with its own executionId.\n const effectiveExecutionId = options?.skipUserMessage\n ? messagesRef.current.findLast((m) => m.role === \"user\")?.executionId ??\n userMessage.executionId\n : userMessage.executionId;\n\n try {\n await runAgent(input, {\n ...options,\n optimisticExecutionId: effectiveExecutionId,\n });\n } catch (error) {\n if (!options?.skipUserMessage) {\n setMessages((prev) => {\n const updatedMessages = prev.some((m) => m === userMessage)\n ? prev\n : [...prev, userMessage];\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n }\n throw error;\n }\n },\n [runAgent, sessionUtils.syncSessionRef],\n );\n\n const resumeTool = useCallback(\n async (callId: string, result: any) => {\n // Update the widget status and persist the result\n setMessages((prev) => {\n const updatedMessages = prev.map((msg) => {\n if (msg.parts) {\n const updatedParts = msg.parts.map((part) => {\n if (part.type === \"widget\" && part.callId === callId) {\n return { ...part, status: \"submitted\" as const, result };\n }\n return part;\n });\n return { ...msg, parts: updatedParts };\n }\n return msg;\n });\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n\n // Emit synthetic tool_call_end for the debug panel\n const debugKey = messagesRef.current.findLast((m) => m.role === \"user\")?.executionId;\n if (debugKey) {\n debugHandlers.handleStreamEvent({\n type: \"tool_call_end\",\n data: { callId, toolName: \"\", toolType: \"client\" as const, result },\n meta: { executionId: debugKey, sequence: 0 },\n } as StreamEvent);\n }\n\n // Resume the agent with the tool result\n await runAgent(undefined, {\n resumeToolCallId: callId,\n resumeToolResult: result,\n });\n },\n [runAgent, sessionUtils.syncSessionRef, debugHandlers],\n );\n\n const addOptimisticMessage = useCallback(\n (input: string) => {\n const userMessage = {\n role: \"user\" as const,\n content: input,\n executionId: Date.now().toString(),\n };\n\n setMessages((prev) => {\n const updatedMessages = [...prev, userMessage];\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n },\n [sessionUtils.syncSessionRef],\n );\n\n const abort = useCallback(() => {\n if (controller.current) {\n controller.current.abort();\n }\n setInProgress(false);\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(messagesRef.current);\n }\n }, [sessionUtils.syncSessionRef]);\n\n return {\n inProgress,\n messages,\n handleSend,\n resumeTool,\n addOptimisticMessage,\n abort,\n sessionId: currentSessionId,\n switchSession: sessionUtils.switchSession,\n deleteSession: sessionUtils.deleteSession,\n sessions: sessionUtils.sessionsList,\n debugData,\n };\n}\n","export const AGENT_SESSIONS_KEY = \"buildship:agent:conversations\";\nexport const AGENT_DEBUG_DATA_KEY = \"buildship:agent:debug\";\n\nexport const DEFAULT_SESSION_NAME = \"New Chat\";\nexport const TEMPORARY_SESSION_ID = \"sess_temp\";\n","import { useCallback, useMemo, useRef } from \"react\";\nimport type { Message, Session } from \"./types\";\nimport { TEMPORARY_SESSION_ID } from \"./constants\";\n\nexport const useSessionUtils = (\n agentId: string,\n allSessions: Record<string, Record<string, Session>>,\n setAllSessions: (\n value:\n | Record<string, Record<string, Session>>\n | ((\n prev: Record<string, Record<string, Session>>,\n ) => Record<string, Record<string, Session>>),\n ) => void,\n currentSessionId: string,\n setCurrentSessionId: (sessionId: string) => void,\n messagesRef: React.MutableRefObject<Array<Message>>,\n) => {\n const agentSessions = useMemo(() => allSessions[agentId] || {}, [agentId, allSessions]);\n\n const syncSessionRef = useRef<(messages?: Array<Message>) => void>();\n\n syncSessionRef.current = (updatedMessages?: Array<Message>) => {\n if (!currentSessionId || currentSessionId === TEMPORARY_SESSION_ID) {\n return;\n }\n\n setAllSessions((prev) => ({\n ...prev,\n [agentId]: {\n ...prev[agentId],\n [currentSessionId]: {\n ...prev[agentId]?.[currentSessionId],\n messages: updatedMessages ?? messagesRef.current,\n updatedAt: Date.now(),\n },\n },\n }));\n };\n\n const getInitialSessionId = () => {\n const sessions = Object.values(agentSessions);\n if (sessions.length > 0) {\n return sessions.sort((a, b) => b.updatedAt - a.updatedAt)[0].id;\n }\n return TEMPORARY_SESSION_ID;\n };\n\n const switchSession = useCallback(\n (sessionId: string = TEMPORARY_SESSION_ID) => {\n setCurrentSessionId(sessionId);\n },\n [setCurrentSessionId],\n );\n\n const deleteSession = useCallback(\n (sessionId: string) => {\n if (!sessionId || sessionId === TEMPORARY_SESSION_ID) {\n return;\n }\n\n setAllSessions((prev) => {\n const updatedAgentSessions = { ...prev[agentId] };\n delete updatedAgentSessions[sessionId];\n\n return {\n ...prev,\n [agentId]: updatedAgentSessions,\n };\n });\n\n if (sessionId === currentSessionId) {\n const remainingSessions = Object.values(agentSessions).filter((s) => s.id !== sessionId);\n if (remainingSessions.length > 0) {\n const mostRecent = remainingSessions.sort((a, b) => b.updatedAt - a.updatedAt)[0];\n setCurrentSessionId(mostRecent.id);\n } else {\n setCurrentSessionId(TEMPORARY_SESSION_ID);\n }\n }\n },\n [agentId, currentSessionId, agentSessions, setAllSessions, setCurrentSessionId],\n );\n\n const sessionsList = useMemo(\n () => Object.values(agentSessions).sort((a, b) => b.updatedAt - a.updatedAt),\n [agentSessions],\n );\n\n const createSessionFromResponse = (\n sessionId: string,\n sessionName: string,\n currentMessages: Array<Message>,\n ) => {\n setAllSessions((prev) => ({\n ...prev,\n [agentId]: {\n ...prev[agentId],\n [sessionId]: {\n id: sessionId,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n messages: currentMessages,\n name: sessionName,\n },\n },\n }));\n };\n\n return {\n agentSessions,\n syncSessionRef,\n getInitialSessionId,\n switchSession,\n deleteSession,\n sessionsList,\n createSessionFromResponse,\n };\n};\n","import type { StreamEvent } from \"../core/types\";\nimport type { DebugDataType, ToolExecutionItem, ReasoningItem, HandoffItem } from \"./types\";\n\nexport const createDebugHandlers = (\n setDebugData: (\n value:\n | Record<string, DebugDataType>\n | ((prev: Record<string, DebugDataType>) => Record<string, DebugDataType>),\n ) => void,\n) => {\n const handleStreamEvent = (event: StreamEvent) => {\n const executionId = event.meta.executionId;\n\n switch (event.type) {\n case \"tool_call_start\": {\n const { callId, toolName, toolType, inputs, serverName } = event.data;\n setDebugData((prev) => ({\n ...prev,\n [executionId]: [\n ...(prev[executionId] || []),\n {\n itemType: \"tool_call\",\n toolName,\n callId,\n toolType,\n status: \"progress\",\n inputs,\n serverName,\n } as ToolExecutionItem,\n ],\n }));\n break;\n }\n\n case \"tool_call_end\": {\n const { callId, result, error } = event.data;\n setDebugData((prev) => {\n const currentData = [...(prev[executionId] || [])];\n\n for (let i = currentData.length - 1; i >= 0; i--) {\n if (currentData[i].itemType === \"tool_call\") {\n const toolItem = currentData[i] as ToolExecutionItem;\n if (toolItem.callId === callId) {\n currentData[i] = {\n ...toolItem,\n status: error ? \"error\" : \"complete\",\n output: result,\n error,\n };\n break;\n }\n }\n }\n\n return {\n ...prev,\n [executionId]: currentData,\n };\n });\n break;\n }\n\n case \"reasoning_delta\": {\n const { delta, index } = event.data;\n setDebugData((prev) => {\n const currentData = [...(prev[executionId] || [])];\n\n let existingItemIndex = -1;\n for (let i = currentData.length - 1; i >= 0; i--) {\n const item = currentData[i];\n if (item.itemType === \"reasoning\" && (item as ReasoningItem).index === index) {\n existingItemIndex = i;\n break;\n }\n }\n\n if (existingItemIndex === -1) {\n currentData.push({ itemType: \"reasoning\", reasoning: delta, index });\n } else {\n currentData[existingItemIndex] = {\n itemType: \"reasoning\",\n reasoning: (currentData[existingItemIndex] as ReasoningItem).reasoning + delta,\n index,\n };\n }\n\n return {\n ...prev,\n [executionId]: currentData,\n };\n });\n break;\n }\n\n case \"agent_handoff\": {\n setDebugData((prev) => ({\n ...prev,\n [executionId]: [\n ...(prev[executionId] || []),\n {\n itemType: \"handoff\",\n agentName: event.data.agentName,\n } as HandoffItem,\n ],\n }));\n break;\n }\n }\n };\n\n return {\n handleStreamEvent,\n };\n};\n","import { useCallback, useContext } from \"react\";\nimport { toJSONSchema, type ZodSchema } from \"zod\";\n\nimport type { ExecuteRequestBody, ClientTool } from \"../core/types\";\nimport type { AgentToolContextValue } from \"./agent-context\";\nimport { cleanSchema } from \"./utils/schema\";\n\n/**\n * Resolve parameters — accepts Zod schema or plain JSON Schema object.\n */\nexport function resolveParameters(params: any): Record<string, any> {\n let schema: Record<string, any>;\n\n // Detect Zod schema: ZodType instances have a `_def` property\n if (params && typeof params === \"object\" && \"_def\" in params) {\n schema = toJSONSchema(params as ZodSchema) as Record<string, any>;\n delete schema.$schema;\n } else {\n schema = cleanSchema(params) as Record<string, any>;\n }\n\n // Gemini requires additionalProperties: false and required to include every key\n if (schema.type === \"object\") {\n schema.additionalProperties = false;\n if (schema.properties) {\n schema.required = Object.keys(schema.properties);\n }\n }\n\n return schema;\n}\n\n/**\n * Build the ClientTool map from registered tools (for handlers).\n * Widget-only tools are NOT included — they're handled via onEvent.\n */\nexport function useClientToolHelpers(agentId: string, toolContext: AgentToolContextValue | null) {\n const getClientToolsMap = useCallback((): Map<string, ClientTool> => {\n if (!toolContext) return new Map();\n const tools = toolContext.getToolsForAgent(agentId);\n const map = new Map<string, ClientTool>();\n\n for (const tool of tools) {\n if (tool.handler) {\n map.set(tool.name, {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n await: tool.await,\n handler: tool.handler,\n });\n }\n }\n\n return map;\n }, [agentId, toolContext]);\n\n /**\n * Build client tool definitions for the request body.\n * Includes ALL registered tools (handlers + widgets).\n */\n const getClientToolDefs = useCallback((): ExecuteRequestBody[\"clientTools\"] => {\n if (!toolContext) return [];\n const tools = toolContext.getToolsForAgent(agentId);\n\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: resolveParameters(tool.parameters),\n await: tool.await,\n }));\n }, [agentId, toolContext]);\n\n return { getClientToolsMap, getClientToolDefs };\n}\n","/**\n * Helper to clean JSON Schema for LLM compatibility.\n * Replaces modern Draft 2020-12 features with older, more compatible alternatives.\n * Specifically handles OpenAI's 'Strict Mode' requirements.\n */\nexport function cleanSchema(obj: unknown): unknown {\n if (Array.isArray(obj)) {\n return obj.map(cleanSchema);\n } else if (obj !== null && typeof obj === \"object\") {\n const newObj: Record<string, unknown> = {};\n const currentObj = obj as Record<string, any>;\n\n for (const key in currentObj) {\n // Remove keys that are not supported by most LLMs\n if (key === \"propertyNames\" || key === \"$schema\") {\n continue;\n }\n newObj[key] = cleanSchema(currentObj[key]);\n }\n\n // OpenAI and some other LLMs require additionalProperties: false for all objects in strict mode\n // AND every property must be explicitly listed in the 'required' array\n if (newObj.type === \"object\") {\n if (\n newObj.additionalProperties === undefined ||\n (newObj.additionalProperties &&\n typeof newObj.additionalProperties === \"object\" &&\n Object.keys(newObj.additionalProperties).length === 0)\n ) {\n newObj.additionalProperties = false;\n }\n\n if (newObj.additionalProperties === false && newObj.properties) {\n newObj.required = Object.keys(newObj.properties as object);\n }\n }\n\n return newObj;\n }\n return obj;\n}\n\n/**\n * Safely attempts to parse a value as JSON if it's a string.\n */\nexport function tryParseJSON(value: unknown): any {\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n return value;\n}\n","import type { StreamEvent, StreamOptions, SessionId } from \"./types\";\n\n/**\n * Fatal error — will NOT be retried.\n */\nclass FatalStreamError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message);\n this.name = \"FatalStreamError\";\n }\n}\n\n/**\n * Opens an SSE connection to the BuildShip agent endpoint using native fetch,\n * parses events, and dispatches to the appropriate callbacks.\n *\n * Works in both Node.js (18+) and browsers — no browser-only dependencies.\n *\n * @internal\n */\nexport async function executeStream(options: StreamOptions): Promise<void> {\n const {\n url,\n body,\n headers,\n callbacks,\n clientTools,\n signal,\n onSessionId,\n onPaused,\n onAutoResume,\n onResponse,\n } = options;\n\n let fullText = \"\";\n\n // Track pending auto-resume operations so we don't call onComplete prematurely\n const pendingAutoResumes: Promise<void>[] = [];\n\n // ── Make the POST request ──────────────────────────────────────────\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n ...headers,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n // ── Extract session ID from response headers ───────────────────────\n const sessionId = response.headers.get(\"X-BuildShip-Agent-Session-ID\");\n if (sessionId && onSessionId) {\n onSessionId(sessionId as SessionId);\n }\n\n // ── Expose the raw Response object ─────────────────────────────────\n onResponse?.(response);\n\n // ── Handle HTTP errors ─────────────────────────────────────────────\n if (!response.ok) {\n let errorBody = \"\";\n try {\n errorBody = await response.text();\n } catch {\n // ignore\n }\n const error = new FatalStreamError(\n `HTTP ${response.status}: ${errorBody || response.statusText}`,\n response.status,\n );\n callbacks.onError?.(error);\n throw error;\n }\n\n // ── Read the SSE stream ────────────────────────────────────────────\n if (!response.body) {\n const error = new Error(\"Response body is null — streaming not supported\");\n callbacks.onError?.(error);\n throw error;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n // Keep the last (potentially incomplete) part in the buffer\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const dataLine = part.split(\"\\n\").find((line) => line.startsWith(\"data:\"));\n\n if (!dataLine) continue;\n\n const jsonStr = dataLine.slice(5).trim(); // strip \"data:\" prefix\n if (!jsonStr) continue;\n\n let raw: any;\n try {\n raw = JSON.parse(jsonStr);\n } catch {\n // Skip malformed events\n continue;\n }\n\n // Normalize backend event type names (llm_text_delta → text_delta, etc.)\n const event = normalizeEvent(raw) as StreamEvent;\n\n handleEvent(\n event,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n\n // Accumulate text\n if (event.type === \"text_delta\") {\n fullText += event.data;\n }\n }\n }\n\n // Flush any remaining buffer\n if (buffer.trim()) {\n const dataLine = buffer.split(\"\\n\").find((line) => line.startsWith(\"data:\"));\n if (dataLine) {\n const jsonStr = dataLine.slice(5).trim();\n if (jsonStr) {\n try {\n const event = normalizeEvent(JSON.parse(jsonStr)) as StreamEvent;\n handleEvent(\n event,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n if (event.type === \"text_delta\") {\n fullText += event.data;\n }\n } catch {\n // skip\n }\n }\n }\n }\n\n // Wait for any pending auto-resume handlers before signaling completion\n if (pendingAutoResumes.length > 0) {\n await Promise.allSettled(pendingAutoResumes);\n }\n\n // Stream complete\n callbacks.onComplete?.(fullText);\n } catch (err) {\n // AbortError — just rethrow\n if (err instanceof Error && err.name === \"AbortError\") {\n throw err;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n callbacks.onError?.(error);\n throw error;\n }\n}\n\n/**\n * Normalize backend event type names.\n * The backend sends `llm_text_delta` / `llm_reasoning_delta` but the SDK\n * exposes them as `text_delta` / `reasoning_delta`.\n * @internal\n */\nfunction normalizeEvent(raw: any): any {\n const typeMap: Record<string, string> = {\n llm_text_delta: \"text_delta\",\n llm_reasoning_delta: \"reasoning_delta\",\n };\n if (raw && typeof raw.type === \"string\" && typeMap[raw.type]) {\n raw.type = typeMap[raw.type];\n }\n return raw;\n}\n\n/**\n * Dispatch a parsed stream event to the appropriate callbacks.\n * @internal\n */\nfunction handleEvent(\n event: StreamEvent,\n _fullText: string,\n callbacks: StreamOptions[\"callbacks\"],\n clientTools: StreamOptions[\"clientTools\"],\n onPaused: StreamOptions[\"onPaused\"],\n onAutoResume: StreamOptions[\"onAutoResume\"],\n pendingAutoResumes: Promise<void>[],\n): void {\n // Notify raw event consumers\n callbacks.onEvent?.(event);\n\n switch (event.type) {\n case \"text_delta\": {\n callbacks.onText?.(event.data);\n break;\n }\n\n case \"reasoning_delta\": {\n callbacks.onReasoning?.(event.data.delta, event.data.index);\n break;\n }\n\n case \"agent_handoff\": {\n callbacks.onAgentHandoff?.(event.data.agentName);\n break;\n }\n\n case \"tool_call_start\": {\n const { callId, toolName, toolType, inputs, paused } = event.data;\n\n // Notify callback\n callbacks.onToolStart?.(toolName, toolType);\n\n // Handle client tools\n if (toolType === \"client\") {\n const tool = clientTools.get(toolName);\n if (tool) {\n if (paused && tool.handler) {\n // Blocking tool with handler → auto-execute and resume\n const handlerPromise = (async () => {\n try {\n const result = await tool.handler!(inputs);\n await onAutoResume?.(callId, result);\n } catch {\n // If handler fails, still call onPaused so user can decide\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n })();\n pendingAutoResumes.push(handlerPromise);\n } else if (paused) {\n // Blocking tool without handler → pause for user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n } else if (tool.handler) {\n // Fire-and-forget tool with handler\n try {\n tool.handler(inputs);\n } catch {\n // Swallow errors on fire-and-forget\n }\n }\n } else if (paused) {\n // No registered tool but paused — notify user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n }\n break;\n }\n\n case \"tool_call_end\": {\n const { toolName, result, error } = event.data;\n callbacks.onToolEnd?.(toolName, result, error);\n break;\n }\n }\n}\n","import type { MessagePart } from \"../types\";\n\n/**\n * Updates a list of message parts with a new part,\n * appending it and merging with the previous part if both are contiguous text deltas.\n * Parts are kept in arrival order (no sorting) since events stream chronologically.\n */\nexport function updateAgentMessageParts(parts: MessagePart[], newPart: MessagePart): MessagePart[] {\n const last = parts[parts.length - 1];\n\n // Merge contiguous text deltas\n const canMerge =\n last?.type === \"text\" &&\n newPart.type === \"text\" &&\n newPart.firstSequence === last.lastSequence + 1;\n\n if (canMerge) {\n return [\n ...parts.slice(0, -1),\n {\n ...last,\n text: last.text + newPart.text,\n lastSequence: newPart.lastSequence,\n },\n ];\n }\n\n return [...parts, newPart];\n}\n","import { executeStream } from \"../core/stream\";\nimport type {\n StreamCallbacks,\n StreamEvent,\n TextDeltaEvent,\n ToolCallStartEvent,\n ExecuteRequestBody,\n ClientTool,\n} from \"../core/types\";\n\nimport type { AgentToolContextValue } from \"./agent-context\";\nimport type { createDebugHandlers } from \"./debug-handlers\";\nimport type { Message, MessagePart } from \"./types\";\nimport { tryParseJSON } from \"./utils/schema\";\nimport { updateAgentMessageParts } from \"./utils/message\";\n\n// ── Types ──────────────────────────────────────────────────────────────\n\nexport type RunOptions = {\n context?: object;\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n optimisticExecutionId?: string;\n /** @deprecated Use `useClientTool` hook instead. */\n clientTools?: Array<{\n name: string;\n description: string;\n parameters: unknown;\n await?: boolean;\n }>;\n // Resume params\n resumeToolCallId?: string;\n resumeToolResult?: any;\n};\n\nexport type StreamDeps = {\n agentUrl: string;\n agentId: string;\n accessKey?: string;\n currentSessionId: string;\n messagesRef: React.MutableRefObject<Array<Message>>;\n setMessages: React.Dispatch<React.SetStateAction<Array<Message>>>;\n setInProgress: React.Dispatch<React.SetStateAction<boolean>>;\n syncSessionRef: React.MutableRefObject<((messages?: Array<Message>) => void) | undefined>;\n createSessionFromResponse: (\n sessionId: string,\n sessionName: string,\n currentMessages: Array<Message>,\n ) => void;\n setCurrentSessionId: (sessionId: string) => void;\n debugHandlers: ReturnType<typeof createDebugHandlers>;\n toolContext: AgentToolContextValue | null;\n lastRequestContextRef: React.MutableRefObject<{\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n sessionId?: string;\n }>;\n getClientToolsMap: () => Map<string, ClientTool>;\n signal: AbortSignal;\n /** Recursive self-reference so onAutoResume can call runAgent again */\n runAgentRef: React.MutableRefObject<\n ((input: string | undefined, options?: RunOptions) => Promise<void>) | undefined\n >;\n};\n\n// ── Build callbacks ────────────────────────────────────────────────────\n\n/**\n * Build the StreamCallbacks object from dependencies.\n * Keeps event-handling logic out of the main hook.\n */\nexport function buildStreamCallbacks(\n deps: StreamDeps,\n debugKey: string | undefined,\n): StreamCallbacks {\n const { setMessages, setInProgress, syncSessionRef, messagesRef, toolContext, agentId } = deps;\n\n return {\n onComplete: () => {\n console.log(\"Agent closed\");\n setInProgress(false);\n if (syncSessionRef.current) {\n syncSessionRef.current(messagesRef.current);\n }\n },\n onError: (error: Error) => {\n console.log(\"Agent error\", error);\n setInProgress(false);\n if (syncSessionRef.current) {\n syncSessionRef.current(messagesRef.current);\n }\n },\n onEvent: (event: StreamEvent) => {\n if (event.type === \"text_delta\") {\n handleTextDelta(event, setMessages, syncSessionRef);\n } else if (event.type === \"tool_call_start\" && event.data.toolType === \"client\") {\n // Create a widget part for tools with a render function\n handleClientToolCall(event, setMessages, syncSessionRef, toolContext, agentId);\n // Send to debug so the tool shows in the debug panel\n if (debugKey) {\n const debugMeta = { ...event.meta, executionId: debugKey };\n deps.debugHandlers.handleStreamEvent({\n ...event,\n meta: debugMeta,\n } as StreamEvent);\n\n // Server never sends tool_call_end for client tools.\n // For non-paused (fire-and-forget) tools, immediately mark complete.\n if (!event.data.paused) {\n deps.debugHandlers.handleStreamEvent({\n type: \"tool_call_end\",\n data: {\n callId: event.data.callId,\n toolName: event.data.toolName,\n toolType: event.data.toolType,\n },\n meta: debugMeta,\n } as StreamEvent);\n }\n }\n } else if (debugKey) {\n // All other events (server tools, reasoning, handoffs, etc.)\n deps.debugHandlers.handleStreamEvent({\n ...event,\n meta: { ...event.meta, executionId: debugKey },\n } as StreamEvent);\n }\n },\n };\n}\n\n// ── Execute agent stream ───────────────────────────────────────────────\n\nconst TEMPORARY_SESSION_ID = \"sess_temp\";\nconst DEFAULT_SESSION_NAME = \"New Chat\";\n\n/**\n * Execute the agent stream with all wiring (session, auto-resume, etc.).\n */\nexport async function executeAgentStream(\n deps: StreamDeps,\n body: ExecuteRequestBody,\n headers: Record<string, string>,\n callbacks: StreamCallbacks,\n debugKey?: string,\n) {\n const {\n agentUrl,\n signal,\n currentSessionId,\n lastRequestContextRef,\n messagesRef,\n createSessionFromResponse,\n setMessages,\n syncSessionRef,\n runAgentRef,\n } = deps;\n\n await executeStream({\n url: agentUrl,\n body,\n headers,\n callbacks,\n clientTools: deps.getClientToolsMap(),\n signal,\n\n onSessionId: (sessionId) => {\n // Always keep the ref up to date for resume calls\n lastRequestContextRef.current.sessionId = sessionId;\n if (!currentSessionId || currentSessionId === TEMPORARY_SESSION_ID) {\n createSessionFromResponse(sessionId, DEFAULT_SESSION_NAME, messagesRef.current);\n deps.setCurrentSessionId(sessionId);\n }\n },\n\n // Session creation is handled by onSessionId above.\n\n onAutoResume: async (callId, result) => {\n // Persist the handler result in the widget part\n setMessages((prev) => {\n const updatedMessages = prev.map((msg) => {\n if (msg.parts) {\n const updatedParts = msg.parts.map((part) => {\n if (part.type === \"widget\" && part.callId === callId) {\n return { ...part, status: \"submitted\" as const, result };\n }\n return part;\n });\n return { ...msg, parts: updatedParts };\n }\n return msg;\n });\n if (syncSessionRef.current) {\n syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n\n // Emit synthetic tool_call_end for the debug panel\n if (debugKey) {\n deps.debugHandlers.handleStreamEvent({\n type: \"tool_call_end\",\n data: { callId, toolName: \"\", toolType: \"client\" as const, result },\n meta: { executionId: debugKey, sequence: 0 },\n } as StreamEvent);\n }\n\n // Auto-resume: send result back to agent\n try {\n await runAgentRef.current?.(undefined, {\n resumeToolCallId: callId,\n resumeToolResult: result,\n });\n } catch (error) {\n console.error(\"Auto-resume failed\", error);\n }\n },\n });\n}\n\n// ── Event handlers (private) ───────────────────────────────────────────\n\nfunction handleTextDelta(\n event: TextDeltaEvent,\n setMessages: React.Dispatch<React.SetStateAction<Array<Message>>>,\n syncSessionRef: React.MutableRefObject<((messages?: Array<Message>) => void) | undefined>,\n) {\n const sequence = event.meta.sequence;\n const text = event.data;\n const eventExecutionId = event.meta.executionId;\n\n setMessages((prev) => {\n const lastMessage = prev[prev.length - 1];\n const newPart: MessagePart = {\n type: \"text\",\n text,\n firstSequence: sequence,\n lastSequence: sequence,\n };\n\n let updatedMessages: Message[];\n\n if (lastMessage?.role === \"agent\") {\n const updatedMessage: Message = {\n ...lastMessage,\n content: lastMessage.content + text,\n parts: updateAgentMessageParts(lastMessage.parts || [], newPart),\n };\n updatedMessages = [...prev.slice(0, -1), updatedMessage];\n } else {\n const updatedMessage: Message = {\n role: \"agent\" as const,\n content: text,\n parts: [newPart],\n executionId: eventExecutionId,\n };\n updatedMessages = [...prev, updatedMessage];\n }\n\n if (syncSessionRef.current) {\n syncSessionRef.current(updatedMessages);\n }\n\n return updatedMessages;\n });\n}\n\nfunction handleClientToolCall(\n event: ToolCallStartEvent,\n setMessages: React.Dispatch<React.SetStateAction<Array<Message>>>,\n syncSessionRef: React.MutableRefObject<((messages?: Array<Message>) => void) | undefined>,\n toolContext: AgentToolContextValue | null,\n agentId: string,\n) {\n // Only create widget for tools with a registered render function\n const tool = toolContext?.getTool(agentId, event.data.toolName);\n if (!tool?.render) return;\n\n setMessages((prev) => {\n const lastMessage = prev[prev.length - 1];\n const newPart: MessagePart = {\n type: \"widget\",\n toolName: event.data.toolName,\n callId: event.data.callId,\n inputs: tryParseJSON(event.data.inputs),\n sequence: event.meta.sequence,\n paused: event.data.paused,\n status: \"pending\",\n };\n\n let updatedMessages: Message[];\n\n if (lastMessage?.role === \"agent\") {\n const updatedMessage: Message = {\n ...lastMessage,\n parts: updateAgentMessageParts(lastMessage.parts || [], newPart),\n };\n updatedMessages = [...prev.slice(0, -1), updatedMessage];\n } else {\n const updatedMessage: Message = {\n role: \"agent\" as const,\n content: \"\",\n parts: [newPart],\n executionId: event.meta.executionId,\n };\n updatedMessages = [...prev, updatedMessage];\n }\n\n if (syncSessionRef.current) {\n syncSessionRef.current(updatedMessages);\n }\n\n return updatedMessages;\n });\n}\n","import { useState, useEffect, useCallback } from \"react\";\n\n// Helper to handle JSON parsing cleanly\nfunction parseJSON<T>(value: string | null, defaultValue: T): T {\n if (value === null) return defaultValue;\n try {\n return JSON.parse(value);\n } catch {\n return defaultValue;\n }\n}\n\nexport function useSyncedLocalStorage<T>(\n key: string,\n initialValue: T,\n): [T, (value: T | ((val: T) => T)) => void] {\n // Initialize state function to avoid reading localStorage on every render\n const [storedValue, setStoredValue] = useState<T>(() => {\n if (typeof window === \"undefined\") {\n return initialValue;\n }\n try {\n const item = window.localStorage.getItem(key);\n return parseJSON(item, initialValue);\n } catch (error) {\n console.warn(`Error reading localStorage key \"${key}\":`, error);\n return initialValue;\n }\n });\n\n // Function to update state and localStorage\n const setValue = useCallback(\n (value: T | ((val: T) => T)) => {\n try {\n setStoredValue((prev) => {\n const valueToStore = value instanceof Function ? value(prev) : value;\n\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(key, JSON.stringify(valueToStore));\n // Dispatch a custom event so other hooks in the same window update\n window.dispatchEvent(\n new StorageEvent(\"storage\", { key, newValue: JSON.stringify(valueToStore) }),\n );\n }\n return valueToStore;\n });\n } catch (error) {\n console.warn(`Error setting localStorage key \"${key}\":`, error);\n }\n },\n [key],\n );\n\n // Sync across tabs/windows and within the same window\n useEffect(() => {\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key === key) {\n setStoredValue(parseJSON(event.newValue, initialValue));\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [key, initialValue]);\n\n return [storedValue, setValue];\n}\n","import { useContext, useEffect, useState, useCallback, createElement } from \"react\";\nimport type { ZodSchema } from \"zod\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * Infer the output type from a Zod schema's structural shape (`_zod.output`).\n * Falls back to `any` for raw JSON Schema objects or untyped parameters.\n * @internal\n */\ntype InferInput<T> = T extends { _zod: { output: infer O } } ? O : any;\n\nexport interface ClientToolRenderProps<T = any> {\n /** Parsed inputs from the agent. */\n inputs: T;\n /** Submit a result back to the agent (only available when `await: true`). */\n submit: (result: any) => void;\n /** Current status of this widget instance. */\n status: \"pending\" | \"submitted\";\n /** The persisted result from a previous submission (available after submit or on reload). */\n result?: any;\n}\n\nexport interface ClientToolConfig<TParams = any> {\n /** Tool name — must match the name the agent knows. */\n name: string;\n /** Description of what the tool does. */\n description: string;\n /**\n * Tool parameters — accepts a **Zod schema** or a raw JSON Schema object.\n * When a Zod schema is provided, `handler` and `render` inputs are\n * automatically typed — no explicit generic needed.\n *\n * @example\n * parameters: z.object({ question: z.string() })\n */\n parameters: TParams;\n /** If true, agent pauses and waits for the tool result before continuing. */\n await?: boolean;\n /**\n * Handler function for headless tools (no UI).\n * If `await: true`, the return value is sent back to the agent.\n * If `await: false`, runs as fire-and-forget.\n * Inputs are automatically typed when `parameters` is a Zod schema.\n */\n handler?: (inputs: InferInput<TParams>) => any | Promise<any>;\n /**\n * Render function for widget tools (with UI).\n * Receives `{ inputs, submit, status }`.\n * - `submit(result)` resumes the agent when `await: true`.\n * - `status` is `\"pending\"` until submitted, then `\"submitted\"`.\n * Inputs are automatically typed when `parameters` is a Zod schema.\n */\n render?: (props: ClientToolRenderProps<InferInput<TParams>>) => any;\n}\n\n// ─── Context import (late-bound to avoid circular deps) ──────────────────────\n\n// We import the context lazily from agent-context\nimport { AgentToolContext } from \"./agent-context\";\n\n// ─── useClientTool hook ──────────────────────────────────────────────────────\n\n/**\n * Register a client tool for a specific agent.\n *\n * @example\n * ```tsx\n * // Headless tool\n * useClientTool(\"agent-123\", {\n * name: \"get_location\",\n * description: \"Gets user location\",\n * parameters: z.object({}),\n * handler: async () => {\n * const pos = await getPosition();\n * return { lat: pos.coords.latitude, lng: pos.coords.longitude };\n * },\n * });\n *\n * // Widget tool with submission\n * useClientTool(\"agent-123\", {\n * name: \"feedback_form\",\n * description: \"Collects feedback\",\n * parameters: z.object({ question: z.string() }),\n * await: true,\n * render: ({ inputs, submit, status }) => (\n * <form onSubmit={() => submit({ answer: \"...\" })}>\n * <p>{inputs.question}</p>\n * <button disabled={status !== \"pending\"}>Submit</button>\n * </form>\n * ),\n * });\n * ```\n */\nexport function useClientTool<TParams>(agentId: string, config: ClientToolConfig<TParams>): void {\n const context = useContext(AgentToolContext);\n\n if (!context) {\n throw new Error(\"useClientTool must be used within <AgentContextProvider>\");\n }\n\n useEffect(() => {\n context.registerTool(agentId, config);\n return () => {\n context.unregisterTool(agentId, config.name);\n };\n // Note: consumers should memoize `config` to avoid unnecessary re-registrations.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agentId, config.name, config.handler, config.render, config.parameters]);\n}\n\n// ─── ToolRenderer component ──────────────────────────────────────────────────\n\ninterface ToolRendererProps {\n /** The agent ID this tool belongs to. */\n agentId: string;\n /** The widget message part to render. */\n part: {\n toolName: string;\n callId: string;\n inputs: any;\n paused?: boolean;\n status?: \"pending\" | \"submitted\";\n result?: any;\n };\n}\n\n/**\n * Renders a registered widget tool.\n * Looks up the tool by name from the registry and renders it with\n * the appropriate props (inputs, submit, status).\n *\n * @example\n * ```tsx\n * {message.parts?.map((part) => {\n * if (part.type === \"widget\") {\n * return <ToolRenderer key={part.callId} agentId=\"agent-123\" part={part} />;\n * }\n * return <Markdown key={part.firstSequence}>{part.text}</Markdown>;\n * })}\n * ```\n */\nexport function ToolRenderer({ agentId, part }: ToolRendererProps) {\n const context = useContext(AgentToolContext);\n const [localStatus, setLocalStatus] = useState<\"pending\" | \"submitted\">(part.status || \"pending\");\n\n // Sync localStatus when part.status changes externally\n // (e.g., messages reloaded from session storage after resume)\n useEffect(() => {\n setLocalStatus(part.status || \"pending\");\n }, [part.status]);\n\n if (!context) {\n throw new Error(\"ToolRenderer must be used within <AgentContextProvider>\");\n }\n\n const tool = context.getTool(agentId, part.toolName);\n\n const handleSubmit = useCallback(\n (result: any) => {\n if (localStatus === \"submitted\") return; // Prevent double-submission\n setLocalStatus(\"submitted\");\n context.resumeTool(agentId, part.callId, result);\n },\n [agentId, part.callId, localStatus, context],\n );\n\n if (!tool?.render) {\n return null; // No registered render function for this tool\n }\n\n return tool.render({\n inputs: part.inputs,\n submit: part.paused ? handleSubmit : () => {},\n status: localStatus,\n result: part.result,\n });\n}\n"],"mappings":"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","names":["useContext","useCallback","useRef","useState","useEffect","useMemo","useCallback","useRef","useContext","useMemo","useCallback","useCallback","TEMPORARY_SESSION_ID","DEFAULT_SESSION_NAME","useContext","useRef","useMemo","useCallback","useState","useEffect","useCallback","useRef","useState","useCallback","useMemo","useContext","useEffect","useContext","useEffect","useState","useCallback","useContext","useEffect","useState","useCallback"]}
1
+ {"version":3,"sources":["../../src/react/agent-context.tsx","../../src/react/use-agent.ts","../../src/react/constants.ts","../../src/react/session-utils.ts","../../src/react/debug-handlers.ts","../../src/react/client-tools.ts","../../src/react/utils/schema.ts","../../src/core/stream.ts","../../src/react/utils/message.ts","../../src/react/stream-callbacks.ts","../../src/react/utils/use-synced-local-storage.ts","../../src/react/use-client-tool.ts"],"sourcesContent":["import {\n createContext,\n useContext,\n useCallback,\n useRef,\n useState,\n useEffect,\n useMemo,\n ReactNode,\n} from \"react\";\nimport useAgent from \"./use-agent\";\nimport type { Message, Session, DebugDataType } from \"./types\";\nimport type { ClientToolConfig } from \"./use-client-tool\";\nimport { useSyncedLocalStorage } from \"./utils/use-synced-local-storage\";\nimport { AGENT_SESSIONS_KEY, AGENT_DEBUG_DATA_KEY } from \"./constants\";\n\nexport interface AgentRunner {\n messages: Message[];\n inProgress: boolean;\n sessionId: string;\n sessions: Session[];\n debugData: Record<string, DebugDataType>;\n handleSend: (\n input: string,\n options?: {\n context?: Record<string, unknown>;\n skipUserMessage?: boolean;\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n /** @deprecated Use `useClientTool` hook instead. */\n clientTools?: Array<{\n name: string;\n description: string;\n parameters: unknown;\n await?: boolean;\n }>;\n },\n ) => Promise<void>;\n resumeTool: (callId: string, result: any) => Promise<void>;\n switchSession: (sessionId?: string) => void;\n deleteSession: (sessionId: string) => void;\n addOptimisticMessage: (input: string) => void;\n abort: () => void;\n}\n\n// ─── Tool Registry Context ──────────────────────────────────────────────────\n\nexport interface AgentToolContextValue {\n registerTool: (agentId: string, config: ClientToolConfig) => void;\n unregisterTool: (agentId: string, toolName: string) => void;\n getTool: (agentId: string, toolName: string) => ClientToolConfig | undefined;\n getToolsForAgent: (agentId: string) => ClientToolConfig[];\n resumeTool: (agentId: string, callId: string, result: any) => void;\n}\n\nexport const AgentToolContext = createContext<AgentToolContextValue | null>(null);\n\n// ─── Agent Context ──────────────────────────────────────────────────────────\n\ninterface AgentContextValue {\n initializeAgent: (agentId: string, agentUrl: string, accessKey?: string) => void;\n registerRunner: (agentId: string, runner: AgentRunner) => void;\n getRunner: (agentId: string) => AgentRunner | null;\n // Global state provided to useAgent hooks\n allSessions: Record<string, Record<string, Session>>;\n setAllSessions: (\n value:\n | Record<string, Record<string, Session>>\n | ((\n prev: Record<string, Record<string, Session>>,\n ) => Record<string, Record<string, Session>>),\n ) => void;\n debugData: Record<string, DebugDataType>;\n setDebugData: (\n value:\n | Record<string, DebugDataType>\n | ((prev: Record<string, DebugDataType>) => Record<string, DebugDataType>),\n ) => void;\n}\n\nconst AgentContext = createContext<AgentContextValue | null>(null);\n\nexport function AgentContextProvider({ children }: { children: ReactNode }) {\n const activeAgentsRef = useRef<Map<string, { agentUrl: string; accessKey?: string }>>(new Map());\n const runnersRef = useRef<Map<string, AgentRunner>>(new Map());\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Tool registry: agentId -> Map<toolName, ClientToolConfig>\n const toolRegistryRef = useRef<Map<string, Map<string, ClientToolConfig>>>(new Map());\n\n const [, forceUpdate] = useState({});\n\n // Global Sync State managed here to be shared\n const [allSessions, setAllSessions] = useSyncedLocalStorage<\n Record<string, Record<string, Session>>\n >(AGENT_SESSIONS_KEY, {});\n\n const [debugData, setDebugData] = useSyncedLocalStorage<Record<string, DebugDataType>>(\n AGENT_DEBUG_DATA_KEY,\n {},\n );\n\n const initializeAgent = useCallback((agentId: string, agentUrl: string, accessKey?: string) => {\n const existing = activeAgentsRef.current.get(agentId);\n\n if (!existing) {\n activeAgentsRef.current.set(agentId, { agentUrl, accessKey });\n forceUpdate({});\n } else if (existing.agentUrl !== agentUrl || existing.accessKey !== accessKey) {\n activeAgentsRef.current.set(agentId, { agentUrl, accessKey });\n forceUpdate({});\n }\n }, []);\n\n const registerRunner = useCallback((agentId: string, runner: AgentRunner) => {\n runnersRef.current.set(agentId, runner);\n // Notify listeners for this agentId\n const listeners = listenersRef.current.get(agentId);\n if (listeners) {\n listeners.forEach((callback) => callback());\n }\n }, []);\n\n const getRunner = useCallback((agentId: string) => {\n return runnersRef.current.get(agentId) || null;\n }, []);\n\n // ─── Tool registry methods ─────────────────────────────────────────\n\n const registerTool = useCallback((agentId: string, config: ClientToolConfig) => {\n if (!toolRegistryRef.current.has(agentId)) {\n toolRegistryRef.current.set(agentId, new Map());\n }\n toolRegistryRef.current.get(agentId)!.set(config.name, config);\n }, []);\n\n const unregisterTool = useCallback((agentId: string, toolName: string) => {\n toolRegistryRef.current.get(agentId)?.delete(toolName);\n }, []);\n\n const getTool = useCallback((agentId: string, toolName: string) => {\n return toolRegistryRef.current.get(agentId)?.get(toolName);\n }, []);\n\n const getToolsForAgent = useCallback((agentId: string) => {\n const toolMap = toolRegistryRef.current.get(agentId);\n return toolMap ? Array.from(toolMap.values()) : [];\n }, []);\n\n const resumeToolFromContext = useCallback((agentId: string, callId: string, result: any) => {\n const runner = runnersRef.current.get(agentId);\n if (runner) {\n runner.resumeTool(callId, result);\n } else {\n console.warn(`Cannot resume tool: no runner found for agent \"${agentId}\"`);\n }\n }, []);\n\n // ─── Context values ────────────────────────────────────────────────\n\n const agentContextValue = useMemo(\n () => ({\n initializeAgent,\n registerRunner,\n getRunner,\n allSessions,\n setAllSessions,\n debugData,\n setDebugData,\n runnersRef,\n listenersRef,\n }),\n [\n initializeAgent,\n registerRunner,\n getRunner,\n allSessions,\n setAllSessions,\n debugData,\n setDebugData,\n ],\n );\n\n const toolContextValue = useMemo(\n () => ({\n registerTool,\n unregisterTool,\n getTool,\n getToolsForAgent,\n resumeTool: resumeToolFromContext,\n }),\n [registerTool, unregisterTool, getTool, getToolsForAgent, resumeToolFromContext],\n );\n\n return (\n <AgentContext.Provider value={agentContextValue}>\n <AgentToolContext.Provider value={toolContextValue}>\n {children}\n {Array.from(activeAgentsRef.current.entries()).map(([agentId, { agentUrl, accessKey }]) => (\n <AgentRunnerInstance\n key={agentId}\n agentId={agentId}\n agentUrl={agentUrl}\n accessKey={accessKey}\n />\n ))}\n </AgentToolContext.Provider>\n </AgentContext.Provider>\n );\n}\n\nfunction AgentRunnerInstance({\n agentId,\n agentUrl,\n accessKey,\n}: {\n agentId: string;\n agentUrl: string;\n accessKey?: string;\n}) {\n const agent = useAgent(agentId, agentUrl, accessKey);\n const context = useContext(AgentContext);\n\n useEffect(() => {\n if (context) {\n context.registerRunner(agentId, agent);\n }\n }, [agentId, agent, context]);\n\n if (!context) return null;\n\n return null;\n}\n\nexport function useAgentContext(\n agentId: string,\n agentUrl: string,\n accessKey?: string,\n): AgentRunner {\n const context = useContext(AgentContext);\n\n if (!context) {\n throw new Error(\"useAgentContext must be used within AgentContextProvider\");\n }\n\n const { initializeAgent, getRunner, listenersRef } = context as AgentContextValue & {\n listenersRef: React.MutableRefObject<Map<string, Set<() => void>>>;\n };\n\n useEffect(() => {\n initializeAgent(agentId, agentUrl, accessKey);\n }, [agentId, agentUrl, initializeAgent]);\n\n // Reactive subscription to runner updates\n const [runner, setRunner] = useState<AgentRunner | null>(() => getRunner(agentId));\n\n useEffect(() => {\n // Current runner state\n const currentRunner = getRunner(agentId);\n if (currentRunner !== runner) {\n setRunner(currentRunner);\n }\n\n // Subscribe to future updates\n const callback = () => {\n setRunner(getRunner(agentId));\n };\n\n if (!listenersRef.current.has(agentId)) {\n listenersRef.current.set(agentId, new Set());\n }\n listenersRef.current.get(agentId)?.add(callback);\n\n return () => {\n listenersRef.current.get(agentId)?.delete(callback);\n };\n }, [agentId, getRunner]);\n\n const placeholder = useMemo(\n () => ({\n messages: [],\n inProgress: false,\n sessionId: \"\",\n sessions: [],\n debugData: {},\n handleSend: async () => {},\n resumeTool: async () => {},\n switchSession: () => {},\n deleteSession: () => {},\n addOptimisticMessage: () => {},\n abort: () => {},\n }),\n [],\n );\n\n return runner || placeholder;\n}\n\n// Hook to access the global state for use-agent\nexport function useAgentGlobalState() {\n const context = useContext(AgentContext);\n if (!context) {\n throw new Error(\"useAgentGlobalState must be used within AgentContextProvider\");\n }\n return {\n allSessions: context.allSessions,\n setAllSessions: context.setAllSessions,\n debugData: context.debugData,\n setDebugData: context.setDebugData,\n };\n}\n","import { useCallback, useRef, useState, useEffect, useContext, useMemo } from \"react\";\n\nimport type { ExecuteRequestBody, StreamEvent } from \"../core/types\";\n\nimport { DEFAULT_SESSION_NAME, TEMPORARY_SESSION_ID } from \"./constants\";\nimport { useSessionUtils } from \"./session-utils\";\nimport { createDebugHandlers } from \"./debug-handlers\";\nimport { useAgentGlobalState, AgentToolContext } from \"./agent-context\";\nimport type { Message } from \"./types\";\nimport { useClientToolHelpers } from \"./client-tools\";\nimport { buildStreamCallbacks, executeAgentStream } from \"./stream-callbacks\";\nimport type { RunOptions } from \"./stream-callbacks\";\n\nexport default function useAgent(agentId: string, agentUrl: string, accessKey?: string) {\n const { allSessions, setAllSessions, debugData, setDebugData } = useAgentGlobalState();\n const toolContext = useContext(AgentToolContext);\n\n const [inProgress, setInProgress] = useState(false);\n const [messages, setMessages] = useState<Array<Message>>([]);\n const messagesRef = useRef<Array<Message>>([]);\n\n const [currentSessionId, setCurrentSessionId] = useState<string>(TEMPORARY_SESSION_ID);\n\n const sessionUtils = useSessionUtils(\n agentId,\n allSessions,\n setAllSessions,\n currentSessionId,\n setCurrentSessionId,\n messagesRef,\n );\n\n useEffect(() => {\n const initialSessionId = sessionUtils.getInitialSessionId();\n setCurrentSessionId(initialSessionId);\n }, []);\n\n const debugHandlers = useMemo(() => createDebugHandlers(setDebugData), [setDebugData]);\n\n useEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n\n // Reload messages from session storage only on session/agent switch\n useEffect(() => {\n if (inProgress) return;\n const session = sessionUtils.agentSessions[currentSessionId];\n if (session) {\n setMessages(session.messages);\n } else {\n setMessages([]);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentSessionId, agentId]);\n\n useEffect(() => {\n return () => {\n if (messagesRef.current.length > 0 && sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current();\n }\n };\n }, []);\n\n const controller = useRef<AbortController>();\n\n // Persist additionalHeaders + additionalBody + sessionId for resume calls\n const lastRequestContextRef = useRef<{\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n sessionId?: string;\n }>({});\n\n const { getClientToolsMap, getClientToolDefs } = useClientToolHelpers(agentId, toolContext);\n\n // Ref for recursive auto-resume calls\n const runAgentRef = useRef<\n ((input: string | undefined, options?: RunOptions) => Promise<void>) | undefined\n >();\n\n const runAgent = useCallback(\n async (input: string | undefined, runOptions?: RunOptions) => {\n // Resolve session ID (exclude temp placeholder)\n const realSessionId =\n currentSessionId && currentSessionId !== TEMPORARY_SESSION_ID\n ? currentSessionId\n : lastRequestContextRef.current.sessionId;\n\n // Persist context for resume calls\n lastRequestContextRef.current = {\n additionalHeaders:\n runOptions?.additionalHeaders ?? lastRequestContextRef.current.additionalHeaders,\n additionalBody: runOptions?.additionalBody ?? lastRequestContextRef.current.additionalBody,\n sessionId: realSessionId,\n };\n\n setInProgress(true);\n // Only abort a previous in-flight stream if this is NOT a resume.\n if (!runOptions?.resumeToolCallId && controller.current) {\n controller.current.abort();\n }\n controller.current = new AbortController();\n\n // ── Build request ────────────────────────────────────────────\n const headers: Record<string, string> = {\n ...(lastRequestContextRef.current.additionalHeaders || {}),\n ...(accessKey ? { Authorization: `Bearer ${accessKey}` } : {}),\n };\n\n if (realSessionId) {\n headers[\"x-buildship-agent-session-id\"] = realSessionId;\n }\n\n const body: ExecuteRequestBody = {\n stream: true,\n ...(lastRequestContextRef.current.additionalBody || {}),\n };\n\n if (input !== undefined) {\n body.input = input;\n }\n\n if (runOptions?.context) {\n Object.assign(body, { context: runOptions.context });\n }\n\n if (runOptions?.resumeToolCallId) {\n body.toolCallResult = {\n callId: runOptions.resumeToolCallId,\n result: runOptions.resumeToolResult,\n };\n }\n\n // Client tool definitions\n const registeredToolDefs = getClientToolDefs() || [];\n const legacyToolDefs = (runOptions?.clientTools || []) as NonNullable<\n ExecuteRequestBody[\"clientTools\"]\n >;\n const allToolDefs = [...registeredToolDefs, ...legacyToolDefs];\n if (allToolDefs.length > 0) {\n body.clientTools = allToolDefs;\n }\n\n // ── Debug key ────────────────────────────────────────────────\n const debugKey =\n runOptions?.optimisticExecutionId ||\n messagesRef.current.findLast((m) => m.role === \"user\")?.executionId;\n\n // ── Build callbacks & execute ────────────────────────────────\n const deps = {\n agentUrl,\n agentId,\n accessKey,\n currentSessionId,\n messagesRef,\n setMessages,\n setInProgress,\n setCurrentSessionId,\n syncSessionRef: sessionUtils.syncSessionRef,\n createSessionFromResponse: sessionUtils.createSessionFromResponse,\n debugHandlers,\n toolContext,\n lastRequestContextRef,\n getClientToolsMap,\n signal: controller.current.signal,\n runAgentRef,\n };\n\n const callbacks = buildStreamCallbacks(deps, debugKey);\n\n try {\n await executeAgentStream(deps, body, headers, callbacks, debugKey);\n } catch (error) {\n console.log(\"Agent execution failed\", error);\n setInProgress(false);\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(messagesRef.current);\n }\n throw error;\n }\n },\n [\n agentUrl,\n accessKey,\n currentSessionId,\n sessionUtils.syncSessionRef,\n sessionUtils.createSessionFromResponse,\n debugHandlers,\n getClientToolsMap,\n getClientToolDefs,\n agentId,\n toolContext,\n ],\n );\n\n // Keep the ref in sync so onAutoResume can call runAgent\n useEffect(() => {\n runAgentRef.current = runAgent;\n }, [runAgent]);\n\n const handleSend = useCallback(\n async (\n input: string,\n options?: {\n context?: object;\n skipUserMessage?: boolean;\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n /** @deprecated Use `useClientTool` hook instead. */\n clientTools?: Array<{\n name: string;\n description: string;\n parameters: unknown;\n await?: boolean;\n }>;\n },\n ) => {\n const userMessage = {\n role: \"user\" as const,\n content: input,\n executionId: Date.now().toString(),\n };\n\n if (!options?.skipUserMessage) {\n setMessages((prev) => {\n const updatedMessages = [...prev, userMessage];\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n }\n\n // When skipUserMessage is true, the user message was already added\n // externally (e.g. via addOptimisticMessage) with its own executionId.\n const effectiveExecutionId = options?.skipUserMessage\n ? messagesRef.current.findLast((m) => m.role === \"user\")?.executionId ??\n userMessage.executionId\n : userMessage.executionId;\n\n try {\n await runAgent(input, {\n ...options,\n optimisticExecutionId: effectiveExecutionId,\n });\n } catch (error) {\n if (!options?.skipUserMessage) {\n setMessages((prev) => {\n const updatedMessages = prev.some((m) => m === userMessage)\n ? prev\n : [...prev, userMessage];\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n }\n throw error;\n }\n },\n [runAgent, sessionUtils.syncSessionRef],\n );\n\n const resumeTool = useCallback(\n async (callId: string, result: any) => {\n // Update the widget status and persist the result\n setMessages((prev) => {\n const updatedMessages = prev.map((msg) => {\n if (msg.parts) {\n const updatedParts = msg.parts.map((part) => {\n if (part.type === \"widget\" && part.callId === callId) {\n return { ...part, status: \"submitted\" as const, result };\n }\n return part;\n });\n return { ...msg, parts: updatedParts };\n }\n return msg;\n });\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n\n // Emit synthetic tool_call_end for the debug panel\n const debugKey = messagesRef.current.findLast((m) => m.role === \"user\")?.executionId;\n if (debugKey) {\n debugHandlers.handleStreamEvent({\n type: \"tool_call_end\",\n data: { callId, toolName: \"\", toolType: \"client\" as const, result },\n meta: { executionId: debugKey, sequence: 0 },\n } as StreamEvent);\n }\n\n // Resume the agent with the tool result\n await runAgent(undefined, {\n resumeToolCallId: callId,\n resumeToolResult: result,\n });\n },\n [runAgent, sessionUtils.syncSessionRef, debugHandlers],\n );\n\n const addOptimisticMessage = useCallback(\n (input: string) => {\n const userMessage = {\n role: \"user\" as const,\n content: input,\n executionId: Date.now().toString(),\n };\n\n setMessages((prev) => {\n const updatedMessages = [...prev, userMessage];\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n },\n [sessionUtils.syncSessionRef],\n );\n\n const abort = useCallback(() => {\n if (controller.current) {\n controller.current.abort();\n }\n setInProgress(false);\n if (sessionUtils.syncSessionRef.current) {\n sessionUtils.syncSessionRef.current(messagesRef.current);\n }\n }, [sessionUtils.syncSessionRef]);\n\n return {\n inProgress,\n messages,\n handleSend,\n resumeTool,\n addOptimisticMessage,\n abort,\n sessionId: currentSessionId,\n switchSession: sessionUtils.switchSession,\n deleteSession: sessionUtils.deleteSession,\n sessions: sessionUtils.sessionsList,\n debugData,\n };\n}\n","export const AGENT_SESSIONS_KEY = \"buildship:agent:conversations\";\nexport const AGENT_DEBUG_DATA_KEY = \"buildship:agent:debug\";\n\nexport const DEFAULT_SESSION_NAME = \"New Chat\";\nexport const TEMPORARY_SESSION_ID = \"sess_temp\";\n","import { useCallback, useMemo, useRef } from \"react\";\nimport type { Message, Session } from \"./types\";\nimport { TEMPORARY_SESSION_ID } from \"./constants\";\n\nexport const useSessionUtils = (\n agentId: string,\n allSessions: Record<string, Record<string, Session>>,\n setAllSessions: (\n value:\n | Record<string, Record<string, Session>>\n | ((\n prev: Record<string, Record<string, Session>>,\n ) => Record<string, Record<string, Session>>),\n ) => void,\n currentSessionId: string,\n setCurrentSessionId: (sessionId: string) => void,\n messagesRef: React.MutableRefObject<Array<Message>>,\n) => {\n const agentSessions = useMemo(() => allSessions[agentId] || {}, [agentId, allSessions]);\n\n const syncSessionRef = useRef<(messages?: Array<Message>) => void>();\n\n syncSessionRef.current = (updatedMessages?: Array<Message>) => {\n if (!currentSessionId || currentSessionId === TEMPORARY_SESSION_ID) {\n return;\n }\n\n setAllSessions((prev) => ({\n ...prev,\n [agentId]: {\n ...prev[agentId],\n [currentSessionId]: {\n ...prev[agentId]?.[currentSessionId],\n messages: updatedMessages ?? messagesRef.current,\n updatedAt: Date.now(),\n },\n },\n }));\n };\n\n const getInitialSessionId = () => {\n const sessions = Object.values(agentSessions);\n if (sessions.length > 0) {\n return sessions.sort((a, b) => b.updatedAt - a.updatedAt)[0].id;\n }\n return TEMPORARY_SESSION_ID;\n };\n\n const switchSession = useCallback(\n (sessionId: string = TEMPORARY_SESSION_ID) => {\n setCurrentSessionId(sessionId);\n },\n [setCurrentSessionId],\n );\n\n const deleteSession = useCallback(\n (sessionId: string) => {\n if (!sessionId || sessionId === TEMPORARY_SESSION_ID) {\n return;\n }\n\n setAllSessions((prev) => {\n const updatedAgentSessions = { ...prev[agentId] };\n delete updatedAgentSessions[sessionId];\n\n return {\n ...prev,\n [agentId]: updatedAgentSessions,\n };\n });\n\n if (sessionId === currentSessionId) {\n const remainingSessions = Object.values(agentSessions).filter((s) => s.id !== sessionId);\n if (remainingSessions.length > 0) {\n const mostRecent = remainingSessions.sort((a, b) => b.updatedAt - a.updatedAt)[0];\n setCurrentSessionId(mostRecent.id);\n } else {\n setCurrentSessionId(TEMPORARY_SESSION_ID);\n }\n }\n },\n [agentId, currentSessionId, agentSessions, setAllSessions, setCurrentSessionId],\n );\n\n const sessionsList = useMemo(\n () => Object.values(agentSessions).sort((a, b) => b.updatedAt - a.updatedAt),\n [agentSessions],\n );\n\n const createSessionFromResponse = (\n sessionId: string,\n sessionName: string,\n currentMessages: Array<Message>,\n ) => {\n setAllSessions((prev) => ({\n ...prev,\n [agentId]: {\n ...prev[agentId],\n [sessionId]: {\n id: sessionId,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n messages: currentMessages,\n name: sessionName,\n },\n },\n }));\n };\n\n return {\n agentSessions,\n syncSessionRef,\n getInitialSessionId,\n switchSession,\n deleteSession,\n sessionsList,\n createSessionFromResponse,\n };\n};\n","import type { StreamEvent } from \"../core/types\";\nimport type {\n DebugDataType,\n ToolExecutionItem,\n ReasoningItem,\n HandoffItem,\n RunErrorItem,\n} from \"./types\";\n\nexport const createDebugHandlers = (\n setDebugData: (\n value:\n | Record<string, DebugDataType>\n | ((prev: Record<string, DebugDataType>) => Record<string, DebugDataType>),\n ) => void,\n) => {\n const handleStreamEvent = (event: StreamEvent) => {\n const executionId = event.meta.executionId;\n\n switch (event.type) {\n case \"tool_call_start\": {\n const { callId, toolName, toolType, inputs, serverName } = event.data;\n setDebugData((prev) => ({\n ...prev,\n [executionId]: [\n ...(prev[executionId] || []),\n {\n itemType: \"tool_call\",\n toolName,\n callId,\n toolType,\n status: \"progress\",\n inputs,\n serverName,\n } as ToolExecutionItem,\n ],\n }));\n break;\n }\n\n case \"tool_call_end\": {\n const { callId, result, error } = event.data;\n setDebugData((prev) => {\n const currentData = [...(prev[executionId] || [])];\n\n for (let i = currentData.length - 1; i >= 0; i--) {\n if (currentData[i].itemType === \"tool_call\") {\n const toolItem = currentData[i] as ToolExecutionItem;\n if (toolItem.callId === callId) {\n currentData[i] = {\n ...toolItem,\n status: error ? \"error\" : \"complete\",\n output: result,\n error,\n };\n break;\n }\n }\n }\n\n return {\n ...prev,\n [executionId]: currentData,\n };\n });\n break;\n }\n\n case \"reasoning_delta\": {\n const { delta, index } = event.data;\n setDebugData((prev) => {\n const currentData = [...(prev[executionId] || [])];\n\n let existingItemIndex = -1;\n for (let i = currentData.length - 1; i >= 0; i--) {\n const item = currentData[i];\n if (item.itemType === \"reasoning\" && (item as ReasoningItem).index === index) {\n existingItemIndex = i;\n break;\n }\n }\n\n if (existingItemIndex === -1) {\n currentData.push({ itemType: \"reasoning\", reasoning: delta, index });\n } else {\n currentData[existingItemIndex] = {\n itemType: \"reasoning\",\n reasoning: (currentData[existingItemIndex] as ReasoningItem).reasoning + delta,\n index,\n };\n }\n\n return {\n ...prev,\n [executionId]: currentData,\n };\n });\n break;\n }\n\n case \"agent_handoff\": {\n setDebugData((prev) => ({\n ...prev,\n [executionId]: [\n ...(prev[executionId] || []),\n {\n itemType: \"handoff\",\n agentName: event.data.agentName,\n } as HandoffItem,\n ],\n }));\n break;\n }\n\n case \"run_error\": {\n setDebugData((prev) => ({\n ...prev,\n [executionId]: [\n ...(prev[executionId] || []),\n {\n itemType: \"run_error\",\n message: event.data.message,\n code: event.data.code,\n } as RunErrorItem,\n ],\n }));\n break;\n }\n }\n };\n\n return {\n handleStreamEvent,\n };\n};\n","import { useCallback, useContext } from \"react\";\nimport { toJSONSchema, type ZodSchema } from \"zod\";\n\nimport type { ExecuteRequestBody, ClientTool } from \"../core/types\";\nimport type { AgentToolContextValue } from \"./agent-context\";\nimport { cleanSchema } from \"./utils/schema\";\n\n/**\n * Resolve parameters — accepts Zod schema or plain JSON Schema object.\n */\nexport function resolveParameters(params: any): Record<string, any> {\n let schema: Record<string, any>;\n\n // Detect Zod schema: ZodType instances have a `_def` property\n if (params && typeof params === \"object\" && \"_def\" in params) {\n schema = toJSONSchema(params as ZodSchema) as Record<string, any>;\n delete schema.$schema;\n } else {\n schema = cleanSchema(params) as Record<string, any>;\n }\n\n // Gemini requires additionalProperties: false and required to include every key\n if (schema.type === \"object\") {\n schema.additionalProperties = false;\n if (schema.properties) {\n schema.required = Object.keys(schema.properties);\n }\n }\n\n return schema;\n}\n\n/**\n * Build the ClientTool map from registered tools (for handlers).\n * Widget-only tools are NOT included — they're handled via onEvent.\n */\nexport function useClientToolHelpers(agentId: string, toolContext: AgentToolContextValue | null) {\n const getClientToolsMap = useCallback((): Map<string, ClientTool> => {\n if (!toolContext) return new Map();\n const tools = toolContext.getToolsForAgent(agentId);\n const map = new Map<string, ClientTool>();\n\n for (const tool of tools) {\n if (tool.handler) {\n map.set(tool.name, {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n await: tool.await,\n handler: tool.handler,\n });\n }\n }\n\n return map;\n }, [agentId, toolContext]);\n\n /**\n * Build client tool definitions for the request body.\n * Includes ALL registered tools (handlers + widgets).\n */\n const getClientToolDefs = useCallback((): ExecuteRequestBody[\"clientTools\"] => {\n if (!toolContext) return [];\n const tools = toolContext.getToolsForAgent(agentId);\n\n return tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: resolveParameters(tool.parameters),\n await: tool.await,\n }));\n }, [agentId, toolContext]);\n\n return { getClientToolsMap, getClientToolDefs };\n}\n","/**\n * Helper to clean JSON Schema for LLM compatibility.\n * Replaces modern Draft 2020-12 features with older, more compatible alternatives.\n * Specifically handles OpenAI's 'Strict Mode' requirements.\n */\nexport function cleanSchema(obj: unknown): unknown {\n if (Array.isArray(obj)) {\n return obj.map(cleanSchema);\n } else if (obj !== null && typeof obj === \"object\") {\n const newObj: Record<string, unknown> = {};\n const currentObj = obj as Record<string, any>;\n\n for (const key in currentObj) {\n // Remove keys that are not supported by most LLMs\n if (key === \"propertyNames\" || key === \"$schema\") {\n continue;\n }\n newObj[key] = cleanSchema(currentObj[key]);\n }\n\n // OpenAI and some other LLMs require additionalProperties: false for all objects in strict mode\n // AND every property must be explicitly listed in the 'required' array\n if (newObj.type === \"object\") {\n if (\n newObj.additionalProperties === undefined ||\n (newObj.additionalProperties &&\n typeof newObj.additionalProperties === \"object\" &&\n Object.keys(newObj.additionalProperties).length === 0)\n ) {\n newObj.additionalProperties = false;\n }\n\n if (newObj.additionalProperties === false && newObj.properties) {\n newObj.required = Object.keys(newObj.properties as object);\n }\n }\n\n return newObj;\n }\n return obj;\n}\n\n/**\n * Safely attempts to parse a value as JSON if it's a string.\n */\nexport function tryParseJSON(value: unknown): any {\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n return value;\n}\n","import type { StreamEvent, StreamOptions, SessionId } from \"./types\";\n\n/** Safely parse a value as JSON if it's a string, otherwise return as-is. */\nfunction tryParseJSON(value: unknown): any {\n if (typeof value === \"string\") {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n return value;\n}\n\n/**\n * Fatal error — will NOT be retried.\n */\nclass FatalStreamError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n ) {\n super(message);\n this.name = \"FatalStreamError\";\n }\n}\n\n/**\n * Opens an SSE connection to the BuildShip agent endpoint using native\n * `fetch` + `ReadableStream`, parses events, and dispatches to the\n * appropriate callbacks.\n *\n * Zero runtime dependencies — works in both browser and Node.js.\n *\n * @internal\n */\nexport async function executeStream(options: StreamOptions): Promise<void> {\n const {\n url,\n body,\n headers,\n callbacks,\n clientTools,\n signal,\n onSessionId,\n onPaused,\n onAutoResume,\n onResponse,\n } = options;\n\n let fullText = \"\";\n\n // Track pending auto-resume operations so we don't call onComplete prematurely\n const pendingAutoResumes: Promise<void>[] = [];\n\n // ── Make the request ────────────────────────────────────────────────\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"text/event-stream\",\n ...headers,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n // ── Extract session ID and name from response headers ──────────────\n const sessionId = response.headers.get(\"X-BuildShip-Agent-Session-ID\");\n if (sessionId && onSessionId) {\n const sessionName = response.headers.get(\"X-BuildShip-Agent-Session-Name\") || undefined;\n onSessionId(sessionId as SessionId, sessionName);\n }\n\n // Expose the raw Response object\n onResponse?.(response);\n\n // ── Handle HTTP errors ─────────────────────────────────────────────\n if (!response.ok) {\n let errorBody = \"\";\n try {\n errorBody = await response.text();\n } catch {\n // ignore\n }\n const error = new FatalStreamError(\n `HTTP ${response.status}: ${errorBody || response.statusText}`,\n response.status,\n );\n callbacks.onError?.(error);\n throw error;\n }\n\n // ── Read the SSE stream ────────────────────────────────────────────\n if (!response.body) {\n callbacks.onComplete?.(fullText);\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // SSE events are separated by double newlines\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() || \"\";\n\n for (const part of parts) {\n const trimmedPart = part.trim();\n if (!trimmedPart) continue;\n\n // Extract the data field from SSE format\n let jsonStr = \"\";\n for (const line of trimmedPart.split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n jsonStr += line.slice(6);\n } else if (line.startsWith(\"data:\")) {\n jsonStr += line.slice(5);\n }\n }\n\n jsonStr = jsonStr.trim();\n if (!jsonStr) continue;\n\n let raw: any;\n try {\n raw = JSON.parse(jsonStr);\n } catch {\n // Skip malformed events\n continue;\n }\n\n // Normalize backend event type names (llm_text_delta → text_delta, etc.)\n const streamEvent = normalizeEvent(raw) as StreamEvent;\n\n handleEvent(\n streamEvent,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n\n // Accumulate text\n if (streamEvent.type === \"text_delta\") {\n fullText += streamEvent.data;\n }\n }\n }\n\n // Process any remaining data in buffer\n if (buffer.trim()) {\n let jsonStr = \"\";\n for (const line of buffer.trim().split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n jsonStr += line.slice(6);\n } else if (line.startsWith(\"data:\")) {\n jsonStr += line.slice(5);\n }\n }\n\n jsonStr = jsonStr.trim();\n if (jsonStr) {\n try {\n const raw = JSON.parse(jsonStr);\n const streamEvent = normalizeEvent(raw) as StreamEvent;\n handleEvent(\n streamEvent,\n fullText,\n callbacks,\n clientTools,\n onPaused,\n onAutoResume,\n pendingAutoResumes,\n );\n if (streamEvent.type === \"text_delta\") {\n fullText += streamEvent.data;\n }\n } catch {\n // Skip malformed trailing data\n }\n }\n }\n } catch (err) {\n // AbortError — re-throw\n if (err instanceof Error && err.name === \"AbortError\") {\n throw err;\n }\n\n const error = err instanceof Error ? err : new Error(String(err));\n callbacks.onError?.(error);\n throw error;\n }\n\n // Wait for any pending auto-resume handlers before signaling completion\n if (pendingAutoResumes.length > 0) {\n await Promise.allSettled(pendingAutoResumes);\n }\n\n callbacks.onComplete?.(fullText);\n}\n\n/**\n * Normalize backend event type names.\n * The backend sends `llm_text_delta` / `llm_reasoning_delta` but the SDK\n * exposes them as `text_delta` / `reasoning_delta`.\n * @internal\n */\nfunction normalizeEvent(raw: any): any {\n const typeMap: Record<string, string> = {\n llm_text_delta: \"text_delta\",\n llm_reasoning_delta: \"reasoning_delta\",\n };\n if (raw && typeof raw.type === \"string\" && typeMap[raw.type]) {\n raw.type = typeMap[raw.type];\n }\n return raw;\n}\n\n/**\n * Dispatch a parsed stream event to the appropriate callbacks.\n * @internal\n */\nfunction handleEvent(\n event: StreamEvent,\n _fullText: string,\n callbacks: StreamOptions[\"callbacks\"],\n clientTools: StreamOptions[\"clientTools\"],\n onPaused: StreamOptions[\"onPaused\"],\n onAutoResume: StreamOptions[\"onAutoResume\"],\n pendingAutoResumes: Promise<void>[],\n): void {\n // Notify raw event consumers\n callbacks.onEvent?.(event);\n\n switch (event.type) {\n case \"text_delta\": {\n callbacks.onText?.(event.data);\n break;\n }\n\n case \"reasoning_delta\": {\n callbacks.onReasoning?.(event.data.delta, event.data.index);\n break;\n }\n\n case \"agent_handoff\": {\n callbacks.onAgentHandoff?.(event.data.agentName);\n break;\n }\n\n case \"tool_call_start\": {\n const { callId, toolName, toolType, inputs: rawInputs, paused } = event.data;\n // Backend sends toolCall.arguments as a JSON string — parse it\n const inputs = tryParseJSON(rawInputs);\n\n // Notify callback\n callbacks.onToolStart?.(toolName, toolType);\n\n // Handle client tools\n if (toolType === \"client\") {\n const tool = clientTools.get(toolName);\n if (tool) {\n if (paused && tool.handler) {\n // Blocking tool with handler → auto-execute and resume\n const handlerPromise = (async () => {\n try {\n const result = await tool.handler!(inputs);\n await onAutoResume?.(callId, result);\n } catch {\n // If handler fails, still call onPaused so user can decide\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n })();\n pendingAutoResumes.push(handlerPromise);\n } else if (paused) {\n // Blocking tool without handler → pause for user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n } else if (tool.handler) {\n // Fire-and-forget tool with handler\n try {\n tool.handler(inputs);\n } catch {\n // Swallow errors on fire-and-forget\n }\n }\n } else if (paused) {\n // No registered tool but paused — notify user\n callbacks.onPaused?.(toolName, inputs);\n onPaused?.({ callId, toolName, args: inputs });\n }\n }\n break;\n }\n\n case \"tool_call_end\": {\n const { toolName, result, error } = event.data;\n callbacks.onToolEnd?.(toolName, result, error);\n break;\n }\n\n case \"run_error\": {\n const { message, code } = event.data;\n const error = new Error(message);\n if (code != null) (error as any).code = code;\n callbacks.onError?.(error);\n break;\n }\n }\n}\n","import type { MessagePart } from \"../types\";\n\n/**\n * Updates a list of message parts with a new part,\n * appending it and merging with the previous part if both are contiguous text deltas.\n * Parts are kept in arrival order (no sorting) since events stream chronologically.\n */\nexport function updateAgentMessageParts(parts: MessagePart[], newPart: MessagePart): MessagePart[] {\n const last = parts[parts.length - 1];\n\n // Merge contiguous text deltas\n const canMerge =\n last?.type === \"text\" &&\n newPart.type === \"text\" &&\n newPart.firstSequence === last.lastSequence + 1;\n\n if (canMerge) {\n return [\n ...parts.slice(0, -1),\n {\n ...last,\n text: last.text + newPart.text,\n lastSequence: newPart.lastSequence,\n },\n ];\n }\n\n return [...parts, newPart];\n}\n","import { executeStream } from \"../core/stream\";\nimport type {\n StreamCallbacks,\n StreamEvent,\n TextDeltaEvent,\n ToolCallStartEvent,\n ExecuteRequestBody,\n ClientTool,\n} from \"../core/types\";\n\nimport type { AgentToolContextValue } from \"./agent-context\";\nimport type { createDebugHandlers } from \"./debug-handlers\";\nimport type { Message, MessagePart } from \"./types\";\nimport { tryParseJSON } from \"./utils/schema\";\nimport { updateAgentMessageParts } from \"./utils/message\";\n\n// ── Types ──────────────────────────────────────────────────────────────\n\nexport type RunOptions = {\n context?: object;\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n optimisticExecutionId?: string;\n /** @deprecated Use `useClientTool` hook instead. */\n clientTools?: Array<{\n name: string;\n description: string;\n parameters: unknown;\n await?: boolean;\n }>;\n // Resume params\n resumeToolCallId?: string;\n resumeToolResult?: any;\n};\n\nexport type StreamDeps = {\n agentUrl: string;\n agentId: string;\n accessKey?: string;\n currentSessionId: string;\n messagesRef: React.MutableRefObject<Array<Message>>;\n setMessages: React.Dispatch<React.SetStateAction<Array<Message>>>;\n setInProgress: React.Dispatch<React.SetStateAction<boolean>>;\n syncSessionRef: React.MutableRefObject<((messages?: Array<Message>) => void) | undefined>;\n createSessionFromResponse: (\n sessionId: string,\n sessionName: string,\n currentMessages: Array<Message>,\n ) => void;\n setCurrentSessionId: (sessionId: string) => void;\n debugHandlers: ReturnType<typeof createDebugHandlers>;\n toolContext: AgentToolContextValue | null;\n lastRequestContextRef: React.MutableRefObject<{\n additionalHeaders?: Record<string, string>;\n additionalBody?: Record<string, unknown>;\n sessionId?: string;\n }>;\n getClientToolsMap: () => Map<string, ClientTool>;\n signal: AbortSignal;\n /** Recursive self-reference so onAutoResume can call runAgent again */\n runAgentRef: React.MutableRefObject<\n ((input: string | undefined, options?: RunOptions) => Promise<void>) | undefined\n >;\n};\n\n// ── Build callbacks ────────────────────────────────────────────────────\n\n/**\n * Build the StreamCallbacks object from dependencies.\n * Keeps event-handling logic out of the main hook.\n */\nexport function buildStreamCallbacks(\n deps: StreamDeps,\n debugKey: string | undefined,\n): StreamCallbacks {\n const { setMessages, setInProgress, syncSessionRef, messagesRef, toolContext, agentId } = deps;\n\n return {\n onComplete: () => {\n console.log(\"Agent closed\");\n setInProgress(false);\n if (syncSessionRef.current) {\n syncSessionRef.current(messagesRef.current);\n }\n },\n onError: (error: Error) => {\n console.log(\"Agent error\", error);\n setInProgress(false);\n if (syncSessionRef.current) {\n syncSessionRef.current(messagesRef.current);\n }\n },\n onEvent: (event: StreamEvent) => {\n if (event.type === \"text_delta\") {\n handleTextDelta(event, setMessages, syncSessionRef);\n } else if (event.type === \"tool_call_start\" && event.data.toolType === \"client\") {\n // Create a widget part for tools with a render function\n handleClientToolCall(event, setMessages, syncSessionRef, toolContext, agentId);\n // Send to debug so the tool shows in the debug panel\n if (debugKey) {\n const debugMeta = { ...event.meta, executionId: debugKey };\n deps.debugHandlers.handleStreamEvent({\n ...event,\n meta: debugMeta,\n } as StreamEvent);\n\n // Server never sends tool_call_end for client tools.\n // For non-paused (fire-and-forget) tools, immediately mark complete.\n if (!event.data.paused) {\n deps.debugHandlers.handleStreamEvent({\n type: \"tool_call_end\",\n data: {\n callId: event.data.callId,\n toolName: event.data.toolName,\n toolType: event.data.toolType,\n },\n meta: debugMeta,\n } as StreamEvent);\n }\n }\n } else if (debugKey) {\n // All other events (server tools, reasoning, handoffs, etc.)\n deps.debugHandlers.handleStreamEvent({\n ...event,\n meta: { ...event.meta, executionId: debugKey },\n } as StreamEvent);\n }\n },\n };\n}\n\n// ── Execute agent stream ───────────────────────────────────────────────\n\nconst TEMPORARY_SESSION_ID = \"sess_temp\";\nconst DEFAULT_SESSION_NAME = \"New Chat\";\n\n/**\n * Execute the agent stream with all wiring (session, auto-resume, etc.).\n */\nexport async function executeAgentStream(\n deps: StreamDeps,\n body: ExecuteRequestBody,\n headers: Record<string, string>,\n callbacks: StreamCallbacks,\n debugKey?: string,\n) {\n const {\n agentUrl,\n signal,\n currentSessionId,\n lastRequestContextRef,\n messagesRef,\n createSessionFromResponse,\n setMessages,\n syncSessionRef,\n runAgentRef,\n } = deps;\n\n await executeStream({\n url: agentUrl,\n body,\n headers,\n callbacks,\n clientTools: deps.getClientToolsMap(),\n signal,\n\n onSessionId: (sessionId, sessionName) => {\n // Always keep the ref up to date for resume calls\n lastRequestContextRef.current.sessionId = sessionId;\n if (!currentSessionId || currentSessionId === TEMPORARY_SESSION_ID) {\n createSessionFromResponse(\n sessionId,\n sessionName || DEFAULT_SESSION_NAME,\n messagesRef.current,\n );\n deps.setCurrentSessionId(sessionId);\n }\n },\n\n // Session creation is handled by onSessionId above.\n\n onAutoResume: async (callId, result) => {\n // Persist the handler result in the widget part\n setMessages((prev) => {\n const updatedMessages = prev.map((msg) => {\n if (msg.parts) {\n const updatedParts = msg.parts.map((part) => {\n if (part.type === \"widget\" && part.callId === callId) {\n return { ...part, status: \"submitted\" as const, result };\n }\n return part;\n });\n return { ...msg, parts: updatedParts };\n }\n return msg;\n });\n if (syncSessionRef.current) {\n syncSessionRef.current(updatedMessages);\n }\n return updatedMessages;\n });\n\n // Emit synthetic tool_call_end for the debug panel\n if (debugKey) {\n deps.debugHandlers.handleStreamEvent({\n type: \"tool_call_end\",\n data: { callId, toolName: \"\", toolType: \"client\" as const, result },\n meta: { executionId: debugKey, sequence: 0 },\n } as StreamEvent);\n }\n\n // Auto-resume: send result back to agent\n try {\n await runAgentRef.current?.(undefined, {\n resumeToolCallId: callId,\n resumeToolResult: result,\n });\n } catch (error) {\n console.error(\"Auto-resume failed\", error);\n }\n },\n });\n}\n\n// ── Event handlers (private) ───────────────────────────────────────────\n\nfunction handleTextDelta(\n event: TextDeltaEvent,\n setMessages: React.Dispatch<React.SetStateAction<Array<Message>>>,\n syncSessionRef: React.MutableRefObject<((messages?: Array<Message>) => void) | undefined>,\n) {\n const sequence = event.meta.sequence;\n const text = event.data;\n const eventExecutionId = event.meta.executionId;\n\n setMessages((prev) => {\n const lastMessage = prev[prev.length - 1];\n const newPart: MessagePart = {\n type: \"text\",\n text,\n firstSequence: sequence,\n lastSequence: sequence,\n };\n\n let updatedMessages: Message[];\n\n if (lastMessage?.role === \"agent\") {\n const updatedMessage: Message = {\n ...lastMessage,\n content: lastMessage.content + text,\n parts: updateAgentMessageParts(lastMessage.parts || [], newPart),\n };\n updatedMessages = [...prev.slice(0, -1), updatedMessage];\n } else {\n const updatedMessage: Message = {\n role: \"agent\" as const,\n content: text,\n parts: [newPart],\n executionId: eventExecutionId,\n };\n updatedMessages = [...prev, updatedMessage];\n }\n\n if (syncSessionRef.current) {\n syncSessionRef.current(updatedMessages);\n }\n\n return updatedMessages;\n });\n}\n\nfunction handleClientToolCall(\n event: ToolCallStartEvent,\n setMessages: React.Dispatch<React.SetStateAction<Array<Message>>>,\n syncSessionRef: React.MutableRefObject<((messages?: Array<Message>) => void) | undefined>,\n toolContext: AgentToolContextValue | null,\n agentId: string,\n) {\n // Only create widget for tools with a registered render function\n const tool = toolContext?.getTool(agentId, event.data.toolName);\n if (!tool?.render) return;\n\n setMessages((prev) => {\n const lastMessage = prev[prev.length - 1];\n const newPart: MessagePart = {\n type: \"widget\",\n toolName: event.data.toolName,\n callId: event.data.callId,\n inputs: tryParseJSON(event.data.inputs),\n sequence: event.meta.sequence,\n paused: event.data.paused,\n status: \"pending\",\n };\n\n let updatedMessages: Message[];\n\n if (lastMessage?.role === \"agent\") {\n const updatedMessage: Message = {\n ...lastMessage,\n parts: updateAgentMessageParts(lastMessage.parts || [], newPart),\n };\n updatedMessages = [...prev.slice(0, -1), updatedMessage];\n } else {\n const updatedMessage: Message = {\n role: \"agent\" as const,\n content: \"\",\n parts: [newPart],\n executionId: event.meta.executionId,\n };\n updatedMessages = [...prev, updatedMessage];\n }\n\n if (syncSessionRef.current) {\n syncSessionRef.current(updatedMessages);\n }\n\n return updatedMessages;\n });\n}\n","import { useState, useEffect, useCallback } from \"react\";\n\n// Helper to handle JSON parsing cleanly\nfunction parseJSON<T>(value: string | null, defaultValue: T): T {\n if (value === null) return defaultValue;\n try {\n return JSON.parse(value);\n } catch {\n return defaultValue;\n }\n}\n\nexport function useSyncedLocalStorage<T>(\n key: string,\n initialValue: T,\n): [T, (value: T | ((val: T) => T)) => void] {\n // Initialize state function to avoid reading localStorage on every render\n const [storedValue, setStoredValue] = useState<T>(() => {\n if (typeof window === \"undefined\") {\n return initialValue;\n }\n try {\n const item = window.localStorage.getItem(key);\n return parseJSON(item, initialValue);\n } catch (error) {\n console.warn(`Error reading localStorage key \"${key}\":`, error);\n return initialValue;\n }\n });\n\n // Function to update state and localStorage\n const setValue = useCallback(\n (value: T | ((val: T) => T)) => {\n try {\n setStoredValue((prev) => {\n const valueToStore = value instanceof Function ? value(prev) : value;\n\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(key, JSON.stringify(valueToStore));\n // Dispatch a custom event so other hooks in the same window update\n window.dispatchEvent(\n new StorageEvent(\"storage\", { key, newValue: JSON.stringify(valueToStore) }),\n );\n }\n return valueToStore;\n });\n } catch (error) {\n console.warn(`Error setting localStorage key \"${key}\":`, error);\n }\n },\n [key],\n );\n\n // Sync across tabs/windows and within the same window\n useEffect(() => {\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key === key) {\n setStoredValue(parseJSON(event.newValue, initialValue));\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [key, initialValue]);\n\n return [storedValue, setValue];\n}\n","import { useContext, useEffect, useState, useCallback, createElement } from \"react\";\nimport type { ZodSchema } from \"zod\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * Infer the output type from a Zod schema's structural shape (`_zod.output`).\n * Falls back to `any` for raw JSON Schema objects or untyped parameters.\n * @internal\n */\ntype InferInput<T> = T extends { _zod: { output: infer O } } ? O : any;\n\nexport interface ClientToolRenderProps<T = any> {\n /** Parsed inputs from the agent. */\n inputs: T;\n /** Submit a result back to the agent (only available when `await: true`). */\n submit: (result: any) => void;\n /** Current status of this widget instance. */\n status: \"pending\" | \"submitted\";\n /** The persisted result from a previous submission (available after submit or on reload). */\n result?: any;\n}\n\nexport interface ClientToolConfig<TParams = any> {\n /** Tool name — must match the name the agent knows. */\n name: string;\n /** Description of what the tool does. */\n description: string;\n /**\n * Tool parameters — accepts a **Zod schema** or a raw JSON Schema object.\n * When a Zod schema is provided, `handler` and `render` inputs are\n * automatically typed — no explicit generic needed.\n *\n * @example\n * parameters: z.object({ question: z.string() })\n */\n parameters: TParams;\n /** If true, agent pauses and waits for the tool result before continuing. */\n await?: boolean;\n /**\n * Handler function for headless tools (no UI).\n * If `await: true`, the return value is sent back to the agent.\n * If `await: false`, runs as fire-and-forget.\n * Inputs are automatically typed when `parameters` is a Zod schema.\n */\n handler?: (inputs: InferInput<TParams>) => any | Promise<any>;\n /**\n * Render function for widget tools (with UI).\n * Receives `{ inputs, submit, status }`.\n * - `submit(result)` resumes the agent when `await: true`.\n * - `status` is `\"pending\"` until submitted, then `\"submitted\"`.\n * Inputs are automatically typed when `parameters` is a Zod schema.\n */\n render?: (props: ClientToolRenderProps<InferInput<TParams>>) => any;\n}\n\n// ─── Context import (late-bound to avoid circular deps) ──────────────────────\n\n// We import the context lazily from agent-context\nimport { AgentToolContext } from \"./agent-context\";\n\n// ─── useClientTool hook ──────────────────────────────────────────────────────\n\n/**\n * Register a client tool for a specific agent.\n *\n * @example\n * ```tsx\n * // Headless tool\n * useClientTool(\"agent-123\", {\n * name: \"get_location\",\n * description: \"Gets user location\",\n * parameters: z.object({}),\n * handler: async () => {\n * const pos = await getPosition();\n * return { lat: pos.coords.latitude, lng: pos.coords.longitude };\n * },\n * });\n *\n * // Widget tool with submission\n * useClientTool(\"agent-123\", {\n * name: \"feedback_form\",\n * description: \"Collects feedback\",\n * parameters: z.object({ question: z.string() }),\n * await: true,\n * render: ({ inputs, submit, status }) => (\n * <form onSubmit={() => submit({ answer: \"...\" })}>\n * <p>{inputs.question}</p>\n * <button disabled={status !== \"pending\"}>Submit</button>\n * </form>\n * ),\n * });\n * ```\n */\nexport function useClientTool<TParams>(agentId: string, config: ClientToolConfig<TParams>): void {\n const context = useContext(AgentToolContext);\n\n if (!context) {\n throw new Error(\"useClientTool must be used within <AgentContextProvider>\");\n }\n\n useEffect(() => {\n context.registerTool(agentId, config);\n return () => {\n context.unregisterTool(agentId, config.name);\n };\n // Note: consumers should memoize `config` to avoid unnecessary re-registrations.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agentId, config.name, config.handler, config.render, config.parameters]);\n}\n\n// ─── ToolRenderer component ──────────────────────────────────────────────────\n\ninterface ToolRendererProps {\n /** The agent ID this tool belongs to. */\n agentId: string;\n /** The widget message part to render. */\n part: {\n toolName: string;\n callId: string;\n inputs: any;\n paused?: boolean;\n status?: \"pending\" | \"submitted\";\n result?: any;\n };\n}\n\n/**\n * Renders a registered widget tool.\n * Looks up the tool by name from the registry and renders it with\n * the appropriate props (inputs, submit, status).\n *\n * @example\n * ```tsx\n * {message.parts?.map((part) => {\n * if (part.type === \"widget\") {\n * return <ToolRenderer key={part.callId} agentId=\"agent-123\" part={part} />;\n * }\n * return <Markdown key={part.firstSequence}>{part.text}</Markdown>;\n * })}\n * ```\n */\nexport function ToolRenderer({ agentId, part }: ToolRendererProps) {\n const context = useContext(AgentToolContext);\n const [localStatus, setLocalStatus] = useState<\"pending\" | \"submitted\">(part.status || \"pending\");\n\n // Sync localStatus when part.status changes externally\n // (e.g., messages reloaded from session storage after resume)\n useEffect(() => {\n setLocalStatus(part.status || \"pending\");\n }, [part.status]);\n\n if (!context) {\n throw new Error(\"ToolRenderer must be used within <AgentContextProvider>\");\n }\n\n const tool = context.getTool(agentId, part.toolName);\n\n const handleSubmit = useCallback(\n (result: any) => {\n if (localStatus === \"submitted\") return; // Prevent double-submission\n setLocalStatus(\"submitted\");\n context.resumeTool(agentId, part.callId, result);\n },\n [agentId, part.callId, localStatus, context],\n );\n\n if (!tool?.render) {\n return null; // No registered render function for this tool\n }\n\n return tool.render({\n inputs: part.inputs,\n submit: part.paused ? handleSubmit : () => {},\n status: localStatus,\n result: part.result,\n });\n}\n"],"mappings":"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","names":["useContext","useCallback","useRef","useState","useEffect","useMemo","useCallback","useRef","useContext","useMemo","useCallback","useCallback","tryParseJSON","TEMPORARY_SESSION_ID","DEFAULT_SESSION_NAME","useContext","useRef","useMemo","useCallback","useState","useEffect","useCallback","useRef","useState","useCallback","useMemo","useContext","useEffect","useContext","useEffect","useState","useCallback","useContext","useEffect","useState","useCallback"]}
@@ -53,7 +53,15 @@ type ToolCallEndEvent = {
53
53
  };
54
54
  meta: StreamEventMeta;
55
55
  };
56
- type StreamEvent = TextDeltaEvent | ReasoningDeltaEvent | AgentHandoffEvent | ToolCallStartEvent | ToolCallEndEvent;
56
+ type RunErrorEvent = {
57
+ type: "run_error";
58
+ data: {
59
+ message: string;
60
+ code?: string;
61
+ };
62
+ meta: StreamEventMeta;
63
+ };
64
+ type StreamEvent = TextDeltaEvent | ReasoningDeltaEvent | AgentHandoffEvent | ToolCallStartEvent | ToolCallEndEvent | RunErrorEvent;
57
65
  /** Branded session ID type. */
58
66
  type SessionId = string & {
59
67
  readonly __brand: unique symbol;
@@ -140,7 +148,7 @@ interface StreamOptions {
140
148
  clientTools: Map<string, ClientTool>;
141
149
  signal?: AbortSignal;
142
150
  /** Called when session ID is received from response headers. */
143
- onSessionId?: (sessionId: SessionId) => void;
151
+ onSessionId?: (sessionId: SessionId, sessionName?: string) => void;
144
152
  /** Called when paused tool info is detected. */
145
153
  onPaused?: (info: PausedToolInfo) => void;
146
154
  /** Called to auto-resume after a client tool handler completes. */
@@ -149,4 +157,4 @@ interface StreamOptions {
149
157
  onResponse?: (response: Response) => void;
150
158
  }
151
159
 
152
- export type { AgentConfig as A, ClientTool as C, ExecuteRequestBody as E, PausedToolInfo as P, ReasoningDeltaEvent as R, SessionId as S, ToolType as T, StreamCallbacks as a, StreamOptions as b, StreamEvent as c, StreamEventMeta as d, TextDeltaEvent as e, AgentHandoffEvent as f, ToolCallStartEvent as g, ToolCallEndEvent as h };
160
+ export type { AgentConfig as A, ClientTool as C, ExecuteRequestBody as E, PausedToolInfo as P, ReasoningDeltaEvent as R, SessionId as S, ToolType as T, StreamCallbacks as a, StreamOptions as b, StreamEvent as c, StreamEventMeta as d, TextDeltaEvent as e, AgentHandoffEvent as f, ToolCallStartEvent as g, ToolCallEndEvent as h, RunErrorEvent as i };
@@ -53,7 +53,15 @@ type ToolCallEndEvent = {
53
53
  };
54
54
  meta: StreamEventMeta;
55
55
  };
56
- type StreamEvent = TextDeltaEvent | ReasoningDeltaEvent | AgentHandoffEvent | ToolCallStartEvent | ToolCallEndEvent;
56
+ type RunErrorEvent = {
57
+ type: "run_error";
58
+ data: {
59
+ message: string;
60
+ code?: string;
61
+ };
62
+ meta: StreamEventMeta;
63
+ };
64
+ type StreamEvent = TextDeltaEvent | ReasoningDeltaEvent | AgentHandoffEvent | ToolCallStartEvent | ToolCallEndEvent | RunErrorEvent;
57
65
  /** Branded session ID type. */
58
66
  type SessionId = string & {
59
67
  readonly __brand: unique symbol;
@@ -140,7 +148,7 @@ interface StreamOptions {
140
148
  clientTools: Map<string, ClientTool>;
141
149
  signal?: AbortSignal;
142
150
  /** Called when session ID is received from response headers. */
143
- onSessionId?: (sessionId: SessionId) => void;
151
+ onSessionId?: (sessionId: SessionId, sessionName?: string) => void;
144
152
  /** Called when paused tool info is detected. */
145
153
  onPaused?: (info: PausedToolInfo) => void;
146
154
  /** Called to auto-resume after a client tool handler completes. */
@@ -149,4 +157,4 @@ interface StreamOptions {
149
157
  onResponse?: (response: Response) => void;
150
158
  }
151
159
 
152
- export type { AgentConfig as A, ClientTool as C, ExecuteRequestBody as E, PausedToolInfo as P, ReasoningDeltaEvent as R, SessionId as S, ToolType as T, StreamCallbacks as a, StreamOptions as b, StreamEvent as c, StreamEventMeta as d, TextDeltaEvent as e, AgentHandoffEvent as f, ToolCallStartEvent as g, ToolCallEndEvent as h };
160
+ export type { AgentConfig as A, ClientTool as C, ExecuteRequestBody as E, PausedToolInfo as P, ReasoningDeltaEvent as R, SessionId as S, ToolType as T, StreamCallbacks as a, StreamOptions as b, StreamEvent as c, StreamEventMeta as d, TextDeltaEvent as e, AgentHandoffEvent as f, ToolCallStartEvent as g, ToolCallEndEvent as h, RunErrorEvent as i };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bs-agent",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "BuildShip Agent SDK — core + React bindings.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -33,6 +33,8 @@
33
33
  "scripts": {
34
34
  "build": "tsup",
35
35
  "dev": "tsup --watch",
36
+ "test": "vitest run --exclude 'tests/e2e/**'",
37
+ "test:e2e": "vitest run tests/e2e",
36
38
  "prepublishOnly": "npm run build"
37
39
  },
38
40
  "keywords": [
@@ -53,6 +55,7 @@
53
55
  "devDependencies": {
54
56
  "@types/react": "^18.2.14",
55
57
  "tsup": "^8.5.1",
56
- "typescript": "^5.2.2"
58
+ "typescript": "^5.2.2",
59
+ "vitest": "^4.0.18"
57
60
  }
58
61
  }