@deltakit/react 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -34,11 +34,13 @@ var import_react = require("react");
34
34
  var DEFAULT_THRESHOLD = 50;
35
35
  function useAutoScroll(dependencies, options) {
36
36
  const {
37
- behavior = "instant",
37
+ behavior = "smooth",
38
38
  enabled = true,
39
39
  threshold = DEFAULT_THRESHOLD
40
40
  } = options ?? {};
41
41
  const ref = (0, import_react.useRef)(null);
42
+ const behaviorRef = (0, import_react.useRef)(behavior);
43
+ behaviorRef.current = behavior;
42
44
  const isAtBottomRef = (0, import_react.useRef)(true);
43
45
  const [isAtBottom, setIsAtBottom] = (0, import_react.useState)(true);
44
46
  const rafRef = (0, import_react.useRef)(null);
@@ -63,7 +65,7 @@ function useAutoScroll(dependencies, options) {
63
65
  if (heightChanged || distanceFromBottom > 0) {
64
66
  lastAutoScrollHeightRef.current = nextHeight;
65
67
  pendingVerificationFramesRef.current = 1;
66
- el.scrollTop = nextHeight;
68
+ el.scrollTo({ top: nextHeight, behavior: behaviorRef.current });
67
69
  } else {
68
70
  pendingVerificationFramesRef.current = Math.max(
69
71
  pendingVerificationFramesRef.current - 1,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/use-auto-scroll.ts","../src/use-stream-chat.ts","../src/chat-controller.ts","../src/transports.ts"],"sourcesContent":["// Re-export core types so consumers only need to import from @deltakit/react\nexport type {\n\tContentPart,\n\tMessage,\n\tReasoningPart,\n\tSSEEvent,\n\tTextDeltaEvent,\n\tTextPart,\n\tToolCallEvent,\n\tToolCallPart,\n\tToolResultEvent,\n} from \"@deltakit/core\";\nexport {\n\tfromAgnoAgents,\n\tfromOpenAiAgents,\n\tparseSSEStream,\n} from \"@deltakit/core\";\n\nexport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tEventHelpers,\n\tTransportOptions,\n\tUseAutoScrollOptions,\n\tUseAutoScrollReturn,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n\tWebSocketTransportOptions,\n} from \"./types\";\nexport { useAutoScroll } from \"./use-auto-scroll\";\nexport { useStreamChat } from \"./use-stream-chat\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { UseAutoScrollOptions, UseAutoScrollReturn } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_THRESHOLD = 50;\n\n// ---------------------------------------------------------------------------\n// useAutoScroll\n// ---------------------------------------------------------------------------\n\nexport function useAutoScroll<T extends HTMLElement = HTMLDivElement>(\n\tdependencies: unknown[],\n\toptions?: UseAutoScrollOptions,\n): UseAutoScrollReturn<T> {\n\tconst {\n\t\tbehavior = \"instant\",\n\t\tenabled = true,\n\t\tthreshold = DEFAULT_THRESHOLD,\n\t} = options ?? {};\n\n\tconst ref = useRef<T | null>(null);\n\tconst isAtBottomRef = useRef(true);\n\tconst [isAtBottom, setIsAtBottom] = useState(true);\n\n\t// A single rAF id shared across all scroll sources — ensures we never\n\t// call scrollTo() more than once per frame, no matter how many\n\t// MutationObserver / ResizeObserver callbacks fire.\n\tconst rafRef = useRef<number | null>(null);\n\tconst lastAutoScrollHeightRef = useRef<number | null>(null);\n\tconst pendingVerificationFramesRef = useRef(0);\n\n\tconst scheduleScroll = useCallback(() => {\n\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\tpendingVerificationFramesRef.current,\n\t\t\t1,\n\t\t);\n\t\tif (rafRef.current != null) return;\n\n\t\tconst tick = () => {\n\t\t\trafRef.current = null;\n\t\t\tconst el = ref.current;\n\t\t\tif (!el || !isAtBottomRef.current) {\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst nextHeight = el.scrollHeight;\n\t\t\tconst heightChanged = lastAutoScrollHeightRef.current !== nextHeight;\n\t\t\tconst distanceFromBottom = nextHeight - el.scrollTop - el.clientHeight;\n\n\t\t\tif (heightChanged || distanceFromBottom > 0) {\n\t\t\t\tlastAutoScrollHeightRef.current = nextHeight;\n\t\t\t\tpendingVerificationFramesRef.current = 1;\n\n\t\t\t\t// Keep the viewport pinned during streaming without restarting a\n\t\t\t\t// smooth scroll animation on every DOM mutation.\n\t\t\t\tel.scrollTop = nextHeight;\n\t\t\t} else {\n\t\t\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\t\t\tpendingVerificationFramesRef.current - 1,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (pendingVerificationFramesRef.current > 0) {\n\t\t\t\trafRef.current = requestAnimationFrame(tick);\n\t\t\t}\n\t\t};\n\n\t\trafRef.current = requestAnimationFrame(tick);\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// Track whether the user is near the bottom via scroll events.\n\t// Only triggers a React re-render when the boolean actually changes.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst handleScroll = () => {\n\t\t\tconst atBottom =\n\t\t\t\tel.scrollHeight - el.scrollTop - el.clientHeight <= threshold;\n\t\t\tisAtBottomRef.current = atBottom;\n\t\t\tif (!atBottom) {\n\t\t\t\tlastAutoScrollHeightRef.current = null;\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t}\n\t\t\tsetIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n\t\t};\n\n\t\tel.addEventListener(\"scroll\", handleScroll, { passive: true });\n\t\thandleScroll();\n\t\treturn () => el.removeEventListener(\"scroll\", handleScroll);\n\t}, [enabled, threshold]);\n\n\t// -----------------------------------------------------------------------\n\t// Scroll to bottom when dependencies change (if pinned).\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tif (!enabled || !isAtBottomRef.current) return;\n\t\tscheduleScroll();\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: dependencies are passed dynamically by the consumer\n\t}, dependencies);\n\n\t// -----------------------------------------------------------------------\n\t// MutationObserver + ResizeObserver — catch content changes during\n\t// streaming that happen between React re-renders (e.g. DOM mutations\n\t// from markdown renderers). Scroll calls are batched via rAF so we\n\t// scroll at most once per frame.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst resizeObserver = new ResizeObserver(scheduleScroll);\n\n\t\t// Observe existing children for size changes.\n\t\tfor (const child of el.children) {\n\t\t\tresizeObserver.observe(child);\n\t\t}\n\n\t\t// Watch for new children added to the container.\n\t\tconst mutationObserver = new MutationObserver((mutations) => {\n\t\t\tfor (const mutation of mutations) {\n\t\t\t\tfor (const node of mutation.addedNodes) {\n\t\t\t\t\tif (node instanceof Element) {\n\t\t\t\t\t\tresizeObserver.observe(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tscheduleScroll();\n\t\t});\n\n\t\tmutationObserver.observe(el, { childList: true, subtree: true });\n\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [enabled, scheduleScroll]);\n\n\t// -----------------------------------------------------------------------\n\t// Cancel any pending rAF on unmount.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (rafRef.current != null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t};\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// scrollToBottom — imperative function that scrolls to the bottom and\n\t// re-pins auto-scroll.\n\t// -----------------------------------------------------------------------\n\n\tconst scrollToBottom = useCallback(() => {\n\t\tconst el = ref.current;\n\t\tif (!el) return;\n\n\t\tisAtBottomRef.current = true;\n\t\tlastAutoScrollHeightRef.current = el.scrollHeight;\n\t\tpendingVerificationFramesRef.current = 0;\n\t\tsetIsAtBottom(true);\n\t\tel.scrollTo({ top: el.scrollHeight, behavior });\n\t}, [behavior]);\n\n\treturn { ref, scrollToBottom, isAtBottom };\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { createChatTransportContext, createMessage } from \"./chat-controller\";\nimport { resolveTransport } from \"./transports\";\nimport type {\n\tChatTransportRun,\n\tEventHelpers,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Default event handler — accumulates `text_delta` into the last\n// assistant message's parts.\n// ---------------------------------------------------------------------------\n\nfunction defaultOnEvent(\n\tevent: SSEEvent,\n\thelpers: EventHelpers<ContentPart>,\n): void {\n\tif (event.type === \"text_delta\") {\n\t\thelpers.appendText(event.delta);\n\t}\n\t// Other event types (e.g. tool_call) are silently ignored by default.\n\t// Users can provide their own `onEvent` to handle them.\n}\n\n// ---------------------------------------------------------------------------\n// useStreamChat\n// ---------------------------------------------------------------------------\n\nexport function useStreamChat<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart> {\n\tconst { initialMessages, onEvent, onMessage, onError, onFinish } = options;\n\n\tconst [messages, setMessages] = useState(initialMessages ?? []);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst [runId, setRunId] = useState<string | null>(null);\n\n\tconst runRef = useRef<ChatTransportRun | null>(null);\n\n\t// Track which run id has already been resumed to prevent re-triggering.\n\tconst resumedRunIdRef = useRef<string | null>(null);\n\n\t// When the user manually stops a run, suppress auto-resume until the\n\t// next explicit `sendMessage` call.\n\tconst manuallyStoppedRef = useRef(false);\n\n\t// We use a ref for the latest messages so callbacks created inside\n\t// transport handlers always see the current value without re-creating\n\t// closures.\n\tconst messagesRef = useRef(messages);\n\tmessagesRef.current = messages;\n\n\t// Keep transport options in a ref so that callbacks always read the\n\t// latest values without causing memoisation instability.\n\tconst transportOptionsRef = useRef(options.transportOptions);\n\ttransportOptionsRef.current = options.transportOptions;\n\n\tconst appendText = useCallback((delta: string) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\tconst parts = [...last.parts];\n\t\t\tconst lastPart = parts[parts.length - 1];\n\n\t\t\tif (lastPart && lastPart.type === \"text\" && \"text\" in lastPart) {\n\t\t\t\tconst textPart = lastPart as { type: \"text\"; text: string };\n\t\t\t\tparts[parts.length - 1] = {\n\t\t\t\t\t...lastPart,\n\t\t\t\t\ttext: textPart.text + delta,\n\t\t\t\t} as unknown as TPart;\n\t\t\t} else {\n\t\t\t\tparts.push({ type: \"text\", text: delta } as unknown as TPart);\n\t\t\t}\n\n\t\t\treturn [...prev.slice(0, -1), { ...last, parts }];\n\t\t});\n\t}, []);\n\n\tconst appendPart = useCallback((part: TPart) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\treturn [\n\t\t\t\t...prev.slice(0, -1),\n\t\t\t\t{\n\t\t\t\t\t...last,\n\t\t\t\t\tparts: [...last.parts, part],\n\t\t\t\t},\n\t\t\t];\n\t\t});\n\t}, []);\n\n\t// Stabilise transport creation: resolve once and store in a ref so that\n\t// changing values like `runId` in transportOptions won't cause a new\n\t// transport instance (and therefore a new WebSocket) to be created.\n\tconst transportRef = useRef<ReturnType<\n\t\ttypeof resolveTransport<TPart, TEvent>\n\t> | null>(null);\n\tif (!transportRef.current) {\n\t\ttransportRef.current = resolveTransport(options);\n\t}\n\tconst transport = transportRef.current;\n\n\tconst eventHandler =\n\t\tonEvent ??\n\t\t(defaultOnEvent as unknown as (\n\t\t\tevent: TEvent,\n\t\t\thelpers: EventHelpers<TPart>,\n\t\t) => void);\n\n\t// Stabilise the transport context: use refs for values that change\n\t// frequently (transportOptions callbacks) so the context object itself\n\t// stays referentially stable.\n\tconst eventHandlerRef = useRef(eventHandler);\n\teventHandlerRef.current = eventHandler;\n\n\tconst onErrorRef = useRef(onError);\n\tonErrorRef.current = onError;\n\n\tconst onFinishRef = useRef(onFinish);\n\tonFinishRef.current = onFinish;\n\n\tconst onMessageRef = useRef(onMessage);\n\tonMessageRef.current = onMessage;\n\n\tconst transportContext = useMemo(\n\t\t() =>\n\t\t\tcreateChatTransportContext({\n\t\t\t\tappendPart,\n\t\t\t\tappendText,\n\t\t\t\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) =>\n\t\t\t\t\teventHandlerRef.current(event, helpers),\n\t\t\t\tgetMessages: () => messagesRef.current,\n\t\t\t\tonError: (...args) => onErrorRef.current?.(...args),\n\t\t\t\tonFinish: (...args) => onFinishRef.current?.(...args),\n\t\t\t\tonMessage: (...args) => onMessageRef.current?.(...args),\n\t\t\t\tsetError,\n\t\t\t\tsetIsLoading,\n\t\t\t\tsetMessages,\n\t\t\t\tsetRunId: (next) => {\n\t\t\t\t\tsetRunId(next);\n\t\t\t\t\ttransportOptionsRef.current?.backgroundSSE?.onRunIdChange?.(next);\n\t\t\t\t\ttransportOptionsRef.current?.websocket?.onRunIdChange?.(next);\n\t\t\t\t},\n\t\t\t}),\n\t\t[appendPart, appendText],\n\t);\n\n\tconst stop = useCallback(() => {\n\t\tconst activeRun = runRef.current;\n\t\tif (!activeRun?.stop) {\n\t\t\treturn;\n\t\t}\n\n\t\tmanuallyStoppedRef.current = true;\n\t\tvoid activeRun.stop();\n\t\trunRef.current = null;\n\t\tsetIsLoading(false);\n\t}, []);\n\n\tconst sendMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (runRef.current || isLoading) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst userMessage = createMessage<TPart>(\"user\", [\n\t\t\t\t{ type: \"text\", text } as unknown as TPart,\n\t\t\t]);\n\t\t\tconst assistantMessage = createMessage<TPart>(\"assistant\", []);\n\n\t\t\tsetMessages((prev) => {\n\t\t\t\tconst next = [...prev, userMessage, assistantMessage];\n\t\t\t\tmessagesRef.current = next;\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\t\tonMessage?.(userMessage);\n\t\t\tsetError(null);\n\t\t\tsetIsLoading(true);\n\n\t\t\t// Reset the resume guard so a future resume for a new run is allowed.\n\t\t\tresumedRunIdRef.current = null;\n\t\t\tmanuallyStoppedRef.current = false;\n\n\t\t\tconst run = transport.start({ context: transportContext, message: text });\n\t\t\trunRef.current = run ?? null;\n\t\t\tif (run?.runId) {\n\t\t\t\tsetRunId(run.runId);\n\t\t\t}\n\t\t},\n\t\t[isLoading, onMessage, transport, transportContext],\n\t);\n\n\t// -----------------------------------------------------------------------\n\t// Auto-resume effect: attempt to reconnect to an in-flight run on mount.\n\t//\n\t// The candidate run id is read from transport options (which may change\n\t// when the app updates state). We guard against duplicate resumes for the\n\t// same run id using `resumedRunIdRef`.\n\t// -----------------------------------------------------------------------\n\n\tconst candidateRunId =\n\t\toptions.transportOptions?.backgroundSSE?.runId ??\n\t\toptions.transportOptions?.backgroundSSE?.getResumeKey?.() ??\n\t\toptions.transportOptions?.websocket?.runId ??\n\t\toptions.transportOptions?.websocket?.getResumeKey?.() ??\n\t\tnull;\n\n\tuseEffect(() => {\n\t\t// Already have an active run — don't start another.\n\t\tif (runRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\t// User explicitly stopped — don't auto-resume until next sendMessage.\n\t\tif (manuallyStoppedRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Already resumed this exact run id — don't retry.\n\t\tif (resumedRunIdRef.current === candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!transport.resume) {\n\t\t\treturn;\n\t\t}\n\n\t\tresumedRunIdRef.current = candidateRunId;\n\n\t\tsetError(null);\n\t\tsetIsLoading(true);\n\t\tconst run = transport.resume({\n\t\t\tcontext: transportContext,\n\t\t\trunId: candidateRunId,\n\t\t});\n\t\trunRef.current = run ?? null;\n\t\tsetRunId(candidateRunId);\n\t}, [candidateRunId, transport, transportContext]);\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tvoid runRef.current?.close?.();\n\t\t\trunRef.current = null;\n\t\t};\n\t}, []);\n\n\tconst prevIsLoadingRef = useRef(isLoading);\n\tuseEffect(() => {\n\t\t// Only clear the run ref on a true → false transition, not on mount\n\t\t// where isLoading starts as false. Clearing on mount would race with\n\t\t// the auto-resume effect and null out the run it just created.\n\t\tif (prevIsLoadingRef.current && !isLoading) {\n\t\t\trunRef.current = null;\n\t\t}\n\t\tprevIsLoadingRef.current = isLoading;\n\t}, [isLoading]);\n\n\treturn {\n\t\terror,\n\t\tisLoading,\n\t\tmessages,\n\t\trunId,\n\t\tsendMessage,\n\t\tsetMessages,\n\t\tstop,\n\t};\n}\n","import type { ContentPart, Message, SSEEvent } from \"@deltakit/core\";\nimport type { Dispatch, SetStateAction } from \"react\";\nimport type {\n\tChatTransportContext,\n\tEventHelpers,\n\tUseStreamChatOptions,\n} from \"./types\";\n\nexport interface ChatControllerOptions<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n> {\n\tappendPart: EventHelpers<TPart>[\"appendPart\"];\n\tappendText: EventHelpers<TPart>[\"appendText\"];\n\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) => void;\n\tgetMessages: () => Message<TPart>[];\n\tonError?: UseStreamChatOptions<TPart, TEvent>[\"onError\"];\n\tonFinish?: UseStreamChatOptions<TPart, TEvent>[\"onFinish\"];\n\tonMessage?: UseStreamChatOptions<TPart, TEvent>[\"onMessage\"];\n\tsetError: Dispatch<SetStateAction<Error | null>>;\n\tsetIsLoading: Dispatch<SetStateAction<boolean>>;\n\tsetMessages: Dispatch<SetStateAction<Message<TPart>[]>>;\n\tsetRunId: (runId: string | null) => void;\n}\n\nlet counter = 0;\n\nexport function generateId(): string {\n\treturn `msg_${Date.now()}_${++counter}`;\n}\n\nexport function createMessage<TPart extends { type: string }>(\n\trole: Message[\"role\"],\n\tparts: TPart[],\n): Message<TPart> {\n\treturn { id: generateId(), role, parts };\n}\n\nexport function createChatTransportContext<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(\n\toptions: ChatControllerOptions<TPart, TEvent>,\n): ChatTransportContext<TPart, TEvent> {\n\tconst helpers: EventHelpers<TPart> = {\n\t\tappendPart: options.appendPart,\n\t\tappendText: options.appendText,\n\t\tsetMessages: options.setMessages,\n\t};\n\n\treturn {\n\t\temit: (event) => {\n\t\t\toptions.eventHandler(event, helpers);\n\t\t},\n\t\tensureAssistantMessage: () => {\n\t\t\toptions.setMessages((prev) => {\n\t\t\t\tconst last = prev[prev.length - 1];\n\t\t\t\tif (last?.role === \"assistant\") {\n\t\t\t\t\treturn prev;\n\t\t\t\t}\n\n\t\t\t\treturn [...prev, createMessage<TPart>(\"assistant\", [])];\n\t\t\t});\n\t\t},\n\t\tfail: (error) => {\n\t\t\toptions.setError(error);\n\t\t\toptions.onError?.(error);\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\t\t},\n\t\tfinish: () => {\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\n\t\t\tconst finalMessages = options.getMessages();\n\t\t\tconst lastMessage = finalMessages[finalMessages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\toptions.onMessage?.(lastMessage);\n\t\t\t}\n\n\t\t\toptions.onFinish?.(finalMessages);\n\t\t},\n\t\tgetMessages: options.getMessages,\n\t\tsetRunId: (runId) => {\n\t\t\toptions.setRunId(runId);\n\t\t},\n\t};\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { parseSSEStream } from \"@deltakit/core\";\nimport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tUseStreamChatOptions,\n\tWebSocketTransportOptions,\n} from \"./types\";\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction isAbortError(error: unknown): boolean {\n\treturn error instanceof DOMException && error.name === \"AbortError\";\n}\n\nfunction resolveRunId(response: unknown): string {\n\tif (!response || typeof response !== \"object\") {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\tconst maybeRunId =\n\t\t\"runId\" in response\n\t\t\t? response.runId\n\t\t\t: \"job_id\" in response\n\t\t\t\t? response.job_id\n\t\t\t\t: null;\n\n\tif (typeof maybeRunId !== \"string\" || maybeRunId.length === 0) {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\treturn maybeRunId;\n}\n\nfunction resolveUrl(\n\turl: string | ((runId: string) => string),\n\trunId: string,\n): string {\n\treturn typeof url === \"function\" ? url(runId) : url.replace(\":runId\", runId);\n}\n\nasync function streamFetchSSE<\n\tTPart extends { type: string },\n\tTEvent extends { type: string },\n>(\n\tresponse: Response,\n\tcontext: ChatTransportContext<TPart, TEvent>,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`SSE request failed: ${response.status} ${response.statusText}`,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"Response body is null — SSE streaming not supported\");\n\t}\n\n\tfor await (const event of parseSSEStream(response.body, signal)) {\n\t\tcontext.emit(event as unknown as TEvent);\n\t}\n}\n\nexport function createDirectSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: DirectSSETransportOptions): ChatTransport<TPart, TEvent> {\n\treturn {\n\t\tstart: ({ context, message }) => {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst run: ChatTransportRun = {\n\t\t\t\tclose: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst fetchImpl = config.fetch ?? fetch;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.api, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.body }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.headers,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.method ?? \"POST\",\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\t\tcontext.finish();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn run;\n\t\t},\n\t};\n}\n\nexport function createBackgroundSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: BackgroundSSETransportOptions): ChatTransport<TPart, TEvent> {\n\tconst fetchImpl = config.fetch ?? fetch;\n\n\tconst connect = (\n\t\trunId: string,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t): ChatTransportRun => {\n\t\tconst controller = new AbortController();\n\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst response = await fetchImpl(resolveUrl(config.eventsApi, runId), {\n\t\t\t\t\theaders: config.eventHeaders,\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\tcontext.finish();\n\t\t\t} catch (error) {\n\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\treturn {\n\t\t\tclose: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t},\n\t\t\tstop: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t\tif (config.cancelApi) {\n\t\t\t\t\tvoid fetchImpl(resolveUrl(config.cancelApi, runId), {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\trunId,\n\t\t};\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\treturn connect(runId, context);\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst startController = new AbortController();\n\t\t\tlet activeRun: ChatTransportRun | undefined;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.startApi, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.startBody }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.startHeaders,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.startMethod ?? \"POST\",\n\t\t\t\t\t\tsignal: startController.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Background SSE start failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = (await response.json()) as unknown;\n\t\t\t\t\tconst runId = (config.resolveRunId ?? resolveRunId)(data);\n\t\t\t\t\tcontext.setRunId(runId);\n\t\t\t\t\tactiveRun = connect(runId, context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tvoid activeRun?.close?.();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tactiveRun?.stop?.();\n\t\t\t\t},\n\t\t\t\trunId: null,\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction defaultParseWebSocketMessage<TEvent extends { type: string }>(\n\tdata: unknown,\n): TEvent | TEvent[] | null {\n\tif (typeof data !== \"string\") {\n\t\treturn null;\n\t}\n\n\tconst parsed = JSON.parse(data) as TEvent | TEvent[];\n\treturn parsed;\n}\n\nexport function createWebSocketTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: WebSocketTransportOptions<TEvent>): ChatTransport<TPart, TEvent> {\n\tconst parseMessage = config.parseMessage ?? defaultParseWebSocketMessage;\n\tconst serializeMessage = config.serializeMessage ?? JSON.stringify;\n\n\tlet resolvedRunId: string | null = null;\n\n\tconst applyIncomingEvents = (\n\t\tparsed: TEvent | TEvent[] | null,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t) => {\n\t\tconst events = Array.isArray(parsed) ? parsed : parsed ? [parsed] : [];\n\t\tfor (const item of events) {\n\t\t\tconst nextRunId = config.resolveRunId?.(item) ?? null;\n\t\t\tif (nextRunId) {\n\t\t\t\tresolvedRunId = nextRunId;\n\t\t\t\tcontext.setRunId(nextRunId);\n\t\t\t}\n\t\t\tcontext.emit(item);\n\n\t\t\tif (item.type === \"done\") {\n\t\t\t\tcontext.finish();\n\t\t\t} else if (item.type === \"error\") {\n\t\t\t\tcontext.fail(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"message\" in item && typeof item.message === \"string\"\n\t\t\t\t\t\t\t? item.message\n\t\t\t\t\t\t\t: \"Stream error\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\tcontext.ensureAssistantMessage();\n\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentResumePayload = false;\n\n\t\t\tconst sendResumePayload = () => {\n\t\t\t\tif (sentResumePayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentResumePayload = true;\n\t\t\t\tconst payload =\n\t\t\t\t\tconfig.buildResumePayload?.(runId) ??\n\t\t\t\t\t({ [config.runIdKey ?? \"runId\"]: runId } as Record<string, unknown>);\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendResumePayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendResumePayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst runId = config.runId ?? config.getResumeKey?.() ?? null;\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentStartPayload = false;\n\n\t\t\tconst sendStartPayload = () => {\n\t\t\t\tif (sentStartPayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentStartPayload = true;\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst payload: Record<string, unknown> = {\n\t\t\t\t\tmessage,\n\t\t\t\t\t...config.body,\n\t\t\t\t};\n\n\t\t\t\tif (runId) {\n\t\t\t\t\tpayload[config.runIdKey ?? \"runId\"] = runId;\n\t\t\t\t}\n\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendStartPayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendStartPayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function resolveTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): ChatTransport<TPart, TEvent> {\n\tif (typeof options.transport === \"object\" && options.transport) {\n\t\treturn options.transport;\n\t}\n\n\tconst transportKind = options.transport ?? \"sse\";\n\n\tif (transportKind === \"background-sse\") {\n\t\tconst config = options.transportOptions?.backgroundSSE;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.backgroundSSE` is required when transport is \"background-sse\"',\n\t\t\t);\n\t\t}\n\t\treturn createBackgroundSSETransport(config);\n\t}\n\n\tif (transportKind === \"websocket\") {\n\t\tconst config = options.transportOptions?.websocket;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.websocket` is required when transport is \"websocket\"',\n\t\t\t);\n\t\t}\n\t\treturn createWebSocketTransport(config);\n\t}\n\n\tconst sseConfig = options.transportOptions?.sse ?? {\n\t\tapi: options.api,\n\t\tbody: options.body,\n\t\theaders: options.headers,\n\t};\n\n\tif (!sseConfig.api) {\n\t\tthrow new Error(\n\t\t\t\"`api` or `transportOptions.sse.api` is required when using the default SSE transport\",\n\t\t);\n\t}\n\n\treturn createDirectSSETransport({\n\t\t...sseConfig,\n\t\tapi: sseConfig.api,\n\t});\n}\n"],"mappings":"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","names":["import_core","import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/use-auto-scroll.ts","../src/use-stream-chat.ts","../src/chat-controller.ts","../src/transports.ts"],"sourcesContent":["// Re-export core types so consumers only need to import from @deltakit/react\nexport type {\n\tContentPart,\n\tMessage,\n\tReasoningPart,\n\tSSEEvent,\n\tTextDeltaEvent,\n\tTextPart,\n\tToolCallEvent,\n\tToolCallPart,\n\tToolResultEvent,\n} from \"@deltakit/core\";\nexport {\n\tfromAgnoAgents,\n\tfromOpenAiAgents,\n\tparseSSEStream,\n} from \"@deltakit/core\";\n\nexport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tEventHelpers,\n\tTransportOptions,\n\tUseAutoScrollOptions,\n\tUseAutoScrollReturn,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n\tWebSocketTransportOptions,\n} from \"./types\";\nexport { useAutoScroll } from \"./use-auto-scroll\";\nexport { useStreamChat } from \"./use-stream-chat\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { UseAutoScrollOptions, UseAutoScrollReturn } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_THRESHOLD = 50;\n\n// ---------------------------------------------------------------------------\n// useAutoScroll\n// ---------------------------------------------------------------------------\n\nexport function useAutoScroll<T extends HTMLElement = HTMLDivElement>(\n\tdependencies: unknown[],\n\toptions?: UseAutoScrollOptions,\n): UseAutoScrollReturn<T> {\n\tconst {\n\t\tbehavior = \"smooth\",\n\t\tenabled = true,\n\t\tthreshold = DEFAULT_THRESHOLD,\n\t} = options ?? {};\n\n\tconst ref = useRef<T | null>(null);\n\tconst behaviorRef = useRef(behavior);\n\tbehaviorRef.current = behavior;\n\tconst isAtBottomRef = useRef(true);\n\tconst [isAtBottom, setIsAtBottom] = useState(true);\n\n\t// A single rAF id shared across all scroll sources — ensures we never\n\t// call scrollTo() more than once per frame, no matter how many\n\t// MutationObserver / ResizeObserver callbacks fire.\n\tconst rafRef = useRef<number | null>(null);\n\tconst lastAutoScrollHeightRef = useRef<number | null>(null);\n\tconst pendingVerificationFramesRef = useRef(0);\n\n\tconst scheduleScroll = useCallback(() => {\n\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\tpendingVerificationFramesRef.current,\n\t\t\t1,\n\t\t);\n\t\tif (rafRef.current != null) return;\n\n\t\tconst tick = () => {\n\t\t\trafRef.current = null;\n\t\t\tconst el = ref.current;\n\t\t\tif (!el || !isAtBottomRef.current) {\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst nextHeight = el.scrollHeight;\n\t\t\tconst heightChanged = lastAutoScrollHeightRef.current !== nextHeight;\n\t\t\tconst distanceFromBottom = nextHeight - el.scrollTop - el.clientHeight;\n\n\t\t\tif (heightChanged || distanceFromBottom > 0) {\n\t\t\t\tlastAutoScrollHeightRef.current = nextHeight;\n\t\t\t\tpendingVerificationFramesRef.current = 1;\n\n\t\t\t\t// Keep the viewport pinned during streaming without restarting a\n\t\t\t\t// smooth scroll animation on every DOM mutation.\n\t\t\t\tel.scrollTo({ top: nextHeight, behavior: behaviorRef.current });\n\t\t\t} else {\n\t\t\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\t\t\tpendingVerificationFramesRef.current - 1,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (pendingVerificationFramesRef.current > 0) {\n\t\t\t\trafRef.current = requestAnimationFrame(tick);\n\t\t\t}\n\t\t};\n\n\t\trafRef.current = requestAnimationFrame(tick);\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// Track whether the user is near the bottom via scroll events.\n\t// Only triggers a React re-render when the boolean actually changes.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst handleScroll = () => {\n\t\t\tconst atBottom =\n\t\t\t\tel.scrollHeight - el.scrollTop - el.clientHeight <= threshold;\n\t\t\tisAtBottomRef.current = atBottom;\n\t\t\tif (!atBottom) {\n\t\t\t\tlastAutoScrollHeightRef.current = null;\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t}\n\t\t\tsetIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n\t\t};\n\n\t\tel.addEventListener(\"scroll\", handleScroll, { passive: true });\n\t\thandleScroll();\n\t\treturn () => el.removeEventListener(\"scroll\", handleScroll);\n\t}, [enabled, threshold]);\n\n\t// -----------------------------------------------------------------------\n\t// Scroll to bottom when dependencies change (if pinned).\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tif (!enabled || !isAtBottomRef.current) return;\n\t\tscheduleScroll();\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: dependencies are passed dynamically by the consumer\n\t}, dependencies);\n\n\t// -----------------------------------------------------------------------\n\t// MutationObserver + ResizeObserver — catch content changes during\n\t// streaming that happen between React re-renders (e.g. DOM mutations\n\t// from markdown renderers). Scroll calls are batched via rAF so we\n\t// scroll at most once per frame.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst resizeObserver = new ResizeObserver(scheduleScroll);\n\n\t\t// Observe existing children for size changes.\n\t\tfor (const child of el.children) {\n\t\t\tresizeObserver.observe(child);\n\t\t}\n\n\t\t// Watch for new children added to the container.\n\t\tconst mutationObserver = new MutationObserver((mutations) => {\n\t\t\tfor (const mutation of mutations) {\n\t\t\t\tfor (const node of mutation.addedNodes) {\n\t\t\t\t\tif (node instanceof Element) {\n\t\t\t\t\t\tresizeObserver.observe(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tscheduleScroll();\n\t\t});\n\n\t\tmutationObserver.observe(el, { childList: true, subtree: true });\n\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [enabled, scheduleScroll]);\n\n\t// -----------------------------------------------------------------------\n\t// Cancel any pending rAF on unmount.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (rafRef.current != null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t};\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// scrollToBottom — imperative function that scrolls to the bottom and\n\t// re-pins auto-scroll.\n\t// -----------------------------------------------------------------------\n\n\tconst scrollToBottom = useCallback(() => {\n\t\tconst el = ref.current;\n\t\tif (!el) return;\n\n\t\tisAtBottomRef.current = true;\n\t\tlastAutoScrollHeightRef.current = el.scrollHeight;\n\t\tpendingVerificationFramesRef.current = 0;\n\t\tsetIsAtBottom(true);\n\t\tel.scrollTo({ top: el.scrollHeight, behavior });\n\t}, [behavior]);\n\n\treturn { ref, scrollToBottom, isAtBottom };\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { createChatTransportContext, createMessage } from \"./chat-controller\";\nimport { resolveTransport } from \"./transports\";\nimport type {\n\tChatTransportRun,\n\tEventHelpers,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Default event handler — accumulates `text_delta` into the last\n// assistant message's parts.\n// ---------------------------------------------------------------------------\n\nfunction defaultOnEvent(\n\tevent: SSEEvent,\n\thelpers: EventHelpers<ContentPart>,\n): void {\n\tif (event.type === \"text_delta\") {\n\t\thelpers.appendText(event.delta);\n\t}\n\t// Other event types (e.g. tool_call) are silently ignored by default.\n\t// Users can provide their own `onEvent` to handle them.\n}\n\n// ---------------------------------------------------------------------------\n// useStreamChat\n// ---------------------------------------------------------------------------\n\nexport function useStreamChat<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart> {\n\tconst { initialMessages, onEvent, onMessage, onError, onFinish } = options;\n\n\tconst [messages, setMessages] = useState(initialMessages ?? []);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst [runId, setRunId] = useState<string | null>(null);\n\n\tconst runRef = useRef<ChatTransportRun | null>(null);\n\n\t// Track which run id has already been resumed to prevent re-triggering.\n\tconst resumedRunIdRef = useRef<string | null>(null);\n\n\t// When the user manually stops a run, suppress auto-resume until the\n\t// next explicit `sendMessage` call.\n\tconst manuallyStoppedRef = useRef(false);\n\n\t// We use a ref for the latest messages so callbacks created inside\n\t// transport handlers always see the current value without re-creating\n\t// closures.\n\tconst messagesRef = useRef(messages);\n\tmessagesRef.current = messages;\n\n\t// Keep transport options in a ref so that callbacks always read the\n\t// latest values without causing memoisation instability.\n\tconst transportOptionsRef = useRef(options.transportOptions);\n\ttransportOptionsRef.current = options.transportOptions;\n\n\tconst appendText = useCallback((delta: string) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\tconst parts = [...last.parts];\n\t\t\tconst lastPart = parts[parts.length - 1];\n\n\t\t\tif (lastPart && lastPart.type === \"text\" && \"text\" in lastPart) {\n\t\t\t\tconst textPart = lastPart as { type: \"text\"; text: string };\n\t\t\t\tparts[parts.length - 1] = {\n\t\t\t\t\t...lastPart,\n\t\t\t\t\ttext: textPart.text + delta,\n\t\t\t\t} as unknown as TPart;\n\t\t\t} else {\n\t\t\t\tparts.push({ type: \"text\", text: delta } as unknown as TPart);\n\t\t\t}\n\n\t\t\treturn [...prev.slice(0, -1), { ...last, parts }];\n\t\t});\n\t}, []);\n\n\tconst appendPart = useCallback((part: TPart) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\treturn [\n\t\t\t\t...prev.slice(0, -1),\n\t\t\t\t{\n\t\t\t\t\t...last,\n\t\t\t\t\tparts: [...last.parts, part],\n\t\t\t\t},\n\t\t\t];\n\t\t});\n\t}, []);\n\n\t// Stabilise transport creation: resolve once and store in a ref so that\n\t// changing values like `runId` in transportOptions won't cause a new\n\t// transport instance (and therefore a new WebSocket) to be created.\n\tconst transportRef = useRef<ReturnType<\n\t\ttypeof resolveTransport<TPart, TEvent>\n\t> | null>(null);\n\tif (!transportRef.current) {\n\t\ttransportRef.current = resolveTransport(options);\n\t}\n\tconst transport = transportRef.current;\n\n\tconst eventHandler =\n\t\tonEvent ??\n\t\t(defaultOnEvent as unknown as (\n\t\t\tevent: TEvent,\n\t\t\thelpers: EventHelpers<TPart>,\n\t\t) => void);\n\n\t// Stabilise the transport context: use refs for values that change\n\t// frequently (transportOptions callbacks) so the context object itself\n\t// stays referentially stable.\n\tconst eventHandlerRef = useRef(eventHandler);\n\teventHandlerRef.current = eventHandler;\n\n\tconst onErrorRef = useRef(onError);\n\tonErrorRef.current = onError;\n\n\tconst onFinishRef = useRef(onFinish);\n\tonFinishRef.current = onFinish;\n\n\tconst onMessageRef = useRef(onMessage);\n\tonMessageRef.current = onMessage;\n\n\tconst transportContext = useMemo(\n\t\t() =>\n\t\t\tcreateChatTransportContext({\n\t\t\t\tappendPart,\n\t\t\t\tappendText,\n\t\t\t\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) =>\n\t\t\t\t\teventHandlerRef.current(event, helpers),\n\t\t\t\tgetMessages: () => messagesRef.current,\n\t\t\t\tonError: (...args) => onErrorRef.current?.(...args),\n\t\t\t\tonFinish: (...args) => onFinishRef.current?.(...args),\n\t\t\t\tonMessage: (...args) => onMessageRef.current?.(...args),\n\t\t\t\tsetError,\n\t\t\t\tsetIsLoading,\n\t\t\t\tsetMessages,\n\t\t\t\tsetRunId: (next) => {\n\t\t\t\t\tsetRunId(next);\n\t\t\t\t\ttransportOptionsRef.current?.backgroundSSE?.onRunIdChange?.(next);\n\t\t\t\t\ttransportOptionsRef.current?.websocket?.onRunIdChange?.(next);\n\t\t\t\t},\n\t\t\t}),\n\t\t[appendPart, appendText],\n\t);\n\n\tconst stop = useCallback(() => {\n\t\tconst activeRun = runRef.current;\n\t\tif (!activeRun?.stop) {\n\t\t\treturn;\n\t\t}\n\n\t\tmanuallyStoppedRef.current = true;\n\t\tvoid activeRun.stop();\n\t\trunRef.current = null;\n\t\tsetIsLoading(false);\n\t}, []);\n\n\tconst sendMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (runRef.current || isLoading) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst userMessage = createMessage<TPart>(\"user\", [\n\t\t\t\t{ type: \"text\", text } as unknown as TPart,\n\t\t\t]);\n\t\t\tconst assistantMessage = createMessage<TPart>(\"assistant\", []);\n\n\t\t\tsetMessages((prev) => {\n\t\t\t\tconst next = [...prev, userMessage, assistantMessage];\n\t\t\t\tmessagesRef.current = next;\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\t\tonMessage?.(userMessage);\n\t\t\tsetError(null);\n\t\t\tsetIsLoading(true);\n\n\t\t\t// Reset the resume guard so a future resume for a new run is allowed.\n\t\t\tresumedRunIdRef.current = null;\n\t\t\tmanuallyStoppedRef.current = false;\n\n\t\t\tconst run = transport.start({ context: transportContext, message: text });\n\t\t\trunRef.current = run ?? null;\n\t\t\tif (run?.runId) {\n\t\t\t\tsetRunId(run.runId);\n\t\t\t}\n\t\t},\n\t\t[isLoading, onMessage, transport, transportContext],\n\t);\n\n\t// -----------------------------------------------------------------------\n\t// Auto-resume effect: attempt to reconnect to an in-flight run on mount.\n\t//\n\t// The candidate run id is read from transport options (which may change\n\t// when the app updates state). We guard against duplicate resumes for the\n\t// same run id using `resumedRunIdRef`.\n\t// -----------------------------------------------------------------------\n\n\tconst candidateRunId =\n\t\toptions.transportOptions?.backgroundSSE?.runId ??\n\t\toptions.transportOptions?.backgroundSSE?.getResumeKey?.() ??\n\t\toptions.transportOptions?.websocket?.runId ??\n\t\toptions.transportOptions?.websocket?.getResumeKey?.() ??\n\t\tnull;\n\n\tuseEffect(() => {\n\t\t// Already have an active run — don't start another.\n\t\tif (runRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\t// User explicitly stopped — don't auto-resume until next sendMessage.\n\t\tif (manuallyStoppedRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Already resumed this exact run id — don't retry.\n\t\tif (resumedRunIdRef.current === candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!transport.resume) {\n\t\t\treturn;\n\t\t}\n\n\t\tresumedRunIdRef.current = candidateRunId;\n\n\t\tsetError(null);\n\t\tsetIsLoading(true);\n\t\tconst run = transport.resume({\n\t\t\tcontext: transportContext,\n\t\t\trunId: candidateRunId,\n\t\t});\n\t\trunRef.current = run ?? null;\n\t\tsetRunId(candidateRunId);\n\t}, [candidateRunId, transport, transportContext]);\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tvoid runRef.current?.close?.();\n\t\t\trunRef.current = null;\n\t\t};\n\t}, []);\n\n\tconst prevIsLoadingRef = useRef(isLoading);\n\tuseEffect(() => {\n\t\t// Only clear the run ref on a true → false transition, not on mount\n\t\t// where isLoading starts as false. Clearing on mount would race with\n\t\t// the auto-resume effect and null out the run it just created.\n\t\tif (prevIsLoadingRef.current && !isLoading) {\n\t\t\trunRef.current = null;\n\t\t}\n\t\tprevIsLoadingRef.current = isLoading;\n\t}, [isLoading]);\n\n\treturn {\n\t\terror,\n\t\tisLoading,\n\t\tmessages,\n\t\trunId,\n\t\tsendMessage,\n\t\tsetMessages,\n\t\tstop,\n\t};\n}\n","import type { ContentPart, Message, SSEEvent } from \"@deltakit/core\";\nimport type { Dispatch, SetStateAction } from \"react\";\nimport type {\n\tChatTransportContext,\n\tEventHelpers,\n\tUseStreamChatOptions,\n} from \"./types\";\n\nexport interface ChatControllerOptions<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n> {\n\tappendPart: EventHelpers<TPart>[\"appendPart\"];\n\tappendText: EventHelpers<TPart>[\"appendText\"];\n\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) => void;\n\tgetMessages: () => Message<TPart>[];\n\tonError?: UseStreamChatOptions<TPart, TEvent>[\"onError\"];\n\tonFinish?: UseStreamChatOptions<TPart, TEvent>[\"onFinish\"];\n\tonMessage?: UseStreamChatOptions<TPart, TEvent>[\"onMessage\"];\n\tsetError: Dispatch<SetStateAction<Error | null>>;\n\tsetIsLoading: Dispatch<SetStateAction<boolean>>;\n\tsetMessages: Dispatch<SetStateAction<Message<TPart>[]>>;\n\tsetRunId: (runId: string | null) => void;\n}\n\nlet counter = 0;\n\nexport function generateId(): string {\n\treturn `msg_${Date.now()}_${++counter}`;\n}\n\nexport function createMessage<TPart extends { type: string }>(\n\trole: Message[\"role\"],\n\tparts: TPart[],\n): Message<TPart> {\n\treturn { id: generateId(), role, parts };\n}\n\nexport function createChatTransportContext<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(\n\toptions: ChatControllerOptions<TPart, TEvent>,\n): ChatTransportContext<TPart, TEvent> {\n\tconst helpers: EventHelpers<TPart> = {\n\t\tappendPart: options.appendPart,\n\t\tappendText: options.appendText,\n\t\tsetMessages: options.setMessages,\n\t};\n\n\treturn {\n\t\temit: (event) => {\n\t\t\toptions.eventHandler(event, helpers);\n\t\t},\n\t\tensureAssistantMessage: () => {\n\t\t\toptions.setMessages((prev) => {\n\t\t\t\tconst last = prev[prev.length - 1];\n\t\t\t\tif (last?.role === \"assistant\") {\n\t\t\t\t\treturn prev;\n\t\t\t\t}\n\n\t\t\t\treturn [...prev, createMessage<TPart>(\"assistant\", [])];\n\t\t\t});\n\t\t},\n\t\tfail: (error) => {\n\t\t\toptions.setError(error);\n\t\t\toptions.onError?.(error);\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\t\t},\n\t\tfinish: () => {\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\n\t\t\tconst finalMessages = options.getMessages();\n\t\t\tconst lastMessage = finalMessages[finalMessages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\toptions.onMessage?.(lastMessage);\n\t\t\t}\n\n\t\t\toptions.onFinish?.(finalMessages);\n\t\t},\n\t\tgetMessages: options.getMessages,\n\t\tsetRunId: (runId) => {\n\t\t\toptions.setRunId(runId);\n\t\t},\n\t};\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { parseSSEStream } from \"@deltakit/core\";\nimport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tUseStreamChatOptions,\n\tWebSocketTransportOptions,\n} from \"./types\";\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction isAbortError(error: unknown): boolean {\n\treturn error instanceof DOMException && error.name === \"AbortError\";\n}\n\nfunction resolveRunId(response: unknown): string {\n\tif (!response || typeof response !== \"object\") {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\tconst maybeRunId =\n\t\t\"runId\" in response\n\t\t\t? response.runId\n\t\t\t: \"job_id\" in response\n\t\t\t\t? response.job_id\n\t\t\t\t: null;\n\n\tif (typeof maybeRunId !== \"string\" || maybeRunId.length === 0) {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\treturn maybeRunId;\n}\n\nfunction resolveUrl(\n\turl: string | ((runId: string) => string),\n\trunId: string,\n): string {\n\treturn typeof url === \"function\" ? url(runId) : url.replace(\":runId\", runId);\n}\n\nasync function streamFetchSSE<\n\tTPart extends { type: string },\n\tTEvent extends { type: string },\n>(\n\tresponse: Response,\n\tcontext: ChatTransportContext<TPart, TEvent>,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`SSE request failed: ${response.status} ${response.statusText}`,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"Response body is null — SSE streaming not supported\");\n\t}\n\n\tfor await (const event of parseSSEStream(response.body, signal)) {\n\t\tcontext.emit(event as unknown as TEvent);\n\t}\n}\n\nexport function createDirectSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: DirectSSETransportOptions): ChatTransport<TPart, TEvent> {\n\treturn {\n\t\tstart: ({ context, message }) => {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst run: ChatTransportRun = {\n\t\t\t\tclose: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst fetchImpl = config.fetch ?? fetch;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.api, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.body }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.headers,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.method ?? \"POST\",\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\t\tcontext.finish();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn run;\n\t\t},\n\t};\n}\n\nexport function createBackgroundSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: BackgroundSSETransportOptions): ChatTransport<TPart, TEvent> {\n\tconst fetchImpl = config.fetch ?? fetch;\n\n\tconst connect = (\n\t\trunId: string,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t): ChatTransportRun => {\n\t\tconst controller = new AbortController();\n\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst response = await fetchImpl(resolveUrl(config.eventsApi, runId), {\n\t\t\t\t\theaders: config.eventHeaders,\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\tcontext.finish();\n\t\t\t} catch (error) {\n\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\treturn {\n\t\t\tclose: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t},\n\t\t\tstop: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t\tif (config.cancelApi) {\n\t\t\t\t\tvoid fetchImpl(resolveUrl(config.cancelApi, runId), {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\trunId,\n\t\t};\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\treturn connect(runId, context);\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst startController = new AbortController();\n\t\t\tlet activeRun: ChatTransportRun | undefined;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.startApi, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.startBody }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.startHeaders,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.startMethod ?? \"POST\",\n\t\t\t\t\t\tsignal: startController.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Background SSE start failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = (await response.json()) as unknown;\n\t\t\t\t\tconst runId = (config.resolveRunId ?? resolveRunId)(data);\n\t\t\t\t\tcontext.setRunId(runId);\n\t\t\t\t\tactiveRun = connect(runId, context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tvoid activeRun?.close?.();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tactiveRun?.stop?.();\n\t\t\t\t},\n\t\t\t\trunId: null,\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction defaultParseWebSocketMessage<TEvent extends { type: string }>(\n\tdata: unknown,\n): TEvent | TEvent[] | null {\n\tif (typeof data !== \"string\") {\n\t\treturn null;\n\t}\n\n\tconst parsed = JSON.parse(data) as TEvent | TEvent[];\n\treturn parsed;\n}\n\nexport function createWebSocketTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: WebSocketTransportOptions<TEvent>): ChatTransport<TPart, TEvent> {\n\tconst parseMessage = config.parseMessage ?? defaultParseWebSocketMessage;\n\tconst serializeMessage = config.serializeMessage ?? JSON.stringify;\n\n\tlet resolvedRunId: string | null = null;\n\n\tconst applyIncomingEvents = (\n\t\tparsed: TEvent | TEvent[] | null,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t) => {\n\t\tconst events = Array.isArray(parsed) ? parsed : parsed ? [parsed] : [];\n\t\tfor (const item of events) {\n\t\t\tconst nextRunId = config.resolveRunId?.(item) ?? null;\n\t\t\tif (nextRunId) {\n\t\t\t\tresolvedRunId = nextRunId;\n\t\t\t\tcontext.setRunId(nextRunId);\n\t\t\t}\n\t\t\tcontext.emit(item);\n\n\t\t\tif (item.type === \"done\") {\n\t\t\t\tcontext.finish();\n\t\t\t} else if (item.type === \"error\") {\n\t\t\t\tcontext.fail(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"message\" in item && typeof item.message === \"string\"\n\t\t\t\t\t\t\t? item.message\n\t\t\t\t\t\t\t: \"Stream error\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\tcontext.ensureAssistantMessage();\n\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentResumePayload = false;\n\n\t\t\tconst sendResumePayload = () => {\n\t\t\t\tif (sentResumePayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentResumePayload = true;\n\t\t\t\tconst payload =\n\t\t\t\t\tconfig.buildResumePayload?.(runId) ??\n\t\t\t\t\t({ [config.runIdKey ?? \"runId\"]: runId } as Record<string, unknown>);\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendResumePayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendResumePayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst runId = config.runId ?? config.getResumeKey?.() ?? null;\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentStartPayload = false;\n\n\t\t\tconst sendStartPayload = () => {\n\t\t\t\tif (sentStartPayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentStartPayload = true;\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst payload: Record<string, unknown> = {\n\t\t\t\t\tmessage,\n\t\t\t\t\t...config.body,\n\t\t\t\t};\n\n\t\t\t\tif (runId) {\n\t\t\t\t\tpayload[config.runIdKey ?? \"runId\"] = runId;\n\t\t\t\t}\n\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendStartPayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendStartPayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function resolveTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): ChatTransport<TPart, TEvent> {\n\tif (typeof options.transport === \"object\" && options.transport) {\n\t\treturn options.transport;\n\t}\n\n\tconst transportKind = options.transport ?? \"sse\";\n\n\tif (transportKind === \"background-sse\") {\n\t\tconst config = options.transportOptions?.backgroundSSE;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.backgroundSSE` is required when transport is \"background-sse\"',\n\t\t\t);\n\t\t}\n\t\treturn createBackgroundSSETransport(config);\n\t}\n\n\tif (transportKind === \"websocket\") {\n\t\tconst config = options.transportOptions?.websocket;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.websocket` is required when transport is \"websocket\"',\n\t\t\t);\n\t\t}\n\t\treturn createWebSocketTransport(config);\n\t}\n\n\tconst sseConfig = options.transportOptions?.sse ?? {\n\t\tapi: options.api,\n\t\tbody: options.body,\n\t\theaders: options.headers,\n\t};\n\n\tif (!sseConfig.api) {\n\t\tthrow new Error(\n\t\t\t\"`api` or `transportOptions.sse.api` is required when using the default SSE transport\",\n\t\t);\n\t}\n\n\treturn createDirectSSETransport({\n\t\t...sseConfig,\n\t\tapi: sseConfig.api,\n\t});\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,IAAAA,eAIO;;;AChBP,mBAAyD;AAOzD,IAAM,oBAAoB;AAMnB,SAAS,cACf,cACA,SACyB;AACzB,QAAM;AAAA,IACL,WAAW;AAAA,IACX,UAAU;AAAA,IACV,YAAY;AAAA,EACb,IAAI,WAAW,CAAC;AAEhB,QAAM,UAAM,qBAAiB,IAAI;AACjC,QAAM,kBAAc,qBAAO,QAAQ;AACnC,cAAY,UAAU;AACtB,QAAM,oBAAgB,qBAAO,IAAI;AACjC,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,IAAI;AAKjD,QAAM,aAAS,qBAAsB,IAAI;AACzC,QAAM,8BAA0B,qBAAsB,IAAI;AAC1D,QAAM,mCAA+B,qBAAO,CAAC;AAE7C,QAAM,qBAAiB,0BAAY,MAAM;AACxC,iCAA6B,UAAU,KAAK;AAAA,MAC3C,6BAA6B;AAAA,MAC7B;AAAA,IACD;AACA,QAAI,OAAO,WAAW,KAAM;AAE5B,UAAM,OAAO,MAAM;AAClB,aAAO,UAAU;AACjB,YAAM,KAAK,IAAI;AACf,UAAI,CAAC,MAAM,CAAC,cAAc,SAAS;AAClC,qCAA6B,UAAU;AACvC;AAAA,MACD;AAEA,YAAM,aAAa,GAAG;AACtB,YAAM,gBAAgB,wBAAwB,YAAY;AAC1D,YAAM,qBAAqB,aAAa,GAAG,YAAY,GAAG;AAE1D,UAAI,iBAAiB,qBAAqB,GAAG;AAC5C,gCAAwB,UAAU;AAClC,qCAA6B,UAAU;AAIvC,WAAG,SAAS,EAAE,KAAK,YAAY,UAAU,YAAY,QAAQ,CAAC;AAAA,MAC/D,OAAO;AACN,qCAA6B,UAAU,KAAK;AAAA,UAC3C,6BAA6B,UAAU;AAAA,UACvC;AAAA,QACD;AAAA,MACD;AAEA,UAAI,6BAA6B,UAAU,GAAG;AAC7C,eAAO,UAAU,sBAAsB,IAAI;AAAA,MAC5C;AAAA,IACD;AAEA,WAAO,UAAU,sBAAsB,IAAI;AAAA,EAC5C,GAAG,CAAC,CAAC;AAOL,8BAAU,MAAM;AACf,UAAM,KAAK,IAAI;AACf,QAAI,CAAC,MAAM,CAAC,QAAS;AAErB,UAAM,eAAe,MAAM;AAC1B,YAAM,WACL,GAAG,eAAe,GAAG,YAAY,GAAG,gBAAgB;AACrD,oBAAc,UAAU;AACxB,UAAI,CAAC,UAAU;AACd,gCAAwB,UAAU;AAClC,qCAA6B,UAAU;AAAA,MACxC;AACA,oBAAc,CAAC,SAAU,SAAS,WAAW,OAAO,QAAS;AAAA,IAC9D;AAEA,OAAG,iBAAiB,UAAU,cAAc,EAAE,SAAS,KAAK,CAAC;AAC7D,iBAAa;AACb,WAAO,MAAM,GAAG,oBAAoB,UAAU,YAAY;AAAA,EAC3D,GAAG,CAAC,SAAS,SAAS,CAAC;AAMvB,8BAAU,MAAM;AACf,QAAI,CAAC,WAAW,CAAC,cAAc,QAAS;AACxC,mBAAe;AAAA,EAEhB,GAAG,YAAY;AASf,8BAAU,MAAM;AACf,UAAM,KAAK,IAAI;AACf,QAAI,CAAC,MAAM,CAAC,QAAS;AAErB,UAAM,iBAAiB,IAAI,eAAe,cAAc;AAGxD,eAAW,SAAS,GAAG,UAAU;AAChC,qBAAe,QAAQ,KAAK;AAAA,IAC7B;AAGA,UAAM,mBAAmB,IAAI,iBAAiB,CAAC,cAAc;AAC5D,iBAAW,YAAY,WAAW;AACjC,mBAAW,QAAQ,SAAS,YAAY;AACvC,cAAI,gBAAgB,SAAS;AAC5B,2BAAe,QAAQ,IAAI;AAAA,UAC5B;AAAA,QACD;AAAA,MACD;AACA,qBAAe;AAAA,IAChB,CAAC;AAED,qBAAiB,QAAQ,IAAI,EAAE,WAAW,MAAM,SAAS,KAAK,CAAC;AAE/D,WAAO,MAAM;AACZ,qBAAe,WAAW;AAC1B,uBAAiB,WAAW;AAAA,IAC7B;AAAA,EACD,GAAG,CAAC,SAAS,cAAc,CAAC;AAM5B,8BAAU,MAAM;AACf,WAAO,MAAM;AACZ,UAAI,OAAO,WAAW,MAAM;AAC3B,6BAAqB,OAAO,OAAO;AACnC,eAAO,UAAU;AAAA,MAClB;AACA,mCAA6B,UAAU;AAAA,IACxC;AAAA,EACD,GAAG,CAAC,CAAC;AAOL,QAAM,qBAAiB,0BAAY,MAAM;AACxC,UAAM,KAAK,IAAI;AACf,QAAI,CAAC,GAAI;AAET,kBAAc,UAAU;AACxB,4BAAwB,UAAU,GAAG;AACrC,iCAA6B,UAAU;AACvC,kBAAc,IAAI;AAClB,OAAG,SAAS,EAAE,KAAK,GAAG,cAAc,SAAS,CAAC;AAAA,EAC/C,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO,EAAE,KAAK,gBAAgB,WAAW;AAC1C;;;ACpLA,IAAAC,gBAAkE;;;ACwBlE,IAAI,UAAU;AAEP,SAAS,aAAqB;AACpC,SAAO,OAAO,KAAK,IAAI,CAAC,IAAI,EAAE,OAAO;AACtC;AAEO,SAAS,cACf,MACA,OACiB;AACjB,SAAO,EAAE,IAAI,WAAW,GAAG,MAAM,MAAM;AACxC;AAEO,SAAS,2BAIf,SACsC;AACtC,QAAM,UAA+B;AAAA,IACpC,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,IACpB,aAAa,QAAQ;AAAA,EACtB;AAEA,SAAO;AAAA,IACN,MAAM,CAAC,UAAU;AAChB,cAAQ,aAAa,OAAO,OAAO;AAAA,IACpC;AAAA,IACA,wBAAwB,MAAM;AAC7B,cAAQ,YAAY,CAAC,SAAS;AAC7B,cAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,YAAI,MAAM,SAAS,aAAa;AAC/B,iBAAO;AAAA,QACR;AAEA,eAAO,CAAC,GAAG,MAAM,cAAqB,aAAa,CAAC,CAAC,CAAC;AAAA,MACvD,CAAC;AAAA,IACF;AAAA,IACA,MAAM,CAAC,UAAU;AAChB,cAAQ,SAAS,KAAK;AACtB,cAAQ,UAAU,KAAK;AACvB,cAAQ,aAAa,KAAK;AAC1B,cAAQ,SAAS,IAAI;AAAA,IACtB;AAAA,IACA,QAAQ,MAAM;AACb,cAAQ,aAAa,KAAK;AAC1B,cAAQ,SAAS,IAAI;AAErB,YAAM,gBAAgB,QAAQ,YAAY;AAC1C,YAAM,cAAc,cAAc,cAAc,SAAS,CAAC;AAE1D,UAAI,aAAa,SAAS,aAAa;AACtC,gBAAQ,YAAY,WAAW;AAAA,MAChC;AAEA,cAAQ,WAAW,aAAa;AAAA,IACjC;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,UAAU,CAAC,UAAU;AACpB,cAAQ,SAAS,KAAK;AAAA,IACvB;AAAA,EACD;AACD;;;ACvFA,kBAA+B;AAW/B,SAAS,QAAQ,OAAuB;AACvC,SAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAChE;AAEA,SAAS,aAAa,OAAyB;AAC9C,SAAO,iBAAiB,gBAAgB,MAAM,SAAS;AACxD;AAEA,SAAS,aAAa,UAA2B;AAChD,MAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC9C,UAAM,IAAI,MAAM,wDAAwD;AAAA,EACzE;AAEA,QAAM,aACL,WAAW,WACR,SAAS,QACT,YAAY,WACX,SAAS,SACT;AAEL,MAAI,OAAO,eAAe,YAAY,WAAW,WAAW,GAAG;AAC9D,UAAM,IAAI,MAAM,wDAAwD;AAAA,EACzE;AAEA,SAAO;AACR;AAEA,SAAS,WACR,KACA,OACS;AACT,SAAO,OAAO,QAAQ,aAAa,IAAI,KAAK,IAAI,IAAI,QAAQ,UAAU,KAAK;AAC5E;AAEA,eAAe,eAId,UACA,SACA,QACgB;AAChB,MAAI,CAAC,SAAS,IAAI;AACjB,UAAM,IAAI;AAAA,MACT,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,IAC9D;AAAA,EACD;AAEA,MAAI,CAAC,SAAS,MAAM;AACnB,UAAM,IAAI,MAAM,0DAAqD;AAAA,EACtE;AAEA,mBAAiB,aAAS,4BAAe,SAAS,MAAM,MAAM,GAAG;AAChE,YAAQ,KAAK,KAA0B;AAAA,EACxC;AACD;AAEO,SAAS,yBAGd,QAAiE;AAClE,SAAO;AAAA,IACN,OAAO,CAAC,EAAE,SAAS,QAAQ,MAAM;AAChC,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,MAAwB;AAAA,QAC7B,OAAO,MAAM;AACZ,qBAAW,MAAM;AAAA,QAClB;AAAA,QACA,MAAM,MAAM;AACX,qBAAW,MAAM;AAAA,QAClB;AAAA,MACD;AAEA,YAAM,YAAY,OAAO,SAAS;AAElC,YAAM,YAAY;AACjB,YAAI;AACH,gBAAM,WAAW,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5C,MAAM,KAAK,UAAU,EAAE,SAAS,GAAG,OAAO,KAAK,CAAC;AAAA,YAChD,SAAS;AAAA,cACR,gBAAgB;AAAA,cAChB,GAAG,OAAO;AAAA,YACX;AAAA,YACA,QAAQ,OAAO,UAAU;AAAA,YACzB,QAAQ,WAAW;AAAA,UACpB,CAAC;AAED,gBAAM,eAAe,UAAU,SAAS,WAAW,MAAM;AACzD,kBAAQ,OAAO;AAAA,QAChB,SAAS,OAAO;AACf,cAAI,CAAC,aAAa,KAAK,GAAG;AACzB,oBAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,UAC5B;AAAA,QACD;AAAA,MACD,GAAG;AAEH,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAEO,SAAS,6BAGd,QAAqE;AACtE,QAAM,YAAY,OAAO,SAAS;AAElC,QAAM,UAAU,CACf,OACA,YACsB;AACtB,UAAM,aAAa,IAAI,gBAAgB;AAEvC,UAAM,YAAY;AACjB,UAAI;AACH,gBAAQ,uBAAuB;AAC/B,cAAM,WAAW,MAAM,UAAU,WAAW,OAAO,WAAW,KAAK,GAAG;AAAA,UACrE,SAAS,OAAO;AAAA,UAChB,QAAQ;AAAA,UACR,QAAQ,WAAW;AAAA,QACpB,CAAC;AACD,cAAM,eAAe,UAAU,SAAS,WAAW,MAAM;AACzD,gBAAQ,OAAO;AAAA,MAChB,SAAS,OAAO;AACf,YAAI,CAAC,aAAa,KAAK,GAAG;AACzB,kBAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,QAC5B;AAAA,MACD;AAAA,IACD,GAAG;AAEH,WAAO;AAAA,MACN,OAAO,MAAM;AACZ,mBAAW,MAAM;AAAA,MAClB;AAAA,MACA,MAAM,MAAM;AACX,mBAAW,MAAM;AACjB,YAAI,OAAO,WAAW;AACrB,eAAK,UAAU,WAAW,OAAO,WAAW,KAAK,GAAG;AAAA,YACnD,QAAQ;AAAA,UACT,CAAC;AAAA,QACF;AAAA,MACD;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,QAAQ,CAAC,EAAE,SAAS,MAAM,MAAM;AAC/B,cAAQ,SAAS,KAAK;AACtB,aAAO,QAAQ,OAAO,OAAO;AAAA,IAC9B;AAAA,IACA,OAAO,CAAC,EAAE,SAAS,QAAQ,MAAM;AAChC,YAAM,kBAAkB,IAAI,gBAAgB;AAC5C,UAAI;AAEJ,YAAM,YAAY;AACjB,YAAI;AACH,gBAAM,WAAW,MAAM,UAAU,OAAO,UAAU;AAAA,YACjD,MAAM,KAAK,UAAU,EAAE,SAAS,GAAG,OAAO,UAAU,CAAC;AAAA,YACrD,SAAS;AAAA,cACR,gBAAgB;AAAA,cAChB,GAAG,OAAO;AAAA,YACX;AAAA,YACA,QAAQ,OAAO,eAAe;AAAA,YAC9B,QAAQ,gBAAgB;AAAA,UACzB,CAAC;AAED,cAAI,CAAC,SAAS,IAAI;AACjB,kBAAM,IAAI;AAAA,cACT,gCAAgC,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,YACvE;AAAA,UACD;AAEA,gBAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,gBAAM,SAAS,OAAO,gBAAgB,cAAc,IAAI;AACxD,kBAAQ,SAAS,KAAK;AACtB,sBAAY,QAAQ,OAAO,OAAO;AAAA,QACnC,SAAS,OAAO;AACf,cAAI,CAAC,aAAa,KAAK,GAAG;AACzB,oBAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,UAC5B;AAAA,QACD;AAAA,MACD,GAAG;AAEH,aAAO;AAAA,QACN,OAAO,MAAM;AACZ,0BAAgB,MAAM;AACtB,eAAK,WAAW,QAAQ;AAAA,QACzB;AAAA,QACA,MAAM,MAAM;AACX,0BAAgB,MAAM;AACtB,qBAAW,OAAO;AAAA,QACnB;AAAA,QACA,OAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACD;AAEA,SAAS,6BACR,MAC2B;AAC3B,MAAI,OAAO,SAAS,UAAU;AAC7B,WAAO;AAAA,EACR;AAEA,QAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,SAAO;AACR;AAEO,SAAS,yBAGd,QAAyE;AAC1E,QAAM,eAAe,OAAO,gBAAgB;AAC5C,QAAM,mBAAmB,OAAO,oBAAoB,KAAK;AAEzD,MAAI,gBAA+B;AAEnC,QAAM,sBAAsB,CAC3B,QACA,YACI;AACJ,UAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC;AACrE,eAAW,QAAQ,QAAQ;AAC1B,YAAM,YAAY,OAAO,eAAe,IAAI,KAAK;AACjD,UAAI,WAAW;AACd,wBAAgB;AAChB,gBAAQ,SAAS,SAAS;AAAA,MAC3B;AACA,cAAQ,KAAK,IAAI;AAEjB,UAAI,KAAK,SAAS,QAAQ;AACzB,gBAAQ,OAAO;AAAA,MAChB,WAAW,KAAK,SAAS,SAAS;AACjC,gBAAQ;AAAA,UACP,IAAI;AAAA,YACH,aAAa,QAAQ,OAAO,KAAK,YAAY,WAC1C,KAAK,UACL;AAAA,UACJ;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,QAAQ,CAAC,EAAE,SAAS,MAAM,MAAM;AAC/B,cAAQ,SAAS,KAAK;AACtB,cAAQ,uBAAuB;AAE/B,YAAM,SAAS,IAAI;AAAA,QAClB,OAAO,OAAO,QAAQ,aAAa,OAAO,IAAI,KAAK,IAAI,OAAO;AAAA,QAC9D,OAAO;AAAA,MACR;AACA,UAAI,iBAAiB;AACrB,UAAI,oBAAoB;AAExB,YAAM,oBAAoB,MAAM;AAC/B,YAAI,qBAAqB,OAAO,eAAe,UAAU,MAAM;AAC9D;AAAA,QACD;AACA,4BAAoB;AACpB,cAAM,UACL,OAAO,qBAAqB,KAAK,KAChC,EAAE,CAAC,OAAO,YAAY,OAAO,GAAG,MAAM;AACxC,eAAO,KAAK,iBAAiB,OAAO,CAAC;AAAA,MACtC;AAEA,aAAO,SAAS;AAEhB,aAAO,YAAY,CAAC,UAAU;AAC7B,YAAI;AACH,8BAAoB,aAAa,MAAM,IAAI,GAAG,OAAO;AAAA,QACtD,SAAS,OAAO;AACf,kBAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,QAC5B;AAAA,MACD;AAEA,aAAO,UAAU,MAAM;AACtB,gBAAQ,KAAK,IAAI,MAAM,6BAA6B,CAAC;AAAA,MACtD;AAEA,aAAO,UAAU,MAAM;AACtB,YAAI,CAAC,gBAAgB;AACpB,kBAAQ,OAAO;AAAA,QAChB;AAAA,MACD;AAEA,qBAAe,iBAAiB;AAEhC,aAAO;AAAA,QACN,OAAO,MAAM;AACZ,2BAAiB;AACjB,iBAAO,MAAM;AAAA,QACd;AAAA,QACA,MAAM,MAAM;AACX,2BAAiB;AACjB,gBAAM,YAAY,iBAAiB;AACnC,cAAI,aAAa,OAAO,WAAW;AAClC,iBAAK,MAAM,WAAW,OAAO,WAAW,SAAS,GAAG;AAAA,cACnD,QAAQ;AAAA,YACT,CAAC;AAAA,UACF;AACA,iBAAO,MAAM;AAAA,QACd;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,IACA,OAAO,CAAC,EAAE,SAAS,QAAQ,MAAM;AAChC,YAAM,QAAQ,OAAO,SAAS,OAAO,eAAe,KAAK;AACzD,YAAM,SAAS,IAAI;AAAA,QAClB,OAAO,OAAO,QAAQ,aAAa,OAAO,IAAI,KAAK,IAAI,OAAO;AAAA,QAC9D,OAAO;AAAA,MACR;AACA,UAAI,iBAAiB;AACrB,UAAI,mBAAmB;AAEvB,YAAM,mBAAmB,MAAM;AAC9B,YAAI,oBAAoB,OAAO,eAAe,UAAU,MAAM;AAC7D;AAAA,QACD;AACA,2BAAmB;AACnB,gBAAQ,uBAAuB;AAC/B,cAAM,UAAmC;AAAA,UACxC;AAAA,UACA,GAAG,OAAO;AAAA,QACX;AAEA,YAAI,OAAO;AACV,kBAAQ,OAAO,YAAY,OAAO,IAAI;AAAA,QACvC;AAEA,eAAO,KAAK,iBAAiB,OAAO,CAAC;AAAA,MACtC;AAEA,aAAO,SAAS;AAEhB,aAAO,YAAY,CAAC,UAAU;AAC7B,YAAI;AACH,8BAAoB,aAAa,MAAM,IAAI,GAAG,OAAO;AAAA,QACtD,SAAS,OAAO;AACf,kBAAQ,KAAK,QAAQ,KAAK,CAAC;AAAA,QAC5B;AAAA,MACD;AAEA,aAAO,UAAU,MAAM;AACtB,gBAAQ,KAAK,IAAI,MAAM,6BAA6B,CAAC;AAAA,MACtD;AAEA,aAAO,UAAU,MAAM;AACtB,YAAI,CAAC,gBAAgB;AACpB,kBAAQ,OAAO;AAAA,QAChB;AAAA,MACD;AAEA,qBAAe,gBAAgB;AAE/B,aAAO;AAAA,QACN,OAAO,MAAM;AACZ,2BAAiB;AACjB,iBAAO,MAAM;AAAA,QACd;AAAA,QACA,MAAM,MAAM;AACX,2BAAiB;AACjB,gBAAM,YAAY,iBAAiB;AACnC,cAAI,aAAa,OAAO,WAAW;AAClC,iBAAK,MAAM,WAAW,OAAO,WAAW,SAAS,GAAG;AAAA,cACnD,QAAQ;AAAA,YACT,CAAC;AAAA,UACF;AACA,iBAAO,MAAM;AAAA,QACd;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAEO,SAAS,iBAGd,SAA4E;AAC7E,MAAI,OAAO,QAAQ,cAAc,YAAY,QAAQ,WAAW;AAC/D,WAAO,QAAQ;AAAA,EAChB;AAEA,QAAM,gBAAgB,QAAQ,aAAa;AAE3C,MAAI,kBAAkB,kBAAkB;AACvC,UAAM,SAAS,QAAQ,kBAAkB;AACzC,QAAI,CAAC,QAAQ;AACZ,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AACA,WAAO,6BAA6B,MAAM;AAAA,EAC3C;AAEA,MAAI,kBAAkB,aAAa;AAClC,UAAM,SAAS,QAAQ,kBAAkB;AACzC,QAAI,CAAC,QAAQ;AACZ,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AACA,WAAO,yBAAyB,MAAM;AAAA,EACvC;AAEA,QAAM,YAAY,QAAQ,kBAAkB,OAAO;AAAA,IAClD,KAAK,QAAQ;AAAA,IACb,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,EAClB;AAEA,MAAI,CAAC,UAAU,KAAK;AACnB,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAEA,SAAO,yBAAyB;AAAA,IAC/B,GAAG;AAAA,IACH,KAAK,UAAU;AAAA,EAChB,CAAC;AACF;;;AFraA,SAAS,eACR,OACA,SACO;AACP,MAAI,MAAM,SAAS,cAAc;AAChC,YAAQ,WAAW,MAAM,KAAK;AAAA,EAC/B;AAGD;AAMO,SAAS,cAGd,SAA0E;AAC3E,QAAM,EAAE,iBAAiB,SAAS,WAAW,SAAS,SAAS,IAAI;AAEnE,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,mBAAmB,CAAC,CAAC;AAC9D,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAuB,IAAI;AACrD,QAAM,CAAC,OAAO,QAAQ,QAAI,wBAAwB,IAAI;AAEtD,QAAM,aAAS,sBAAgC,IAAI;AAGnD,QAAM,sBAAkB,sBAAsB,IAAI;AAIlD,QAAM,yBAAqB,sBAAO,KAAK;AAKvC,QAAM,kBAAc,sBAAO,QAAQ;AACnC,cAAY,UAAU;AAItB,QAAM,0BAAsB,sBAAO,QAAQ,gBAAgB;AAC3D,sBAAoB,UAAU,QAAQ;AAEtC,QAAM,iBAAa,2BAAY,CAAC,UAAkB;AACjD,gBAAY,CAAC,SAAS;AACrB,YAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,UAAI,CAAC,QAAQ,KAAK,SAAS,YAAa,QAAO;AAE/C,YAAM,QAAQ,CAAC,GAAG,KAAK,KAAK;AAC5B,YAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AAEvC,UAAI,YAAY,SAAS,SAAS,UAAU,UAAU,UAAU;AAC/D,cAAM,WAAW;AACjB,cAAM,MAAM,SAAS,CAAC,IAAI;AAAA,UACzB,GAAG;AAAA,UACH,MAAM,SAAS,OAAO;AAAA,QACvB;AAAA,MACD,OAAO;AACN,cAAM,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,CAAqB;AAAA,MAC7D;AAEA,aAAO,CAAC,GAAG,KAAK,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC;AAAA,IACjD,CAAC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAa,2BAAY,CAAC,SAAgB;AAC/C,gBAAY,CAAC,SAAS;AACrB,YAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,UAAI,CAAC,QAAQ,KAAK,SAAS,YAAa,QAAO;AAE/C,aAAO;AAAA,QACN,GAAG,KAAK,MAAM,GAAG,EAAE;AAAA,QACnB;AAAA,UACC,GAAG;AAAA,UACH,OAAO,CAAC,GAAG,KAAK,OAAO,IAAI;AAAA,QAC5B;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF,GAAG,CAAC,CAAC;AAKL,QAAM,mBAAe,sBAEX,IAAI;AACd,MAAI,CAAC,aAAa,SAAS;AAC1B,iBAAa,UAAU,iBAAiB,OAAO;AAAA,EAChD;AACA,QAAM,YAAY,aAAa;AAE/B,QAAM,eACL,WACC;AAQF,QAAM,sBAAkB,sBAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,QAAM,iBAAa,sBAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,kBAAc,sBAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,QAAM,mBAAe,sBAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,uBAAmB;AAAA,IACxB,MACC,2BAA2B;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,cAAc,CAAC,OAAe,YAC7B,gBAAgB,QAAQ,OAAO,OAAO;AAAA,MACvC,aAAa,MAAM,YAAY;AAAA,MAC/B,SAAS,IAAI,SAAS,WAAW,UAAU,GAAG,IAAI;AAAA,MAClD,UAAU,IAAI,SAAS,YAAY,UAAU,GAAG,IAAI;AAAA,MACpD,WAAW,IAAI,SAAS,aAAa,UAAU,GAAG,IAAI;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,CAAC,SAAS;AACnB,iBAAS,IAAI;AACb,4BAAoB,SAAS,eAAe,gBAAgB,IAAI;AAChE,4BAAoB,SAAS,WAAW,gBAAgB,IAAI;AAAA,MAC7D;AAAA,IACD,CAAC;AAAA,IACF,CAAC,YAAY,UAAU;AAAA,EACxB;AAEA,QAAM,WAAO,2BAAY,MAAM;AAC9B,UAAM,YAAY,OAAO;AACzB,QAAI,CAAC,WAAW,MAAM;AACrB;AAAA,IACD;AAEA,uBAAmB,UAAU;AAC7B,SAAK,UAAU,KAAK;AACpB,WAAO,UAAU;AACjB,iBAAa,KAAK;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAc;AAAA,IACnB,CAAC,SAAiB;AACjB,UAAI,OAAO,WAAW,WAAW;AAChC;AAAA,MACD;AAEA,YAAM,cAAc,cAAqB,QAAQ;AAAA,QAChD,EAAE,MAAM,QAAQ,KAAK;AAAA,MACtB,CAAC;AACD,YAAM,mBAAmB,cAAqB,aAAa,CAAC,CAAC;AAE7D,kBAAY,CAAC,SAAS;AACrB,cAAM,OAAO,CAAC,GAAG,MAAM,aAAa,gBAAgB;AACpD,oBAAY,UAAU;AACtB,eAAO;AAAA,MACR,CAAC;AAED,kBAAY,WAAW;AACvB,eAAS,IAAI;AACb,mBAAa,IAAI;AAGjB,sBAAgB,UAAU;AAC1B,yBAAmB,UAAU;AAE7B,YAAM,MAAM,UAAU,MAAM,EAAE,SAAS,kBAAkB,SAAS,KAAK,CAAC;AACxE,aAAO,UAAU,OAAO;AACxB,UAAI,KAAK,OAAO;AACf,iBAAS,IAAI,KAAK;AAAA,MACnB;AAAA,IACD;AAAA,IACA,CAAC,WAAW,WAAW,WAAW,gBAAgB;AAAA,EACnD;AAUA,QAAM,iBACL,QAAQ,kBAAkB,eAAe,SACzC,QAAQ,kBAAkB,eAAe,eAAe,KACxD,QAAQ,kBAAkB,WAAW,SACrC,QAAQ,kBAAkB,WAAW,eAAe,KACpD;AAED,+BAAU,MAAM;AAEf,QAAI,OAAO,SAAS;AACnB;AAAA,IACD;AAEA,QAAI,CAAC,gBAAgB;AACpB;AAAA,IACD;AAGA,QAAI,mBAAmB,SAAS;AAC/B;AAAA,IACD;AAGA,QAAI,gBAAgB,YAAY,gBAAgB;AAC/C;AAAA,IACD;AAEA,QAAI,CAAC,UAAU,QAAQ;AACtB;AAAA,IACD;AAEA,oBAAgB,UAAU;AAE1B,aAAS,IAAI;AACb,iBAAa,IAAI;AACjB,UAAM,MAAM,UAAU,OAAO;AAAA,MAC5B,SAAS;AAAA,MACT,OAAO;AAAA,IACR,CAAC;AACD,WAAO,UAAU,OAAO;AACxB,aAAS,cAAc;AAAA,EACxB,GAAG,CAAC,gBAAgB,WAAW,gBAAgB,CAAC;AAEhD,+BAAU,MAAM;AACf,WAAO,MAAM;AACZ,WAAK,OAAO,SAAS,QAAQ;AAC7B,aAAO,UAAU;AAAA,IAClB;AAAA,EACD,GAAG,CAAC,CAAC;AAEL,QAAM,uBAAmB,sBAAO,SAAS;AACzC,+BAAU,MAAM;AAIf,QAAI,iBAAiB,WAAW,CAAC,WAAW;AAC3C,aAAO,UAAU;AAAA,IAClB;AACA,qBAAiB,UAAU;AAAA,EAC5B,GAAG,CAAC,SAAS,CAAC;AAEd,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;","names":["import_core","import_react"]}
package/dist/index.d.cts CHANGED
@@ -198,7 +198,7 @@ interface UseStreamChatReturn<TPart extends {
198
198
  setMessages: Dispatch<SetStateAction<Message<TPart>[]>>;
199
199
  }
200
200
  interface UseAutoScrollOptions {
201
- /** Scroll behavior for explicit `scrollToBottom()` calls. Default: `"instant"`. */
201
+ /** Scroll behavior for `scrollTo()` and `scrollToBottom()` calls. Default: `"smooth"`. */
202
202
  behavior?: ScrollBehavior;
203
203
  /** Whether auto-scroll is enabled. Default: `true`. */
204
204
  enabled?: boolean;
package/dist/index.d.ts CHANGED
@@ -198,7 +198,7 @@ interface UseStreamChatReturn<TPart extends {
198
198
  setMessages: Dispatch<SetStateAction<Message<TPart>[]>>;
199
199
  }
200
200
  interface UseAutoScrollOptions {
201
- /** Scroll behavior for explicit `scrollToBottom()` calls. Default: `"instant"`. */
201
+ /** Scroll behavior for `scrollTo()` and `scrollToBottom()` calls. Default: `"smooth"`. */
202
202
  behavior?: ScrollBehavior;
203
203
  /** Whether auto-scroll is enabled. Default: `true`. */
204
204
  enabled?: boolean;
package/dist/index.js CHANGED
@@ -10,11 +10,13 @@ import { useCallback, useEffect, useRef, useState } from "react";
10
10
  var DEFAULT_THRESHOLD = 50;
11
11
  function useAutoScroll(dependencies, options) {
12
12
  const {
13
- behavior = "instant",
13
+ behavior = "smooth",
14
14
  enabled = true,
15
15
  threshold = DEFAULT_THRESHOLD
16
16
  } = options ?? {};
17
17
  const ref = useRef(null);
18
+ const behaviorRef = useRef(behavior);
19
+ behaviorRef.current = behavior;
18
20
  const isAtBottomRef = useRef(true);
19
21
  const [isAtBottom, setIsAtBottom] = useState(true);
20
22
  const rafRef = useRef(null);
@@ -39,7 +41,7 @@ function useAutoScroll(dependencies, options) {
39
41
  if (heightChanged || distanceFromBottom > 0) {
40
42
  lastAutoScrollHeightRef.current = nextHeight;
41
43
  pendingVerificationFramesRef.current = 1;
42
- el.scrollTop = nextHeight;
44
+ el.scrollTo({ top: nextHeight, behavior: behaviorRef.current });
43
45
  } else {
44
46
  pendingVerificationFramesRef.current = Math.max(
45
47
  pendingVerificationFramesRef.current - 1,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/use-auto-scroll.ts","../src/use-stream-chat.ts","../src/chat-controller.ts","../src/transports.ts"],"sourcesContent":["// Re-export core types so consumers only need to import from @deltakit/react\nexport type {\n\tContentPart,\n\tMessage,\n\tReasoningPart,\n\tSSEEvent,\n\tTextDeltaEvent,\n\tTextPart,\n\tToolCallEvent,\n\tToolCallPart,\n\tToolResultEvent,\n} from \"@deltakit/core\";\nexport {\n\tfromAgnoAgents,\n\tfromOpenAiAgents,\n\tparseSSEStream,\n} from \"@deltakit/core\";\n\nexport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tEventHelpers,\n\tTransportOptions,\n\tUseAutoScrollOptions,\n\tUseAutoScrollReturn,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n\tWebSocketTransportOptions,\n} from \"./types\";\nexport { useAutoScroll } from \"./use-auto-scroll\";\nexport { useStreamChat } from \"./use-stream-chat\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { UseAutoScrollOptions, UseAutoScrollReturn } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_THRESHOLD = 50;\n\n// ---------------------------------------------------------------------------\n// useAutoScroll\n// ---------------------------------------------------------------------------\n\nexport function useAutoScroll<T extends HTMLElement = HTMLDivElement>(\n\tdependencies: unknown[],\n\toptions?: UseAutoScrollOptions,\n): UseAutoScrollReturn<T> {\n\tconst {\n\t\tbehavior = \"instant\",\n\t\tenabled = true,\n\t\tthreshold = DEFAULT_THRESHOLD,\n\t} = options ?? {};\n\n\tconst ref = useRef<T | null>(null);\n\tconst isAtBottomRef = useRef(true);\n\tconst [isAtBottom, setIsAtBottom] = useState(true);\n\n\t// A single rAF id shared across all scroll sources — ensures we never\n\t// call scrollTo() more than once per frame, no matter how many\n\t// MutationObserver / ResizeObserver callbacks fire.\n\tconst rafRef = useRef<number | null>(null);\n\tconst lastAutoScrollHeightRef = useRef<number | null>(null);\n\tconst pendingVerificationFramesRef = useRef(0);\n\n\tconst scheduleScroll = useCallback(() => {\n\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\tpendingVerificationFramesRef.current,\n\t\t\t1,\n\t\t);\n\t\tif (rafRef.current != null) return;\n\n\t\tconst tick = () => {\n\t\t\trafRef.current = null;\n\t\t\tconst el = ref.current;\n\t\t\tif (!el || !isAtBottomRef.current) {\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst nextHeight = el.scrollHeight;\n\t\t\tconst heightChanged = lastAutoScrollHeightRef.current !== nextHeight;\n\t\t\tconst distanceFromBottom = nextHeight - el.scrollTop - el.clientHeight;\n\n\t\t\tif (heightChanged || distanceFromBottom > 0) {\n\t\t\t\tlastAutoScrollHeightRef.current = nextHeight;\n\t\t\t\tpendingVerificationFramesRef.current = 1;\n\n\t\t\t\t// Keep the viewport pinned during streaming without restarting a\n\t\t\t\t// smooth scroll animation on every DOM mutation.\n\t\t\t\tel.scrollTop = nextHeight;\n\t\t\t} else {\n\t\t\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\t\t\tpendingVerificationFramesRef.current - 1,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (pendingVerificationFramesRef.current > 0) {\n\t\t\t\trafRef.current = requestAnimationFrame(tick);\n\t\t\t}\n\t\t};\n\n\t\trafRef.current = requestAnimationFrame(tick);\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// Track whether the user is near the bottom via scroll events.\n\t// Only triggers a React re-render when the boolean actually changes.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst handleScroll = () => {\n\t\t\tconst atBottom =\n\t\t\t\tel.scrollHeight - el.scrollTop - el.clientHeight <= threshold;\n\t\t\tisAtBottomRef.current = atBottom;\n\t\t\tif (!atBottom) {\n\t\t\t\tlastAutoScrollHeightRef.current = null;\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t}\n\t\t\tsetIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n\t\t};\n\n\t\tel.addEventListener(\"scroll\", handleScroll, { passive: true });\n\t\thandleScroll();\n\t\treturn () => el.removeEventListener(\"scroll\", handleScroll);\n\t}, [enabled, threshold]);\n\n\t// -----------------------------------------------------------------------\n\t// Scroll to bottom when dependencies change (if pinned).\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tif (!enabled || !isAtBottomRef.current) return;\n\t\tscheduleScroll();\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: dependencies are passed dynamically by the consumer\n\t}, dependencies);\n\n\t// -----------------------------------------------------------------------\n\t// MutationObserver + ResizeObserver — catch content changes during\n\t// streaming that happen between React re-renders (e.g. DOM mutations\n\t// from markdown renderers). Scroll calls are batched via rAF so we\n\t// scroll at most once per frame.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst resizeObserver = new ResizeObserver(scheduleScroll);\n\n\t\t// Observe existing children for size changes.\n\t\tfor (const child of el.children) {\n\t\t\tresizeObserver.observe(child);\n\t\t}\n\n\t\t// Watch for new children added to the container.\n\t\tconst mutationObserver = new MutationObserver((mutations) => {\n\t\t\tfor (const mutation of mutations) {\n\t\t\t\tfor (const node of mutation.addedNodes) {\n\t\t\t\t\tif (node instanceof Element) {\n\t\t\t\t\t\tresizeObserver.observe(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tscheduleScroll();\n\t\t});\n\n\t\tmutationObserver.observe(el, { childList: true, subtree: true });\n\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [enabled, scheduleScroll]);\n\n\t// -----------------------------------------------------------------------\n\t// Cancel any pending rAF on unmount.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (rafRef.current != null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t};\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// scrollToBottom — imperative function that scrolls to the bottom and\n\t// re-pins auto-scroll.\n\t// -----------------------------------------------------------------------\n\n\tconst scrollToBottom = useCallback(() => {\n\t\tconst el = ref.current;\n\t\tif (!el) return;\n\n\t\tisAtBottomRef.current = true;\n\t\tlastAutoScrollHeightRef.current = el.scrollHeight;\n\t\tpendingVerificationFramesRef.current = 0;\n\t\tsetIsAtBottom(true);\n\t\tel.scrollTo({ top: el.scrollHeight, behavior });\n\t}, [behavior]);\n\n\treturn { ref, scrollToBottom, isAtBottom };\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { createChatTransportContext, createMessage } from \"./chat-controller\";\nimport { resolveTransport } from \"./transports\";\nimport type {\n\tChatTransportRun,\n\tEventHelpers,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Default event handler — accumulates `text_delta` into the last\n// assistant message's parts.\n// ---------------------------------------------------------------------------\n\nfunction defaultOnEvent(\n\tevent: SSEEvent,\n\thelpers: EventHelpers<ContentPart>,\n): void {\n\tif (event.type === \"text_delta\") {\n\t\thelpers.appendText(event.delta);\n\t}\n\t// Other event types (e.g. tool_call) are silently ignored by default.\n\t// Users can provide their own `onEvent` to handle them.\n}\n\n// ---------------------------------------------------------------------------\n// useStreamChat\n// ---------------------------------------------------------------------------\n\nexport function useStreamChat<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart> {\n\tconst { initialMessages, onEvent, onMessage, onError, onFinish } = options;\n\n\tconst [messages, setMessages] = useState(initialMessages ?? []);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst [runId, setRunId] = useState<string | null>(null);\n\n\tconst runRef = useRef<ChatTransportRun | null>(null);\n\n\t// Track which run id has already been resumed to prevent re-triggering.\n\tconst resumedRunIdRef = useRef<string | null>(null);\n\n\t// When the user manually stops a run, suppress auto-resume until the\n\t// next explicit `sendMessage` call.\n\tconst manuallyStoppedRef = useRef(false);\n\n\t// We use a ref for the latest messages so callbacks created inside\n\t// transport handlers always see the current value without re-creating\n\t// closures.\n\tconst messagesRef = useRef(messages);\n\tmessagesRef.current = messages;\n\n\t// Keep transport options in a ref so that callbacks always read the\n\t// latest values without causing memoisation instability.\n\tconst transportOptionsRef = useRef(options.transportOptions);\n\ttransportOptionsRef.current = options.transportOptions;\n\n\tconst appendText = useCallback((delta: string) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\tconst parts = [...last.parts];\n\t\t\tconst lastPart = parts[parts.length - 1];\n\n\t\t\tif (lastPart && lastPart.type === \"text\" && \"text\" in lastPart) {\n\t\t\t\tconst textPart = lastPart as { type: \"text\"; text: string };\n\t\t\t\tparts[parts.length - 1] = {\n\t\t\t\t\t...lastPart,\n\t\t\t\t\ttext: textPart.text + delta,\n\t\t\t\t} as unknown as TPart;\n\t\t\t} else {\n\t\t\t\tparts.push({ type: \"text\", text: delta } as unknown as TPart);\n\t\t\t}\n\n\t\t\treturn [...prev.slice(0, -1), { ...last, parts }];\n\t\t});\n\t}, []);\n\n\tconst appendPart = useCallback((part: TPart) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\treturn [\n\t\t\t\t...prev.slice(0, -1),\n\t\t\t\t{\n\t\t\t\t\t...last,\n\t\t\t\t\tparts: [...last.parts, part],\n\t\t\t\t},\n\t\t\t];\n\t\t});\n\t}, []);\n\n\t// Stabilise transport creation: resolve once and store in a ref so that\n\t// changing values like `runId` in transportOptions won't cause a new\n\t// transport instance (and therefore a new WebSocket) to be created.\n\tconst transportRef = useRef<ReturnType<\n\t\ttypeof resolveTransport<TPart, TEvent>\n\t> | null>(null);\n\tif (!transportRef.current) {\n\t\ttransportRef.current = resolveTransport(options);\n\t}\n\tconst transport = transportRef.current;\n\n\tconst eventHandler =\n\t\tonEvent ??\n\t\t(defaultOnEvent as unknown as (\n\t\t\tevent: TEvent,\n\t\t\thelpers: EventHelpers<TPart>,\n\t\t) => void);\n\n\t// Stabilise the transport context: use refs for values that change\n\t// frequently (transportOptions callbacks) so the context object itself\n\t// stays referentially stable.\n\tconst eventHandlerRef = useRef(eventHandler);\n\teventHandlerRef.current = eventHandler;\n\n\tconst onErrorRef = useRef(onError);\n\tonErrorRef.current = onError;\n\n\tconst onFinishRef = useRef(onFinish);\n\tonFinishRef.current = onFinish;\n\n\tconst onMessageRef = useRef(onMessage);\n\tonMessageRef.current = onMessage;\n\n\tconst transportContext = useMemo(\n\t\t() =>\n\t\t\tcreateChatTransportContext({\n\t\t\t\tappendPart,\n\t\t\t\tappendText,\n\t\t\t\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) =>\n\t\t\t\t\teventHandlerRef.current(event, helpers),\n\t\t\t\tgetMessages: () => messagesRef.current,\n\t\t\t\tonError: (...args) => onErrorRef.current?.(...args),\n\t\t\t\tonFinish: (...args) => onFinishRef.current?.(...args),\n\t\t\t\tonMessage: (...args) => onMessageRef.current?.(...args),\n\t\t\t\tsetError,\n\t\t\t\tsetIsLoading,\n\t\t\t\tsetMessages,\n\t\t\t\tsetRunId: (next) => {\n\t\t\t\t\tsetRunId(next);\n\t\t\t\t\ttransportOptionsRef.current?.backgroundSSE?.onRunIdChange?.(next);\n\t\t\t\t\ttransportOptionsRef.current?.websocket?.onRunIdChange?.(next);\n\t\t\t\t},\n\t\t\t}),\n\t\t[appendPart, appendText],\n\t);\n\n\tconst stop = useCallback(() => {\n\t\tconst activeRun = runRef.current;\n\t\tif (!activeRun?.stop) {\n\t\t\treturn;\n\t\t}\n\n\t\tmanuallyStoppedRef.current = true;\n\t\tvoid activeRun.stop();\n\t\trunRef.current = null;\n\t\tsetIsLoading(false);\n\t}, []);\n\n\tconst sendMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (runRef.current || isLoading) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst userMessage = createMessage<TPart>(\"user\", [\n\t\t\t\t{ type: \"text\", text } as unknown as TPart,\n\t\t\t]);\n\t\t\tconst assistantMessage = createMessage<TPart>(\"assistant\", []);\n\n\t\t\tsetMessages((prev) => {\n\t\t\t\tconst next = [...prev, userMessage, assistantMessage];\n\t\t\t\tmessagesRef.current = next;\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\t\tonMessage?.(userMessage);\n\t\t\tsetError(null);\n\t\t\tsetIsLoading(true);\n\n\t\t\t// Reset the resume guard so a future resume for a new run is allowed.\n\t\t\tresumedRunIdRef.current = null;\n\t\t\tmanuallyStoppedRef.current = false;\n\n\t\t\tconst run = transport.start({ context: transportContext, message: text });\n\t\t\trunRef.current = run ?? null;\n\t\t\tif (run?.runId) {\n\t\t\t\tsetRunId(run.runId);\n\t\t\t}\n\t\t},\n\t\t[isLoading, onMessage, transport, transportContext],\n\t);\n\n\t// -----------------------------------------------------------------------\n\t// Auto-resume effect: attempt to reconnect to an in-flight run on mount.\n\t//\n\t// The candidate run id is read from transport options (which may change\n\t// when the app updates state). We guard against duplicate resumes for the\n\t// same run id using `resumedRunIdRef`.\n\t// -----------------------------------------------------------------------\n\n\tconst candidateRunId =\n\t\toptions.transportOptions?.backgroundSSE?.runId ??\n\t\toptions.transportOptions?.backgroundSSE?.getResumeKey?.() ??\n\t\toptions.transportOptions?.websocket?.runId ??\n\t\toptions.transportOptions?.websocket?.getResumeKey?.() ??\n\t\tnull;\n\n\tuseEffect(() => {\n\t\t// Already have an active run — don't start another.\n\t\tif (runRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\t// User explicitly stopped — don't auto-resume until next sendMessage.\n\t\tif (manuallyStoppedRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Already resumed this exact run id — don't retry.\n\t\tif (resumedRunIdRef.current === candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!transport.resume) {\n\t\t\treturn;\n\t\t}\n\n\t\tresumedRunIdRef.current = candidateRunId;\n\n\t\tsetError(null);\n\t\tsetIsLoading(true);\n\t\tconst run = transport.resume({\n\t\t\tcontext: transportContext,\n\t\t\trunId: candidateRunId,\n\t\t});\n\t\trunRef.current = run ?? null;\n\t\tsetRunId(candidateRunId);\n\t}, [candidateRunId, transport, transportContext]);\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tvoid runRef.current?.close?.();\n\t\t\trunRef.current = null;\n\t\t};\n\t}, []);\n\n\tconst prevIsLoadingRef = useRef(isLoading);\n\tuseEffect(() => {\n\t\t// Only clear the run ref on a true → false transition, not on mount\n\t\t// where isLoading starts as false. Clearing on mount would race with\n\t\t// the auto-resume effect and null out the run it just created.\n\t\tif (prevIsLoadingRef.current && !isLoading) {\n\t\t\trunRef.current = null;\n\t\t}\n\t\tprevIsLoadingRef.current = isLoading;\n\t}, [isLoading]);\n\n\treturn {\n\t\terror,\n\t\tisLoading,\n\t\tmessages,\n\t\trunId,\n\t\tsendMessage,\n\t\tsetMessages,\n\t\tstop,\n\t};\n}\n","import type { ContentPart, Message, SSEEvent } from \"@deltakit/core\";\nimport type { Dispatch, SetStateAction } from \"react\";\nimport type {\n\tChatTransportContext,\n\tEventHelpers,\n\tUseStreamChatOptions,\n} from \"./types\";\n\nexport interface ChatControllerOptions<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n> {\n\tappendPart: EventHelpers<TPart>[\"appendPart\"];\n\tappendText: EventHelpers<TPart>[\"appendText\"];\n\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) => void;\n\tgetMessages: () => Message<TPart>[];\n\tonError?: UseStreamChatOptions<TPart, TEvent>[\"onError\"];\n\tonFinish?: UseStreamChatOptions<TPart, TEvent>[\"onFinish\"];\n\tonMessage?: UseStreamChatOptions<TPart, TEvent>[\"onMessage\"];\n\tsetError: Dispatch<SetStateAction<Error | null>>;\n\tsetIsLoading: Dispatch<SetStateAction<boolean>>;\n\tsetMessages: Dispatch<SetStateAction<Message<TPart>[]>>;\n\tsetRunId: (runId: string | null) => void;\n}\n\nlet counter = 0;\n\nexport function generateId(): string {\n\treturn `msg_${Date.now()}_${++counter}`;\n}\n\nexport function createMessage<TPart extends { type: string }>(\n\trole: Message[\"role\"],\n\tparts: TPart[],\n): Message<TPart> {\n\treturn { id: generateId(), role, parts };\n}\n\nexport function createChatTransportContext<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(\n\toptions: ChatControllerOptions<TPart, TEvent>,\n): ChatTransportContext<TPart, TEvent> {\n\tconst helpers: EventHelpers<TPart> = {\n\t\tappendPart: options.appendPart,\n\t\tappendText: options.appendText,\n\t\tsetMessages: options.setMessages,\n\t};\n\n\treturn {\n\t\temit: (event) => {\n\t\t\toptions.eventHandler(event, helpers);\n\t\t},\n\t\tensureAssistantMessage: () => {\n\t\t\toptions.setMessages((prev) => {\n\t\t\t\tconst last = prev[prev.length - 1];\n\t\t\t\tif (last?.role === \"assistant\") {\n\t\t\t\t\treturn prev;\n\t\t\t\t}\n\n\t\t\t\treturn [...prev, createMessage<TPart>(\"assistant\", [])];\n\t\t\t});\n\t\t},\n\t\tfail: (error) => {\n\t\t\toptions.setError(error);\n\t\t\toptions.onError?.(error);\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\t\t},\n\t\tfinish: () => {\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\n\t\t\tconst finalMessages = options.getMessages();\n\t\t\tconst lastMessage = finalMessages[finalMessages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\toptions.onMessage?.(lastMessage);\n\t\t\t}\n\n\t\t\toptions.onFinish?.(finalMessages);\n\t\t},\n\t\tgetMessages: options.getMessages,\n\t\tsetRunId: (runId) => {\n\t\t\toptions.setRunId(runId);\n\t\t},\n\t};\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { parseSSEStream } from \"@deltakit/core\";\nimport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tUseStreamChatOptions,\n\tWebSocketTransportOptions,\n} from \"./types\";\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction isAbortError(error: unknown): boolean {\n\treturn error instanceof DOMException && error.name === \"AbortError\";\n}\n\nfunction resolveRunId(response: unknown): string {\n\tif (!response || typeof response !== \"object\") {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\tconst maybeRunId =\n\t\t\"runId\" in response\n\t\t\t? response.runId\n\t\t\t: \"job_id\" in response\n\t\t\t\t? response.job_id\n\t\t\t\t: null;\n\n\tif (typeof maybeRunId !== \"string\" || maybeRunId.length === 0) {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\treturn maybeRunId;\n}\n\nfunction resolveUrl(\n\turl: string | ((runId: string) => string),\n\trunId: string,\n): string {\n\treturn typeof url === \"function\" ? url(runId) : url.replace(\":runId\", runId);\n}\n\nasync function streamFetchSSE<\n\tTPart extends { type: string },\n\tTEvent extends { type: string },\n>(\n\tresponse: Response,\n\tcontext: ChatTransportContext<TPart, TEvent>,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`SSE request failed: ${response.status} ${response.statusText}`,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"Response body is null — SSE streaming not supported\");\n\t}\n\n\tfor await (const event of parseSSEStream(response.body, signal)) {\n\t\tcontext.emit(event as unknown as TEvent);\n\t}\n}\n\nexport function createDirectSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: DirectSSETransportOptions): ChatTransport<TPart, TEvent> {\n\treturn {\n\t\tstart: ({ context, message }) => {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst run: ChatTransportRun = {\n\t\t\t\tclose: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst fetchImpl = config.fetch ?? fetch;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.api, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.body }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.headers,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.method ?? \"POST\",\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\t\tcontext.finish();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn run;\n\t\t},\n\t};\n}\n\nexport function createBackgroundSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: BackgroundSSETransportOptions): ChatTransport<TPart, TEvent> {\n\tconst fetchImpl = config.fetch ?? fetch;\n\n\tconst connect = (\n\t\trunId: string,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t): ChatTransportRun => {\n\t\tconst controller = new AbortController();\n\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst response = await fetchImpl(resolveUrl(config.eventsApi, runId), {\n\t\t\t\t\theaders: config.eventHeaders,\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\tcontext.finish();\n\t\t\t} catch (error) {\n\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\treturn {\n\t\t\tclose: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t},\n\t\t\tstop: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t\tif (config.cancelApi) {\n\t\t\t\t\tvoid fetchImpl(resolveUrl(config.cancelApi, runId), {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\trunId,\n\t\t};\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\treturn connect(runId, context);\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst startController = new AbortController();\n\t\t\tlet activeRun: ChatTransportRun | undefined;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.startApi, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.startBody }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.startHeaders,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.startMethod ?? \"POST\",\n\t\t\t\t\t\tsignal: startController.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Background SSE start failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = (await response.json()) as unknown;\n\t\t\t\t\tconst runId = (config.resolveRunId ?? resolveRunId)(data);\n\t\t\t\t\tcontext.setRunId(runId);\n\t\t\t\t\tactiveRun = connect(runId, context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tvoid activeRun?.close?.();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tactiveRun?.stop?.();\n\t\t\t\t},\n\t\t\t\trunId: null,\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction defaultParseWebSocketMessage<TEvent extends { type: string }>(\n\tdata: unknown,\n): TEvent | TEvent[] | null {\n\tif (typeof data !== \"string\") {\n\t\treturn null;\n\t}\n\n\tconst parsed = JSON.parse(data) as TEvent | TEvent[];\n\treturn parsed;\n}\n\nexport function createWebSocketTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: WebSocketTransportOptions<TEvent>): ChatTransport<TPart, TEvent> {\n\tconst parseMessage = config.parseMessage ?? defaultParseWebSocketMessage;\n\tconst serializeMessage = config.serializeMessage ?? JSON.stringify;\n\n\tlet resolvedRunId: string | null = null;\n\n\tconst applyIncomingEvents = (\n\t\tparsed: TEvent | TEvent[] | null,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t) => {\n\t\tconst events = Array.isArray(parsed) ? parsed : parsed ? [parsed] : [];\n\t\tfor (const item of events) {\n\t\t\tconst nextRunId = config.resolveRunId?.(item) ?? null;\n\t\t\tif (nextRunId) {\n\t\t\t\tresolvedRunId = nextRunId;\n\t\t\t\tcontext.setRunId(nextRunId);\n\t\t\t}\n\t\t\tcontext.emit(item);\n\n\t\t\tif (item.type === \"done\") {\n\t\t\t\tcontext.finish();\n\t\t\t} else if (item.type === \"error\") {\n\t\t\t\tcontext.fail(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"message\" in item && typeof item.message === \"string\"\n\t\t\t\t\t\t\t? item.message\n\t\t\t\t\t\t\t: \"Stream error\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\tcontext.ensureAssistantMessage();\n\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentResumePayload = false;\n\n\t\t\tconst sendResumePayload = () => {\n\t\t\t\tif (sentResumePayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentResumePayload = true;\n\t\t\t\tconst payload =\n\t\t\t\t\tconfig.buildResumePayload?.(runId) ??\n\t\t\t\t\t({ [config.runIdKey ?? \"runId\"]: runId } as Record<string, unknown>);\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendResumePayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendResumePayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst runId = config.runId ?? config.getResumeKey?.() ?? null;\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentStartPayload = false;\n\n\t\t\tconst sendStartPayload = () => {\n\t\t\t\tif (sentStartPayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentStartPayload = true;\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst payload: Record<string, unknown> = {\n\t\t\t\t\tmessage,\n\t\t\t\t\t...config.body,\n\t\t\t\t};\n\n\t\t\t\tif (runId) {\n\t\t\t\t\tpayload[config.runIdKey ?? \"runId\"] = runId;\n\t\t\t\t}\n\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendStartPayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendStartPayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function resolveTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): ChatTransport<TPart, TEvent> {\n\tif (typeof options.transport === \"object\" && options.transport) {\n\t\treturn options.transport;\n\t}\n\n\tconst transportKind = options.transport ?? \"sse\";\n\n\tif (transportKind === \"background-sse\") {\n\t\tconst config = options.transportOptions?.backgroundSSE;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.backgroundSSE` is required when transport is \"background-sse\"',\n\t\t\t);\n\t\t}\n\t\treturn createBackgroundSSETransport(config);\n\t}\n\n\tif (transportKind === \"websocket\") {\n\t\tconst config = options.transportOptions?.websocket;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.websocket` is required when transport is \"websocket\"',\n\t\t\t);\n\t\t}\n\t\treturn createWebSocketTransport(config);\n\t}\n\n\tconst sseConfig = options.transportOptions?.sse ?? {\n\t\tapi: options.api,\n\t\tbody: options.body,\n\t\theaders: options.headers,\n\t};\n\n\tif (!sseConfig.api) {\n\t\tthrow new Error(\n\t\t\t\"`api` or `transportOptions.sse.api` is required when using the default SSE transport\",\n\t\t);\n\t}\n\n\treturn createDirectSSETransport({\n\t\t...sseConfig,\n\t\tapi: sseConfig.api,\n\t});\n}\n"],"mappings":"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","names":["parseSSEStream","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/use-auto-scroll.ts","../src/use-stream-chat.ts","../src/chat-controller.ts","../src/transports.ts"],"sourcesContent":["// Re-export core types so consumers only need to import from @deltakit/react\nexport type {\n\tContentPart,\n\tMessage,\n\tReasoningPart,\n\tSSEEvent,\n\tTextDeltaEvent,\n\tTextPart,\n\tToolCallEvent,\n\tToolCallPart,\n\tToolResultEvent,\n} from \"@deltakit/core\";\nexport {\n\tfromAgnoAgents,\n\tfromOpenAiAgents,\n\tparseSSEStream,\n} from \"@deltakit/core\";\n\nexport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tEventHelpers,\n\tTransportOptions,\n\tUseAutoScrollOptions,\n\tUseAutoScrollReturn,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n\tWebSocketTransportOptions,\n} from \"./types\";\nexport { useAutoScroll } from \"./use-auto-scroll\";\nexport { useStreamChat } from \"./use-stream-chat\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { UseAutoScrollOptions, UseAutoScrollReturn } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_THRESHOLD = 50;\n\n// ---------------------------------------------------------------------------\n// useAutoScroll\n// ---------------------------------------------------------------------------\n\nexport function useAutoScroll<T extends HTMLElement = HTMLDivElement>(\n\tdependencies: unknown[],\n\toptions?: UseAutoScrollOptions,\n): UseAutoScrollReturn<T> {\n\tconst {\n\t\tbehavior = \"smooth\",\n\t\tenabled = true,\n\t\tthreshold = DEFAULT_THRESHOLD,\n\t} = options ?? {};\n\n\tconst ref = useRef<T | null>(null);\n\tconst behaviorRef = useRef(behavior);\n\tbehaviorRef.current = behavior;\n\tconst isAtBottomRef = useRef(true);\n\tconst [isAtBottom, setIsAtBottom] = useState(true);\n\n\t// A single rAF id shared across all scroll sources — ensures we never\n\t// call scrollTo() more than once per frame, no matter how many\n\t// MutationObserver / ResizeObserver callbacks fire.\n\tconst rafRef = useRef<number | null>(null);\n\tconst lastAutoScrollHeightRef = useRef<number | null>(null);\n\tconst pendingVerificationFramesRef = useRef(0);\n\n\tconst scheduleScroll = useCallback(() => {\n\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\tpendingVerificationFramesRef.current,\n\t\t\t1,\n\t\t);\n\t\tif (rafRef.current != null) return;\n\n\t\tconst tick = () => {\n\t\t\trafRef.current = null;\n\t\t\tconst el = ref.current;\n\t\t\tif (!el || !isAtBottomRef.current) {\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst nextHeight = el.scrollHeight;\n\t\t\tconst heightChanged = lastAutoScrollHeightRef.current !== nextHeight;\n\t\t\tconst distanceFromBottom = nextHeight - el.scrollTop - el.clientHeight;\n\n\t\t\tif (heightChanged || distanceFromBottom > 0) {\n\t\t\t\tlastAutoScrollHeightRef.current = nextHeight;\n\t\t\t\tpendingVerificationFramesRef.current = 1;\n\n\t\t\t\t// Keep the viewport pinned during streaming without restarting a\n\t\t\t\t// smooth scroll animation on every DOM mutation.\n\t\t\t\tel.scrollTo({ top: nextHeight, behavior: behaviorRef.current });\n\t\t\t} else {\n\t\t\t\tpendingVerificationFramesRef.current = Math.max(\n\t\t\t\t\tpendingVerificationFramesRef.current - 1,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (pendingVerificationFramesRef.current > 0) {\n\t\t\t\trafRef.current = requestAnimationFrame(tick);\n\t\t\t}\n\t\t};\n\n\t\trafRef.current = requestAnimationFrame(tick);\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// Track whether the user is near the bottom via scroll events.\n\t// Only triggers a React re-render when the boolean actually changes.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst handleScroll = () => {\n\t\t\tconst atBottom =\n\t\t\t\tel.scrollHeight - el.scrollTop - el.clientHeight <= threshold;\n\t\t\tisAtBottomRef.current = atBottom;\n\t\t\tif (!atBottom) {\n\t\t\t\tlastAutoScrollHeightRef.current = null;\n\t\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t\t}\n\t\t\tsetIsAtBottom((prev) => (prev === atBottom ? prev : atBottom));\n\t\t};\n\n\t\tel.addEventListener(\"scroll\", handleScroll, { passive: true });\n\t\thandleScroll();\n\t\treturn () => el.removeEventListener(\"scroll\", handleScroll);\n\t}, [enabled, threshold]);\n\n\t// -----------------------------------------------------------------------\n\t// Scroll to bottom when dependencies change (if pinned).\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tif (!enabled || !isAtBottomRef.current) return;\n\t\tscheduleScroll();\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: dependencies are passed dynamically by the consumer\n\t}, dependencies);\n\n\t// -----------------------------------------------------------------------\n\t// MutationObserver + ResizeObserver — catch content changes during\n\t// streaming that happen between React re-renders (e.g. DOM mutations\n\t// from markdown renderers). Scroll calls are batched via rAF so we\n\t// scroll at most once per frame.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\tconst el = ref.current;\n\t\tif (!el || !enabled) return;\n\n\t\tconst resizeObserver = new ResizeObserver(scheduleScroll);\n\n\t\t// Observe existing children for size changes.\n\t\tfor (const child of el.children) {\n\t\t\tresizeObserver.observe(child);\n\t\t}\n\n\t\t// Watch for new children added to the container.\n\t\tconst mutationObserver = new MutationObserver((mutations) => {\n\t\t\tfor (const mutation of mutations) {\n\t\t\t\tfor (const node of mutation.addedNodes) {\n\t\t\t\t\tif (node instanceof Element) {\n\t\t\t\t\t\tresizeObserver.observe(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tscheduleScroll();\n\t\t});\n\n\t\tmutationObserver.observe(el, { childList: true, subtree: true });\n\n\t\treturn () => {\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [enabled, scheduleScroll]);\n\n\t// -----------------------------------------------------------------------\n\t// Cancel any pending rAF on unmount.\n\t// -----------------------------------------------------------------------\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (rafRef.current != null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tpendingVerificationFramesRef.current = 0;\n\t\t};\n\t}, []);\n\n\t// -----------------------------------------------------------------------\n\t// scrollToBottom — imperative function that scrolls to the bottom and\n\t// re-pins auto-scroll.\n\t// -----------------------------------------------------------------------\n\n\tconst scrollToBottom = useCallback(() => {\n\t\tconst el = ref.current;\n\t\tif (!el) return;\n\n\t\tisAtBottomRef.current = true;\n\t\tlastAutoScrollHeightRef.current = el.scrollHeight;\n\t\tpendingVerificationFramesRef.current = 0;\n\t\tsetIsAtBottom(true);\n\t\tel.scrollTo({ top: el.scrollHeight, behavior });\n\t}, [behavior]);\n\n\treturn { ref, scrollToBottom, isAtBottom };\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { createChatTransportContext, createMessage } from \"./chat-controller\";\nimport { resolveTransport } from \"./transports\";\nimport type {\n\tChatTransportRun,\n\tEventHelpers,\n\tUseStreamChatOptions,\n\tUseStreamChatReturn,\n} from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Default event handler — accumulates `text_delta` into the last\n// assistant message's parts.\n// ---------------------------------------------------------------------------\n\nfunction defaultOnEvent(\n\tevent: SSEEvent,\n\thelpers: EventHelpers<ContentPart>,\n): void {\n\tif (event.type === \"text_delta\") {\n\t\thelpers.appendText(event.delta);\n\t}\n\t// Other event types (e.g. tool_call) are silently ignored by default.\n\t// Users can provide their own `onEvent` to handle them.\n}\n\n// ---------------------------------------------------------------------------\n// useStreamChat\n// ---------------------------------------------------------------------------\n\nexport function useStreamChat<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): UseStreamChatReturn<TPart> {\n\tconst { initialMessages, onEvent, onMessage, onError, onFinish } = options;\n\n\tconst [messages, setMessages] = useState(initialMessages ?? []);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst [runId, setRunId] = useState<string | null>(null);\n\n\tconst runRef = useRef<ChatTransportRun | null>(null);\n\n\t// Track which run id has already been resumed to prevent re-triggering.\n\tconst resumedRunIdRef = useRef<string | null>(null);\n\n\t// When the user manually stops a run, suppress auto-resume until the\n\t// next explicit `sendMessage` call.\n\tconst manuallyStoppedRef = useRef(false);\n\n\t// We use a ref for the latest messages so callbacks created inside\n\t// transport handlers always see the current value without re-creating\n\t// closures.\n\tconst messagesRef = useRef(messages);\n\tmessagesRef.current = messages;\n\n\t// Keep transport options in a ref so that callbacks always read the\n\t// latest values without causing memoisation instability.\n\tconst transportOptionsRef = useRef(options.transportOptions);\n\ttransportOptionsRef.current = options.transportOptions;\n\n\tconst appendText = useCallback((delta: string) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\tconst parts = [...last.parts];\n\t\t\tconst lastPart = parts[parts.length - 1];\n\n\t\t\tif (lastPart && lastPart.type === \"text\" && \"text\" in lastPart) {\n\t\t\t\tconst textPart = lastPart as { type: \"text\"; text: string };\n\t\t\t\tparts[parts.length - 1] = {\n\t\t\t\t\t...lastPart,\n\t\t\t\t\ttext: textPart.text + delta,\n\t\t\t\t} as unknown as TPart;\n\t\t\t} else {\n\t\t\t\tparts.push({ type: \"text\", text: delta } as unknown as TPart);\n\t\t\t}\n\n\t\t\treturn [...prev.slice(0, -1), { ...last, parts }];\n\t\t});\n\t}, []);\n\n\tconst appendPart = useCallback((part: TPart) => {\n\t\tsetMessages((prev) => {\n\t\t\tconst last = prev[prev.length - 1];\n\t\t\tif (!last || last.role !== \"assistant\") return prev;\n\n\t\t\treturn [\n\t\t\t\t...prev.slice(0, -1),\n\t\t\t\t{\n\t\t\t\t\t...last,\n\t\t\t\t\tparts: [...last.parts, part],\n\t\t\t\t},\n\t\t\t];\n\t\t});\n\t}, []);\n\n\t// Stabilise transport creation: resolve once and store in a ref so that\n\t// changing values like `runId` in transportOptions won't cause a new\n\t// transport instance (and therefore a new WebSocket) to be created.\n\tconst transportRef = useRef<ReturnType<\n\t\ttypeof resolveTransport<TPart, TEvent>\n\t> | null>(null);\n\tif (!transportRef.current) {\n\t\ttransportRef.current = resolveTransport(options);\n\t}\n\tconst transport = transportRef.current;\n\n\tconst eventHandler =\n\t\tonEvent ??\n\t\t(defaultOnEvent as unknown as (\n\t\t\tevent: TEvent,\n\t\t\thelpers: EventHelpers<TPart>,\n\t\t) => void);\n\n\t// Stabilise the transport context: use refs for values that change\n\t// frequently (transportOptions callbacks) so the context object itself\n\t// stays referentially stable.\n\tconst eventHandlerRef = useRef(eventHandler);\n\teventHandlerRef.current = eventHandler;\n\n\tconst onErrorRef = useRef(onError);\n\tonErrorRef.current = onError;\n\n\tconst onFinishRef = useRef(onFinish);\n\tonFinishRef.current = onFinish;\n\n\tconst onMessageRef = useRef(onMessage);\n\tonMessageRef.current = onMessage;\n\n\tconst transportContext = useMemo(\n\t\t() =>\n\t\t\tcreateChatTransportContext({\n\t\t\t\tappendPart,\n\t\t\t\tappendText,\n\t\t\t\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) =>\n\t\t\t\t\teventHandlerRef.current(event, helpers),\n\t\t\t\tgetMessages: () => messagesRef.current,\n\t\t\t\tonError: (...args) => onErrorRef.current?.(...args),\n\t\t\t\tonFinish: (...args) => onFinishRef.current?.(...args),\n\t\t\t\tonMessage: (...args) => onMessageRef.current?.(...args),\n\t\t\t\tsetError,\n\t\t\t\tsetIsLoading,\n\t\t\t\tsetMessages,\n\t\t\t\tsetRunId: (next) => {\n\t\t\t\t\tsetRunId(next);\n\t\t\t\t\ttransportOptionsRef.current?.backgroundSSE?.onRunIdChange?.(next);\n\t\t\t\t\ttransportOptionsRef.current?.websocket?.onRunIdChange?.(next);\n\t\t\t\t},\n\t\t\t}),\n\t\t[appendPart, appendText],\n\t);\n\n\tconst stop = useCallback(() => {\n\t\tconst activeRun = runRef.current;\n\t\tif (!activeRun?.stop) {\n\t\t\treturn;\n\t\t}\n\n\t\tmanuallyStoppedRef.current = true;\n\t\tvoid activeRun.stop();\n\t\trunRef.current = null;\n\t\tsetIsLoading(false);\n\t}, []);\n\n\tconst sendMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (runRef.current || isLoading) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst userMessage = createMessage<TPart>(\"user\", [\n\t\t\t\t{ type: \"text\", text } as unknown as TPart,\n\t\t\t]);\n\t\t\tconst assistantMessage = createMessage<TPart>(\"assistant\", []);\n\n\t\t\tsetMessages((prev) => {\n\t\t\t\tconst next = [...prev, userMessage, assistantMessage];\n\t\t\t\tmessagesRef.current = next;\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\t\tonMessage?.(userMessage);\n\t\t\tsetError(null);\n\t\t\tsetIsLoading(true);\n\n\t\t\t// Reset the resume guard so a future resume for a new run is allowed.\n\t\t\tresumedRunIdRef.current = null;\n\t\t\tmanuallyStoppedRef.current = false;\n\n\t\t\tconst run = transport.start({ context: transportContext, message: text });\n\t\t\trunRef.current = run ?? null;\n\t\t\tif (run?.runId) {\n\t\t\t\tsetRunId(run.runId);\n\t\t\t}\n\t\t},\n\t\t[isLoading, onMessage, transport, transportContext],\n\t);\n\n\t// -----------------------------------------------------------------------\n\t// Auto-resume effect: attempt to reconnect to an in-flight run on mount.\n\t//\n\t// The candidate run id is read from transport options (which may change\n\t// when the app updates state). We guard against duplicate resumes for the\n\t// same run id using `resumedRunIdRef`.\n\t// -----------------------------------------------------------------------\n\n\tconst candidateRunId =\n\t\toptions.transportOptions?.backgroundSSE?.runId ??\n\t\toptions.transportOptions?.backgroundSSE?.getResumeKey?.() ??\n\t\toptions.transportOptions?.websocket?.runId ??\n\t\toptions.transportOptions?.websocket?.getResumeKey?.() ??\n\t\tnull;\n\n\tuseEffect(() => {\n\t\t// Already have an active run — don't start another.\n\t\tif (runRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\t// User explicitly stopped — don't auto-resume until next sendMessage.\n\t\tif (manuallyStoppedRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Already resumed this exact run id — don't retry.\n\t\tif (resumedRunIdRef.current === candidateRunId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!transport.resume) {\n\t\t\treturn;\n\t\t}\n\n\t\tresumedRunIdRef.current = candidateRunId;\n\n\t\tsetError(null);\n\t\tsetIsLoading(true);\n\t\tconst run = transport.resume({\n\t\t\tcontext: transportContext,\n\t\t\trunId: candidateRunId,\n\t\t});\n\t\trunRef.current = run ?? null;\n\t\tsetRunId(candidateRunId);\n\t}, [candidateRunId, transport, transportContext]);\n\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tvoid runRef.current?.close?.();\n\t\t\trunRef.current = null;\n\t\t};\n\t}, []);\n\n\tconst prevIsLoadingRef = useRef(isLoading);\n\tuseEffect(() => {\n\t\t// Only clear the run ref on a true → false transition, not on mount\n\t\t// where isLoading starts as false. Clearing on mount would race with\n\t\t// the auto-resume effect and null out the run it just created.\n\t\tif (prevIsLoadingRef.current && !isLoading) {\n\t\t\trunRef.current = null;\n\t\t}\n\t\tprevIsLoadingRef.current = isLoading;\n\t}, [isLoading]);\n\n\treturn {\n\t\terror,\n\t\tisLoading,\n\t\tmessages,\n\t\trunId,\n\t\tsendMessage,\n\t\tsetMessages,\n\t\tstop,\n\t};\n}\n","import type { ContentPart, Message, SSEEvent } from \"@deltakit/core\";\nimport type { Dispatch, SetStateAction } from \"react\";\nimport type {\n\tChatTransportContext,\n\tEventHelpers,\n\tUseStreamChatOptions,\n} from \"./types\";\n\nexport interface ChatControllerOptions<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n> {\n\tappendPart: EventHelpers<TPart>[\"appendPart\"];\n\tappendText: EventHelpers<TPart>[\"appendText\"];\n\teventHandler: (event: TEvent, helpers: EventHelpers<TPart>) => void;\n\tgetMessages: () => Message<TPart>[];\n\tonError?: UseStreamChatOptions<TPart, TEvent>[\"onError\"];\n\tonFinish?: UseStreamChatOptions<TPart, TEvent>[\"onFinish\"];\n\tonMessage?: UseStreamChatOptions<TPart, TEvent>[\"onMessage\"];\n\tsetError: Dispatch<SetStateAction<Error | null>>;\n\tsetIsLoading: Dispatch<SetStateAction<boolean>>;\n\tsetMessages: Dispatch<SetStateAction<Message<TPart>[]>>;\n\tsetRunId: (runId: string | null) => void;\n}\n\nlet counter = 0;\n\nexport function generateId(): string {\n\treturn `msg_${Date.now()}_${++counter}`;\n}\n\nexport function createMessage<TPart extends { type: string }>(\n\trole: Message[\"role\"],\n\tparts: TPart[],\n): Message<TPart> {\n\treturn { id: generateId(), role, parts };\n}\n\nexport function createChatTransportContext<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(\n\toptions: ChatControllerOptions<TPart, TEvent>,\n): ChatTransportContext<TPart, TEvent> {\n\tconst helpers: EventHelpers<TPart> = {\n\t\tappendPart: options.appendPart,\n\t\tappendText: options.appendText,\n\t\tsetMessages: options.setMessages,\n\t};\n\n\treturn {\n\t\temit: (event) => {\n\t\t\toptions.eventHandler(event, helpers);\n\t\t},\n\t\tensureAssistantMessage: () => {\n\t\t\toptions.setMessages((prev) => {\n\t\t\t\tconst last = prev[prev.length - 1];\n\t\t\t\tif (last?.role === \"assistant\") {\n\t\t\t\t\treturn prev;\n\t\t\t\t}\n\n\t\t\t\treturn [...prev, createMessage<TPart>(\"assistant\", [])];\n\t\t\t});\n\t\t},\n\t\tfail: (error) => {\n\t\t\toptions.setError(error);\n\t\t\toptions.onError?.(error);\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\t\t},\n\t\tfinish: () => {\n\t\t\toptions.setIsLoading(false);\n\t\t\toptions.setRunId(null);\n\n\t\t\tconst finalMessages = options.getMessages();\n\t\t\tconst lastMessage = finalMessages[finalMessages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\toptions.onMessage?.(lastMessage);\n\t\t\t}\n\n\t\t\toptions.onFinish?.(finalMessages);\n\t\t},\n\t\tgetMessages: options.getMessages,\n\t\tsetRunId: (runId) => {\n\t\t\toptions.setRunId(runId);\n\t\t},\n\t};\n}\n","import type { ContentPart, SSEEvent } from \"@deltakit/core\";\nimport { parseSSEStream } from \"@deltakit/core\";\nimport type {\n\tBackgroundSSETransportOptions,\n\tChatTransport,\n\tChatTransportContext,\n\tChatTransportRun,\n\tDirectSSETransportOptions,\n\tUseStreamChatOptions,\n\tWebSocketTransportOptions,\n} from \"./types\";\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction isAbortError(error: unknown): boolean {\n\treturn error instanceof DOMException && error.name === \"AbortError\";\n}\n\nfunction resolveRunId(response: unknown): string {\n\tif (!response || typeof response !== \"object\") {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\tconst maybeRunId =\n\t\t\"runId\" in response\n\t\t\t? response.runId\n\t\t\t: \"job_id\" in response\n\t\t\t\t? response.job_id\n\t\t\t\t: null;\n\n\tif (typeof maybeRunId !== \"string\" || maybeRunId.length === 0) {\n\t\tthrow new Error(\"Background SSE start response did not contain a run id\");\n\t}\n\n\treturn maybeRunId;\n}\n\nfunction resolveUrl(\n\turl: string | ((runId: string) => string),\n\trunId: string,\n): string {\n\treturn typeof url === \"function\" ? url(runId) : url.replace(\":runId\", runId);\n}\n\nasync function streamFetchSSE<\n\tTPart extends { type: string },\n\tTEvent extends { type: string },\n>(\n\tresponse: Response,\n\tcontext: ChatTransportContext<TPart, TEvent>,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`SSE request failed: ${response.status} ${response.statusText}`,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"Response body is null — SSE streaming not supported\");\n\t}\n\n\tfor await (const event of parseSSEStream(response.body, signal)) {\n\t\tcontext.emit(event as unknown as TEvent);\n\t}\n}\n\nexport function createDirectSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: DirectSSETransportOptions): ChatTransport<TPart, TEvent> {\n\treturn {\n\t\tstart: ({ context, message }) => {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst run: ChatTransportRun = {\n\t\t\t\tclose: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tcontroller.abort();\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst fetchImpl = config.fetch ?? fetch;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.api, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.body }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.headers,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.method ?? \"POST\",\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\t\tcontext.finish();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn run;\n\t\t},\n\t};\n}\n\nexport function createBackgroundSSETransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: BackgroundSSETransportOptions): ChatTransport<TPart, TEvent> {\n\tconst fetchImpl = config.fetch ?? fetch;\n\n\tconst connect = (\n\t\trunId: string,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t): ChatTransportRun => {\n\t\tconst controller = new AbortController();\n\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst response = await fetchImpl(resolveUrl(config.eventsApi, runId), {\n\t\t\t\t\theaders: config.eventHeaders,\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\tawait streamFetchSSE(response, context, controller.signal);\n\t\t\t\tcontext.finish();\n\t\t\t} catch (error) {\n\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\treturn {\n\t\t\tclose: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t},\n\t\t\tstop: () => {\n\t\t\t\tcontroller.abort();\n\t\t\t\tif (config.cancelApi) {\n\t\t\t\t\tvoid fetchImpl(resolveUrl(config.cancelApi, runId), {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\trunId,\n\t\t};\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\treturn connect(runId, context);\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst startController = new AbortController();\n\t\t\tlet activeRun: ChatTransportRun | undefined;\n\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await fetchImpl(config.startApi, {\n\t\t\t\t\t\tbody: JSON.stringify({ message, ...config.startBody }),\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t\t\t...config.startHeaders,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmethod: config.startMethod ?? \"POST\",\n\t\t\t\t\t\tsignal: startController.signal,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Background SSE start failed: ${response.status} ${response.statusText}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = (await response.json()) as unknown;\n\t\t\t\t\tconst runId = (config.resolveRunId ?? resolveRunId)(data);\n\t\t\t\t\tcontext.setRunId(runId);\n\t\t\t\t\tactiveRun = connect(runId, context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isAbortError(error)) {\n\t\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})();\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tvoid activeRun?.close?.();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tstartController.abort();\n\t\t\t\t\tactiveRun?.stop?.();\n\t\t\t\t},\n\t\t\t\trunId: null,\n\t\t\t};\n\t\t},\n\t};\n}\n\nfunction defaultParseWebSocketMessage<TEvent extends { type: string }>(\n\tdata: unknown,\n): TEvent | TEvent[] | null {\n\tif (typeof data !== \"string\") {\n\t\treturn null;\n\t}\n\n\tconst parsed = JSON.parse(data) as TEvent | TEvent[];\n\treturn parsed;\n}\n\nexport function createWebSocketTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(config: WebSocketTransportOptions<TEvent>): ChatTransport<TPart, TEvent> {\n\tconst parseMessage = config.parseMessage ?? defaultParseWebSocketMessage;\n\tconst serializeMessage = config.serializeMessage ?? JSON.stringify;\n\n\tlet resolvedRunId: string | null = null;\n\n\tconst applyIncomingEvents = (\n\t\tparsed: TEvent | TEvent[] | null,\n\t\tcontext: ChatTransportContext<TPart, TEvent>,\n\t) => {\n\t\tconst events = Array.isArray(parsed) ? parsed : parsed ? [parsed] : [];\n\t\tfor (const item of events) {\n\t\t\tconst nextRunId = config.resolveRunId?.(item) ?? null;\n\t\t\tif (nextRunId) {\n\t\t\t\tresolvedRunId = nextRunId;\n\t\t\t\tcontext.setRunId(nextRunId);\n\t\t\t}\n\t\t\tcontext.emit(item);\n\n\t\t\tif (item.type === \"done\") {\n\t\t\t\tcontext.finish();\n\t\t\t} else if (item.type === \"error\") {\n\t\t\t\tcontext.fail(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"message\" in item && typeof item.message === \"string\"\n\t\t\t\t\t\t\t? item.message\n\t\t\t\t\t\t\t: \"Stream error\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n\n\treturn {\n\t\tresume: ({ context, runId }) => {\n\t\t\tcontext.setRunId(runId);\n\t\t\tcontext.ensureAssistantMessage();\n\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentResumePayload = false;\n\n\t\t\tconst sendResumePayload = () => {\n\t\t\t\tif (sentResumePayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentResumePayload = true;\n\t\t\t\tconst payload =\n\t\t\t\t\tconfig.buildResumePayload?.(runId) ??\n\t\t\t\t\t({ [config.runIdKey ?? \"runId\"]: runId } as Record<string, unknown>);\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendResumePayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendResumePayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t\tstart: ({ context, message }) => {\n\t\t\tconst runId = config.runId ?? config.getResumeKey?.() ?? null;\n\t\t\tconst socket = new WebSocket(\n\t\t\t\ttypeof config.url === \"function\" ? config.url(runId) : config.url,\n\t\t\t\tconfig.protocols,\n\t\t\t);\n\t\t\tlet manuallyClosed = false;\n\t\t\tlet sentStartPayload = false;\n\n\t\t\tconst sendStartPayload = () => {\n\t\t\t\tif (sentStartPayload || socket.readyState !== WebSocket.OPEN) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsentStartPayload = true;\n\t\t\t\tcontext.ensureAssistantMessage();\n\t\t\t\tconst payload: Record<string, unknown> = {\n\t\t\t\t\tmessage,\n\t\t\t\t\t...config.body,\n\t\t\t\t};\n\n\t\t\t\tif (runId) {\n\t\t\t\t\tpayload[config.runIdKey ?? \"runId\"] = runId;\n\t\t\t\t}\n\n\t\t\t\tsocket.send(serializeMessage(payload));\n\t\t\t};\n\n\t\t\tsocket.onopen = sendStartPayload;\n\n\t\t\tsocket.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tapplyIncomingEvents(parseMessage(event.data), context);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcontext.fail(toError(error));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tsocket.onerror = () => {\n\t\t\t\tcontext.fail(new Error(\"WebSocket connection failed\"));\n\t\t\t};\n\n\t\t\tsocket.onclose = () => {\n\t\t\t\tif (!manuallyClosed) {\n\t\t\t\t\tcontext.finish();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tqueueMicrotask(sendStartPayload);\n\n\t\t\treturn {\n\t\t\t\tclose: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tmanuallyClosed = true;\n\t\t\t\t\tconst stopRunId = resolvedRunId ?? runId;\n\t\t\t\t\tif (stopRunId && config.cancelUrl) {\n\t\t\t\t\t\tvoid fetch(resolveUrl(config.cancelUrl, stopRunId), {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsocket.close();\n\t\t\t\t},\n\t\t\t\trunId,\n\t\t\t};\n\t\t},\n\t};\n}\n\nexport function resolveTransport<\n\tTPart extends { type: string } = ContentPart,\n\tTEvent extends { type: string } = SSEEvent,\n>(options: UseStreamChatOptions<TPart, TEvent>): ChatTransport<TPart, TEvent> {\n\tif (typeof options.transport === \"object\" && options.transport) {\n\t\treturn options.transport;\n\t}\n\n\tconst transportKind = options.transport ?? \"sse\";\n\n\tif (transportKind === \"background-sse\") {\n\t\tconst config = options.transportOptions?.backgroundSSE;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.backgroundSSE` is required when transport is \"background-sse\"',\n\t\t\t);\n\t\t}\n\t\treturn createBackgroundSSETransport(config);\n\t}\n\n\tif (transportKind === \"websocket\") {\n\t\tconst config = options.transportOptions?.websocket;\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'`transportOptions.websocket` is required when transport is \"websocket\"',\n\t\t\t);\n\t\t}\n\t\treturn createWebSocketTransport(config);\n\t}\n\n\tconst sseConfig = options.transportOptions?.sse ?? {\n\t\tapi: options.api,\n\t\tbody: options.body,\n\t\theaders: options.headers,\n\t};\n\n\tif (!sseConfig.api) {\n\t\tthrow new Error(\n\t\t\t\"`api` or `transportOptions.sse.api` is required when using the default SSE transport\",\n\t\t);\n\t}\n\n\treturn createDirectSSETransport({\n\t\t...sseConfig,\n\t\tapi: sseConfig.api,\n\t});\n}\n"],"mappings":"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","names":["parseSSEStream","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deltakit/react",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "React hooks for streaming AI conversations with real-time updates",
5
5
  "homepage": "https://deltakit.dev",
6
6
  "type": "module",
@@ -33,6 +33,7 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@testing-library/react": "^16.3.0",
36
+ "@vitest/coverage-v8": "^3.2.1",
36
37
  "@types/react": "^18.3.18",
37
38
  "@types/react-dom": "^18.3.5",
38
39
  "jsdom": "^28.1.0",
@@ -51,6 +52,7 @@
51
52
  "dev": "tsup --watch",
52
53
  "check": "biome check src/",
53
54
  "test": "vitest run",
55
+ "test:coverage": "vitest run --coverage",
54
56
  "typecheck": "tsc --noEmit",
55
57
  "clean": "rm -rf dist"
56
58
  }