{"version":3,"file":"stream.custom.cjs","names":["BytesLineDecoder","SSEDecoder","IterableReadableStream","MessageTupleManager","StreamManager","useControllableThreadId","userFacingInterruptsFromValuesArray","getToolCallsWithResults"],"sources":["../../src/react/stream.custom.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n  GetUpdateType,\n  GetCustomEventType,\n  GetInterruptType,\n  GetToolCallsType,\n  GetConfigurableType,\n  UseStreamTransport,\n  AnyStreamCustomOptions,\n  CustomSubmitOptions,\n} from \"../ui/types.js\";\nimport type { UseStreamCustom } from \"./types.js\";\nimport { type Message } from \"../types.messages.js\";\nimport { getToolCallsWithResults } from \"../utils/tools.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { userFacingInterruptsFromValuesArray } from \"../ui/interrupts.js\";\nimport { Interrupt, type ThreadState } from \"../schema.js\";\nimport { BytesLineDecoder, SSEDecoder } from \"../utils/sse.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { useControllableThreadId } from \"./thread.js\";\nimport { Command } from \"../types.js\";\nimport type { BagTemplate } from \"../types.template.js\";\nimport { flushPendingHeadlessToolInterrupts } from \"../headless-tools.js\";\n\ninterface FetchStreamTransportOptions {\n  /**\n   * The URL of the API to use.\n   */\n  apiUrl: string;\n\n  /**\n   * Default headers to send with requests.\n   */\n  defaultHeaders?: HeadersInit;\n\n  /**\n   * Specify a custom fetch implementation.\n   */\n  fetch?: typeof fetch | ((...args: any[]) => any); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n  /**\n   * Callback that is called before the request is made.\n   */\n  onRequest?: (\n    url: string,\n    init: RequestInit\n  ) => Promise<RequestInit> | RequestInit;\n}\n\nexport class FetchStreamTransport<\n  StateType extends Record<string, unknown> = Record<string, unknown>,\n  Bag extends BagTemplate = BagTemplate,\n> implements UseStreamTransport<StateType, Bag> {\n  constructor(private readonly options: FetchStreamTransportOptions) {}\n\n  async stream(payload: {\n    input: GetUpdateType<Bag, StateType> | null | undefined;\n    context: GetConfigurableType<Bag> | undefined;\n    command: Command | undefined;\n    signal: AbortSignal;\n  }): Promise<AsyncGenerator<{ id?: string; event: string; data: unknown }>> {\n    const { signal, ...body } = payload;\n\n    let requestInit: RequestInit = {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        ...this.options.defaultHeaders,\n      },\n      body: JSON.stringify(body),\n      signal,\n    };\n\n    if (this.options.onRequest) {\n      requestInit = await this.options.onRequest(\n        this.options.apiUrl,\n        requestInit\n      );\n    }\n    const fetchFn = this.options.fetch ?? fetch;\n\n    const response = await fetchFn(this.options.apiUrl, requestInit);\n    if (!response.ok) {\n      throw new Error(`Failed to stream: ${response.statusText}`);\n    }\n\n    const stream = (\n      response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })\n    )\n      .pipeThrough(BytesLineDecoder())\n      .pipeThrough(SSEDecoder());\n\n    return IterableReadableStream.fromReadableStream(stream);\n  }\n}\n\nfunction createCustomTransportThreadState<\n  StateType extends Record<string, unknown>,\n>(values: StateType, threadId: string): ThreadState<StateType> {\n  return {\n    values,\n    next: [],\n    tasks: [],\n    metadata: undefined,\n    created_at: null,\n    checkpoint: {\n      thread_id: threadId,\n      checkpoint_id: null,\n      checkpoint_ns: \"\",\n      checkpoint_map: null,\n    },\n    parent_checkpoint: null,\n  };\n}\n\nexport function useStreamCustom<\n  StateType extends Record<string, unknown> = Record<string, unknown>,\n  Bag extends BagTemplate = BagTemplate,\n>(\n  options: AnyStreamCustomOptions<StateType, Bag>\n): UseStreamCustom<StateType, Bag> {\n  type UpdateType = GetUpdateType<Bag, StateType>;\n  type CustomType = GetCustomEventType<Bag>;\n  type InterruptType = GetInterruptType<Bag>;\n  type ConfigurableType = GetConfigurableType<Bag>;\n  type ToolCallType = GetToolCallsType<StateType>;\n\n  const [messageManager] = useState(() => new MessageTupleManager());\n  const [stream] = useState(\n    () =>\n      new StreamManager<StateType, Bag>(messageManager, {\n        throttle: options.throttle ?? false,\n        subagentToolNames: options.subagentToolNames,\n        filterSubagentMessages: options.filterSubagentMessages,\n      })\n  );\n\n  useSyncExternalStore(\n    stream.subscribe,\n    stream.getSnapshot,\n    stream.getSnapshot\n  );\n\n  const [threadId, onThreadId] = useControllableThreadId(options);\n  const threadIdRef = useRef<string | null>(threadId);\n\n  // Cancel the stream if thread ID has changed\n  useEffect(() => {\n    if (threadIdRef.current !== threadId) {\n      threadIdRef.current = threadId;\n      stream.clear();\n    }\n  }, [threadId, stream]);\n\n  const getMessages = (value: StateType): Message[] => {\n    const messagesKey = options.messagesKey ?? \"messages\";\n    return Array.isArray(value[messagesKey])\n      ? (value[messagesKey] as Message[])\n      : [];\n  };\n\n  const setMessages = (current: StateType, messages: Message[]): StateType => {\n    const messagesKey = options.messagesKey ?? \"messages\";\n    return { ...current, [messagesKey]: messages };\n  };\n\n  const historyValues = options.initialValues ?? ({} as StateType);\n\n  // Reconstruct subagents from initialValues when:\n  // 1. Subagent filtering is enabled\n  // 2. Not currently streaming\n  // 3. initialValues has messages\n  // This ensures subagent visualization works with cached/persisted state\n  const historyMessages = getMessages(historyValues);\n  const shouldReconstructSubagents =\n    options.filterSubagentMessages &&\n    !stream.isLoading &&\n    historyMessages.length > 0;\n\n  useEffect(() => {\n    if (shouldReconstructSubagents) {\n      // skipIfPopulated: true ensures we don't overwrite subagents from active streaming\n      stream.reconstructSubagents(historyMessages, { skipIfPopulated: true });\n    }\n    // We intentionally only run this when shouldReconstructSubagents changes\n    // to avoid unnecessary reconstructions during streaming\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [shouldReconstructSubagents, historyMessages.length]);\n\n  const stop = () => stream.stop(historyValues, { onStop: options.onStop });\n\n  const submit = async (\n    values: UpdateType | null | undefined,\n    submitOptions?: CustomSubmitOptions<StateType, ConfigurableType>\n  ) => {\n    let usableThreadId = threadId;\n\n    stream.setStreamValues(() => {\n      if (submitOptions?.optimisticValues != null) {\n        return {\n          ...historyValues,\n          ...(typeof submitOptions.optimisticValues === \"function\"\n            ? submitOptions.optimisticValues(historyValues)\n            : submitOptions.optimisticValues),\n        };\n      }\n\n      return { ...historyValues };\n    });\n\n    await stream.start(\n      async (signal: AbortSignal) => {\n        if (!usableThreadId) {\n          // generate random thread id\n          usableThreadId = crypto.randomUUID();\n          threadIdRef.current = usableThreadId;\n          onThreadId(usableThreadId);\n        }\n\n        if (!usableThreadId) {\n          throw new Error(\"Failed to obtain valid thread ID.\");\n        }\n\n        return options.transport.stream({\n          input: values,\n          context: submitOptions?.context,\n          command: submitOptions?.command,\n          signal,\n          config: {\n            ...submitOptions?.config,\n            configurable: {\n              thread_id: usableThreadId,\n              ...submitOptions?.config?.configurable,\n            } as unknown as GetConfigurableType<Bag>,\n          },\n        }) as Promise<\n          AsyncGenerator<EventStreamEvent<StateType, UpdateType, CustomType>>\n        >;\n      },\n      {\n        getMessages,\n        setMessages,\n\n        initialValues: {} as StateType,\n        callbacks: options,\n\n        onSuccess: () => {\n          if (!usableThreadId) return undefined;\n\n          const finalValues = stream.values ?? historyValues;\n          options.onFinish?.(\n            createCustomTransportThreadState(finalValues, usableThreadId),\n            undefined\n          );\n\n          return undefined;\n        },\n        onError(error) {\n          options.onError?.(error, undefined);\n        },\n      }\n    );\n  };\n\n  const handledToolsRef = useRef<Set<string>>(new Set());\n  useEffect(() => {\n    handledToolsRef.current.clear();\n  }, [threadId]);\n\n  useEffect(() => {\n    flushPendingHeadlessToolInterrupts(\n      stream.values as Record<string, unknown> | null,\n      options.tools,\n      handledToolsRef.current,\n      {\n        onTool: options.onTool,\n        defer: (run) => {\n          void Promise.resolve().then(run);\n        },\n        resumeSubmit: (command) =>\n          submit(null, {\n            command,\n          }),\n      }\n    );\n  }, [options.onTool, options.tools, stream.values, submit]);\n\n  return {\n    get values() {\n      return stream.values ?? ({} as StateType);\n    },\n\n    error: stream.error,\n    isLoading: stream.isLoading,\n\n    stop,\n    submit,\n\n    get interrupts(): Interrupt<InterruptType>[] {\n      if (\n        stream.values != null &&\n        \"__interrupt__\" in stream.values &&\n        Array.isArray(stream.values.__interrupt__)\n      ) {\n        return userFacingInterruptsFromValuesArray<InterruptType>(\n          stream.values.__interrupt__ as Interrupt<InterruptType>[]\n        );\n      }\n\n      return [];\n    },\n\n    get interrupt(): Interrupt<InterruptType> | undefined {\n      const all = this.interrupts;\n      if (all.length === 0) return undefined;\n      if (all.length === 1) return all[0];\n\n      // Multiple interrupts: return the array for backward compat\n      return all as Interrupt<InterruptType>;\n    },\n\n    get messages(): Message<ToolCallType>[] {\n      if (!stream.values) return [];\n      return getMessages(stream.values);\n    },\n\n    get toolCalls() {\n      if (!stream.values) return [];\n      const msgs = getMessages(stream.values);\n      return getToolCallsWithResults<ToolCallType>(msgs);\n    },\n\n    getToolCalls(message) {\n      if (!stream.values) return [];\n      const msgs = getMessages(stream.values);\n      const allToolCalls = getToolCallsWithResults<ToolCallType>(msgs);\n      return allToolCalls.filter((tc) => tc.aiMessage.id === message.id);\n    },\n\n    get subagents() {\n      return stream.getSubagents();\n    },\n\n    get activeSubagents() {\n      return stream.getActiveSubagents();\n    },\n\n    getSubagent(toolCallId: string) {\n      return stream.getSubagent(toolCallId);\n    },\n\n    getSubagentsByType(type: string) {\n      return stream.getSubagentsByType(type);\n    },\n\n    getSubagentsByMessage(messageId: string) {\n      return stream.getSubagentsByMessage(messageId);\n    },\n  };\n}\n"],"mappings":"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"}