@personaai/react 0.7.6 → 0.7.8

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/index.ts","../src/context/PersonaContext.tsx","../src/hooks/useChat.ts","../src/streaming.ts","../src/hooks/useMemory.ts","../src/hooks/useThreads.ts","../src/hooks/useVoice.ts","../src/hooks/voiceWorklets.ts","../src/hooks/useFiles.ts","../src/hooks/useAgents.ts","../src/hooks/useConnection.ts","../src/hooks/useMcpConnections.ts"],"sourcesContent":["export * from \"./types.js\";\nexport * from \"./context/PersonaContext.js\";\nexport * from \"./hooks/useChat.js\";\nexport * from \"./hooks/useMemory.js\";\nexport * from \"./hooks/useThreads.js\";\nexport * from \"./hooks/useVoice.js\";\nexport * from \"./hooks/useFiles.js\";\nexport * from \"./hooks/useAgents.js\";\nexport * from \"./hooks/useConnection.js\";\nexport * from \"./hooks/useMcpConnections.js\";\nexport * from \"./streaming.js\";\nexport {\n createLogger,\n createNoopLogger,\n setLogLevel,\n getLogLevel,\n isLevelEnabled,\n} from \"@personaai/logger\";\nexport type {\n Logger,\n LogLevel,\n LogTransport,\n CreateLoggerOptions,\n} from \"@personaai/logger\";\n\nexport const VERSION = \"0.7.3\";\n","\"use client\";\r\n\r\nimport React, { createContext, useContext, useMemo } from \"react\";\r\nimport type { PersonaProviderProps } from \"../types.js\";\r\nimport { createLogger, type Logger } from \"@personaai/logger\";\r\n\r\ninterface PersonaContextValue {\r\n baseUrl: string;\r\n getAuthToken?: () =>\r\n Promise<string | null | undefined> | string | null | undefined;\r\n defaultAgentId?: string;\r\n fetchWithAuth: (path: string, init?: RequestInit) => Promise<Response>;\r\n logger: Logger;\r\n}\r\n\r\nconst PersonaContext = createContext<PersonaContextValue | null>(null);\r\n\r\nexport function PersonaProvider({\r\n baseUrl,\r\n getAuthToken,\r\n defaultAgentId,\r\n logLevel,\r\n logger: loggerProp,\r\n children,\r\n}: PersonaProviderProps) {\r\n const normalizedBaseUrl = useMemo(\r\n () => baseUrl.replace(/\\/+$/, \"\"),\r\n [baseUrl],\r\n );\r\n\r\n const logger = useMemo<Logger>(() => {\r\n const l =\r\n loggerProp ??\r\n createLogger(\r\n \"react\",\r\n logLevel !== undefined ? { level: logLevel } : undefined,\r\n );\r\n l.debug(\"PersonaProvider created\", {\r\n baseUrl: normalizedBaseUrl,\r\n hasDefaultAgentId: !!defaultAgentId,\r\n });\r\n l.info(\"PersonaProvider mounted\", { baseUrl: normalizedBaseUrl });\r\n l.trace(\"PersonaProvider config\", {\r\n baseUrl: normalizedBaseUrl,\r\n hasGetAuthToken: !!getAuthToken,\r\n });\r\n return l;\r\n }, [loggerProp, logLevel, normalizedBaseUrl, defaultAgentId, getAuthToken]);\r\n\r\n const value = useMemo<PersonaContextValue>(() => {\r\n async function fetchWithAuth(\r\n path: string,\r\n init: RequestInit = {},\r\n ): Promise<Response> {\r\n const token = getAuthToken ? await getAuthToken() : null;\r\n const headers = new Headers(init.headers || {});\r\n if (token) {\r\n headers.set(\"Authorization\", `Bearer ${token}`);\r\n logger.trace(\"fetchWithAuth with token\", { path });\r\n } else {\r\n logger.trace(\"fetchWithAuth without token\", { path });\r\n logger.debug(\"fetchWithAuth no token\", { path });\r\n }\r\n\r\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\r\n const url = `${normalizedBaseUrl}${cleanPath}`;\r\n logger.debug(\"fetchWithAuth request\", {\r\n path: cleanPath,\r\n url,\r\n hasToken: !!token,\r\n });\r\n logger.trace(\"fetchWithAuth details\", {\r\n url,\r\n path: cleanPath,\r\n hasToken: !!token,\r\n });\r\n\r\n try {\r\n const res = await fetch(url, {\r\n ...init,\r\n headers,\r\n });\r\n logger.debug(\"fetchWithAuth response\", {\r\n path: cleanPath,\r\n status: res.status,\r\n ok: res.ok,\r\n });\r\n if (!res.ok) {\r\n logger.warn(\"fetchWithAuth non-ok\", {\r\n path: cleanPath,\r\n status: res.status,\r\n });\r\n } else {\r\n logger.info(\"fetchWithAuth succeeded\", {\r\n path: cleanPath,\r\n status: res.status,\r\n });\r\n }\r\n return res;\r\n } catch (err) {\r\n logger.error(\"fetchWithAuth failed\", {\r\n path: cleanPath,\r\n error: err instanceof Error ? err.message : String(err),\r\n });\r\n throw err;\r\n }\r\n }\r\n\r\n return {\r\n baseUrl: normalizedBaseUrl,\r\n getAuthToken,\r\n defaultAgentId,\r\n fetchWithAuth,\r\n logger,\r\n };\r\n }, [normalizedBaseUrl, getAuthToken, defaultAgentId, logger]);\r\n\r\n return (\r\n <PersonaContext.Provider value={value}>{children}</PersonaContext.Provider>\r\n );\r\n}\r\n\r\nexport function usePersonaContext(): PersonaContextValue {\r\n const context = useContext(PersonaContext);\r\n if (!context) {\r\n throw new Error(\r\n \"usePersonaContext must be used within a <PersonaProvider>\",\r\n );\r\n }\r\n return context;\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport { openSSEStream } from \"../streaming.js\";\r\nimport type {\r\n PersonaInterrupt,\r\n PersonaMessage,\r\n PersonaPresentedFile,\r\n PersonaResumeValue,\r\n PersonaRole,\r\n PersonaStreamingEvent,\r\n PersonaSubagentActivityEntry,\r\n PersonaTodo,\r\n PersonaToolCall,\r\n PersonaWorkspaceFile,\r\n SendMessageOverride,\r\n UseChatOptions,\r\n} from \"../types.js\";\r\n\r\n// A failed tool call's TOOL_CALL_RESULT content is a JSON envelope\r\n// (`{status:'error',message}`, see aguiTranslator.js's buildToolErrorContent)\r\n// rather than a separate boolean field on the event itself.\r\nfunction isErrorToolContent(content: string): boolean {\r\n if (typeof content !== \"string\" || !content.trim().startsWith(\"{\"))\r\n return false;\r\n try {\r\n return JSON.parse(content)?.status === \"error\";\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n// Persisted subagent trace item shape (agent-backend's foldSubagentEvent/\r\n// subagentTrace.js) — already folded/paired server-side for compact storage,\r\n// DIFFERENT from the raw per-event `PersonaSubagentActivityEntry` shape the\r\n// live SSE stream sends (kind: 'text'|'tool_start'|'tool_result'). Reloading\r\n// a thread previously never read `data.subagentTraces` at all — a completed\r\n// subagent's activity (its own text/tool timeline) was silently dropped on\r\n// reload even though the backend already persists and returns it, keyed by\r\n// the owning `task` tool call's toolCallId (see agui.controller.js's\r\n// `subagentTraces[callId]`, matching `PersonaToolCall.toolCallId` exactly).\r\ntype PersistedSubagentTraceItem =\r\n | { type: \"text\"; text: string }\r\n | {\r\n type: \"tool\";\r\n name: string;\r\n argsText: string;\r\n resultText: string;\r\n status: \"running\" | \"completed\";\r\n };\r\n\r\n// Re-expands the folded/paired persisted shape back into the raw kind-based\r\n// entries `PersonaSubagentActivityEntry` (and everything downstream that\r\n// consumes it — buildSubagentTimeline, the live-preview row, the activity\r\n// dialog) already knows how to render, so no sdk/ui changes are needed.\r\nfunction persistedTraceToActivityEntries(\r\n items: PersistedSubagentTraceItem[],\r\n): PersonaSubagentActivityEntry[] {\r\n const entries: PersonaSubagentActivityEntry[] = [];\r\n for (const item of items) {\r\n if (item.type === \"text\") {\r\n if (item.text) entries.push({ kind: \"text\", delta: item.text });\r\n } else {\r\n entries.push({\r\n kind: \"tool_start\",\r\n toolName: item.name,\r\n args: item.argsText,\r\n });\r\n if (item.status === \"completed\") {\r\n entries.push({\r\n kind: \"tool_result\",\r\n toolName: item.name,\r\n result: item.resultText,\r\n });\r\n }\r\n }\r\n }\r\n return entries;\r\n}\r\n\r\n// present_file's result is `{status:'success', filePath, title, description}`\r\n// (see present.tool.js) — a signal to highlight that path in the workspace\r\n// files panel, not something meant to render as a generic tool-result blob.\r\nfunction parsePresentedFile(content: string): PersonaPresentedFile | null {\r\n try {\r\n const parsed = JSON.parse(content);\r\n if (parsed?.status !== \"success\" || typeof parsed.filePath !== \"string\")\r\n return null;\r\n return {\r\n path: parsed.filePath,\r\n title: typeof parsed.title === \"string\" ? parsed.title : parsed.filePath,\r\n description:\r\n typeof parsed.description === \"string\" ? parsed.description : \"\",\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n// buildFilesTodosSnapshot (aguiTranslator.js) emits snake_case\r\n// created_at/modified_at on the wire — both from the live STATE_SNAPSHOT\r\n// event and from a reloaded thread's persisted state (checkpoint.service.js\r\n// runs the same function). Normalize to the SDK's usual camelCase shape.\r\nfunction normalizeWorkspaceFiles(\r\n raw: Record<\r\n string,\r\n {\r\n content: string;\r\n size: number;\r\n created_at: string | null;\r\n modified_at: string | null;\r\n }\r\n >,\r\n): Record<string, PersonaWorkspaceFile> {\r\n const normalized: Record<string, PersonaWorkspaceFile> = {};\r\n for (const [path, file] of Object.entries(raw || {})) {\r\n normalized[path] = {\r\n content: file.content,\r\n size: file.size,\r\n createdAt: file.created_at,\r\n modifiedAt: file.modified_at,\r\n };\r\n }\r\n return normalized;\r\n}\r\n\r\n// checkpointService.getMessages() wraps a paused thread's interrupt as\r\n// `{ kind, value }` (see checkpoint.service.js) — the same envelope shape\r\n// the live hitl_request/clarification_request CUSTOM events carry, just\r\n// nested one level deeper. Flatten both into the same PersonaInterrupt shape.\r\nfunction normalizePendingInterrupt(pending: unknown): PersonaInterrupt | null {\r\n if (!pending || typeof pending !== \"object\") return null;\r\n const p = pending as { kind?: string; value?: Record<string, unknown> };\r\n if (p.kind === \"hitl\") {\r\n return {\r\n kind: \"hitl\",\r\n actionRequests: (p.value?.actionRequests ?? []) as Extract<\r\n PersonaInterrupt,\r\n { kind: \"hitl\" }\r\n >[\"actionRequests\"],\r\n reviewConfigs: (p.value?.reviewConfigs ?? []) as unknown[],\r\n };\r\n }\r\n if (p.kind === \"clarification\") {\r\n return {\r\n kind: \"clarification\",\r\n questions: (p.value?.questions ?? []) as Extract<\r\n PersonaInterrupt,\r\n { kind: \"clarification\" }\r\n >[\"questions\"],\r\n };\r\n }\r\n return null;\r\n}\r\n\r\nexport function useChat(options: UseChatOptions = {}) {\r\n const { defaultAgentId, fetchWithAuth, baseUrl, getAuthToken, logger } =\r\n usePersonaContext();\r\n const chatLogger = useMemo(() => logger.child(\"chat\"), [logger]);\r\n const agentId = options.agentId || defaultAgentId;\r\n const threadId = options.threadId;\r\n\r\n // Log hook initialization at most once per mount (debug/info visible, trace for details)\r\n // This runs during render, so guard with a ref to avoid spam on every re-render\r\n const didLogInitRef = useRef(false);\r\n if (!didLogInitRef.current) {\r\n didLogInitRef.current = true;\r\n chatLogger.debug(\"useChat init\", {\r\n agentId,\r\n threadId,\r\n hasInitialMessages: !!options.initialMessages?.length,\r\n });\r\n chatLogger.trace(\"useChat options\", {\r\n agentId,\r\n threadId,\r\n initialMessageCount: options.initialMessages?.length ?? 0,\r\n });\r\n }\r\n\r\n const [messages, setMessages] = useState<PersonaMessage[]>(\r\n options.initialMessages || [],\r\n );\r\n const [input, setInput] = useState(\"\");\r\n const [isStreaming, setIsStreaming] = useState(false);\r\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [interrupt, setInterrupt] = useState<PersonaInterrupt | null>(null);\r\n const [files, setFiles] = useState<Record<string, PersonaWorkspaceFile>>({});\r\n const [todos, setTodos] = useState<PersonaTodo[]>([]);\r\n const [presentedFile, setPresentedFile] =\r\n useState<PersonaPresentedFile | null>(null);\r\n\r\n const abortControllerRef = useRef<AbortController | null>(null);\r\n const loadedThreadIdRef = useRef<string | undefined>(undefined);\r\n\r\n // Voice sync bookkeeping — see the effect below. Kept as refs (not state)\r\n // because they're pure injection-cursor plumbing, never rendered.\r\n const voiceThreadRef = useRef<string | undefined>(threadId);\r\n const voicePrevLenRef = useRef(0);\r\n const voiceStreamingIdRef = useRef<string | null>(null);\r\n\r\n const stop = useCallback(() => {\r\n if (abortControllerRef.current) {\r\n chatLogger.info(\"stop streaming\", {});\r\n chatLogger.debug(\"abort controller\", {\r\n hasController: !!abortControllerRef.current,\r\n });\r\n abortControllerRef.current.abort();\r\n abortControllerRef.current = null;\r\n setIsStreaming(false);\r\n chatLogger.debug(\"streaming stopped\");\r\n } else {\r\n chatLogger.trace(\"stop called — no active stream\");\r\n }\r\n }, [chatLogger]);\r\n\r\n const clear = useCallback(() => {\r\n chatLogger.info(\"clear chat\", { messageCount: messages.length });\r\n chatLogger.debug(\"clear\", { messageCount: messages.length });\r\n stop();\r\n setMessages([]);\r\n setError(null);\r\n setInterrupt(null);\r\n setFiles({});\r\n setTodos([]);\r\n setPresentedFile(null);\r\n }, [stop, chatLogger, messages.length]);\r\n\r\n const loadThreadMessages = useCallback(\r\n async (id: string) => {\r\n chatLogger.debug(\"loadThreadMessages start\", { threadId: id });\r\n chatLogger.trace(\"loadThreadMessages\", { threadId: id });\r\n setIsLoadingHistory(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(`/threads/${id}/messages`);\r\n if (!res.ok)\r\n throw new Error(`Failed to load thread history: ${res.statusText}`);\r\n const body = await res.json();\r\n const data = body?.data ?? body;\r\n const raw = (data?.messages ?? []) as Array<{\r\n id?: string;\r\n role: PersonaMessage[\"role\"];\r\n content: string;\r\n toolCalls?: PersonaToolCall[];\r\n }>;\r\n const subagentTraces = (data?.subagentTraces ?? {}) as Record<\r\n string,\r\n PersistedSubagentTraceItem[]\r\n >;\r\n const loaded: PersonaMessage[] = raw.map((m, i) => ({\r\n id: m.id || `history-${id}-${i}`,\r\n role: m.role,\r\n content: m.content,\r\n createdAt: new Date(),\r\n toolCalls: m.toolCalls?.map((tc) => {\r\n const trace = subagentTraces[tc.toolCallId];\r\n return Array.isArray(trace) && trace.length > 0\r\n ? {\r\n ...tc,\r\n subagentActivity: persistedTraceToActivityEntries(trace),\r\n }\r\n : tc;\r\n }),\r\n }));\r\n setMessages(loaded);\r\n // Re-show the approval/clarification card on reload if this thread\r\n // is currently paused — otherwise it wouldn't reappear until the\r\n // next live stream re-surfaces it.\r\n setInterrupt(normalizePendingInterrupt(data?.pendingInterrupt));\r\n // Restore the workspace files/todos this thread already had (same\r\n // cleaned shape checkpoint.service.js now derives via\r\n // buildFilesTodosSnapshot, matching the live STATE_SNAPSHOT event).\r\n setFiles(normalizeWorkspaceFiles(data?.state?.files ?? {}));\r\n setTodos((data?.state?.todos ?? []) as PersonaTodo[]);\r\n chatLogger.info(\"loadThreadMessages succeeded\", {\r\n threadId: id,\r\n messageCount: loaded.length,\r\n });\r\n chatLogger.debug(\"loadThreadMessages completed\", {\r\n threadId: id,\r\n messageCount: loaded.length,\r\n });\r\n return loaded;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n chatLogger.warn(\"loadThreadMessages failed\", {\r\n threadId: id,\r\n error: errorObj.message,\r\n });\r\n chatLogger.error(\"loadThreadMessages error\", {\r\n threadId: id,\r\n error: errorObj.message,\r\n });\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoadingHistory(false);\r\n chatLogger.trace(\"loadThreadMessages end\", { threadId: id });\r\n }\r\n },\r\n [fetchWithAuth, chatLogger],\r\n );\r\n\r\n // Auto-load history the first time a thread with no in-memory messages is\r\n // selected (switching threads in the sidebar). Skipped for a thread whose\r\n // messages already live in state — e.g. one just created by handleSend,\r\n // which sets its placeholder messages in the same render batch as the\r\n // threadId change, so `messages` there is never empty at effect time.\r\n useEffect(() => {\r\n if (!threadId || isStreaming) {\r\n chatLogger.trace(\"auto-load skipped\", { threadId, isStreaming });\r\n return;\r\n }\r\n if (loadedThreadIdRef.current === threadId) {\r\n chatLogger.trace(\"auto-load already loaded\", { threadId });\r\n return;\r\n }\r\n if (messages.length > 0) {\r\n chatLogger.trace(\"auto-load has messages\", {\r\n threadId,\r\n count: messages.length,\r\n });\r\n return;\r\n }\r\n loadedThreadIdRef.current = threadId;\r\n chatLogger.info(\"auto-load thread history\", { threadId });\r\n chatLogger.debug(\"loadThreadMessages trigger\", { threadId });\r\n void loadThreadMessages(threadId);\r\n }, [threadId, isStreaming, messages.length, loadThreadMessages, chatLogger]);\r\n\r\n // Merge a `useVoice()` session's live transcript into `messages` — see\r\n // `UseChatOptions.voice`. This replaces the hand-rolled sync effects the\r\n // README used to tell every consumer to write themselves (dedup against\r\n // thread history, merge same-speaker fragments into one bubble, update the\r\n // in-progress agent line in place, and not replay a call's old transcript\r\n // after a threadId switch under the same `useVoice()` instance).\r\n const voice = options.voice;\r\n useEffect(() => {\r\n if (!voice) return;\r\n\r\n // The passed useVoice() instance now targets a different thread (e.g. the\r\n // host app switched conversations without remounting either hook) — its\r\n // transcript belongs to a call that's over as far as this feed is\r\n // concerned. Stop injecting and don't let anything already spoken bleed\r\n // into the new thread's feed once a new call starts.\r\n if (voiceThreadRef.current !== threadId) {\r\n voiceThreadRef.current = threadId;\r\n voicePrevLenRef.current = voice.transcript.length;\r\n voiceStreamingIdRef.current = null;\r\n return;\r\n }\r\n\r\n const isVoiceActive =\r\n voice.state !== \"idle\" && voice.state !== \"ended\" && voice.state !== \"error\";\r\n const curLen = voice.transcript.length;\r\n\r\n // start() resets transcript to [] for a fresh call — realign the cursor.\r\n if (curLen < voicePrevLenRef.current) {\r\n voicePrevLenRef.current = 0;\r\n voiceStreamingIdRef.current = null;\r\n }\r\n\r\n if (!isVoiceActive) {\r\n // Not on a call: keep the cursor aligned to whatever's in transcript\r\n // (thread-reload growth must not be replayed as a live inject later),\r\n // and settle any streaming voice bubble left open from the last call.\r\n voicePrevLenRef.current = voice.transcript.length;\r\n if (voiceStreamingIdRef.current) {\r\n const doneId = voiceStreamingIdRef.current;\r\n voiceStreamingIdRef.current = null;\r\n setMessages((prev) =>\r\n prev.map((m) => (m.id === doneId ? { ...m, isStreaming: false } : m)),\r\n );\r\n }\r\n return;\r\n }\r\n\r\n if (curLen > voicePrevLenRef.current) {\r\n const newLines = voice.transcript.slice(voicePrevLenRef.current);\r\n voicePrevLenRef.current = curLen;\r\n for (const line of newLines) {\r\n const text = (line.text || \"\").trim();\r\n if (!text) continue;\r\n const role: PersonaRole = line.speaker === \"user\" ? \"user\" : \"assistant\";\r\n const voiceId = `voice-${line.id}`;\r\n setMessages((prev) => {\r\n // Already injected this exact line.\r\n if (prev.some((m) => m.id === voiceId)) return prev;\r\n // Already on the thread as a persisted turn (voice shares the\r\n // thread, so a refresh/reload can already hold it).\r\n if (\r\n prev.some(\r\n (m) =>\r\n !m.id.startsWith(\"voice-\") &&\r\n m.role === role &&\r\n m.content.trim() === text,\r\n )\r\n )\r\n return prev;\r\n const last = prev[prev.length - 1];\r\n // Consecutive agent finals of one spoken answer merge into the\r\n // bubble they opened, same as useVoice() does for `transcript`\r\n // itself — mirrors how the thread coalesces them on reload.\r\n if (last?.id.startsWith(\"voice-\") && last.role === \"assistant\" && role === \"assistant\") {\r\n const merged = text.startsWith(last.content)\r\n ? text\r\n : `${last.content} ${text}`.trim();\r\n return [...prev.slice(0, -1), { ...last, content: merged, isStreaming: false }];\r\n }\r\n return [...prev, { id: voiceId, role, content: text, createdAt: new Date() }];\r\n });\r\n }\r\n }\r\n\r\n // Live partial (agent mid-utterance) — update the open streaming bubble\r\n // in place, matching the assistant-message streaming UX text chat gets.\r\n const partialText = voice.partial?.speaker === \"agent\" ? voice.partial.text.trim() : \"\";\r\n if (partialText) {\r\n setMessages((prev) => {\r\n const last = prev[prev.length - 1];\r\n if (last?.id.startsWith(\"voice-\") && last.role === \"assistant\") {\r\n voiceStreamingIdRef.current = last.id;\r\n return [...prev.slice(0, -1), { ...last, content: partialText, isStreaming: true }];\r\n }\r\n const id = voiceStreamingIdRef.current || `voice-partial-${Date.now()}`;\r\n voiceStreamingIdRef.current = id;\r\n return [...prev, { id, role: \"assistant\", content: partialText, isStreaming: true, createdAt: new Date() }];\r\n });\r\n } else if (voice.state !== \"speaking\" && voiceStreamingIdRef.current) {\r\n const doneId = voiceStreamingIdRef.current;\r\n voiceStreamingIdRef.current = null;\r\n setMessages((prev) =>\r\n prev.map((m) => (m.id === doneId ? { ...m, isStreaming: false } : m)),\r\n );\r\n }\r\n // `voice` itself isn't a dep — useVoice() returns a fresh object every\r\n // render, so keying off it would re-run this every render regardless of\r\n // whether the transcript actually changed.\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [voice?.transcript, voice?.partial, voice?.state, threadId]);\r\n\r\n const sendMessage = useCallback(\r\n async (contentToSend?: string, overrideOptions?: SendMessageOverride) => {\r\n const prompt = (contentToSend ?? input).trim();\r\n if (!prompt || isStreaming) {\r\n chatLogger.trace(\"sendMessage skipped\", {\r\n hasPrompt: !!prompt,\r\n isStreaming,\r\n });\r\n return;\r\n }\r\n\r\n const targetAgentId = overrideOptions?.agentId || agentId;\r\n if (!targetAgentId) {\r\n const err = new Error(\"No Agent ID specified for useChat.\");\r\n chatLogger.warn(\"sendMessage no agentId\", {});\r\n chatLogger.error(\"sendMessage failed — no agent\", {\r\n error: err.message,\r\n });\r\n setError(err);\r\n options.onError?.(err);\r\n return;\r\n }\r\n\r\n chatLogger.debug(\"sendMessage start\", {\r\n promptPreview: prompt.slice(0, 100),\r\n agentId: targetAgentId,\r\n threadId: threadId ?? (overrideOptions?.threadId as string | undefined),\r\n hasResume: !!overrideOptions?.resume,\r\n hasContextOverride: !!overrideOptions?.contextOverride,\r\n messageCount: messages.length,\r\n });\r\n chatLogger.trace(\"sendMessage details\", {\r\n agentId: targetAgentId,\r\n promptPreview: prompt.slice(0, 200),\r\n hasResume: !!overrideOptions?.resume,\r\n hasContextOverride: !!overrideOptions?.contextOverride,\r\n });\r\n\r\n const userMessage: PersonaMessage = {\r\n id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\r\n role: \"user\",\r\n content: prompt,\r\n createdAt: new Date(),\r\n };\r\n\r\n const assistantMessageId = `assistant-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\r\n const placeholderAssistant: PersonaMessage = {\r\n id: assistantMessageId,\r\n role: \"assistant\",\r\n content: \"\",\r\n createdAt: new Date(),\r\n isStreaming: true,\r\n toolCalls: [],\r\n };\r\n\r\n const nextMessages = [...messages, userMessage];\r\n setMessages([...nextMessages, placeholderAssistant]);\r\n setInput(\"\");\r\n setIsStreaming(true);\r\n setError(null);\r\n setInterrupt(null);\r\n\r\n const controller = new AbortController();\r\n abortControllerRef.current = controller;\r\n\r\n // Marks any reasoning message still flagged streaming as done — for\r\n // runs that end (abort/error) without a final REASONING_END. Declared\r\n // outside the try so the finally block can reach it.\r\n const finalizeReasoning = () => {\r\n setMessages((prev) =>\r\n prev.map((m) =>\r\n m.role === \"reasoning\" && m.isStreaming\r\n ? { ...m, isStreaming: false }\r\n : m,\r\n ),\r\n );\r\n };\r\n\r\n try {\r\n // Reasoning messages are ephemeral client-side thoughts — never part\r\n // of the transcript sent back to the server (the backend already has\r\n // its own persisted copy and would treat them as user turns).\r\n const payloadMessages = nextMessages\r\n .filter((m) => m.role !== \"reasoning\")\r\n .map((m) => ({\r\n role:\r\n m.role === \"assistant\"\r\n ? (\"assistant\" as const)\r\n : (\"user\" as const),\r\n content: m.content,\r\n }));\r\n\r\n // Resolved here, not earlier — everything above this line (the\r\n // optimistic message + placeholder, clearing input, etc.) already\r\n // ran synchronously, so a caller passing an in-flight thread-creation\r\n // promise gets an instant UI update without the message send itself\r\n // waiting on it any longer than the network call already would.\r\n const resolvedThreadId = await (overrideOptions?.threadId ??\r\n options.threadId);\r\n chatLogger.trace(\"resolved threadId\", { threadId: resolvedThreadId });\r\n\r\n // openSSEStream, not fetchWithAuth: the transport has to be chosen\r\n // before the request goes out. React Native's fetch never populates\r\n // response.body and only settles once the whole response has arrived,\r\n // so discovering the missing body afterwards would already have cost\r\n // us the stream. See src/streaming.ts.\r\n const token = getAuthToken ? await getAuthToken() : null;\r\n chatLogger.debug(\"opening SSE stream\", {\r\n agentId: targetAgentId,\r\n hasToken: !!token,\r\n hasThreadId: !!resolvedThreadId,\r\n });\r\n const stream = await openSSEStream({\r\n url: `${baseUrl}/chat`,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\r\n },\r\n body: JSON.stringify({\r\n agentId: targetAgentId,\r\n messages: payloadMessages,\r\n threadId: resolvedThreadId,\r\n resume: overrideOptions?.resume,\r\n contextOverride: overrideOptions?.contextOverride,\r\n }),\r\n signal: controller.signal,\r\n });\r\n\r\n if (!stream.ok) {\r\n chatLogger.warn(\"SSE stream not ok\", {\r\n status: stream.status,\r\n errorText: stream.errorText,\r\n });\r\n chatLogger.error(\"chat stream failed\", {\r\n agentId: targetAgentId,\r\n status: stream.status,\r\n error: stream.errorText,\r\n });\r\n throw new Error(\r\n `Chat error (${stream.status}): ${stream.errorText ?? \"Stream failed\"}`,\r\n );\r\n }\r\n chatLogger.debug(\"SSE stream opened\", {\r\n agentId: targetAgentId,\r\n status: stream.status,\r\n });\r\n chatLogger.info(\"chat stream started\", {\r\n agentId: targetAgentId,\r\n threadId: resolvedThreadId,\r\n });\r\n\r\n const reader = stream.reader;\r\n let buffer = \"\";\r\n let accumulatedText = \"\";\r\n const toolCallsMap = new Map<string, PersonaToolCall>();\r\n // Reasoning streams as its own `role: 'reasoning'` message per phase\r\n // (REASONING_MESSAGE_START … CONTENT … REASONING_END), never merged\r\n // into the assistant message or into a single accumulated blob —\r\n // mirrors the web timeline where each phase is a separate \"Thoughts\"\r\n // bubble. Each phase's message is inserted directly above the assistant\r\n // message so thoughts render above the answer, not underneath it.\r\n //\r\n // A monotonic counter shared by reasoning phases AND tool calls stamps\r\n // each with a `seq` in stream order (the backend emits REASONING_END\r\n // right before the next TOOL_CALL_CHUNK, then the next phase after the\r\n // result). Clients sort by it to interleave thoughts and tool calls\r\n // chronologically instead of stacking all thoughts above the answer.\r\n let streamSeq = 0;\r\n let activeReasoningId: string | null = null;\r\n const reasoningById = new Map<string, { content: string }>();\r\n\r\n const patchAssistant = (patch: Partial<PersonaMessage>) => {\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId\r\n ? {\r\n ...msg,\r\n toolCalls: Array.from(toolCallsMap.values()),\r\n ...patch,\r\n }\r\n : msg,\r\n ),\r\n );\r\n };\r\n\r\n const insertReasoningMessage = (id: string, seq: number) => {\r\n const msg: PersonaMessage = {\r\n id,\r\n role: \"reasoning\",\r\n content: \"\",\r\n createdAt: new Date(),\r\n isStreaming: true,\r\n seq,\r\n };\r\n setMessages((prev) => {\r\n const idx = prev.findIndex((m) => m.id === assistantMessageId);\r\n if (idx === -1) return [...prev, msg];\r\n const next = [...prev];\r\n next.splice(idx, 0, msg);\r\n return next;\r\n });\r\n };\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n\r\n buffer += value ?? \"\";\r\n const lines = buffer.split(\"\\n\");\r\n buffer = lines.pop() ?? \"\";\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || !trimmed.startsWith(\"data:\")) continue;\r\n\r\n const raw = trimmed.replace(/^data:\\s*/, \"\");\r\n if (raw === \"[DONE]\") break;\r\n\r\n try {\r\n const event = JSON.parse(raw) as PersonaStreamingEvent;\r\n chatLogger.trace(\"stream event\", { type: event.type, event });\r\n options.onEvent?.(event);\r\n\r\n if (event.type === \"TEXT_MESSAGE_CHUNK\" && event.delta) {\r\n chatLogger.debug(\"text chunk\", {\r\n deltaLength: event.delta.length,\r\n });\r\n accumulatedText += event.delta;\r\n patchAssistant({ content: accumulatedText, isStreaming: true });\r\n } else if (event.type === \"TOOL_CALL_CHUNK\" && event.toolCallId) {\r\n chatLogger.debug(\"tool call chunk\", {\r\n toolCallId: event.toolCallId,\r\n toolCallName: event.toolCallName,\r\n });\r\n // The backend streams tool calls as accumulating chunks\r\n // (id/name arrive on the first chunk, args stream in pieces\r\n // across subsequent ones) rather than separate start/args\r\n // events.\r\n const existing = toolCallsMap.get(event.toolCallId);\r\n if (existing) {\r\n existing.args = (existing.args || \"\") + (event.delta || \"\");\r\n } else {\r\n toolCallsMap.set(event.toolCallId, {\r\n toolCallId: event.toolCallId,\r\n toolName: event.toolCallName || \"\",\r\n args: event.delta || \"\",\r\n seq: streamSeq++,\r\n });\r\n }\r\n patchAssistant({});\r\n } else if (event.type === \"TOOL_CALL_RESULT\") {\r\n chatLogger.debug(\"tool call result\", {\r\n toolCallId: event.toolCallId,\r\n });\r\n const existing = toolCallsMap.get(event.toolCallId);\r\n if (existing) {\r\n existing.result = event.content;\r\n existing.isError = isErrorToolContent(event.content);\r\n if (existing.isError)\r\n chatLogger.warn(\"tool call error\", {\r\n toolCallId: event.toolCallId,\r\n });\r\n if (\r\n existing.toolName === \"present_file\" &&\r\n !existing.isError\r\n ) {\r\n const presented = parsePresentedFile(event.content);\r\n if (presented) {\r\n chatLogger.info(\"present_file\", { path: presented.path });\r\n setPresentedFile(presented);\r\n }\r\n }\r\n patchAssistant({});\r\n }\r\n } else if (event.type === \"STATE_SNAPSHOT\") {\r\n chatLogger.debug(\"state snapshot\", {\r\n fileCount: Object.keys(event.snapshot.files ?? {}).length,\r\n todoCount: event.snapshot.todos?.length ?? 0,\r\n });\r\n setFiles(normalizeWorkspaceFiles(event.snapshot.files));\r\n setTodos(event.snapshot.todos);\r\n } else if (\r\n event.type === \"REASONING_MESSAGE_START\" &&\r\n event.messageId\r\n ) {\r\n chatLogger.debug(\"reasoning start\", {\r\n messageId: event.messageId,\r\n });\r\n // A fresh reasoning phase — its own message, regardless of how\r\n // many phases this run produces. seq stamps it into stream\r\n // order against the tool calls it brackets.\r\n activeReasoningId = event.messageId;\r\n reasoningById.set(event.messageId, { content: \"\" });\r\n insertReasoningMessage(event.messageId, streamSeq++);\r\n } else if (event.type === \"REASONING_MESSAGE_CONTENT\") {\r\n // Defensive: if the backend ever skips REASONING_MESSAGE_START,\r\n // lazily open the message on the first content chunk.\r\n let rid: string = event.messageId || activeReasoningId || \"\";\r\n if (!rid || !reasoningById.has(rid)) {\r\n rid =\r\n rid ||\r\n `reasoning-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\r\n activeReasoningId = rid;\r\n reasoningById.set(rid, { content: \"\" });\r\n insertReasoningMessage(rid, streamSeq++);\r\n chatLogger.debug(\"reasoning lazy start\", { messageId: rid });\r\n }\r\n const entry = reasoningById.get(rid)!;\r\n entry.content += event.delta;\r\n chatLogger.trace(\"reasoning content\", {\r\n messageId: rid,\r\n deltaLength: event.delta?.length ?? 0,\r\n });\r\n setMessages((prev) =>\r\n prev.map((m) =>\r\n m.id === rid\r\n ? { ...m, content: entry.content, isStreaming: true }\r\n : m,\r\n ),\r\n );\r\n } else if (event.type === \"REASONING_END\") {\r\n chatLogger.debug(\"reasoning end\", {\r\n messageId: activeReasoningId,\r\n });\r\n const rid = activeReasoningId;\r\n activeReasoningId = null;\r\n if (rid) {\r\n setMessages((prev) =>\r\n prev.map((m) =>\r\n m.id === rid ? { ...m, isStreaming: false } : m,\r\n ),\r\n );\r\n }\r\n } else if (event.type === \"CUSTOM\") {\r\n chatLogger.debug(\"custom event\", { name: event.name });\r\n if (event.name === \"hitl_request\") {\r\n const value = event.value as Extract<\r\n PersonaInterrupt,\r\n { kind: \"hitl\" }\r\n >;\r\n chatLogger.info(\"hitl interrupt\", {\r\n actionCount: value.actionRequests?.length ?? 0,\r\n });\r\n setInterrupt({\r\n kind: \"hitl\",\r\n actionRequests: value.actionRequests,\r\n reviewConfigs: value.reviewConfigs,\r\n });\r\n } else if (event.name === \"clarification_request\") {\r\n const value = event.value as Extract<\r\n PersonaInterrupt,\r\n { kind: \"clarification\" }\r\n >;\r\n chatLogger.info(\"clarification interrupt\", {\r\n questionCount: value.questions?.length ?? 0,\r\n });\r\n setInterrupt({\r\n kind: \"clarification\",\r\n questions: value.questions,\r\n });\r\n } else if (event.name === \"subagent_activity\") {\r\n const { toolCallId, ...entry } = event.value as {\r\n toolCallId: string;\r\n } & PersonaSubagentActivityEntry;\r\n chatLogger.trace(\"subagent activity\", {\r\n toolCallId,\r\n kind: entry.kind,\r\n });\r\n const existing = toolCallsMap.get(toolCallId);\r\n if (existing) {\r\n existing.subagentActivity = [\r\n ...(existing.subagentActivity || []),\r\n entry,\r\n ];\r\n patchAssistant({});\r\n }\r\n }\r\n // 'mcp_app' custom events carry no chat-transcript UI here —\r\n // consumers that render MCP widgets read them via onEvent.\r\n } else if (event.type === \"RUN_ERROR\") {\r\n chatLogger.warn(\"run error\", {\r\n message: event.message,\r\n code: event.code,\r\n });\r\n chatLogger.error(\"stream run error\", {\r\n code: event.code,\r\n message: event.message,\r\n });\r\n throw new Error(event.message || \"Stream error from agent\");\r\n } else {\r\n chatLogger.trace(\"unhandled event\", { type: event.type });\r\n }\r\n } catch (e) {\r\n if (e instanceof Error && e.message.startsWith(\"Stream error\")) {\r\n throw e;\r\n }\r\n chatLogger.warn(\"event parse error\", {\r\n raw: raw.slice(0, 200),\r\n error: e instanceof Error ? e.message : String(e),\r\n });\r\n }\r\n }\r\n }\r\n\r\n const finalMessage: PersonaMessage = {\r\n id: assistantMessageId,\r\n role: \"assistant\",\r\n content: accumulatedText,\r\n createdAt: new Date(),\r\n isStreaming: false,\r\n toolCalls: Array.from(toolCallsMap.values()),\r\n };\r\n\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId ? finalMessage : msg,\r\n ),\r\n );\r\n\r\n chatLogger.info(\"sendMessage succeeded\", {\r\n agentId: targetAgentId,\r\n textLength: accumulatedText.length,\r\n toolCallCount: toolCallsMap.size,\r\n });\r\n chatLogger.debug(\"sendMessage completed\", {\r\n agentId: targetAgentId,\r\n textLength: accumulatedText.length,\r\n eventCount: toolCallsMap.size + 1,\r\n });\r\n options.onFinish?.(finalMessage);\r\n } catch (err) {\r\n if (controller.signal.aborted) {\r\n chatLogger.info(\"sendMessage aborted\", { agentId: targetAgentId });\r\n chatLogger.debug(\"stream aborted\", { agentId: targetAgentId });\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId\r\n ? { ...msg, isStreaming: false }\r\n : msg,\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n chatLogger.warn(\"sendMessage failed\", {\r\n agentId: targetAgentId,\r\n error: errorObj.message,\r\n });\r\n chatLogger.error(\"sendMessage error\", {\r\n agentId: targetAgentId,\r\n error: errorObj.message,\r\n });\r\n setError(errorObj);\r\n options.onError?.(errorObj);\r\n\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId\r\n ? {\r\n ...msg,\r\n content:\r\n msg.content ||\r\n `⚠️ Error: ${errorObj.message || \"Failed to get response.\"}`,\r\n isStreaming: false,\r\n }\r\n : msg,\r\n ),\r\n );\r\n } finally {\r\n setIsStreaming(false);\r\n abortControllerRef.current = null;\r\n // A run that ends without a final REASONING_END (abort, error) must\r\n // still flip its in-flight reasoning messages to done.\r\n finalizeReasoning();\r\n chatLogger.debug(\"sendMessage finally\", {\r\n agentId: targetAgentId,\r\n isStreaming: false,\r\n });\r\n chatLogger.trace(\"sendMessage end\", { agentId: targetAgentId });\r\n }\r\n },\r\n [\r\n agentId,\r\n baseUrl,\r\n getAuthToken,\r\n input,\r\n isStreaming,\r\n messages,\r\n options,\r\n chatLogger,\r\n threadId,\r\n ],\r\n );\r\n\r\n const handleInputChange = useCallback(\r\n (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\r\n chatLogger.trace(\"handleInputChange\", { length: e.target.value.length });\r\n setInput(e.target.value);\r\n },\r\n [chatLogger],\r\n );\r\n\r\n const handleSubmit = useCallback(\r\n (e?: React.FormEvent) => {\r\n if (e) e.preventDefault();\r\n chatLogger.debug(\"handleSubmit\", {});\r\n void sendMessage();\r\n },\r\n [sendMessage, chatLogger],\r\n );\r\n\r\n const reload = useCallback(() => {\r\n if (messages.length === 0 || isStreaming) {\r\n chatLogger.trace(\"reload skipped\", {\r\n messageCount: messages.length,\r\n isStreaming,\r\n });\r\n return;\r\n }\r\n let lastUserIndex = -1;\r\n for (let i = messages.length - 1; i >= 0; i--) {\r\n if (messages[i].role === \"user\") {\r\n lastUserIndex = i;\r\n break;\r\n }\r\n }\r\n if (lastUserIndex === -1) {\r\n chatLogger.warn(\"reload no user message\", {});\r\n return;\r\n }\r\n\r\n const lastUserMessage = messages[lastUserIndex];\r\n chatLogger.info(\"reload\", { messageId: lastUserMessage.id });\r\n chatLogger.debug(\"reload last user\", {\r\n preview: lastUserMessage.content.slice(0, 100),\r\n });\r\n setMessages(messages.slice(0, lastUserIndex));\r\n void sendMessage(lastUserMessage.content);\r\n }, [isStreaming, messages, sendMessage, chatLogger]);\r\n\r\n // Unpauses a paused HITL/clarification run. `displayContent` becomes the\r\n // visible user-turn bubble (e.g. \"Approved\", or the typed clarification\r\n // answer) — the server resolves the actual resume value from `resume`\r\n // itself, `displayContent` is only ever used for its own transcript text.\r\n const resumeInterrupt = useCallback(\r\n (resume: PersonaResumeValue, displayContent: string) => {\r\n chatLogger.info(\"resumeInterrupt\", {\r\n kind: (resume as { decisions?: unknown[] }).decisions\r\n ? \"hitl\"\r\n : \"clarification\",\r\n preview: displayContent.slice(0, 50),\r\n });\r\n return sendMessage(displayContent, { resume });\r\n },\r\n [sendMessage, chatLogger],\r\n );\r\n\r\n const dismissPresentedFile = useCallback(() => {\r\n chatLogger.debug(\"dismissPresentedFile\", {});\r\n setPresentedFile(null);\r\n }, [chatLogger]);\r\n\r\n // Manually re-open a workspace file — e.g. a present_file tool card's\r\n // \"Open\" button, after the auto-opened drawer was closed or a different\r\n // file was selected since.\r\n const openWorkspaceFile = useCallback(\r\n (path: string) => {\r\n chatLogger.debug(\"openWorkspaceFile\", { path });\r\n setPresentedFile({\r\n path,\r\n title: path.split(\"/\").pop() || path,\r\n description: \"\",\r\n });\r\n },\r\n [chatLogger],\r\n );\r\n\r\n return {\r\n messages,\r\n input,\r\n setInput,\r\n handleInputChange,\r\n handleSubmit,\r\n sendMessage,\r\n isStreaming,\r\n isLoading: isStreaming,\r\n isLoadingHistory,\r\n error,\r\n interrupt,\r\n resumeInterrupt,\r\n files,\r\n todos,\r\n presentedFile,\r\n dismissPresentedFile,\r\n openWorkspaceFile,\r\n stop,\r\n reload,\r\n clear,\r\n setMessages,\r\n loadThreadMessages,\r\n };\r\n}\r\n","/**\r\n * SSE transport for chat streams, with a React Native fallback.\r\n *\r\n * On the web, `fetch` gives a streaming `response.body` and we read it with a\r\n * ReadableStream reader. React Native's `fetch` is the whatwg-fetch polyfill\r\n * over XMLHttpRequest: `response.body` is `undefined`, and the promise only\r\n * settles once the entire response has arrived. That means the check cannot be\r\n * \"call fetch, then see whether body exists\" - by that point the whole stream\r\n * has already been buffered and the chance to stream is gone. The transport has\r\n * to be chosen *before* the request is made.\r\n *\r\n * XMLHttpRequest itself does stream everywhere React Native runs: it appends to\r\n * `responseText` and fires `readyState === 3` (LOADING) on every chunk, which is\r\n * all an SSE consumer needs. So the RN path issues the request over raw XHR and\r\n * hands back the same reader interface the fetch path does, leaving callers\r\n * unaware of which one they got.\r\n */\r\n\r\n/** Minimal reader interface, mirroring the shape of a ReadableStream reader. */\r\nexport interface SSEReader {\r\n /** Resolves with the next decoded chunk, or `{ done: true }` at end of stream. */\r\n read(): Promise<{ done: boolean; value?: string }>;\r\n /** Aborts the underlying request. */\r\n cancel(): void;\r\n}\r\n\r\nexport interface SSEStream {\r\n status: number;\r\n ok: boolean;\r\n getHeader(name: string): string | null;\r\n /** Present only when `ok` is false, so callers can surface the server's message. */\r\n errorText?: string;\r\n reader: SSEReader;\r\n}\r\n\r\nexport interface OpenSSEOptions {\r\n url: string;\r\n headers: Record<string, string>;\r\n body: string;\r\n signal?: AbortSignal;\r\n}\r\n\r\n/**\r\n * Whether `fetch` on this platform yields a streaming body.\r\n *\r\n * `navigator.product === 'ReactNative'` is the long-standing marker React\r\n * Native sets, and is checked rather than feature-detecting `ReadableStream`:\r\n * newer RN versions do expose a global `ReadableStream` while still leaving\r\n * `response.body` undefined, so the presence of the type says nothing about\r\n * whether fetch will populate it.\r\n */\r\nexport function supportsStreamingFetch(): boolean {\r\n if (\r\n typeof navigator !== \"undefined\" &&\r\n (navigator as { product?: string }).product === \"ReactNative\"\r\n ) {\r\n return false;\r\n }\r\n return typeof fetch !== \"undefined\" && typeof ReadableStream !== \"undefined\";\r\n}\r\n\r\n/** Wraps a whatwg ReadableStream reader so it decodes to strings. */\r\nfunction fetchReader(\r\n response: Response,\r\n controller: AbortController,\r\n): SSEReader {\r\n const reader = response.body!.getReader();\r\n const decoder = new TextDecoder(\"utf-8\");\r\n\r\n return {\r\n async read() {\r\n const { done, value } = await reader.read();\r\n if (done) return { done: true };\r\n return { done: false, value: decoder.decode(value, { stream: true }) };\r\n },\r\n cancel() {\r\n controller.abort();\r\n void reader.cancel().catch(() => {});\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Issues the request over XMLHttpRequest and exposes new text as it arrives.\r\n *\r\n * XHR keeps the whole response in `responseText` and only ever appends, so each\r\n * chunk is the slice past what has already been handed out.\r\n */\r\nfunction xhrStream(opts: OpenSSEOptions): Promise<SSEStream> {\r\n return new Promise<SSEStream>((resolveStream, rejectStream) => {\r\n const xhr = new XMLHttpRequest();\r\n xhr.open(\"POST\", opts.url);\r\n for (const [key, val] of Object.entries(opts.headers))\r\n xhr.setRequestHeader(key, val);\r\n\r\n let consumed = 0;\r\n let finished = false;\r\n let failure: Error | null = null;\r\n // Chunks that arrived before the consumer asked for them, and the pending\r\n // read waiting for one - only one of the two is ever non-empty.\r\n const queue: string[] = [];\r\n let waiting: ((r: { done: boolean; value?: string }) => void) | null = null;\r\n let waitingReject: ((e: Error) => void) | null = null;\r\n let headersResolved = false;\r\n\r\n const pump = () => {\r\n const text = xhr.responseText;\r\n if (text.length <= consumed) return;\r\n const chunk = text.slice(consumed);\r\n consumed = text.length;\r\n\r\n if (waiting) {\r\n const resolve = waiting;\r\n waiting = null;\r\n waitingReject = null;\r\n resolve({ done: false, value: chunk });\r\n } else {\r\n queue.push(chunk);\r\n }\r\n };\r\n\r\n const finish = (err?: Error) => {\r\n if (finished) return;\r\n finished = true;\r\n failure = err ?? null;\r\n if (waiting) {\r\n const resolve = waiting;\r\n const reject = waitingReject;\r\n waiting = null;\r\n waitingReject = null;\r\n if (err && reject) reject(err);\r\n else resolve({ done: true });\r\n }\r\n };\r\n\r\n const reader: SSEReader = {\r\n read() {\r\n if (queue.length > 0) {\r\n return Promise.resolve({ done: false, value: queue.shift() });\r\n }\r\n if (finished) {\r\n return failure\r\n ? Promise.reject(failure)\r\n : Promise.resolve({ done: true });\r\n }\r\n return new Promise((resolve, reject) => {\r\n waiting = resolve;\r\n waitingReject = reject;\r\n });\r\n },\r\n cancel() {\r\n finish();\r\n xhr.abort();\r\n },\r\n };\r\n\r\n // Headers are available from readyState 2, which is what lets a non-2xx\r\n // response be reported without waiting for the body to finish.\r\n const resolveHeaders = () => {\r\n if (headersResolved) return;\r\n headersResolved = true;\r\n const ok = xhr.status >= 200 && xhr.status < 300;\r\n resolveStream({\r\n status: xhr.status,\r\n ok,\r\n getHeader: (name: string) => xhr.getResponseHeader(name),\r\n reader,\r\n });\r\n };\r\n\r\n xhr.onreadystatechange = () => {\r\n if (xhr.readyState === 2) {\r\n resolveHeaders();\r\n } else if (xhr.readyState === 3) {\r\n resolveHeaders();\r\n pump();\r\n } else if (xhr.readyState === 4) {\r\n resolveHeaders();\r\n pump();\r\n finish();\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n const err = new Error(\"Network request failed\");\r\n if (!headersResolved) rejectStream(err);\r\n finish(err);\r\n };\r\n xhr.ontimeout = () => {\r\n const err = new Error(\"Network request timed out\");\r\n if (!headersResolved) rejectStream(err);\r\n finish(err);\r\n };\r\n\r\n if (opts.signal) {\r\n if (opts.signal.aborted) {\r\n xhr.abort();\r\n finish();\r\n } else {\r\n opts.signal.addEventListener(\"abort\", () => {\r\n finish();\r\n xhr.abort();\r\n });\r\n }\r\n }\r\n\r\n xhr.send(opts.body);\r\n });\r\n}\r\n\r\n/**\r\n * Opens an SSE stream, using whichever transport this platform can stream over.\r\n */\r\nexport async function openSSEStream(opts: OpenSSEOptions): Promise<SSEStream> {\r\n if (!supportsStreamingFetch()) {\r\n return xhrStream(opts);\r\n }\r\n\r\n const controller = new AbortController();\r\n if (opts.signal) {\r\n if (opts.signal.aborted) controller.abort();\r\n else opts.signal.addEventListener(\"abort\", () => controller.abort());\r\n }\r\n\r\n const response = await fetch(opts.url, {\r\n method: \"POST\",\r\n headers: opts.headers,\r\n body: opts.body,\r\n signal: controller.signal,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => \"Stream failed\");\r\n return {\r\n status: response.status,\r\n ok: false,\r\n errorText,\r\n getHeader: (name: string) => response.headers.get(name),\r\n reader: {\r\n read: async () => ({ done: true }),\r\n cancel: () => controller.abort(),\r\n },\r\n };\r\n }\r\n\r\n if (!response.body) {\r\n // A streaming-capable platform that still gave no body - fall back to the\r\n // buffered text rather than failing outright.\r\n const text = await response.text();\r\n let handed = false;\r\n return {\r\n status: response.status,\r\n ok: true,\r\n getHeader: (name: string) => response.headers.get(name),\r\n reader: {\r\n read: async () =>\r\n handed\r\n ? { done: true }\r\n : ((handed = true), { done: false, value: text }),\r\n cancel: () => controller.abort(),\r\n },\r\n };\r\n }\r\n\r\n return {\r\n status: response.status,\r\n ok: true,\r\n getHeader: (name: string) => response.headers.get(name),\r\n reader: fetchReader(response, controller),\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport type { PersonaMemoryFile, PersonaMemoryList } from \"../types.js\";\r\n\r\nexport function useMemory(autoFetch = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [memory, setMemory] = useState<PersonaMemoryList>({\r\n userFiles: [],\r\n agentMemories: [],\r\n });\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchMemory = useCallback(async () => {\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(\"/memory\");\r\n if (!res.ok) {\r\n throw new Error(`Failed to fetch memory: ${res.statusText}`);\r\n }\r\n const data = (await res.json()) as PersonaMemoryList;\r\n setMemory(data);\r\n return data;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return { userFiles: [], agentMemories: [] };\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n const getFile = useCallback(\r\n async (params: {\r\n path: string;\r\n scope?: \"user\" | \"agent\";\r\n agentId?: string;\r\n }) => {\r\n const query = new URLSearchParams({ path: params.path });\r\n if (params.scope) query.set(\"scope\", params.scope);\r\n if (params.agentId) query.set(\"agentId\", params.agentId);\r\n\r\n const res = await fetchWithAuth(`/memory/file?${query.toString()}`);\r\n if (!res.ok)\r\n throw new Error(`Failed to get memory file: ${res.statusText}`);\r\n return (await res.json()) as PersonaMemoryFile;\r\n },\r\n [fetchWithAuth],\r\n );\r\n\r\n const writeFile = useCallback(\r\n async (params: {\r\n path: string;\r\n content: string;\r\n scope?: \"user\" | \"agent\";\r\n agentId?: string;\r\n }) => {\r\n const res = await fetchWithAuth(\"/memory/file\", {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(params),\r\n });\r\n if (!res.ok)\r\n throw new Error(`Failed to write memory file: ${res.statusText}`);\r\n const updated = (await res.json()) as PersonaMemoryFile;\r\n void fetchMemory();\r\n return updated;\r\n },\r\n [fetchWithAuth, fetchMemory],\r\n );\r\n\r\n const deleteFile = useCallback(\r\n async (params: {\r\n path: string;\r\n scope?: \"user\" | \"agent\";\r\n agentId?: string;\r\n }) => {\r\n const query = new URLSearchParams({ path: params.path });\r\n if (params.scope) query.set(\"scope\", params.scope);\r\n if (params.agentId) query.set(\"agentId\", params.agentId);\r\n\r\n const res = await fetchWithAuth(`/memory/file?${query.toString()}`, {\r\n method: \"DELETE\",\r\n });\r\n if (!res.ok)\r\n throw new Error(`Failed to delete memory file: ${res.statusText}`);\r\n void fetchMemory();\r\n },\r\n [fetchWithAuth, fetchMemory],\r\n );\r\n\r\n useEffect(() => {\r\n if (autoFetch) {\r\n void fetchMemory();\r\n }\r\n }, [autoFetch, fetchMemory]);\r\n\r\n return {\r\n memory,\r\n isLoading,\r\n error,\r\n refetch: fetchMemory,\r\n getFile,\r\n writeFile,\r\n deleteFile,\r\n };\r\n}\r\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\nimport type { PersonaThread } from \"../types.js\";\n\nexport function useThreads(autoFetch = true) {\n const { fetchWithAuth, defaultAgentId } = usePersonaContext();\n const [threads, setThreads] = useState<PersonaThread[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchThreads = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const res = await fetchWithAuth(\"/threads\");\n if (!res.ok) throw new Error(`Failed to list threads: ${res.statusText}`);\n const data = await res.json();\n // Real shape is { items, pagination }. Bare array / `.data` / `.threads`\n // are defensive fallbacks for other deployments, not the actual contract.\n const items: PersonaThread[] = Array.isArray(data)\n ? data\n : data?.items ||\n data?.threads ||\n (Array.isArray(data?.data) ? data.data : undefined) ||\n [];\n setThreads(items);\n return items;\n } catch (err) {\n const errorObj = err instanceof Error ? err : new Error(String(err));\n setError(errorObj);\n return [];\n } finally {\n setIsLoading(false);\n }\n }, [fetchWithAuth]);\n\n const createThread = useCallback(\n async (agentId?: string) => {\n const targetAgentId = agentId || defaultAgentId;\n const res = await fetchWithAuth(\"/threads\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ agentId: targetAgentId }),\n });\n if (!res.ok)\n throw new Error(`Failed to create thread: ${res.statusText}`);\n const data = await res.json();\n const created = (data?.data ?? data) as PersonaThread;\n void fetchThreads();\n return created;\n },\n [fetchWithAuth, defaultAgentId, fetchThreads],\n );\n\n const deleteThread = useCallback(\n async (threadId: string) => {\n const res = await fetchWithAuth(`/threads/${threadId}`, {\n method: \"DELETE\",\n });\n if (!res.ok)\n throw new Error(`Failed to delete thread: ${res.statusText}`);\n setThreads((prev) => prev.filter((t) => t._id !== threadId));\n },\n [fetchWithAuth],\n );\n\n // Best-effort batch delete — no not-found id aborts the rest. Up to 100\n // ids per call, matching the server's own limit.\n const bulkDeleteThreads = useCallback(\n async (threadIds: string[]) => {\n const res = await fetchWithAuth(\"/threads/bulk-delete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ ids: threadIds }),\n });\n if (!res.ok)\n throw new Error(`Failed to bulk-delete threads: ${res.statusText}`);\n const data = await res.json();\n const result = (data?.data ?? data) as {\n deleted: string[];\n failed: Array<{ id: string; reason: string }>;\n };\n const deletedSet = new Set(result.deleted);\n setThreads((prev) => prev.filter((t) => !deletedSet.has(t._id)));\n return result;\n },\n [fetchWithAuth],\n );\n\n // Convenience wrapper: there is no server-side \"delete everything\"\n // endpoint, only bulk-delete-by-id — so this bulk-deletes every\n // currently-loaded thread (up to 100 per call, chunked if there are more).\n const deleteAllThreads = useCallback(async () => {\n const ids = threads.map((t) => t._id);\n for (let i = 0; i < ids.length; i += 100) {\n await bulkDeleteThreads(ids.slice(i, i + 100));\n }\n }, [threads, bulkDeleteThreads]);\n\n // General-purpose update — { title?, isArchived? }.\n const updateThread = useCallback(\n async (\n threadId: string,\n input: { title?: string; isArchived?: boolean },\n ) => {\n const res = await fetchWithAuth(`/threads/${threadId}`, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n });\n if (!res.ok)\n throw new Error(`Failed to update thread: ${res.statusText}`);\n const data = await res.json();\n const updated = (data?.data ?? data) as PersonaThread;\n setThreads((prev) =>\n prev.map((t) => (t._id === threadId ? { ...t, ...updated } : t)),\n );\n return updated;\n },\n [fetchWithAuth],\n );\n\n const renameThread = useCallback(\n (threadId: string, title: string) => updateThread(threadId, { title }),\n [updateThread],\n );\n\n // Clears a thread's conversation content in place (message history, files/\n // todos, subagent traces) while keeping the same thread id/title — unlike\n // deleteThread, nothing about the thread's identity changes, so callers\n // can reuse it as a fresh conversation instead of creating a new one.\n const resetThread = useCallback(\n async (threadId: string) => {\n const res = await fetchWithAuth(`/threads/${threadId}/reset`, {\n method: \"POST\",\n });\n if (!res.ok) throw new Error(`Failed to reset thread: ${res.statusText}`);\n const data = await res.json();\n const reset = (data?.data ?? data) as PersonaThread;\n setThreads((prev) =>\n prev.map((t) => (t._id === threadId ? { ...t, ...reset } : t)),\n );\n return reset;\n },\n [fetchWithAuth],\n );\n\n const getThread = useCallback(\n async (threadId: string) => {\n const res = await fetchWithAuth(`/threads/${threadId}`);\n if (!res.ok) throw new Error(`Failed to fetch thread: ${res.statusText}`);\n const data = await res.json();\n return (data?.data ?? data) as PersonaThread;\n },\n [fetchWithAuth],\n );\n\n useEffect(() => {\n if (autoFetch) {\n void fetchThreads();\n }\n }, [autoFetch, fetchThreads]);\n\n return {\n threads,\n isLoading,\n error,\n refetch: fetchThreads,\n createThread,\n deleteThread,\n bulkDeleteThreads,\n deleteAllThreads,\n updateThread,\n renameThread,\n resetThread,\n getThread,\n };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\nimport { recorderWorkletUrl, playerWorkletUrl } from \"./voiceWorklets.js\";\nimport type {\n PersonaVoiceEndReason,\n PersonaVoiceState,\n PersonaVoiceToolCall,\n PersonaVoiceTranscriptLine,\n UseVoiceOptions,\n UseVoiceResult,\n} from \"../types.js\";\n\ninterface VoiceSessionTicket {\n ticket: string;\n wsUrl: string;\n expiresAt: string;\n session: {\n model: string;\n voice: string;\n inputSampleRate: number;\n outputSampleRate: number;\n maxDurationMs: number;\n };\n}\n\n// Gemini Live delivers an agent utterance's output transcription as SEVERAL\n// incremental fragments (one serverContent message per fragment) inside a\n// single model turn — there is no per-fragment \"finished\" flag; only\n// turnComplete closes the turn. The gateway forwards each fragment as its own\n// isFinal:true voice_transcript event, so without merging here every fragment\n// would render as its own stacked bubble even though the concatenated text is\n// one sentence. Fragments arrive as EITHER a cumulative full snapshot OR\n// incremental new words (Gemini does both), so handle both:\n// - cumulative: next already contains prev from the start -> take next\n// - incremental: append next, inserting a space only at a clean word seam\nfunction mergeTranscriptText(prev: string, next: string): string {\n if (!prev) return next;\n if (!next) return prev;\n if (next === prev || prev.endsWith(next)) return prev; // no-op / dup tail\n if (next.startsWith(prev)) return next; // cumulative snapshot\n const needSpace = !/\\s$/.test(prev) && !/^\\s/.test(next);\n return prev + (needSpace ? \" \" : \"\") + next;\n}\n\ninterface VoiceTranscriptValue {\n speaker: \"user\" | \"agent\";\n text: string;\n isFinal: boolean;\n turnSeq?: number;\n}\n\n/**\n * Drives a real-time voice call with an Agent (powered by Gemini Live).\n *\n * Ticket minting goes through YOUR OWN backend (`POST /voice/sessions` on\n * whichever `@personaai/runtime`-based adapter you've mounted) via\n * `fetchWithAuth` — same as every other hook in this package. The actual\n * call does NOT: once a ticket comes back, this hook opens a WebSocket\n * DIRECTLY to Persona (`ticket.wsUrl`), bypassing your backend entirely for\n * the live audio. This is deliberate — see the package README's Voice\n * section for why (short version: a multi-minute relay would not survive\n * on a serverless deployment the way `POST /chat`'s bounded SSE relay\n * does), and it means your backend never has to become a WebSocket relay.\n *\n * Requires a browser with `AudioWorklet` support (all current evergreen\n * browsers). The processor code itself needs no `/public` file of your\n * own — it's embedded and loaded via a Blob URL (see `voiceWorklets.ts`).\n */\nexport function useVoice(options: UseVoiceOptions = {}): UseVoiceResult {\n const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();\n const voiceLogger = useMemo(() => logger.child(\"voice\"), [logger]);\n const agentId = options.agentId || defaultAgentId;\n const threadId = options.threadId;\n const contextOverride = options.contextOverride;\n\n const [state, setState] = useState<PersonaVoiceState>(\"idle\");\n const [isMuted, setIsMuted] = useState(false);\n const [transcript, setTranscript] = useState<PersonaVoiceTranscriptLine[]>(\n [],\n );\n const [partial, setPartial] = useState<PersonaVoiceTranscriptLine | null>(\n null,\n );\n const [toolCalls, setToolCalls] = useState<PersonaVoiceToolCall[]>([]);\n const [error, setError] = useState<Error | null>(null);\n const [endReason, setEndReason] = useState<PersonaVoiceEndReason | null>(\n null,\n );\n\n const wsRef = useRef<WebSocket | null>(null);\n const streamRef = useRef<MediaStream | null>(null);\n const inputCtxRef = useRef<AudioContext | null>(null);\n const outputCtxRef = useRef<AudioContext | null>(null);\n const recorderNodeRef = useRef<AudioWorkletNode | null>(null);\n const playerNodeRef = useRef<AudioWorkletNode | null>(null);\n const acceptedTurnSeqRef = useRef(0);\n const mountedRef = useRef(true);\n // Speaker + turnSeq of the last committed transcript line. Consecutive\n // finals with the same speaker AND turnSeq are fragments of one utterance\n // (the server bumps turnSeq only at turnComplete), so they merge into the\n // line they created instead of spawning a new bubble.\n const lastFinalTurnRef = useRef<{ speaker: string; turnSeq?: number } | null>(\n null,\n );\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n const teardownAudio = useCallback(() => {\n try {\n streamRef.current?.getTracks().forEach((track) => track.stop());\n } catch {\n // ignore\n }\n streamRef.current = null;\n\n try {\n recorderNodeRef.current?.disconnect();\n } catch {\n // ignore\n }\n recorderNodeRef.current = null;\n\n try {\n playerNodeRef.current?.disconnect();\n } catch {\n // ignore\n }\n playerNodeRef.current = null;\n\n try {\n void inputCtxRef.current?.close();\n } catch {\n // ignore\n }\n inputCtxRef.current = null;\n\n try {\n void outputCtxRef.current?.close();\n } catch {\n // ignore\n }\n outputCtxRef.current = null;\n }, []);\n\n const stop = useCallback(() => {\n voiceLogger.debug(\"stop() called\");\n try {\n wsRef.current?.close(1000, \"client_stop\");\n } catch {\n // ignore\n }\n wsRef.current = null;\n teardownAudio();\n if (mountedRef.current) setState(\"idle\");\n }, [teardownAudio, voiceLogger]);\n\n useEffect(() => stop, [stop]);\n\n const startCapture = useCallback(async (inputSampleRate: number) => {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n channelCount: 1,\n },\n });\n streamRef.current = stream;\n\n const inputCtx = new AudioContext({ sampleRate: inputSampleRate });\n inputCtxRef.current = inputCtx;\n await inputCtx.audioWorklet.addModule(recorderWorkletUrl());\n\n const source = inputCtx.createMediaStreamSource(stream);\n const recorderNode = new AudioWorkletNode(\n inputCtx,\n \"pcm-recorder-processor\",\n );\n recorderNode.port.onmessage = (event: MessageEvent<ArrayBuffer>) => {\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n wsRef.current.send(event.data);\n }\n };\n recorderNodeRef.current = recorderNode;\n source.connect(recorderNode);\n }, []);\n\n const setupPlayback = useCallback(async (outputSampleRate: number) => {\n const outputCtx = new AudioContext({ sampleRate: outputSampleRate });\n outputCtxRef.current = outputCtx;\n await outputCtx.audioWorklet.addModule(playerWorkletUrl());\n\n const playerNode = new AudioWorkletNode(outputCtx, \"pcm-player-processor\");\n playerNode.connect(outputCtx.destination);\n playerNodeRef.current = playerNode;\n }, []);\n\n const upsertToolCall = useCallback(\n (id: string, patch: Partial<PersonaVoiceToolCall>) => {\n setToolCalls((prev) => {\n const idx = prev.findIndex((t) => t.id === id);\n if (idx === -1) return [...prev, { id, status: \"running\", ...patch }];\n const next = [...prev];\n next[idx] = { ...next[idx], ...patch } as PersonaVoiceToolCall;\n return next;\n });\n },\n [],\n );\n\n const handleTranscript = useCallback((value: VoiceTranscriptValue) => {\n const { speaker, text, isFinal, turnSeq } = value;\n if (!isFinal) {\n setPartial({ id: \"partial\", speaker, text });\n return;\n }\n\n // A final may land while a partial of the same speaker is showing (the\n // last interim is superseded by the final) — clear it only for that case.\n setPartial((prev) => (prev?.speaker === speaker ? null : prev));\n\n const last = lastFinalTurnRef.current;\n const sameUserBurst =\n speaker === \"user\" &&\n last &&\n last.speaker === speaker &&\n last.turnSeq === turnSeq;\n\n setTranscript((prev) => {\n const tail = prev[prev.length - 1];\n // An agent \"answer\" can arrive as several separate finals: per-fragment\n // finals of one utterance, or distinct spoken segments split by a tool\n // call mid-answer. Keep them as ONE bubble while no user line has\n // intervened — this is exactly how the thread reads the same turns back\n // (checkpoint.service normalizeMessages merges consecutive assistant\n // messages) and how text chat shows one assistant message per answer.\n // A committed user line between two agent lines separates answers, so\n // the merge only applies when the open line is also agent.\n const agentContinues = speaker === \"agent\" && tail?.speaker === \"agent\";\n if (agentContinues || (sameUserBurst && tail?.speaker === \"user\")) {\n const merged = mergeTranscriptText(tail.text, text);\n if (merged === tail.text) return prev;\n return prev.map((l, i) =>\n i === prev.length - 1 ? { ...l, text: merged } : l,\n );\n }\n return [...prev, { id: `${speaker}-${prev.length}`, speaker, text }];\n });\n lastFinalTurnRef.current = { speaker, turnSeq };\n }, []);\n\n const handleCustomEvent = useCallback(\n (name: string, value: Record<string, unknown>) => {\n switch (name) {\n case \"voice_session_ready\":\n voiceLogger.debug(\"voice_session_ready\", value);\n Promise.all([\n setupPlayback(value.outputSampleRate as number),\n startCapture(value.inputSampleRate as number),\n ])\n .then(() => {\n if (mountedRef.current) setState(\"listening\");\n })\n .catch((err) => {\n voiceLogger.error(\"audio graph setup failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n if (mountedRef.current) {\n setError(err instanceof Error ? err : new Error(String(err)));\n setState(\"error\");\n }\n });\n break;\n case \"voice_activity\":\n if (value.speaker === \"user\" && value.state === \"start\") {\n setState(\"listening\");\n } else if (value.speaker === \"user\" && value.state === \"end\") {\n setState(\"thinking\");\n } else if (value.speaker === \"agent\" && value.state === \"start\") {\n setState(\"speaking\");\n } else if (value.speaker === \"agent\" && value.state === \"end\") {\n setState(\"listening\");\n }\n break;\n case \"voice_transcript\":\n handleTranscript(value as unknown as VoiceTranscriptValue);\n break;\n case \"voice_interrupted\":\n acceptedTurnSeqRef.current = value.turnSeq as number;\n playerNodeRef.current?.port.postMessage({ type: \"flush\" });\n break;\n case \"voice_session_resumed\":\n voiceLogger.info(\"session transparently resumed\");\n break;\n case \"voice_session_ended\":\n voiceLogger.info(\"session ended\", { reason: value.reason });\n setState(\"ended\");\n setEndReason((value.reason as PersonaVoiceEndReason) ?? null);\n teardownAudio();\n try {\n wsRef.current?.close();\n } catch {\n // ignore\n }\n wsRef.current = null;\n break;\n default:\n break;\n }\n },\n [handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger],\n );\n\n const handleMessage = useCallback(\n (event: MessageEvent<ArrayBuffer | string>) => {\n if (typeof event.data !== \"string\") {\n const buf = event.data;\n const view = new DataView(buf);\n const turnSeq = view.getUint32(0, true);\n // Accept (and adopt) anything >= the last accepted value rather\n // than an exact match — the server bumps turnSeq on EVERY new\n // agent turn, not only on a barge-in. WebSocket delivers messages\n // in send order on one connection, so a voice_interrupted event\n // always arrives before any frame from the generation it\n // announces — nothing stale can arrive after it.\n if (turnSeq >= acceptedTurnSeqRef.current) {\n acceptedTurnSeqRef.current = turnSeq;\n const pcmBytes = buf.slice(4);\n playerNodeRef.current?.port.postMessage(pcmBytes, [pcmBytes]);\n }\n return;\n }\n\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data);\n } catch {\n return;\n }\n\n switch (msg.type) {\n case \"CUSTOM\":\n handleCustomEvent(\n msg.name as string,\n msg.value as Record<string, unknown>,\n );\n break;\n case \"TOOL_CALL_CHUNK\":\n upsertToolCall(msg.toolCallId as string, {\n name: msg.toolCallName as string | undefined,\n status: \"running\",\n });\n break;\n case \"TOOL_CALL_RESULT\": {\n let parsed: { output?: unknown; error?: string } | null = null;\n try {\n parsed = JSON.parse(msg.content as string);\n } catch {\n parsed = { output: msg.content };\n }\n upsertToolCall(msg.toolCallId as string, {\n status: parsed?.error ? \"error\" : \"done\",\n summary:\n parsed?.error ||\n (typeof parsed?.output === \"string\"\n ? parsed.output\n : JSON.stringify(parsed?.output ?? \"\")),\n });\n break;\n }\n case \"RUN_ERROR\":\n voiceLogger.warn(\"RUN_ERROR\", { message: msg.message });\n setError(\n new Error((msg.message as string) || \"The agent run failed.\"),\n );\n setState(\"error\");\n break;\n default:\n break;\n }\n },\n [handleCustomEvent, upsertToolCall, voiceLogger],\n );\n\n const start = useCallback(async () => {\n if (!agentId) {\n const err = new Error(\n \"useVoice: no agentId provided and no defaultAgentId set on PersonaProvider\",\n );\n setError(err);\n setState(\"error\");\n return;\n }\n\n setError(null);\n setEndReason(null);\n setTranscript([]);\n setPartial(null);\n setToolCalls([]);\n acceptedTurnSeqRef.current = 0;\n setState(\"connecting\");\n voiceLogger.debug(\"start() called\", {\n agentId,\n threadId,\n hasContextOverride: !!contextOverride,\n });\n\n try {\n const res = await fetchWithAuth(\"/voice/sessions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n agentId,\n ...(threadId ? { threadId } : {}),\n ...(contextOverride ? { contextOverride } : {}),\n }),\n });\n if (!res.ok) {\n throw new Error(`Failed to start voice session: ${res.statusText}`);\n }\n const data = await res.json();\n const ticket = (data?.data ?? data) as VoiceSessionTicket;\n if (!ticket?.wsUrl) {\n throw new Error(\"Server did not return a voice session URL.\");\n }\n\n const ws = new WebSocket(ticket.wsUrl);\n ws.binaryType = \"arraybuffer\";\n wsRef.current = ws;\n\n ws.onmessage = handleMessage;\n ws.onerror = () => {\n voiceLogger.warn(\"WebSocket error\");\n if (mountedRef.current) {\n setError(new Error(\"Voice connection error.\"));\n setState(\"error\");\n }\n };\n ws.onclose = () => {\n if (mountedRef.current && wsRef.current === ws) {\n setState((prev) => (prev === \"error\" ? prev : \"idle\"));\n }\n };\n } catch (err) {\n const errorObj = err instanceof Error ? err : new Error(String(err));\n voiceLogger.error(\"start() failed\", { error: errorObj.message });\n if (mountedRef.current) {\n setError(errorObj);\n setState(\"error\");\n }\n teardownAudio();\n }\n }, [agentId, threadId, contextOverride, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);\n\n const mute = useCallback((muted: boolean) => {\n setIsMuted(muted);\n streamRef.current?.getAudioTracks().forEach((track) => {\n track.enabled = !muted;\n });\n }, []);\n\n const sendText = useCallback((text: string) => {\n if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;\n wsRef.current.send(JSON.stringify({ type: \"voice.text\", text }));\n }, []);\n\n return {\n state,\n isMuted,\n transcript,\n partial,\n toolCalls,\n error,\n endReason,\n start,\n stop,\n mute,\n sendText,\n };\n}\n","/**\n * AudioWorklet processor source for `useVoice`, embedded as strings rather\n * than shipped as separate static files. A consumer app has no `/public`\n * directory we can rely on being copied into (unlike our own first-party\n * frontend, which loads these from `/voice/*.js`) — `URL.createObjectURL`\n * + a Blob is the standard way to hand `audioWorklet.addModule()` a module\n * with zero setup required from the host app.\n */\n\nconst RECORDER_WORKLET_SOURCE = `\nclass PCMRecorderProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this._buffer = [];\n this._chunkSamples = 320; // 20ms @ 16kHz\n }\n\n process(inputs) {\n const input = inputs[0];\n const channel = input && input[0];\n if (channel) {\n for (let i = 0; i < channel.length; i++) {\n this._buffer.push(channel[i]);\n }\n while (this._buffer.length >= this._chunkSamples) {\n const chunk = this._buffer.splice(0, this._chunkSamples);\n const int16 = new Int16Array(chunk.length);\n for (let i = 0; i < chunk.length; i++) {\n const s = Math.max(-1, Math.min(1, chunk[i]));\n int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n this.port.postMessage(int16.buffer, [int16.buffer]);\n }\n }\n return true;\n }\n}\n\nregisterProcessor('pcm-recorder-processor', PCMRecorderProcessor);\n`;\n\nconst PLAYER_WORKLET_SOURCE = `\nclass PCMPlayerProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this._queue = [];\n this._readOffset = 0;\n this.port.onmessage = (event) => {\n const msg = event.data;\n if (msg && msg.type === 'flush') {\n this._queue = [];\n this._readOffset = 0;\n return;\n }\n const int16 = new Int16Array(msg);\n const float32 = new Float32Array(int16.length);\n for (let i = 0; i < int16.length; i++) {\n float32[i] = int16[i] / 0x8000;\n }\n this._queue.push(float32);\n };\n }\n\n process(_inputs, outputs) {\n const output = outputs[0][0];\n let outIdx = 0;\n while (outIdx < output.length) {\n if (this._queue.length === 0) {\n output[outIdx++] = 0;\n continue;\n }\n const current = this._queue[0];\n const remaining = current.length - this._readOffset;\n const toCopy = Math.min(remaining, output.length - outIdx);\n output.set(current.subarray(this._readOffset, this._readOffset + toCopy), outIdx);\n outIdx += toCopy;\n this._readOffset += toCopy;\n if (this._readOffset >= current.length) {\n this._queue.shift();\n this._readOffset = 0;\n }\n }\n return true;\n }\n}\n\nregisterProcessor('pcm-player-processor', PCMPlayerProcessor);\n`;\n\nfunction toModuleUrl(source: string): string {\n const blob = new Blob([source], { type: \"application/javascript\" });\n return URL.createObjectURL(blob);\n}\n\nexport function recorderWorkletUrl(): string {\n return toModuleUrl(RECORDER_WORKLET_SOURCE);\n}\n\nexport function playerWorkletUrl(): string {\n return toModuleUrl(PLAYER_WORKLET_SOURCE);\n}\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport type { PersonaFileItem } from \"../types.js\";\r\n\r\nexport type { PersonaFileItem };\r\n\r\nexport function useFiles(autoFetch = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [files, setFiles] = useState<PersonaFileItem[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [isUploading, setIsUploading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchFiles = useCallback(async () => {\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(\"/files\");\r\n if (!res.ok) throw new Error(`Failed to list files: ${res.statusText}`);\r\n const data = await res.json();\r\n // Real shape is { items, pagination } — bare array/`.files` are\r\n // defensive fallbacks, not the actual wire contract.\r\n const items: PersonaFileItem[] = Array.isArray(data)\r\n ? data\r\n : data?.items || data?.files || [];\r\n setFiles(items);\r\n return items;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n const uploadFile = useCallback(\r\n async (\r\n fileOrFormData: FormData | { name: string; uri: string; type?: string },\r\n ) => {\r\n setIsUploading(true);\r\n setError(null);\r\n try {\r\n let body: FormData;\r\n if (fileOrFormData instanceof FormData) {\r\n body = fileOrFormData;\r\n } else {\r\n // React Native FormData support\r\n body = new FormData();\r\n body.append(\"file\", fileOrFormData as unknown as Blob);\r\n }\r\n\r\n const res = await fetchWithAuth(\"/files\", {\r\n method: \"POST\",\r\n body,\r\n });\r\n\r\n if (!res.ok) {\r\n const errText = await res.text().catch(() => \"Upload failed\");\r\n throw new Error(`Upload error (${res.status}): ${errText}`);\r\n }\r\n\r\n const uploaded = (await res.json()) as PersonaFileItem;\r\n void fetchFiles();\r\n return uploaded;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n throw errorObj;\r\n } finally {\r\n setIsUploading(false);\r\n }\r\n },\r\n [fetchWithAuth, fetchFiles],\r\n );\r\n\r\n const deleteFile = useCallback(\r\n async (fileId: string) => {\r\n const res = await fetchWithAuth(`/files/${fileId}`, { method: \"DELETE\" });\r\n if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);\r\n setFiles((prev) => prev.filter((f) => f.id !== fileId));\r\n },\r\n [fetchWithAuth],\r\n );\r\n\r\n const bulkDeleteFiles = useCallback(\r\n async (fileIds: string[]) => {\r\n const res = await fetchWithAuth(\"/files/bulk-delete\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ ids: fileIds }),\r\n });\r\n if (!res.ok)\r\n throw new Error(`Failed to bulk-delete files: ${res.statusText}`);\r\n const idSet = new Set(fileIds);\r\n setFiles((prev) => prev.filter((f) => !idSet.has(f.id)));\r\n return (await res.json()) as {\r\n deleted: string[];\r\n failed: Array<{ id: string; reason: string }>;\r\n };\r\n },\r\n [fetchWithAuth],\r\n );\r\n\r\n const getDownloadUrl = useCallback((fileId: string) => {\r\n return `/files/${fileId}`;\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (autoFetch) {\r\n void fetchFiles();\r\n }\r\n }, [autoFetch, fetchFiles]);\r\n\r\n return {\r\n files,\r\n isLoading,\r\n isUploading,\r\n error,\r\n refetch: fetchFiles,\r\n uploadFile,\r\n deleteFile,\r\n bulkDeleteFiles,\r\n getDownloadUrl,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\n\r\nexport interface PersonaAgentSummary {\r\n _id: string;\r\n name: string;\r\n slug: string;\r\n description?: string;\r\n tagline?: string;\r\n avatar?: string;\r\n}\r\n\r\nexport function useAgents(autoFetch = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [agents, setAgents] = useState<PersonaAgentSummary[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchAgents = useCallback(async () => {\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(\"/agents\");\r\n if (!res.ok) throw new Error(`Failed to list agents: ${res.statusText}`);\r\n const data = await res.json();\r\n // Real shape is { items, pagination }.\r\n const items: PersonaAgentSummary[] = Array.isArray(data)\r\n ? data\r\n : data?.items || data?.agents || [];\r\n setAgents(items);\r\n return items;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n useEffect(() => {\r\n if (autoFetch) {\r\n void fetchAgents();\r\n }\r\n }, [autoFetch, fetchAgents]);\r\n\r\n return {\r\n agents,\r\n isLoading,\r\n error,\r\n refetch: fetchAgents,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\n\r\nexport interface PersonaHealthInfo {\r\n status: string;\r\n version?: string;\r\n capabilities?: Record<string, boolean>;\r\n}\r\n\r\nexport function useConnection(autoCheck = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [health, setHealth] = useState<PersonaHealthInfo | null>(null);\r\n const [isConnected, setIsConnected] = useState(false);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n const checkHealth = useCallback(async () => {\r\n setIsLoading(true);\r\n try {\r\n const res = await fetchWithAuth(\"/health\");\r\n if (res.ok) {\r\n const data = (await res.json()) as PersonaHealthInfo;\r\n setHealth(data);\r\n setIsConnected(true);\r\n return data;\r\n }\r\n setIsConnected(false);\r\n return null;\r\n } catch {\r\n setIsConnected(false);\r\n return null;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n useEffect(() => {\r\n if (autoCheck) {\r\n void checkHealth();\r\n }\r\n }, [autoCheck, checkHealth]);\r\n\r\n return {\r\n isConnected,\r\n health,\r\n isLoading,\r\n checkHealth,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\n\r\n/**\r\n * One `authType: 'oauth', authMode: 'user'` MCP an Agent has attached, and\r\n * whether the current end user has connected it yet. `authorizeUrl` is only\r\n * present when `connected` is `false` — navigate the browser there (a\r\n * same-tab redirect is fine; it's a real OAuth authorization URL) to start\r\n * the consent flow.\r\n */\r\nexport interface PersonaMcpConnection {\r\n mcpId: string;\r\n name: string;\r\n description: string;\r\n connected: boolean;\r\n authorizeUrl: string | null;\r\n}\r\n\r\nexport interface UseMcpConnectionsOptions {\r\n /** @default the PersonaProvider's defaultAgentId */\r\n agentId?: string;\r\n /** Where the browser lands after OAuth consent completes. @default window.location.href */\r\n returnTo?: string;\r\n /** @default true */\r\n autoFetch?: boolean;\r\n}\r\n\r\n/**\r\n * Surfaces the gap that used to be invisible entirely: a user-mode MCP tool\r\n * call for a user who hasn't connected yet is silently dropped from the\r\n * Agent's toolset server-side, with no signal in the chat stream at all.\r\n * Check this before (or alongside) a chat session to show a real \"Connect\r\n * your account\" affordance instead of a capability that just quietly isn't\r\n * there.\r\n */\r\nexport function useMcpConnections(options: UseMcpConnectionsOptions = {}) {\r\n const { defaultAgentId, fetchWithAuth } = usePersonaContext();\r\n const agentId = options.agentId ?? defaultAgentId;\r\n const autoFetch = options.autoFetch ?? true;\r\n\r\n const [connections, setConnections] = useState<PersonaMcpConnection[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchConnections = useCallback(async () => {\r\n if (!agentId) return [];\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const returnTo =\r\n options.returnTo ??\r\n (typeof window !== \"undefined\" ? window.location.href : undefined);\r\n const query = returnTo ? `?returnTo=${encodeURIComponent(returnTo)}` : \"\";\r\n const res = await fetchWithAuth(\r\n `/agents/${agentId}/mcp-connections${query}`,\r\n );\r\n if (!res.ok)\r\n throw new Error(`Failed to load MCP connections: ${res.statusText}`);\r\n const data = await res.json();\r\n const items: PersonaMcpConnection[] = Array.isArray(data)\r\n ? data\r\n : data?.items || [];\r\n setConnections(items);\r\n return items;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [agentId, fetchWithAuth, options.returnTo]);\r\n\r\n useEffect(() => {\r\n if (autoFetch) void fetchConnections();\r\n }, [autoFetch, fetchConnections]);\r\n\r\n return {\r\n connections,\r\n /** Convenience filter for the common \"show a banner for what's missing\" case. */\r\n unconnected: connections.filter((c) => !c.connected),\r\n isLoading,\r\n error,\r\n refetch: fetchConnections,\r\n };\r\n}\r\n"],"mappings":"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","names":["import_react","value","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_logger"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context/PersonaContext.tsx","../src/hooks/useChat.ts","../src/streaming.ts","../src/hooks/useMemory.ts","../src/hooks/useThreads.ts","../src/hooks/useVoice.ts","../src/hooks/voiceWorklets.ts","../src/hooks/useFiles.ts","../src/hooks/useAgents.ts","../src/hooks/useConnection.ts","../src/hooks/useMcpConnections.ts"],"sourcesContent":["export * from \"./types.js\";\nexport * from \"./context/PersonaContext.js\";\nexport * from \"./hooks/useChat.js\";\nexport * from \"./hooks/useMemory.js\";\nexport * from \"./hooks/useThreads.js\";\nexport * from \"./hooks/useVoice.js\";\nexport * from \"./hooks/useFiles.js\";\nexport * from \"./hooks/useAgents.js\";\nexport * from \"./hooks/useConnection.js\";\nexport * from \"./hooks/useMcpConnections.js\";\nexport * from \"./streaming.js\";\nexport {\n createLogger,\n createNoopLogger,\n setLogLevel,\n getLogLevel,\n isLevelEnabled,\n} from \"@personaai/logger\";\nexport type {\n Logger,\n LogLevel,\n LogTransport,\n CreateLoggerOptions,\n} from \"@personaai/logger\";\n\nexport const VERSION = \"0.7.3\";\n","\"use client\";\r\n\r\nimport React, { createContext, useContext, useMemo } from \"react\";\r\nimport type { PersonaProviderProps } from \"../types.js\";\r\nimport { createLogger, type Logger } from \"@personaai/logger\";\r\n\r\ninterface PersonaContextValue {\r\n baseUrl: string;\r\n getAuthToken?: () =>\r\n Promise<string | null | undefined> | string | null | undefined;\r\n defaultAgentId?: string;\r\n fetchWithAuth: (path: string, init?: RequestInit) => Promise<Response>;\r\n logger: Logger;\r\n}\r\n\r\nconst PersonaContext = createContext<PersonaContextValue | null>(null);\r\n\r\nexport function PersonaProvider({\r\n baseUrl,\r\n getAuthToken,\r\n defaultAgentId,\r\n logLevel,\r\n logger: loggerProp,\r\n children,\r\n}: PersonaProviderProps) {\r\n const normalizedBaseUrl = useMemo(\r\n () => baseUrl.replace(/\\/+$/, \"\"),\r\n [baseUrl],\r\n );\r\n\r\n const logger = useMemo<Logger>(() => {\r\n const l =\r\n loggerProp ??\r\n createLogger(\r\n \"react\",\r\n logLevel !== undefined ? { level: logLevel } : undefined,\r\n );\r\n l.debug(\"PersonaProvider created\", {\r\n baseUrl: normalizedBaseUrl,\r\n hasDefaultAgentId: !!defaultAgentId,\r\n });\r\n l.info(\"PersonaProvider mounted\", { baseUrl: normalizedBaseUrl });\r\n l.trace(\"PersonaProvider config\", {\r\n baseUrl: normalizedBaseUrl,\r\n hasGetAuthToken: !!getAuthToken,\r\n });\r\n return l;\r\n }, [loggerProp, logLevel, normalizedBaseUrl, defaultAgentId, getAuthToken]);\r\n\r\n const value = useMemo<PersonaContextValue>(() => {\r\n async function fetchWithAuth(\r\n path: string,\r\n init: RequestInit = {},\r\n ): Promise<Response> {\r\n const token = getAuthToken ? await getAuthToken() : null;\r\n const headers = new Headers(init.headers || {});\r\n if (token) {\r\n headers.set(\"Authorization\", `Bearer ${token}`);\r\n logger.trace(\"fetchWithAuth with token\", { path });\r\n } else {\r\n logger.trace(\"fetchWithAuth without token\", { path });\r\n logger.debug(\"fetchWithAuth no token\", { path });\r\n }\r\n\r\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\r\n const url = `${normalizedBaseUrl}${cleanPath}`;\r\n logger.debug(\"fetchWithAuth request\", {\r\n path: cleanPath,\r\n url,\r\n hasToken: !!token,\r\n });\r\n logger.trace(\"fetchWithAuth details\", {\r\n url,\r\n path: cleanPath,\r\n hasToken: !!token,\r\n });\r\n\r\n try {\r\n const res = await fetch(url, {\r\n ...init,\r\n headers,\r\n });\r\n logger.debug(\"fetchWithAuth response\", {\r\n path: cleanPath,\r\n status: res.status,\r\n ok: res.ok,\r\n });\r\n if (!res.ok) {\r\n logger.warn(\"fetchWithAuth non-ok\", {\r\n path: cleanPath,\r\n status: res.status,\r\n });\r\n } else {\r\n logger.info(\"fetchWithAuth succeeded\", {\r\n path: cleanPath,\r\n status: res.status,\r\n });\r\n }\r\n return res;\r\n } catch (err) {\r\n logger.error(\"fetchWithAuth failed\", {\r\n path: cleanPath,\r\n error: err instanceof Error ? err.message : String(err),\r\n });\r\n throw err;\r\n }\r\n }\r\n\r\n return {\r\n baseUrl: normalizedBaseUrl,\r\n getAuthToken,\r\n defaultAgentId,\r\n fetchWithAuth,\r\n logger,\r\n };\r\n }, [normalizedBaseUrl, getAuthToken, defaultAgentId, logger]);\r\n\r\n return (\r\n <PersonaContext.Provider value={value}>{children}</PersonaContext.Provider>\r\n );\r\n}\r\n\r\nexport function usePersonaContext(): PersonaContextValue {\r\n const context = useContext(PersonaContext);\r\n if (!context) {\r\n throw new Error(\r\n \"usePersonaContext must be used within a <PersonaProvider>\",\r\n );\r\n }\r\n return context;\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport { openSSEStream } from \"../streaming.js\";\r\nimport type {\r\n PersonaInterrupt,\r\n PersonaMessage,\r\n PersonaPresentedFile,\r\n PersonaResumeValue,\r\n PersonaRole,\r\n PersonaStreamingEvent,\r\n PersonaSubagentActivityEntry,\r\n PersonaTodo,\r\n PersonaToolCall,\r\n PersonaWorkspaceFile,\r\n SendMessageOverride,\r\n UseChatOptions,\r\n} from \"../types.js\";\r\n\r\n// A failed tool call's TOOL_CALL_RESULT content is a JSON envelope\r\n// (`{status:'error',message}`, see aguiTranslator.js's buildToolErrorContent)\r\n// rather than a separate boolean field on the event itself.\r\nfunction isErrorToolContent(content: string): boolean {\r\n if (typeof content !== \"string\" || !content.trim().startsWith(\"{\"))\r\n return false;\r\n try {\r\n return JSON.parse(content)?.status === \"error\";\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n// Persisted subagent trace item shape (agent-backend's foldSubagentEvent/\r\n// subagentTrace.js) — already folded/paired server-side for compact storage,\r\n// DIFFERENT from the raw per-event `PersonaSubagentActivityEntry` shape the\r\n// live SSE stream sends (kind: 'text'|'tool_start'|'tool_result'). Reloading\r\n// a thread previously never read `data.subagentTraces` at all — a completed\r\n// subagent's activity (its own text/tool timeline) was silently dropped on\r\n// reload even though the backend already persists and returns it, keyed by\r\n// the owning `task` tool call's toolCallId (see agui.controller.js's\r\n// `subagentTraces[callId]`, matching `PersonaToolCall.toolCallId` exactly).\r\ntype PersistedSubagentTraceItem =\r\n | { type: \"text\"; text: string }\r\n | {\r\n type: \"tool\";\r\n name: string;\r\n argsText: string;\r\n resultText: string;\r\n status: \"running\" | \"completed\";\r\n };\r\n\r\n// Re-expands the folded/paired persisted shape back into the raw kind-based\r\n// entries `PersonaSubagentActivityEntry` (and everything downstream that\r\n// consumes it — buildSubagentTimeline, the live-preview row, the activity\r\n// dialog) already knows how to render, so no sdk/ui changes are needed.\r\nfunction persistedTraceToActivityEntries(\r\n items: PersistedSubagentTraceItem[],\r\n): PersonaSubagentActivityEntry[] {\r\n const entries: PersonaSubagentActivityEntry[] = [];\r\n for (const item of items) {\r\n if (item.type === \"text\") {\r\n if (item.text) entries.push({ kind: \"text\", delta: item.text });\r\n } else {\r\n entries.push({\r\n kind: \"tool_start\",\r\n toolName: item.name,\r\n args: item.argsText,\r\n });\r\n if (item.status === \"completed\") {\r\n entries.push({\r\n kind: \"tool_result\",\r\n toolName: item.name,\r\n result: item.resultText,\r\n });\r\n }\r\n }\r\n }\r\n return entries;\r\n}\r\n\r\n// present_file's result is `{status:'success', filePath, title, description}`\r\n// (see present.tool.js) — a signal to highlight that path in the workspace\r\n// files panel, not something meant to render as a generic tool-result blob.\r\nfunction parsePresentedFile(content: string): PersonaPresentedFile | null {\r\n try {\r\n const parsed = JSON.parse(content);\r\n if (parsed?.status !== \"success\" || typeof parsed.filePath !== \"string\")\r\n return null;\r\n return {\r\n path: parsed.filePath,\r\n title: typeof parsed.title === \"string\" ? parsed.title : parsed.filePath,\r\n description:\r\n typeof parsed.description === \"string\" ? parsed.description : \"\",\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n// buildFilesTodosSnapshot (aguiTranslator.js) emits snake_case\r\n// created_at/modified_at on the wire — both from the live STATE_SNAPSHOT\r\n// event and from a reloaded thread's persisted state (checkpoint.service.js\r\n// runs the same function). Normalize to the SDK's usual camelCase shape.\r\nfunction normalizeWorkspaceFiles(\r\n raw: Record<\r\n string,\r\n {\r\n content: string;\r\n size: number;\r\n created_at: string | null;\r\n modified_at: string | null;\r\n }\r\n >,\r\n): Record<string, PersonaWorkspaceFile> {\r\n const normalized: Record<string, PersonaWorkspaceFile> = {};\r\n for (const [path, file] of Object.entries(raw || {})) {\r\n normalized[path] = {\r\n content: file.content,\r\n size: file.size,\r\n createdAt: file.created_at,\r\n modifiedAt: file.modified_at,\r\n };\r\n }\r\n return normalized;\r\n}\r\n\r\n// checkpointService.getMessages() wraps a paused thread's interrupt as\r\n// `{ kind, value }` (see checkpoint.service.js) — the same envelope shape\r\n// the live hitl_request/clarification_request CUSTOM events carry, just\r\n// nested one level deeper. Flatten both into the same PersonaInterrupt shape.\r\nfunction normalizePendingInterrupt(pending: unknown): PersonaInterrupt | null {\r\n if (!pending || typeof pending !== \"object\") return null;\r\n const p = pending as { kind?: string; value?: Record<string, unknown> };\r\n if (p.kind === \"hitl\") {\r\n return {\r\n kind: \"hitl\",\r\n actionRequests: (p.value?.actionRequests ?? []) as Extract<\r\n PersonaInterrupt,\r\n { kind: \"hitl\" }\r\n >[\"actionRequests\"],\r\n reviewConfigs: (p.value?.reviewConfigs ?? []) as unknown[],\r\n };\r\n }\r\n if (p.kind === \"clarification\") {\r\n return {\r\n kind: \"clarification\",\r\n questions: (p.value?.questions ?? []) as Extract<\r\n PersonaInterrupt,\r\n { kind: \"clarification\" }\r\n >[\"questions\"],\r\n };\r\n }\r\n return null;\r\n}\r\n\r\nexport function useChat(options: UseChatOptions = {}) {\r\n const { defaultAgentId, fetchWithAuth, baseUrl, getAuthToken, logger } =\r\n usePersonaContext();\r\n const chatLogger = useMemo(() => logger.child(\"chat\"), [logger]);\r\n const agentId = options.agentId || defaultAgentId;\r\n const threadId = options.threadId;\r\n\r\n // Log hook initialization at most once per mount (debug/info visible, trace for details)\r\n // This runs during render, so guard with a ref to avoid spam on every re-render\r\n const didLogInitRef = useRef(false);\r\n if (!didLogInitRef.current) {\r\n didLogInitRef.current = true;\r\n chatLogger.debug(\"useChat init\", {\r\n agentId,\r\n threadId,\r\n hasInitialMessages: !!options.initialMessages?.length,\r\n });\r\n chatLogger.trace(\"useChat options\", {\r\n agentId,\r\n threadId,\r\n initialMessageCount: options.initialMessages?.length ?? 0,\r\n });\r\n }\r\n\r\n const [messages, setMessages] = useState<PersonaMessage[]>(\r\n options.initialMessages || [],\r\n );\r\n const [input, setInput] = useState(\"\");\r\n const [isStreaming, setIsStreaming] = useState(false);\r\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [interrupt, setInterrupt] = useState<PersonaInterrupt | null>(null);\r\n const [files, setFiles] = useState<Record<string, PersonaWorkspaceFile>>({});\r\n const [todos, setTodos] = useState<PersonaTodo[]>([]);\r\n const [presentedFile, setPresentedFile] =\r\n useState<PersonaPresentedFile | null>(null);\r\n\r\n const abortControllerRef = useRef<AbortController | null>(null);\r\n const loadedThreadIdRef = useRef<string | undefined>(undefined);\r\n\r\n // Voice sync bookkeeping — see the effect below. Kept as refs (not state)\r\n // because they're pure injection-cursor plumbing, never rendered.\r\n const voiceThreadRef = useRef<string | undefined>(threadId);\r\n const voicePrevLenRef = useRef(0);\r\n const voiceStreamingIdRef = useRef<string | null>(null);\r\n\r\n const stop = useCallback(() => {\r\n if (abortControllerRef.current) {\r\n chatLogger.info(\"stop streaming\", {});\r\n chatLogger.debug(\"abort controller\", {\r\n hasController: !!abortControllerRef.current,\r\n });\r\n abortControllerRef.current.abort();\r\n abortControllerRef.current = null;\r\n setIsStreaming(false);\r\n chatLogger.debug(\"streaming stopped\");\r\n } else {\r\n chatLogger.trace(\"stop called — no active stream\");\r\n }\r\n }, [chatLogger]);\r\n\r\n const clear = useCallback(() => {\r\n chatLogger.info(\"clear chat\", { messageCount: messages.length });\r\n chatLogger.debug(\"clear\", { messageCount: messages.length });\r\n stop();\r\n setMessages([]);\r\n setError(null);\r\n setInterrupt(null);\r\n setFiles({});\r\n setTodos([]);\r\n setPresentedFile(null);\r\n }, [stop, chatLogger, messages.length]);\r\n\r\n const loadThreadMessages = useCallback(\r\n async (id: string) => {\r\n chatLogger.debug(\"loadThreadMessages start\", { threadId: id });\r\n chatLogger.trace(\"loadThreadMessages\", { threadId: id });\r\n setIsLoadingHistory(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(`/threads/${id}/messages`);\r\n if (!res.ok)\r\n throw new Error(`Failed to load thread history: ${res.statusText}`);\r\n const body = await res.json();\r\n const data = body?.data ?? body;\r\n const raw = (data?.messages ?? []) as Array<{\r\n id?: string;\r\n role: PersonaMessage[\"role\"];\r\n content: string;\r\n toolCalls?: PersonaToolCall[];\r\n }>;\r\n const subagentTraces = (data?.subagentTraces ?? {}) as Record<\r\n string,\r\n PersistedSubagentTraceItem[]\r\n >;\r\n const loaded: PersonaMessage[] = raw.map((m, i) => ({\r\n id: m.id || `history-${id}-${i}`,\r\n role: m.role,\r\n content: m.content,\r\n createdAt: new Date(),\r\n toolCalls: m.toolCalls?.map((tc) => {\r\n const trace = subagentTraces[tc.toolCallId];\r\n return Array.isArray(trace) && trace.length > 0\r\n ? {\r\n ...tc,\r\n subagentActivity: persistedTraceToActivityEntries(trace),\r\n }\r\n : tc;\r\n }),\r\n }));\r\n setMessages(loaded);\r\n // Re-show the approval/clarification card on reload if this thread\r\n // is currently paused — otherwise it wouldn't reappear until the\r\n // next live stream re-surfaces it.\r\n setInterrupt(normalizePendingInterrupt(data?.pendingInterrupt));\r\n // Restore the workspace files/todos this thread already had (same\r\n // cleaned shape checkpoint.service.js now derives via\r\n // buildFilesTodosSnapshot, matching the live STATE_SNAPSHOT event).\r\n setFiles(normalizeWorkspaceFiles(data?.state?.files ?? {}));\r\n setTodos((data?.state?.todos ?? []) as PersonaTodo[]);\r\n chatLogger.info(\"loadThreadMessages succeeded\", {\r\n threadId: id,\r\n messageCount: loaded.length,\r\n });\r\n chatLogger.debug(\"loadThreadMessages completed\", {\r\n threadId: id,\r\n messageCount: loaded.length,\r\n });\r\n return loaded;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n chatLogger.warn(\"loadThreadMessages failed\", {\r\n threadId: id,\r\n error: errorObj.message,\r\n });\r\n chatLogger.error(\"loadThreadMessages error\", {\r\n threadId: id,\r\n error: errorObj.message,\r\n });\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoadingHistory(false);\r\n chatLogger.trace(\"loadThreadMessages end\", { threadId: id });\r\n }\r\n },\r\n [fetchWithAuth, chatLogger],\r\n );\r\n\r\n // Auto-load history the first time a thread with no in-memory messages is\r\n // selected (switching threads in the sidebar). Skipped for a thread whose\r\n // messages already live in state — e.g. one just created by handleSend,\r\n // which sets its placeholder messages in the same render batch as the\r\n // threadId change, so `messages` there is never empty at effect time.\r\n useEffect(() => {\r\n if (!threadId || isStreaming) {\r\n chatLogger.trace(\"auto-load skipped\", { threadId, isStreaming });\r\n return;\r\n }\r\n if (loadedThreadIdRef.current === threadId) {\r\n chatLogger.trace(\"auto-load already loaded\", { threadId });\r\n return;\r\n }\r\n if (messages.length > 0) {\r\n chatLogger.trace(\"auto-load has messages\", {\r\n threadId,\r\n count: messages.length,\r\n });\r\n return;\r\n }\r\n loadedThreadIdRef.current = threadId;\r\n chatLogger.info(\"auto-load thread history\", { threadId });\r\n chatLogger.debug(\"loadThreadMessages trigger\", { threadId });\r\n void loadThreadMessages(threadId);\r\n }, [threadId, isStreaming, messages.length, loadThreadMessages, chatLogger]);\r\n\r\n // Merge a `useVoice()` session's live transcript into `messages` — see\r\n // `UseChatOptions.voice`. This replaces the hand-rolled sync effects the\r\n // README used to tell every consumer to write themselves (dedup against\r\n // thread history, merge same-speaker fragments into one bubble, update the\r\n // in-progress agent line in place, and not replay a call's old transcript\r\n // after a threadId switch under the same `useVoice()` instance).\r\n const voice = options.voice;\r\n useEffect(() => {\r\n if (!voice) return;\r\n\r\n // The passed useVoice() instance now targets a different thread (e.g. the\r\n // host app switched conversations without remounting either hook) — its\r\n // transcript belongs to a call that's over as far as this feed is\r\n // concerned. Stop injecting and don't let anything already spoken bleed\r\n // into the new thread's feed once a new call starts.\r\n if (voiceThreadRef.current !== threadId) {\r\n voiceThreadRef.current = threadId;\r\n voicePrevLenRef.current = voice.transcript.length;\r\n voiceStreamingIdRef.current = null;\r\n return;\r\n }\r\n\r\n const isVoiceActive =\r\n voice.state !== \"idle\" && voice.state !== \"ended\" && voice.state !== \"error\";\r\n const curLen = voice.transcript.length;\r\n\r\n // start() resets transcript to [] for a fresh call — realign the cursor.\r\n if (curLen < voicePrevLenRef.current) {\r\n voicePrevLenRef.current = 0;\r\n voiceStreamingIdRef.current = null;\r\n }\r\n\r\n if (!isVoiceActive) {\r\n // Not on a call: keep the cursor aligned to whatever's in transcript\r\n // (thread-reload growth must not be replayed as a live inject later),\r\n // and settle any streaming voice bubble left open from the last call.\r\n voicePrevLenRef.current = voice.transcript.length;\r\n if (voiceStreamingIdRef.current) {\r\n const doneId = voiceStreamingIdRef.current;\r\n voiceStreamingIdRef.current = null;\r\n setMessages((prev) =>\r\n prev.map((m) => (m.id === doneId ? { ...m, isStreaming: false } : m)),\r\n );\r\n }\r\n return;\r\n }\r\n\r\n if (curLen > voicePrevLenRef.current) {\r\n const newLines = voice.transcript.slice(voicePrevLenRef.current);\r\n voicePrevLenRef.current = curLen;\r\n for (const line of newLines) {\r\n const text = (line.text || \"\").trim();\r\n if (!text) continue;\r\n const role: PersonaRole = line.speaker === \"user\" ? \"user\" : \"assistant\";\r\n const voiceId = `voice-${line.id}`;\r\n setMessages((prev) => {\r\n // Already injected this exact line.\r\n if (prev.some((m) => m.id === voiceId)) return prev;\r\n // Already on the thread as a persisted turn (voice shares the\r\n // thread, so a refresh/reload can already hold it).\r\n if (\r\n prev.some(\r\n (m) =>\r\n !m.id.startsWith(\"voice-\") &&\r\n m.role === role &&\r\n m.content.trim() === text,\r\n )\r\n )\r\n return prev;\r\n const last = prev[prev.length - 1];\r\n // Consecutive agent finals of one spoken answer merge into the\r\n // bubble they opened, same as useVoice() does for `transcript`\r\n // itself — mirrors how the thread coalesces them on reload.\r\n if (last?.id.startsWith(\"voice-\") && last.role === \"assistant\" && role === \"assistant\") {\r\n const merged = text.startsWith(last.content)\r\n ? text\r\n : `${last.content} ${text}`.trim();\r\n return [...prev.slice(0, -1), { ...last, content: merged, isStreaming: false }];\r\n }\r\n return [...prev, { id: voiceId, role, content: text, createdAt: new Date() }];\r\n });\r\n }\r\n }\r\n\r\n // Live partial (agent mid-utterance) — update the open streaming bubble\r\n // in place, matching the assistant-message streaming UX text chat gets.\r\n const partialText = voice.partial?.speaker === \"agent\" ? voice.partial.text.trim() : \"\";\r\n if (partialText) {\r\n setMessages((prev) => {\r\n const last = prev[prev.length - 1];\r\n if (last?.id.startsWith(\"voice-\") && last.role === \"assistant\") {\r\n voiceStreamingIdRef.current = last.id;\r\n return [...prev.slice(0, -1), { ...last, content: partialText, isStreaming: true }];\r\n }\r\n const id = voiceStreamingIdRef.current || `voice-partial-${Date.now()}`;\r\n voiceStreamingIdRef.current = id;\r\n return [...prev, { id, role: \"assistant\", content: partialText, isStreaming: true, createdAt: new Date() }];\r\n });\r\n } else if (voice.state !== \"speaking\" && voiceStreamingIdRef.current) {\r\n const doneId = voiceStreamingIdRef.current;\r\n voiceStreamingIdRef.current = null;\r\n setMessages((prev) =>\r\n prev.map((m) => (m.id === doneId ? { ...m, isStreaming: false } : m)),\r\n );\r\n }\r\n // `voice` itself isn't a dep — useVoice() returns a fresh object every\r\n // render, so keying off it would re-run this every render regardless of\r\n // whether the transcript actually changed.\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [voice?.transcript, voice?.partial, voice?.state, threadId]);\r\n\r\n const sendMessage = useCallback(\r\n async (contentToSend?: string, overrideOptions?: SendMessageOverride) => {\r\n const prompt = (contentToSend ?? input).trim();\r\n if (!prompt || isStreaming) {\r\n chatLogger.trace(\"sendMessage skipped\", {\r\n hasPrompt: !!prompt,\r\n isStreaming,\r\n });\r\n return;\r\n }\r\n\r\n const targetAgentId = overrideOptions?.agentId || agentId;\r\n if (!targetAgentId) {\r\n const err = new Error(\"No Agent ID specified for useChat.\");\r\n chatLogger.warn(\"sendMessage no agentId\", {});\r\n chatLogger.error(\"sendMessage failed — no agent\", {\r\n error: err.message,\r\n });\r\n setError(err);\r\n options.onError?.(err);\r\n return;\r\n }\r\n\r\n chatLogger.debug(\"sendMessage start\", {\r\n promptPreview: prompt.slice(0, 100),\r\n agentId: targetAgentId,\r\n threadId: threadId ?? (overrideOptions?.threadId as string | undefined),\r\n hasResume: !!overrideOptions?.resume,\r\n hasContextOverride: !!overrideOptions?.contextOverride,\r\n messageCount: messages.length,\r\n });\r\n chatLogger.trace(\"sendMessage details\", {\r\n agentId: targetAgentId,\r\n promptPreview: prompt.slice(0, 200),\r\n hasResume: !!overrideOptions?.resume,\r\n hasContextOverride: !!overrideOptions?.contextOverride,\r\n });\r\n\r\n const userMessage: PersonaMessage = {\r\n id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\r\n role: \"user\",\r\n content: prompt,\r\n createdAt: new Date(),\r\n };\r\n\r\n const assistantMessageId = `assistant-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\r\n const placeholderAssistant: PersonaMessage = {\r\n id: assistantMessageId,\r\n role: \"assistant\",\r\n content: \"\",\r\n createdAt: new Date(),\r\n isStreaming: true,\r\n toolCalls: [],\r\n };\r\n\r\n const nextMessages = [...messages, userMessage];\r\n setMessages([...nextMessages, placeholderAssistant]);\r\n setInput(\"\");\r\n setIsStreaming(true);\r\n setError(null);\r\n setInterrupt(null);\r\n\r\n const controller = new AbortController();\r\n abortControllerRef.current = controller;\r\n\r\n // Marks any reasoning message still flagged streaming as done — for\r\n // runs that end (abort/error) without a final REASONING_END. Declared\r\n // outside the try so the finally block can reach it.\r\n const finalizeReasoning = () => {\r\n setMessages((prev) =>\r\n prev.map((m) =>\r\n m.role === \"reasoning\" && m.isStreaming\r\n ? { ...m, isStreaming: false }\r\n : m,\r\n ),\r\n );\r\n };\r\n\r\n try {\r\n // Reasoning messages are ephemeral client-side thoughts — never part\r\n // of the transcript sent back to the server (the backend already has\r\n // its own persisted copy and would treat them as user turns).\r\n const payloadMessages = nextMessages\r\n .filter((m) => m.role !== \"reasoning\")\r\n .map((m) => ({\r\n role:\r\n m.role === \"assistant\"\r\n ? (\"assistant\" as const)\r\n : (\"user\" as const),\r\n content: m.content,\r\n }));\r\n\r\n // Resolved here, not earlier — everything above this line (the\r\n // optimistic message + placeholder, clearing input, etc.) already\r\n // ran synchronously, so a caller passing an in-flight thread-creation\r\n // promise gets an instant UI update without the message send itself\r\n // waiting on it any longer than the network call already would.\r\n const resolvedThreadId = await (overrideOptions?.threadId ??\r\n options.threadId);\r\n chatLogger.trace(\"resolved threadId\", { threadId: resolvedThreadId });\r\n\r\n // openSSEStream, not fetchWithAuth: the transport has to be chosen\r\n // before the request goes out. React Native's fetch never populates\r\n // response.body and only settles once the whole response has arrived,\r\n // so discovering the missing body afterwards would already have cost\r\n // us the stream. See src/streaming.ts.\r\n const token = getAuthToken ? await getAuthToken() : null;\r\n // Resolved here, at send-time — a getter always reads the host\r\n // app's *current* state (e.g. \"which page is open\") with no ref or\r\n // effect needed to keep it fresh. Call-level override wins on key\r\n // collisions. Omitted from the body entirely when empty, rather\r\n // than sending `context: {}` on every turn.\r\n const resolvedHookContext =\r\n typeof options.context === \"function\" ? options.context() : options.context;\r\n const mergedContext = { ...resolvedHookContext, ...overrideOptions?.context };\r\n const hasContext = Object.keys(mergedContext).length > 0;\r\n chatLogger.debug(\"opening SSE stream\", {\r\n agentId: targetAgentId,\r\n hasToken: !!token,\r\n hasThreadId: !!resolvedThreadId,\r\n hasContext,\r\n });\r\n const stream = await openSSEStream({\r\n url: `${baseUrl}/chat`,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\r\n },\r\n body: JSON.stringify({\r\n agentId: targetAgentId,\r\n messages: payloadMessages,\r\n threadId: resolvedThreadId,\r\n resume: overrideOptions?.resume,\r\n contextOverride: overrideOptions?.contextOverride,\r\n ...(hasContext ? { context: mergedContext } : {}),\r\n }),\r\n signal: controller.signal,\r\n });\r\n\r\n if (!stream.ok) {\r\n chatLogger.warn(\"SSE stream not ok\", {\r\n status: stream.status,\r\n errorText: stream.errorText,\r\n });\r\n chatLogger.error(\"chat stream failed\", {\r\n agentId: targetAgentId,\r\n status: stream.status,\r\n error: stream.errorText,\r\n });\r\n throw new Error(\r\n `Chat error (${stream.status}): ${stream.errorText ?? \"Stream failed\"}`,\r\n );\r\n }\r\n chatLogger.debug(\"SSE stream opened\", {\r\n agentId: targetAgentId,\r\n status: stream.status,\r\n });\r\n chatLogger.info(\"chat stream started\", {\r\n agentId: targetAgentId,\r\n threadId: resolvedThreadId,\r\n });\r\n\r\n const reader = stream.reader;\r\n let buffer = \"\";\r\n let accumulatedText = \"\";\r\n const toolCallsMap = new Map<string, PersonaToolCall>();\r\n // Reasoning streams as its own `role: 'reasoning'` message per phase\r\n // (REASONING_MESSAGE_START … CONTENT … REASONING_END), never merged\r\n // into the assistant message or into a single accumulated blob —\r\n // mirrors the web timeline where each phase is a separate \"Thoughts\"\r\n // bubble. Each phase's message is inserted directly above the assistant\r\n // message so thoughts render above the answer, not underneath it.\r\n //\r\n // A monotonic counter shared by reasoning phases AND tool calls stamps\r\n // each with a `seq` in stream order (the backend emits REASONING_END\r\n // right before the next TOOL_CALL_CHUNK, then the next phase after the\r\n // result). Clients sort by it to interleave thoughts and tool calls\r\n // chronologically instead of stacking all thoughts above the answer.\r\n let streamSeq = 0;\r\n let activeReasoningId: string | null = null;\r\n const reasoningById = new Map<string, { content: string }>();\r\n\r\n const patchAssistant = (patch: Partial<PersonaMessage>) => {\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId\r\n ? {\r\n ...msg,\r\n toolCalls: Array.from(toolCallsMap.values()),\r\n ...patch,\r\n }\r\n : msg,\r\n ),\r\n );\r\n };\r\n\r\n const insertReasoningMessage = (id: string, seq: number) => {\r\n const msg: PersonaMessage = {\r\n id,\r\n role: \"reasoning\",\r\n content: \"\",\r\n createdAt: new Date(),\r\n isStreaming: true,\r\n seq,\r\n };\r\n setMessages((prev) => {\r\n const idx = prev.findIndex((m) => m.id === assistantMessageId);\r\n if (idx === -1) return [...prev, msg];\r\n const next = [...prev];\r\n next.splice(idx, 0, msg);\r\n return next;\r\n });\r\n };\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n\r\n buffer += value ?? \"\";\r\n const lines = buffer.split(\"\\n\");\r\n buffer = lines.pop() ?? \"\";\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || !trimmed.startsWith(\"data:\")) continue;\r\n\r\n const raw = trimmed.replace(/^data:\\s*/, \"\");\r\n if (raw === \"[DONE]\") break;\r\n\r\n try {\r\n const event = JSON.parse(raw) as PersonaStreamingEvent;\r\n chatLogger.trace(\"stream event\", { type: event.type, event });\r\n options.onEvent?.(event);\r\n\r\n if (event.type === \"TEXT_MESSAGE_CHUNK\" && event.delta) {\r\n chatLogger.debug(\"text chunk\", {\r\n deltaLength: event.delta.length,\r\n });\r\n accumulatedText += event.delta;\r\n patchAssistant({ content: accumulatedText, isStreaming: true });\r\n } else if (event.type === \"TOOL_CALL_CHUNK\" && event.toolCallId) {\r\n chatLogger.debug(\"tool call chunk\", {\r\n toolCallId: event.toolCallId,\r\n toolCallName: event.toolCallName,\r\n });\r\n // The backend streams tool calls as accumulating chunks\r\n // (id/name arrive on the first chunk, args stream in pieces\r\n // across subsequent ones) rather than separate start/args\r\n // events.\r\n const existing = toolCallsMap.get(event.toolCallId);\r\n if (existing) {\r\n existing.args = (existing.args || \"\") + (event.delta || \"\");\r\n } else {\r\n toolCallsMap.set(event.toolCallId, {\r\n toolCallId: event.toolCallId,\r\n toolName: event.toolCallName || \"\",\r\n args: event.delta || \"\",\r\n seq: streamSeq++,\r\n });\r\n }\r\n patchAssistant({});\r\n } else if (event.type === \"TOOL_CALL_RESULT\") {\r\n chatLogger.debug(\"tool call result\", {\r\n toolCallId: event.toolCallId,\r\n });\r\n const existing = toolCallsMap.get(event.toolCallId);\r\n if (existing) {\r\n existing.result = event.content;\r\n existing.isError = isErrorToolContent(event.content);\r\n if (existing.isError)\r\n chatLogger.warn(\"tool call error\", {\r\n toolCallId: event.toolCallId,\r\n });\r\n if (\r\n existing.toolName === \"present_file\" &&\r\n !existing.isError\r\n ) {\r\n const presented = parsePresentedFile(event.content);\r\n if (presented) {\r\n chatLogger.info(\"present_file\", { path: presented.path });\r\n setPresentedFile(presented);\r\n }\r\n }\r\n patchAssistant({});\r\n }\r\n } else if (event.type === \"STATE_SNAPSHOT\") {\r\n chatLogger.debug(\"state snapshot\", {\r\n fileCount: Object.keys(event.snapshot.files ?? {}).length,\r\n todoCount: event.snapshot.todos?.length ?? 0,\r\n });\r\n setFiles(normalizeWorkspaceFiles(event.snapshot.files));\r\n setTodos(event.snapshot.todos);\r\n } else if (\r\n event.type === \"REASONING_MESSAGE_START\" &&\r\n event.messageId\r\n ) {\r\n chatLogger.debug(\"reasoning start\", {\r\n messageId: event.messageId,\r\n });\r\n // A fresh reasoning phase — its own message, regardless of how\r\n // many phases this run produces. seq stamps it into stream\r\n // order against the tool calls it brackets.\r\n activeReasoningId = event.messageId;\r\n reasoningById.set(event.messageId, { content: \"\" });\r\n insertReasoningMessage(event.messageId, streamSeq++);\r\n } else if (event.type === \"REASONING_MESSAGE_CONTENT\") {\r\n // Defensive: if the backend ever skips REASONING_MESSAGE_START,\r\n // lazily open the message on the first content chunk.\r\n let rid: string = event.messageId || activeReasoningId || \"\";\r\n if (!rid || !reasoningById.has(rid)) {\r\n rid =\r\n rid ||\r\n `reasoning-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\r\n activeReasoningId = rid;\r\n reasoningById.set(rid, { content: \"\" });\r\n insertReasoningMessage(rid, streamSeq++);\r\n chatLogger.debug(\"reasoning lazy start\", { messageId: rid });\r\n }\r\n const entry = reasoningById.get(rid)!;\r\n entry.content += event.delta;\r\n chatLogger.trace(\"reasoning content\", {\r\n messageId: rid,\r\n deltaLength: event.delta?.length ?? 0,\r\n });\r\n setMessages((prev) =>\r\n prev.map((m) =>\r\n m.id === rid\r\n ? { ...m, content: entry.content, isStreaming: true }\r\n : m,\r\n ),\r\n );\r\n } else if (event.type === \"REASONING_END\") {\r\n chatLogger.debug(\"reasoning end\", {\r\n messageId: activeReasoningId,\r\n });\r\n const rid = activeReasoningId;\r\n activeReasoningId = null;\r\n if (rid) {\r\n setMessages((prev) =>\r\n prev.map((m) =>\r\n m.id === rid ? { ...m, isStreaming: false } : m,\r\n ),\r\n );\r\n }\r\n } else if (event.type === \"CUSTOM\") {\r\n chatLogger.debug(\"custom event\", { name: event.name });\r\n if (event.name === \"hitl_request\") {\r\n const value = event.value as Extract<\r\n PersonaInterrupt,\r\n { kind: \"hitl\" }\r\n >;\r\n chatLogger.info(\"hitl interrupt\", {\r\n actionCount: value.actionRequests?.length ?? 0,\r\n });\r\n setInterrupt({\r\n kind: \"hitl\",\r\n actionRequests: value.actionRequests,\r\n reviewConfigs: value.reviewConfigs,\r\n });\r\n } else if (event.name === \"clarification_request\") {\r\n const value = event.value as Extract<\r\n PersonaInterrupt,\r\n { kind: \"clarification\" }\r\n >;\r\n chatLogger.info(\"clarification interrupt\", {\r\n questionCount: value.questions?.length ?? 0,\r\n });\r\n setInterrupt({\r\n kind: \"clarification\",\r\n questions: value.questions,\r\n });\r\n } else if (event.name === \"subagent_activity\") {\r\n const { toolCallId, ...entry } = event.value as {\r\n toolCallId: string;\r\n } & PersonaSubagentActivityEntry;\r\n chatLogger.trace(\"subagent activity\", {\r\n toolCallId,\r\n kind: entry.kind,\r\n });\r\n const existing = toolCallsMap.get(toolCallId);\r\n if (existing) {\r\n existing.subagentActivity = [\r\n ...(existing.subagentActivity || []),\r\n entry,\r\n ];\r\n patchAssistant({});\r\n }\r\n }\r\n // 'mcp_app' custom events carry no chat-transcript UI here —\r\n // consumers that render MCP widgets read them via onEvent.\r\n } else if (event.type === \"RUN_ERROR\") {\r\n chatLogger.warn(\"run error\", {\r\n message: event.message,\r\n code: event.code,\r\n });\r\n chatLogger.error(\"stream run error\", {\r\n code: event.code,\r\n message: event.message,\r\n });\r\n throw new Error(event.message || \"Stream error from agent\");\r\n } else {\r\n chatLogger.trace(\"unhandled event\", { type: event.type });\r\n }\r\n } catch (e) {\r\n if (e instanceof Error && e.message.startsWith(\"Stream error\")) {\r\n throw e;\r\n }\r\n chatLogger.warn(\"event parse error\", {\r\n raw: raw.slice(0, 200),\r\n error: e instanceof Error ? e.message : String(e),\r\n });\r\n }\r\n }\r\n }\r\n\r\n const finalMessage: PersonaMessage = {\r\n id: assistantMessageId,\r\n role: \"assistant\",\r\n content: accumulatedText,\r\n createdAt: new Date(),\r\n isStreaming: false,\r\n toolCalls: Array.from(toolCallsMap.values()),\r\n };\r\n\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId ? finalMessage : msg,\r\n ),\r\n );\r\n\r\n chatLogger.info(\"sendMessage succeeded\", {\r\n agentId: targetAgentId,\r\n textLength: accumulatedText.length,\r\n toolCallCount: toolCallsMap.size,\r\n });\r\n chatLogger.debug(\"sendMessage completed\", {\r\n agentId: targetAgentId,\r\n textLength: accumulatedText.length,\r\n eventCount: toolCallsMap.size + 1,\r\n });\r\n options.onFinish?.(finalMessage);\r\n } catch (err) {\r\n if (controller.signal.aborted) {\r\n chatLogger.info(\"sendMessage aborted\", { agentId: targetAgentId });\r\n chatLogger.debug(\"stream aborted\", { agentId: targetAgentId });\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId\r\n ? { ...msg, isStreaming: false }\r\n : msg,\r\n ),\r\n );\r\n return;\r\n }\r\n\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n chatLogger.warn(\"sendMessage failed\", {\r\n agentId: targetAgentId,\r\n error: errorObj.message,\r\n });\r\n chatLogger.error(\"sendMessage error\", {\r\n agentId: targetAgentId,\r\n error: errorObj.message,\r\n });\r\n setError(errorObj);\r\n options.onError?.(errorObj);\r\n\r\n setMessages((prev) =>\r\n prev.map((msg) =>\r\n msg.id === assistantMessageId\r\n ? {\r\n ...msg,\r\n content:\r\n msg.content ||\r\n `⚠️ Error: ${errorObj.message || \"Failed to get response.\"}`,\r\n isStreaming: false,\r\n }\r\n : msg,\r\n ),\r\n );\r\n } finally {\r\n setIsStreaming(false);\r\n abortControllerRef.current = null;\r\n // A run that ends without a final REASONING_END (abort, error) must\r\n // still flip its in-flight reasoning messages to done.\r\n finalizeReasoning();\r\n chatLogger.debug(\"sendMessage finally\", {\r\n agentId: targetAgentId,\r\n isStreaming: false,\r\n });\r\n chatLogger.trace(\"sendMessage end\", { agentId: targetAgentId });\r\n }\r\n },\r\n [\r\n agentId,\r\n baseUrl,\r\n getAuthToken,\r\n input,\r\n isStreaming,\r\n messages,\r\n options,\r\n chatLogger,\r\n threadId,\r\n ],\r\n );\r\n\r\n const handleInputChange = useCallback(\r\n (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\r\n chatLogger.trace(\"handleInputChange\", { length: e.target.value.length });\r\n setInput(e.target.value);\r\n },\r\n [chatLogger],\r\n );\r\n\r\n const handleSubmit = useCallback(\r\n (e?: React.FormEvent) => {\r\n if (e) e.preventDefault();\r\n chatLogger.debug(\"handleSubmit\", {});\r\n void sendMessage();\r\n },\r\n [sendMessage, chatLogger],\r\n );\r\n\r\n const reload = useCallback(() => {\r\n if (messages.length === 0 || isStreaming) {\r\n chatLogger.trace(\"reload skipped\", {\r\n messageCount: messages.length,\r\n isStreaming,\r\n });\r\n return;\r\n }\r\n let lastUserIndex = -1;\r\n for (let i = messages.length - 1; i >= 0; i--) {\r\n if (messages[i].role === \"user\") {\r\n lastUserIndex = i;\r\n break;\r\n }\r\n }\r\n if (lastUserIndex === -1) {\r\n chatLogger.warn(\"reload no user message\", {});\r\n return;\r\n }\r\n\r\n const lastUserMessage = messages[lastUserIndex];\r\n chatLogger.info(\"reload\", { messageId: lastUserMessage.id });\r\n chatLogger.debug(\"reload last user\", {\r\n preview: lastUserMessage.content.slice(0, 100),\r\n });\r\n setMessages(messages.slice(0, lastUserIndex));\r\n void sendMessage(lastUserMessage.content);\r\n }, [isStreaming, messages, sendMessage, chatLogger]);\r\n\r\n // Unpauses a paused HITL/clarification run. `displayContent` becomes the\r\n // visible user-turn bubble (e.g. \"Approved\", or the typed clarification\r\n // answer) — the server resolves the actual resume value from `resume`\r\n // itself, `displayContent` is only ever used for its own transcript text.\r\n const resumeInterrupt = useCallback(\r\n (resume: PersonaResumeValue, displayContent: string) => {\r\n chatLogger.info(\"resumeInterrupt\", {\r\n kind: (resume as { decisions?: unknown[] }).decisions\r\n ? \"hitl\"\r\n : \"clarification\",\r\n preview: displayContent.slice(0, 50),\r\n });\r\n return sendMessage(displayContent, { resume });\r\n },\r\n [sendMessage, chatLogger],\r\n );\r\n\r\n const dismissPresentedFile = useCallback(() => {\r\n chatLogger.debug(\"dismissPresentedFile\", {});\r\n setPresentedFile(null);\r\n }, [chatLogger]);\r\n\r\n // Manually re-open a workspace file — e.g. a present_file tool card's\r\n // \"Open\" button, after the auto-opened drawer was closed or a different\r\n // file was selected since.\r\n const openWorkspaceFile = useCallback(\r\n (path: string) => {\r\n chatLogger.debug(\"openWorkspaceFile\", { path });\r\n setPresentedFile({\r\n path,\r\n title: path.split(\"/\").pop() || path,\r\n description: \"\",\r\n });\r\n },\r\n [chatLogger],\r\n );\r\n\r\n return {\r\n messages,\r\n input,\r\n setInput,\r\n handleInputChange,\r\n handleSubmit,\r\n sendMessage,\r\n isStreaming,\r\n isLoading: isStreaming,\r\n isLoadingHistory,\r\n error,\r\n interrupt,\r\n resumeInterrupt,\r\n files,\r\n todos,\r\n presentedFile,\r\n dismissPresentedFile,\r\n openWorkspaceFile,\r\n stop,\r\n reload,\r\n clear,\r\n setMessages,\r\n loadThreadMessages,\r\n };\r\n}\r\n","/**\r\n * SSE transport for chat streams, with a React Native fallback.\r\n *\r\n * On the web, `fetch` gives a streaming `response.body` and we read it with a\r\n * ReadableStream reader. React Native's `fetch` is the whatwg-fetch polyfill\r\n * over XMLHttpRequest: `response.body` is `undefined`, and the promise only\r\n * settles once the entire response has arrived. That means the check cannot be\r\n * \"call fetch, then see whether body exists\" - by that point the whole stream\r\n * has already been buffered and the chance to stream is gone. The transport has\r\n * to be chosen *before* the request is made.\r\n *\r\n * XMLHttpRequest itself does stream everywhere React Native runs: it appends to\r\n * `responseText` and fires `readyState === 3` (LOADING) on every chunk, which is\r\n * all an SSE consumer needs. So the RN path issues the request over raw XHR and\r\n * hands back the same reader interface the fetch path does, leaving callers\r\n * unaware of which one they got.\r\n */\r\n\r\n/** Minimal reader interface, mirroring the shape of a ReadableStream reader. */\r\nexport interface SSEReader {\r\n /** Resolves with the next decoded chunk, or `{ done: true }` at end of stream. */\r\n read(): Promise<{ done: boolean; value?: string }>;\r\n /** Aborts the underlying request. */\r\n cancel(): void;\r\n}\r\n\r\nexport interface SSEStream {\r\n status: number;\r\n ok: boolean;\r\n getHeader(name: string): string | null;\r\n /** Present only when `ok` is false, so callers can surface the server's message. */\r\n errorText?: string;\r\n reader: SSEReader;\r\n}\r\n\r\nexport interface OpenSSEOptions {\r\n url: string;\r\n headers: Record<string, string>;\r\n body: string;\r\n signal?: AbortSignal;\r\n}\r\n\r\n/**\r\n * Whether `fetch` on this platform yields a streaming body.\r\n *\r\n * `navigator.product === 'ReactNative'` is the long-standing marker React\r\n * Native sets, and is checked rather than feature-detecting `ReadableStream`:\r\n * newer RN versions do expose a global `ReadableStream` while still leaving\r\n * `response.body` undefined, so the presence of the type says nothing about\r\n * whether fetch will populate it.\r\n */\r\nexport function supportsStreamingFetch(): boolean {\r\n if (\r\n typeof navigator !== \"undefined\" &&\r\n (navigator as { product?: string }).product === \"ReactNative\"\r\n ) {\r\n return false;\r\n }\r\n return typeof fetch !== \"undefined\" && typeof ReadableStream !== \"undefined\";\r\n}\r\n\r\n/** Wraps a whatwg ReadableStream reader so it decodes to strings. */\r\nfunction fetchReader(\r\n response: Response,\r\n controller: AbortController,\r\n): SSEReader {\r\n const reader = response.body!.getReader();\r\n const decoder = new TextDecoder(\"utf-8\");\r\n\r\n return {\r\n async read() {\r\n const { done, value } = await reader.read();\r\n if (done) return { done: true };\r\n return { done: false, value: decoder.decode(value, { stream: true }) };\r\n },\r\n cancel() {\r\n controller.abort();\r\n void reader.cancel().catch(() => {});\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Issues the request over XMLHttpRequest and exposes new text as it arrives.\r\n *\r\n * XHR keeps the whole response in `responseText` and only ever appends, so each\r\n * chunk is the slice past what has already been handed out.\r\n */\r\nfunction xhrStream(opts: OpenSSEOptions): Promise<SSEStream> {\r\n return new Promise<SSEStream>((resolveStream, rejectStream) => {\r\n const xhr = new XMLHttpRequest();\r\n xhr.open(\"POST\", opts.url);\r\n for (const [key, val] of Object.entries(opts.headers))\r\n xhr.setRequestHeader(key, val);\r\n\r\n let consumed = 0;\r\n let finished = false;\r\n let failure: Error | null = null;\r\n // Chunks that arrived before the consumer asked for them, and the pending\r\n // read waiting for one - only one of the two is ever non-empty.\r\n const queue: string[] = [];\r\n let waiting: ((r: { done: boolean; value?: string }) => void) | null = null;\r\n let waitingReject: ((e: Error) => void) | null = null;\r\n let headersResolved = false;\r\n\r\n const pump = () => {\r\n const text = xhr.responseText;\r\n if (text.length <= consumed) return;\r\n const chunk = text.slice(consumed);\r\n consumed = text.length;\r\n\r\n if (waiting) {\r\n const resolve = waiting;\r\n waiting = null;\r\n waitingReject = null;\r\n resolve({ done: false, value: chunk });\r\n } else {\r\n queue.push(chunk);\r\n }\r\n };\r\n\r\n const finish = (err?: Error) => {\r\n if (finished) return;\r\n finished = true;\r\n failure = err ?? null;\r\n if (waiting) {\r\n const resolve = waiting;\r\n const reject = waitingReject;\r\n waiting = null;\r\n waitingReject = null;\r\n if (err && reject) reject(err);\r\n else resolve({ done: true });\r\n }\r\n };\r\n\r\n const reader: SSEReader = {\r\n read() {\r\n if (queue.length > 0) {\r\n return Promise.resolve({ done: false, value: queue.shift() });\r\n }\r\n if (finished) {\r\n return failure\r\n ? Promise.reject(failure)\r\n : Promise.resolve({ done: true });\r\n }\r\n return new Promise((resolve, reject) => {\r\n waiting = resolve;\r\n waitingReject = reject;\r\n });\r\n },\r\n cancel() {\r\n finish();\r\n xhr.abort();\r\n },\r\n };\r\n\r\n // Headers are available from readyState 2, which is what lets a non-2xx\r\n // response be reported without waiting for the body to finish.\r\n const resolveHeaders = () => {\r\n if (headersResolved) return;\r\n headersResolved = true;\r\n const ok = xhr.status >= 200 && xhr.status < 300;\r\n resolveStream({\r\n status: xhr.status,\r\n ok,\r\n getHeader: (name: string) => xhr.getResponseHeader(name),\r\n reader,\r\n });\r\n };\r\n\r\n xhr.onreadystatechange = () => {\r\n if (xhr.readyState === 2) {\r\n resolveHeaders();\r\n } else if (xhr.readyState === 3) {\r\n resolveHeaders();\r\n pump();\r\n } else if (xhr.readyState === 4) {\r\n resolveHeaders();\r\n pump();\r\n finish();\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n const err = new Error(\"Network request failed\");\r\n if (!headersResolved) rejectStream(err);\r\n finish(err);\r\n };\r\n xhr.ontimeout = () => {\r\n const err = new Error(\"Network request timed out\");\r\n if (!headersResolved) rejectStream(err);\r\n finish(err);\r\n };\r\n\r\n if (opts.signal) {\r\n if (opts.signal.aborted) {\r\n xhr.abort();\r\n finish();\r\n } else {\r\n opts.signal.addEventListener(\"abort\", () => {\r\n finish();\r\n xhr.abort();\r\n });\r\n }\r\n }\r\n\r\n xhr.send(opts.body);\r\n });\r\n}\r\n\r\n/**\r\n * Opens an SSE stream, using whichever transport this platform can stream over.\r\n */\r\nexport async function openSSEStream(opts: OpenSSEOptions): Promise<SSEStream> {\r\n if (!supportsStreamingFetch()) {\r\n return xhrStream(opts);\r\n }\r\n\r\n const controller = new AbortController();\r\n if (opts.signal) {\r\n if (opts.signal.aborted) controller.abort();\r\n else opts.signal.addEventListener(\"abort\", () => controller.abort());\r\n }\r\n\r\n const response = await fetch(opts.url, {\r\n method: \"POST\",\r\n headers: opts.headers,\r\n body: opts.body,\r\n signal: controller.signal,\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text().catch(() => \"Stream failed\");\r\n return {\r\n status: response.status,\r\n ok: false,\r\n errorText,\r\n getHeader: (name: string) => response.headers.get(name),\r\n reader: {\r\n read: async () => ({ done: true }),\r\n cancel: () => controller.abort(),\r\n },\r\n };\r\n }\r\n\r\n if (!response.body) {\r\n // A streaming-capable platform that still gave no body - fall back to the\r\n // buffered text rather than failing outright.\r\n const text = await response.text();\r\n let handed = false;\r\n return {\r\n status: response.status,\r\n ok: true,\r\n getHeader: (name: string) => response.headers.get(name),\r\n reader: {\r\n read: async () =>\r\n handed\r\n ? { done: true }\r\n : ((handed = true), { done: false, value: text }),\r\n cancel: () => controller.abort(),\r\n },\r\n };\r\n }\r\n\r\n return {\r\n status: response.status,\r\n ok: true,\r\n getHeader: (name: string) => response.headers.get(name),\r\n reader: fetchReader(response, controller),\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport type { PersonaMemoryFile, PersonaMemoryList } from \"../types.js\";\r\n\r\nexport function useMemory(autoFetch = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [memory, setMemory] = useState<PersonaMemoryList>({\r\n userFiles: [],\r\n agentMemories: [],\r\n });\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchMemory = useCallback(async () => {\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(\"/memory\");\r\n if (!res.ok) {\r\n throw new Error(`Failed to fetch memory: ${res.statusText}`);\r\n }\r\n const data = (await res.json()) as PersonaMemoryList;\r\n setMemory(data);\r\n return data;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return { userFiles: [], agentMemories: [] };\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n const getFile = useCallback(\r\n async (params: {\r\n path: string;\r\n scope?: \"user\" | \"agent\";\r\n agentId?: string;\r\n }) => {\r\n const query = new URLSearchParams({ path: params.path });\r\n if (params.scope) query.set(\"scope\", params.scope);\r\n if (params.agentId) query.set(\"agentId\", params.agentId);\r\n\r\n const res = await fetchWithAuth(`/memory/file?${query.toString()}`);\r\n if (!res.ok)\r\n throw new Error(`Failed to get memory file: ${res.statusText}`);\r\n return (await res.json()) as PersonaMemoryFile;\r\n },\r\n [fetchWithAuth],\r\n );\r\n\r\n const writeFile = useCallback(\r\n async (params: {\r\n path: string;\r\n content: string;\r\n scope?: \"user\" | \"agent\";\r\n agentId?: string;\r\n }) => {\r\n const res = await fetchWithAuth(\"/memory/file\", {\r\n method: \"PUT\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(params),\r\n });\r\n if (!res.ok)\r\n throw new Error(`Failed to write memory file: ${res.statusText}`);\r\n const updated = (await res.json()) as PersonaMemoryFile;\r\n void fetchMemory();\r\n return updated;\r\n },\r\n [fetchWithAuth, fetchMemory],\r\n );\r\n\r\n const deleteFile = useCallback(\r\n async (params: {\r\n path: string;\r\n scope?: \"user\" | \"agent\";\r\n agentId?: string;\r\n }) => {\r\n const query = new URLSearchParams({ path: params.path });\r\n if (params.scope) query.set(\"scope\", params.scope);\r\n if (params.agentId) query.set(\"agentId\", params.agentId);\r\n\r\n const res = await fetchWithAuth(`/memory/file?${query.toString()}`, {\r\n method: \"DELETE\",\r\n });\r\n if (!res.ok)\r\n throw new Error(`Failed to delete memory file: ${res.statusText}`);\r\n void fetchMemory();\r\n },\r\n [fetchWithAuth, fetchMemory],\r\n );\r\n\r\n useEffect(() => {\r\n if (autoFetch) {\r\n void fetchMemory();\r\n }\r\n }, [autoFetch, fetchMemory]);\r\n\r\n return {\r\n memory,\r\n isLoading,\r\n error,\r\n refetch: fetchMemory,\r\n getFile,\r\n writeFile,\r\n deleteFile,\r\n };\r\n}\r\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\nimport type { PersonaThread } from \"../types.js\";\n\nexport function useThreads(autoFetch = true) {\n const { fetchWithAuth, defaultAgentId } = usePersonaContext();\n const [threads, setThreads] = useState<PersonaThread[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const fetchThreads = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const res = await fetchWithAuth(\"/threads\");\n if (!res.ok) throw new Error(`Failed to list threads: ${res.statusText}`);\n const data = await res.json();\n // Real shape is { items, pagination }. Bare array / `.data` / `.threads`\n // are defensive fallbacks for other deployments, not the actual contract.\n const items: PersonaThread[] = Array.isArray(data)\n ? data\n : data?.items ||\n data?.threads ||\n (Array.isArray(data?.data) ? data.data : undefined) ||\n [];\n setThreads(items);\n return items;\n } catch (err) {\n const errorObj = err instanceof Error ? err : new Error(String(err));\n setError(errorObj);\n return [];\n } finally {\n setIsLoading(false);\n }\n }, [fetchWithAuth]);\n\n const createThread = useCallback(\n async (agentId?: string) => {\n const targetAgentId = agentId || defaultAgentId;\n const res = await fetchWithAuth(\"/threads\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ agentId: targetAgentId }),\n });\n if (!res.ok)\n throw new Error(`Failed to create thread: ${res.statusText}`);\n const data = await res.json();\n const created = (data?.data ?? data) as PersonaThread;\n void fetchThreads();\n return created;\n },\n [fetchWithAuth, defaultAgentId, fetchThreads],\n );\n\n const deleteThread = useCallback(\n async (threadId: string) => {\n const res = await fetchWithAuth(`/threads/${threadId}`, {\n method: \"DELETE\",\n });\n if (!res.ok)\n throw new Error(`Failed to delete thread: ${res.statusText}`);\n setThreads((prev) => prev.filter((t) => t._id !== threadId));\n },\n [fetchWithAuth],\n );\n\n // Best-effort batch delete — no not-found id aborts the rest. Up to 100\n // ids per call, matching the server's own limit.\n const bulkDeleteThreads = useCallback(\n async (threadIds: string[]) => {\n const res = await fetchWithAuth(\"/threads/bulk-delete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ ids: threadIds }),\n });\n if (!res.ok)\n throw new Error(`Failed to bulk-delete threads: ${res.statusText}`);\n const data = await res.json();\n const result = (data?.data ?? data) as {\n deleted: string[];\n failed: Array<{ id: string; reason: string }>;\n };\n const deletedSet = new Set(result.deleted);\n setThreads((prev) => prev.filter((t) => !deletedSet.has(t._id)));\n return result;\n },\n [fetchWithAuth],\n );\n\n // Convenience wrapper: there is no server-side \"delete everything\"\n // endpoint, only bulk-delete-by-id — so this bulk-deletes every\n // currently-loaded thread (up to 100 per call, chunked if there are more).\n const deleteAllThreads = useCallback(async () => {\n const ids = threads.map((t) => t._id);\n for (let i = 0; i < ids.length; i += 100) {\n await bulkDeleteThreads(ids.slice(i, i + 100));\n }\n }, [threads, bulkDeleteThreads]);\n\n // General-purpose update — { title?, isArchived? }.\n const updateThread = useCallback(\n async (\n threadId: string,\n input: { title?: string; isArchived?: boolean },\n ) => {\n const res = await fetchWithAuth(`/threads/${threadId}`, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input),\n });\n if (!res.ok)\n throw new Error(`Failed to update thread: ${res.statusText}`);\n const data = await res.json();\n const updated = (data?.data ?? data) as PersonaThread;\n setThreads((prev) =>\n prev.map((t) => (t._id === threadId ? { ...t, ...updated } : t)),\n );\n return updated;\n },\n [fetchWithAuth],\n );\n\n const renameThread = useCallback(\n (threadId: string, title: string) => updateThread(threadId, { title }),\n [updateThread],\n );\n\n // Clears a thread's conversation content in place (message history, files/\n // todos, subagent traces) while keeping the same thread id/title — unlike\n // deleteThread, nothing about the thread's identity changes, so callers\n // can reuse it as a fresh conversation instead of creating a new one.\n const resetThread = useCallback(\n async (threadId: string) => {\n const res = await fetchWithAuth(`/threads/${threadId}/reset`, {\n method: \"POST\",\n });\n if (!res.ok) throw new Error(`Failed to reset thread: ${res.statusText}`);\n const data = await res.json();\n const reset = (data?.data ?? data) as PersonaThread;\n setThreads((prev) =>\n prev.map((t) => (t._id === threadId ? { ...t, ...reset } : t)),\n );\n return reset;\n },\n [fetchWithAuth],\n );\n\n const getThread = useCallback(\n async (threadId: string) => {\n const res = await fetchWithAuth(`/threads/${threadId}`);\n if (!res.ok) throw new Error(`Failed to fetch thread: ${res.statusText}`);\n const data = await res.json();\n return (data?.data ?? data) as PersonaThread;\n },\n [fetchWithAuth],\n );\n\n useEffect(() => {\n if (autoFetch) {\n void fetchThreads();\n }\n }, [autoFetch, fetchThreads]);\n\n return {\n threads,\n isLoading,\n error,\n refetch: fetchThreads,\n createThread,\n deleteThread,\n bulkDeleteThreads,\n deleteAllThreads,\n updateThread,\n renameThread,\n resetThread,\n getThread,\n };\n}\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport { recorderWorkletUrl, playerWorkletUrl } from \"./voiceWorklets.js\";\r\nimport type {\r\n PersonaVoiceEndReason,\r\n PersonaVoiceState,\r\n PersonaVoiceToolCall,\r\n PersonaVoiceTranscriptLine,\r\n UseVoiceOptions,\r\n UseVoiceResult,\r\n} from \"../types.js\";\r\n\r\ninterface VoiceSessionTicket {\r\n ticket: string;\r\n wsUrl: string;\r\n expiresAt: string;\r\n session: {\r\n model: string;\r\n voice: string;\r\n inputSampleRate: number;\r\n outputSampleRate: number;\r\n maxDurationMs: number;\r\n };\r\n}\r\n\r\n// Gemini Live delivers an agent utterance's output transcription as SEVERAL\r\n// incremental fragments (one serverContent message per fragment) inside a\r\n// single model turn — there is no per-fragment \"finished\" flag; only\r\n// turnComplete closes the turn. The gateway forwards each fragment as its own\r\n// isFinal:true voice_transcript event, so without merging here every fragment\r\n// would render as its own stacked bubble even though the concatenated text is\r\n// one sentence. Fragments arrive as EITHER a cumulative full snapshot OR\r\n// incremental new words (Gemini does both), so handle both:\r\n// - cumulative: next already contains prev from the start -> take next\r\n// - incremental: append next, inserting a space only at a clean word seam\r\nfunction mergeTranscriptText(prev: string, next: string): string {\r\n if (!prev) return next;\r\n if (!next) return prev;\r\n if (next === prev || prev.endsWith(next)) return prev; // no-op / dup tail\r\n if (next.startsWith(prev)) return next; // cumulative snapshot\r\n const needSpace = !/\\s$/.test(prev) && !/^\\s/.test(next);\r\n return prev + (needSpace ? \" \" : \"\") + next;\r\n}\r\n\r\ninterface VoiceTranscriptValue {\r\n speaker: \"user\" | \"agent\";\r\n text: string;\r\n isFinal: boolean;\r\n turnSeq?: number;\r\n}\r\n\r\n/**\r\n * Drives a real-time voice call with an Agent (powered by Gemini Live).\r\n *\r\n * Ticket minting goes through YOUR OWN backend (`POST /voice/sessions` on\r\n * whichever `@personaai/runtime`-based adapter you've mounted) via\r\n * `fetchWithAuth` — same as every other hook in this package. The actual\r\n * call does NOT: once a ticket comes back, this hook opens a WebSocket\r\n * DIRECTLY to Persona (`ticket.wsUrl`), bypassing your backend entirely for\r\n * the live audio. This is deliberate — see the package README's Voice\r\n * section for why (short version: a multi-minute relay would not survive\r\n * on a serverless deployment the way `POST /chat`'s bounded SSE relay\r\n * does), and it means your backend never has to become a WebSocket relay.\r\n *\r\n * Requires a browser with `AudioWorklet` support (all current evergreen\r\n * browsers). The processor code itself needs no `/public` file of your\r\n * own — it's embedded and loaded via a Blob URL (see `voiceWorklets.ts`).\r\n */\r\nexport function useVoice(options: UseVoiceOptions = {}): UseVoiceResult {\r\n const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();\r\n const voiceLogger = useMemo(() => logger.child(\"voice\"), [logger]);\r\n const agentId = options.agentId || defaultAgentId;\r\n const threadId = options.threadId;\r\n const contextOverride = options.contextOverride;\r\n const context = options.context;\r\n\r\n const [state, setState] = useState<PersonaVoiceState>(\"idle\");\r\n const [isMuted, setIsMuted] = useState(false);\r\n const [transcript, setTranscript] = useState<PersonaVoiceTranscriptLine[]>(\r\n [],\r\n );\r\n const [partial, setPartial] = useState<PersonaVoiceTranscriptLine | null>(\r\n null,\r\n );\r\n const [toolCalls, setToolCalls] = useState<PersonaVoiceToolCall[]>([]);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [endReason, setEndReason] = useState<PersonaVoiceEndReason | null>(\r\n null,\r\n );\r\n\r\n const wsRef = useRef<WebSocket | null>(null);\r\n const streamRef = useRef<MediaStream | null>(null);\r\n const inputCtxRef = useRef<AudioContext | null>(null);\r\n const outputCtxRef = useRef<AudioContext | null>(null);\r\n const recorderNodeRef = useRef<AudioWorkletNode | null>(null);\r\n const playerNodeRef = useRef<AudioWorkletNode | null>(null);\r\n const acceptedTurnSeqRef = useRef(0);\r\n const mountedRef = useRef(true);\r\n // Speaker + turnSeq of the last committed transcript line. Consecutive\r\n // finals with the same speaker AND turnSeq are fragments of one utterance\r\n // (the server bumps turnSeq only at turnComplete), so they merge into the\r\n // line they created instead of spawning a new bubble.\r\n const lastFinalTurnRef = useRef<{ speaker: string; turnSeq?: number } | null>(\r\n null,\r\n );\r\n\r\n useEffect(() => {\r\n mountedRef.current = true;\r\n return () => {\r\n mountedRef.current = false;\r\n };\r\n }, []);\r\n\r\n const teardownAudio = useCallback(() => {\r\n try {\r\n streamRef.current?.getTracks().forEach((track) => track.stop());\r\n } catch {\r\n // ignore\r\n }\r\n streamRef.current = null;\r\n\r\n try {\r\n recorderNodeRef.current?.disconnect();\r\n } catch {\r\n // ignore\r\n }\r\n recorderNodeRef.current = null;\r\n\r\n try {\r\n playerNodeRef.current?.disconnect();\r\n } catch {\r\n // ignore\r\n }\r\n playerNodeRef.current = null;\r\n\r\n try {\r\n void inputCtxRef.current?.close();\r\n } catch {\r\n // ignore\r\n }\r\n inputCtxRef.current = null;\r\n\r\n try {\r\n void outputCtxRef.current?.close();\r\n } catch {\r\n // ignore\r\n }\r\n outputCtxRef.current = null;\r\n }, []);\r\n\r\n const stop = useCallback(() => {\r\n voiceLogger.debug(\"stop() called\");\r\n try {\r\n wsRef.current?.close(1000, \"client_stop\");\r\n } catch {\r\n // ignore\r\n }\r\n wsRef.current = null;\r\n teardownAudio();\r\n if (mountedRef.current) setState(\"idle\");\r\n }, [teardownAudio, voiceLogger]);\r\n\r\n useEffect(() => stop, [stop]);\r\n\r\n const startCapture = useCallback(async (inputSampleRate: number) => {\r\n const stream = await navigator.mediaDevices.getUserMedia({\r\n audio: {\r\n echoCancellation: true,\r\n noiseSuppression: true,\r\n autoGainControl: true,\r\n channelCount: 1,\r\n },\r\n });\r\n streamRef.current = stream;\r\n\r\n const inputCtx = new AudioContext({ sampleRate: inputSampleRate });\r\n inputCtxRef.current = inputCtx;\r\n await inputCtx.audioWorklet.addModule(recorderWorkletUrl());\r\n\r\n const source = inputCtx.createMediaStreamSource(stream);\r\n const recorderNode = new AudioWorkletNode(\r\n inputCtx,\r\n \"pcm-recorder-processor\",\r\n );\r\n recorderNode.port.onmessage = (event: MessageEvent<ArrayBuffer>) => {\r\n if (wsRef.current?.readyState === WebSocket.OPEN) {\r\n wsRef.current.send(event.data);\r\n }\r\n };\r\n recorderNodeRef.current = recorderNode;\r\n source.connect(recorderNode);\r\n }, []);\r\n\r\n const setupPlayback = useCallback(async (outputSampleRate: number) => {\r\n const outputCtx = new AudioContext({ sampleRate: outputSampleRate });\r\n outputCtxRef.current = outputCtx;\r\n await outputCtx.audioWorklet.addModule(playerWorkletUrl());\r\n\r\n const playerNode = new AudioWorkletNode(outputCtx, \"pcm-player-processor\");\r\n playerNode.connect(outputCtx.destination);\r\n playerNodeRef.current = playerNode;\r\n }, []);\r\n\r\n const upsertToolCall = useCallback(\r\n (id: string, patch: Partial<PersonaVoiceToolCall>) => {\r\n setToolCalls((prev) => {\r\n const idx = prev.findIndex((t) => t.id === id);\r\n if (idx === -1) return [...prev, { id, status: \"running\", ...patch }];\r\n const next = [...prev];\r\n next[idx] = { ...next[idx], ...patch } as PersonaVoiceToolCall;\r\n return next;\r\n });\r\n },\r\n [],\r\n );\r\n\r\n const handleTranscript = useCallback((value: VoiceTranscriptValue) => {\r\n const { speaker, text, isFinal, turnSeq } = value;\r\n if (!isFinal) {\r\n setPartial({ id: \"partial\", speaker, text });\r\n return;\r\n }\r\n\r\n // A final may land while a partial of the same speaker is showing (the\r\n // last interim is superseded by the final) — clear it only for that case.\r\n setPartial((prev) => (prev?.speaker === speaker ? null : prev));\r\n\r\n const last = lastFinalTurnRef.current;\r\n const sameUserBurst =\r\n speaker === \"user\" &&\r\n last &&\r\n last.speaker === speaker &&\r\n last.turnSeq === turnSeq;\r\n\r\n setTranscript((prev) => {\r\n const tail = prev[prev.length - 1];\r\n // An agent \"answer\" can arrive as several separate finals: per-fragment\r\n // finals of one utterance, or distinct spoken segments split by a tool\r\n // call mid-answer. Keep them as ONE bubble while no user line has\r\n // intervened — this is exactly how the thread reads the same turns back\r\n // (checkpoint.service normalizeMessages merges consecutive assistant\r\n // messages) and how text chat shows one assistant message per answer.\r\n // A committed user line between two agent lines separates answers, so\r\n // the merge only applies when the open line is also agent.\r\n const agentContinues = speaker === \"agent\" && tail?.speaker === \"agent\";\r\n if (agentContinues || (sameUserBurst && tail?.speaker === \"user\")) {\r\n const merged = mergeTranscriptText(tail.text, text);\r\n if (merged === tail.text) return prev;\r\n return prev.map((l, i) =>\r\n i === prev.length - 1 ? { ...l, text: merged } : l,\r\n );\r\n }\r\n return [...prev, { id: `${speaker}-${prev.length}`, speaker, text }];\r\n });\r\n lastFinalTurnRef.current = { speaker, turnSeq };\r\n }, []);\r\n\r\n const handleCustomEvent = useCallback(\r\n (name: string, value: Record<string, unknown>) => {\r\n switch (name) {\r\n case \"voice_session_ready\":\r\n voiceLogger.debug(\"voice_session_ready\", value);\r\n Promise.all([\r\n setupPlayback(value.outputSampleRate as number),\r\n startCapture(value.inputSampleRate as number),\r\n ])\r\n .then(() => {\r\n if (mountedRef.current) setState(\"listening\");\r\n })\r\n .catch((err) => {\r\n voiceLogger.error(\"audio graph setup failed\", {\r\n error: err instanceof Error ? err.message : String(err),\r\n });\r\n if (mountedRef.current) {\r\n setError(err instanceof Error ? err : new Error(String(err)));\r\n setState(\"error\");\r\n }\r\n });\r\n break;\r\n case \"voice_activity\":\r\n if (value.speaker === \"user\" && value.state === \"start\") {\r\n setState(\"listening\");\r\n } else if (value.speaker === \"user\" && value.state === \"end\") {\r\n setState(\"thinking\");\r\n } else if (value.speaker === \"agent\" && value.state === \"start\") {\r\n setState(\"speaking\");\r\n } else if (value.speaker === \"agent\" && value.state === \"end\") {\r\n setState(\"listening\");\r\n }\r\n break;\r\n case \"voice_transcript\":\r\n handleTranscript(value as unknown as VoiceTranscriptValue);\r\n break;\r\n case \"voice_interrupted\":\r\n acceptedTurnSeqRef.current = value.turnSeq as number;\r\n playerNodeRef.current?.port.postMessage({ type: \"flush\" });\r\n break;\r\n case \"voice_session_resumed\":\r\n voiceLogger.info(\"session transparently resumed\");\r\n break;\r\n case \"voice_session_ended\":\r\n voiceLogger.info(\"session ended\", { reason: value.reason });\r\n setState(\"ended\");\r\n setEndReason((value.reason as PersonaVoiceEndReason) ?? null);\r\n teardownAudio();\r\n try {\r\n wsRef.current?.close();\r\n } catch {\r\n // ignore\r\n }\r\n wsRef.current = null;\r\n break;\r\n default:\r\n break;\r\n }\r\n },\r\n [handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger],\r\n );\r\n\r\n const handleMessage = useCallback(\r\n (event: MessageEvent<ArrayBuffer | string>) => {\r\n if (typeof event.data !== \"string\") {\r\n const buf = event.data;\r\n const view = new DataView(buf);\r\n const turnSeq = view.getUint32(0, true);\r\n // Accept (and adopt) anything >= the last accepted value rather\r\n // than an exact match — the server bumps turnSeq on EVERY new\r\n // agent turn, not only on a barge-in. WebSocket delivers messages\r\n // in send order on one connection, so a voice_interrupted event\r\n // always arrives before any frame from the generation it\r\n // announces — nothing stale can arrive after it.\r\n if (turnSeq >= acceptedTurnSeqRef.current) {\r\n acceptedTurnSeqRef.current = turnSeq;\r\n const pcmBytes = buf.slice(4);\r\n playerNodeRef.current?.port.postMessage(pcmBytes, [pcmBytes]);\r\n }\r\n return;\r\n }\r\n\r\n let msg: Record<string, unknown>;\r\n try {\r\n msg = JSON.parse(event.data);\r\n } catch {\r\n return;\r\n }\r\n\r\n switch (msg.type) {\r\n case \"CUSTOM\":\r\n handleCustomEvent(\r\n msg.name as string,\r\n msg.value as Record<string, unknown>,\r\n );\r\n break;\r\n case \"TOOL_CALL_CHUNK\":\r\n upsertToolCall(msg.toolCallId as string, {\r\n name: msg.toolCallName as string | undefined,\r\n status: \"running\",\r\n });\r\n break;\r\n case \"TOOL_CALL_RESULT\": {\r\n let parsed: { output?: unknown; error?: string } | null = null;\r\n try {\r\n parsed = JSON.parse(msg.content as string);\r\n } catch {\r\n parsed = { output: msg.content };\r\n }\r\n upsertToolCall(msg.toolCallId as string, {\r\n status: parsed?.error ? \"error\" : \"done\",\r\n summary:\r\n parsed?.error ||\r\n (typeof parsed?.output === \"string\"\r\n ? parsed.output\r\n : JSON.stringify(parsed?.output ?? \"\")),\r\n });\r\n break;\r\n }\r\n case \"RUN_ERROR\":\r\n voiceLogger.warn(\"RUN_ERROR\", { message: msg.message });\r\n setError(\r\n new Error((msg.message as string) || \"The agent run failed.\"),\r\n );\r\n setState(\"error\");\r\n break;\r\n default:\r\n break;\r\n }\r\n },\r\n [handleCustomEvent, upsertToolCall, voiceLogger],\r\n );\r\n\r\n const start = useCallback(async () => {\r\n if (!agentId) {\r\n const err = new Error(\r\n \"useVoice: no agentId provided and no defaultAgentId set on PersonaProvider\",\r\n );\r\n setError(err);\r\n setState(\"error\");\r\n return;\r\n }\r\n\r\n setError(null);\r\n setEndReason(null);\r\n setTranscript([]);\r\n setPartial(null);\r\n setToolCalls([]);\r\n acceptedTurnSeqRef.current = 0;\r\n setState(\"connecting\");\r\n voiceLogger.debug(\"start() called\", {\r\n agentId,\r\n threadId,\r\n hasContextOverride: !!contextOverride,\r\n hasContext: !!context,\r\n });\r\n\r\n try {\r\n const res = await fetchWithAuth(\"/voice/sessions\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n agentId,\r\n ...(threadId ? { threadId } : {}),\r\n ...(contextOverride ? { contextOverride } : {}),\r\n ...(context ? { context } : {}),\r\n }),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Failed to start voice session: ${res.statusText}`);\r\n }\r\n const data = await res.json();\r\n const ticket = (data?.data ?? data) as VoiceSessionTicket;\r\n if (!ticket?.wsUrl) {\r\n throw new Error(\"Server did not return a voice session URL.\");\r\n }\r\n\r\n const ws = new WebSocket(ticket.wsUrl);\r\n ws.binaryType = \"arraybuffer\";\r\n wsRef.current = ws;\r\n\r\n ws.onmessage = handleMessage;\r\n ws.onerror = () => {\r\n voiceLogger.warn(\"WebSocket error\");\r\n if (mountedRef.current) {\r\n setError(new Error(\"Voice connection error.\"));\r\n setState(\"error\");\r\n }\r\n };\r\n ws.onclose = () => {\r\n if (mountedRef.current && wsRef.current === ws) {\r\n setState((prev) => (prev === \"error\" ? prev : \"idle\"));\r\n }\r\n };\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n voiceLogger.error(\"start() failed\", { error: errorObj.message });\r\n if (mountedRef.current) {\r\n setError(errorObj);\r\n setState(\"error\");\r\n }\r\n teardownAudio();\r\n }\r\n }, [agentId, threadId, contextOverride, context, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);\r\n\r\n const mute = useCallback((muted: boolean) => {\r\n setIsMuted(muted);\r\n streamRef.current?.getAudioTracks().forEach((track) => {\r\n track.enabled = !muted;\r\n });\r\n }, []);\r\n\r\n const sendText = useCallback((text: string) => {\r\n if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;\r\n wsRef.current.send(JSON.stringify({ type: \"voice.text\", text }));\r\n }, []);\r\n\r\n // Live refresh for the rest of an already-open call — the backend merges\r\n // this into whatever turnContext it already has (the start() seed, or an\r\n // earlier updateContext() call), so callers only need to send what\r\n // actually changed. A no-op while there's no open socket, same guard\r\n // sendText uses — nothing queues for \"once connected.\"\r\n const updateContext = useCallback((newContext: Record<string, unknown>) => {\r\n if (wsRef.current?.readyState !== WebSocket.OPEN) return;\r\n wsRef.current.send(JSON.stringify({ type: \"voice.context\", context: newContext }));\r\n }, []);\r\n\r\n return {\r\n state,\r\n isMuted,\r\n transcript,\r\n partial,\r\n toolCalls,\r\n error,\r\n endReason,\r\n start,\r\n stop,\r\n mute,\r\n sendText,\r\n updateContext,\r\n };\r\n}\r\n","/**\n * AudioWorklet processor source for `useVoice`, embedded as strings rather\n * than shipped as separate static files. A consumer app has no `/public`\n * directory we can rely on being copied into (unlike our own first-party\n * frontend, which loads these from `/voice/*.js`) — `URL.createObjectURL`\n * + a Blob is the standard way to hand `audioWorklet.addModule()` a module\n * with zero setup required from the host app.\n */\n\nconst RECORDER_WORKLET_SOURCE = `\nclass PCMRecorderProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this._buffer = [];\n this._chunkSamples = 320; // 20ms @ 16kHz\n }\n\n process(inputs) {\n const input = inputs[0];\n const channel = input && input[0];\n if (channel) {\n for (let i = 0; i < channel.length; i++) {\n this._buffer.push(channel[i]);\n }\n while (this._buffer.length >= this._chunkSamples) {\n const chunk = this._buffer.splice(0, this._chunkSamples);\n const int16 = new Int16Array(chunk.length);\n for (let i = 0; i < chunk.length; i++) {\n const s = Math.max(-1, Math.min(1, chunk[i]));\n int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n this.port.postMessage(int16.buffer, [int16.buffer]);\n }\n }\n return true;\n }\n}\n\nregisterProcessor('pcm-recorder-processor', PCMRecorderProcessor);\n`;\n\nconst PLAYER_WORKLET_SOURCE = `\nclass PCMPlayerProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this._queue = [];\n this._readOffset = 0;\n this.port.onmessage = (event) => {\n const msg = event.data;\n if (msg && msg.type === 'flush') {\n this._queue = [];\n this._readOffset = 0;\n return;\n }\n const int16 = new Int16Array(msg);\n const float32 = new Float32Array(int16.length);\n for (let i = 0; i < int16.length; i++) {\n float32[i] = int16[i] / 0x8000;\n }\n this._queue.push(float32);\n };\n }\n\n process(_inputs, outputs) {\n const output = outputs[0][0];\n let outIdx = 0;\n while (outIdx < output.length) {\n if (this._queue.length === 0) {\n output[outIdx++] = 0;\n continue;\n }\n const current = this._queue[0];\n const remaining = current.length - this._readOffset;\n const toCopy = Math.min(remaining, output.length - outIdx);\n output.set(current.subarray(this._readOffset, this._readOffset + toCopy), outIdx);\n outIdx += toCopy;\n this._readOffset += toCopy;\n if (this._readOffset >= current.length) {\n this._queue.shift();\n this._readOffset = 0;\n }\n }\n return true;\n }\n}\n\nregisterProcessor('pcm-player-processor', PCMPlayerProcessor);\n`;\n\nfunction toModuleUrl(source: string): string {\n const blob = new Blob([source], { type: \"application/javascript\" });\n return URL.createObjectURL(blob);\n}\n\nexport function recorderWorkletUrl(): string {\n return toModuleUrl(RECORDER_WORKLET_SOURCE);\n}\n\nexport function playerWorkletUrl(): string {\n return toModuleUrl(PLAYER_WORKLET_SOURCE);\n}\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\nimport type { PersonaFileItem } from \"../types.js\";\r\n\r\nexport type { PersonaFileItem };\r\n\r\nexport function useFiles(autoFetch = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [files, setFiles] = useState<PersonaFileItem[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [isUploading, setIsUploading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchFiles = useCallback(async () => {\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(\"/files\");\r\n if (!res.ok) throw new Error(`Failed to list files: ${res.statusText}`);\r\n const data = await res.json();\r\n // Real shape is { items, pagination } — bare array/`.files` are\r\n // defensive fallbacks, not the actual wire contract.\r\n const items: PersonaFileItem[] = Array.isArray(data)\r\n ? data\r\n : data?.items || data?.files || [];\r\n setFiles(items);\r\n return items;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n const uploadFile = useCallback(\r\n async (\r\n fileOrFormData: FormData | { name: string; uri: string; type?: string },\r\n ) => {\r\n setIsUploading(true);\r\n setError(null);\r\n try {\r\n let body: FormData;\r\n if (fileOrFormData instanceof FormData) {\r\n body = fileOrFormData;\r\n } else {\r\n // React Native FormData support\r\n body = new FormData();\r\n body.append(\"file\", fileOrFormData as unknown as Blob);\r\n }\r\n\r\n const res = await fetchWithAuth(\"/files\", {\r\n method: \"POST\",\r\n body,\r\n });\r\n\r\n if (!res.ok) {\r\n const errText = await res.text().catch(() => \"Upload failed\");\r\n throw new Error(`Upload error (${res.status}): ${errText}`);\r\n }\r\n\r\n const uploaded = (await res.json()) as PersonaFileItem;\r\n void fetchFiles();\r\n return uploaded;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n throw errorObj;\r\n } finally {\r\n setIsUploading(false);\r\n }\r\n },\r\n [fetchWithAuth, fetchFiles],\r\n );\r\n\r\n const deleteFile = useCallback(\r\n async (fileId: string) => {\r\n const res = await fetchWithAuth(`/files/${fileId}`, { method: \"DELETE\" });\r\n if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);\r\n setFiles((prev) => prev.filter((f) => f.id !== fileId));\r\n },\r\n [fetchWithAuth],\r\n );\r\n\r\n const bulkDeleteFiles = useCallback(\r\n async (fileIds: string[]) => {\r\n const res = await fetchWithAuth(\"/files/bulk-delete\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ ids: fileIds }),\r\n });\r\n if (!res.ok)\r\n throw new Error(`Failed to bulk-delete files: ${res.statusText}`);\r\n const idSet = new Set(fileIds);\r\n setFiles((prev) => prev.filter((f) => !idSet.has(f.id)));\r\n return (await res.json()) as {\r\n deleted: string[];\r\n failed: Array<{ id: string; reason: string }>;\r\n };\r\n },\r\n [fetchWithAuth],\r\n );\r\n\r\n const getDownloadUrl = useCallback((fileId: string) => {\r\n return `/files/${fileId}`;\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (autoFetch) {\r\n void fetchFiles();\r\n }\r\n }, [autoFetch, fetchFiles]);\r\n\r\n return {\r\n files,\r\n isLoading,\r\n isUploading,\r\n error,\r\n refetch: fetchFiles,\r\n uploadFile,\r\n deleteFile,\r\n bulkDeleteFiles,\r\n getDownloadUrl,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\n\r\nexport interface PersonaAgentSummary {\r\n _id: string;\r\n name: string;\r\n slug: string;\r\n description?: string;\r\n tagline?: string;\r\n avatar?: string;\r\n}\r\n\r\nexport function useAgents(autoFetch = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [agents, setAgents] = useState<PersonaAgentSummary[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchAgents = useCallback(async () => {\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const res = await fetchWithAuth(\"/agents\");\r\n if (!res.ok) throw new Error(`Failed to list agents: ${res.statusText}`);\r\n const data = await res.json();\r\n // Real shape is { items, pagination }.\r\n const items: PersonaAgentSummary[] = Array.isArray(data)\r\n ? data\r\n : data?.items || data?.agents || [];\r\n setAgents(items);\r\n return items;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n useEffect(() => {\r\n if (autoFetch) {\r\n void fetchAgents();\r\n }\r\n }, [autoFetch, fetchAgents]);\r\n\r\n return {\r\n agents,\r\n isLoading,\r\n error,\r\n refetch: fetchAgents,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\n\r\nexport interface PersonaHealthInfo {\r\n status: string;\r\n version?: string;\r\n capabilities?: Record<string, boolean>;\r\n}\r\n\r\nexport function useConnection(autoCheck = true) {\r\n const { fetchWithAuth } = usePersonaContext();\r\n const [health, setHealth] = useState<PersonaHealthInfo | null>(null);\r\n const [isConnected, setIsConnected] = useState(false);\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n const checkHealth = useCallback(async () => {\r\n setIsLoading(true);\r\n try {\r\n const res = await fetchWithAuth(\"/health\");\r\n if (res.ok) {\r\n const data = (await res.json()) as PersonaHealthInfo;\r\n setHealth(data);\r\n setIsConnected(true);\r\n return data;\r\n }\r\n setIsConnected(false);\r\n return null;\r\n } catch {\r\n setIsConnected(false);\r\n return null;\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [fetchWithAuth]);\r\n\r\n useEffect(() => {\r\n if (autoCheck) {\r\n void checkHealth();\r\n }\r\n }, [autoCheck, checkHealth]);\r\n\r\n return {\r\n isConnected,\r\n health,\r\n isLoading,\r\n checkHealth,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useState } from \"react\";\r\nimport { usePersonaContext } from \"../context/PersonaContext.js\";\r\n\r\n/**\r\n * One `authType: 'oauth', authMode: 'user'` MCP an Agent has attached, and\r\n * whether the current end user has connected it yet. `authorizeUrl` is only\r\n * present when `connected` is `false` — navigate the browser there (a\r\n * same-tab redirect is fine; it's a real OAuth authorization URL) to start\r\n * the consent flow.\r\n */\r\nexport interface PersonaMcpConnection {\r\n mcpId: string;\r\n name: string;\r\n description: string;\r\n connected: boolean;\r\n authorizeUrl: string | null;\r\n}\r\n\r\nexport interface UseMcpConnectionsOptions {\r\n /** @default the PersonaProvider's defaultAgentId */\r\n agentId?: string;\r\n /** Where the browser lands after OAuth consent completes. @default window.location.href */\r\n returnTo?: string;\r\n /** @default true */\r\n autoFetch?: boolean;\r\n}\r\n\r\n/**\r\n * Surfaces the gap that used to be invisible entirely: a user-mode MCP tool\r\n * call for a user who hasn't connected yet is silently dropped from the\r\n * Agent's toolset server-side, with no signal in the chat stream at all.\r\n * Check this before (or alongside) a chat session to show a real \"Connect\r\n * your account\" affordance instead of a capability that just quietly isn't\r\n * there.\r\n */\r\nexport function useMcpConnections(options: UseMcpConnectionsOptions = {}) {\r\n const { defaultAgentId, fetchWithAuth } = usePersonaContext();\r\n const agentId = options.agentId ?? defaultAgentId;\r\n const autoFetch = options.autoFetch ?? true;\r\n\r\n const [connections, setConnections] = useState<PersonaMcpConnection[]>([]);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const fetchConnections = useCallback(async () => {\r\n if (!agentId) return [];\r\n setIsLoading(true);\r\n setError(null);\r\n try {\r\n const returnTo =\r\n options.returnTo ??\r\n (typeof window !== \"undefined\" ? window.location.href : undefined);\r\n const query = returnTo ? `?returnTo=${encodeURIComponent(returnTo)}` : \"\";\r\n const res = await fetchWithAuth(\r\n `/agents/${agentId}/mcp-connections${query}`,\r\n );\r\n if (!res.ok)\r\n throw new Error(`Failed to load MCP connections: ${res.statusText}`);\r\n const data = await res.json();\r\n const items: PersonaMcpConnection[] = Array.isArray(data)\r\n ? data\r\n : data?.items || [];\r\n setConnections(items);\r\n return items;\r\n } catch (err) {\r\n const errorObj = err instanceof Error ? err : new Error(String(err));\r\n setError(errorObj);\r\n return [];\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [agentId, fetchWithAuth, options.returnTo]);\r\n\r\n useEffect(() => {\r\n if (autoFetch) void fetchConnections();\r\n }, [autoFetch, fetchConnections]);\r\n\r\n return {\r\n connections,\r\n /** Convenience filter for the common \"show a banner for what's missing\" case. */\r\n unconnected: connections.filter((c) => !c.connected),\r\n isLoading,\r\n error,\r\n refetch: fetchConnections,\r\n };\r\n}\r\n"],"mappings":"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","names":["import_react","value","import_react","import_react","import_react","import_react","import_react","import_react","import_react","import_logger"]}