{"version":3,"file":"http.cjs","names":["AsyncQueue","reconnectDelayMs","resolveProtocolPath","toAbsoluteUrl","mergeHeaders","toError","isProtocolResponse","BytesLineDecoder","idleReconnectStream","SSEDecoder","IterableReadableStream","isRecord"],"sources":["../../../../src/client/stream/transport/http.ts"],"sourcesContent":["import { AsyncQueue } from \"./queue.js\";\nimport type {\n  Message,\n  SubscribeParams,\n  Command,\n  CommandResponse,\n  ErrorResponse,\n} from \"@langchain/protocol\";\n\nimport type { AsyncCaller } from \"../../../utils/async_caller.js\";\nimport type {\n  HeaderValue,\n  ProtocolRequestHook,\n  ProtocolSseTransportOptions,\n  ProtocolTransportPaths,\n} from \"./types.js\";\nimport type { TransportAdapter, EventStreamHandle } from \"../transport.js\";\nimport {\n  toAbsoluteUrl,\n  isRecord,\n  mergeHeaders,\n  toError,\n  isProtocolResponse,\n  resolveProtocolPath,\n} from \"./utils.js\";\nimport { BytesLineDecoder, SSEDecoder } from \"../../../utils/sse.js\";\nimport {\n  IterableReadableStream,\n  idleReconnectStream,\n  type IdleReconnectMode,\n} from \"../../../utils/stream.js\";\nimport {\n  DEFAULT_MAX_RECONNECT_ATTEMPTS,\n  reconnectDelayMs,\n} from \"../../../utils/reconnect.js\";\nimport { DEFAULT_IDLE_RECONNECT } from \"../../../utils/stream.js\";\n\n/**\n * Transport adapter that speaks the thread-centric protocol over HTTP\n * commands plus SSE event streams. Bound to a `threadId` at construction\n * or later via {@link setThreadId}; request URLs derive from the\n * currently-bound thread. Each {@link openEventStream} call opens an\n * independent filtered SSE connection via\n * `POST /threads/:thread_id/stream/events`.\n */\nexport class ProtocolSseTransportAdapter implements TransportAdapter {\n  threadId: string;\n\n  readonly apiUrl: string;\n\n  private readonly queue = new AsyncQueue<Message>();\n\n  private readonly fetchImpl: typeof fetch;\n\n  private readonly defaultHeaders: Record<string, HeaderValue>;\n\n  private readonly onRequest?: ProtocolRequestHook;\n\n  private readonly fetchFactory?: () => typeof fetch | Promise<typeof fetch>;\n\n  private readonly asyncCaller?: AsyncCaller;\n\n  private readonly maxReconnectAttempts: number;\n\n  private readonly idleReconnect: IdleReconnectMode | null;\n\n  private readonly onReconnect?: ProtocolSseTransportOptions[\"onReconnect\"];\n\n  private readonly onConnected?: ProtocolSseTransportOptions[\"onConnected\"];\n\n  private readonly reconnectDelayMs: (attempt: number) => number;\n\n  private readonly paths?: ProtocolTransportPaths;\n\n  private readonly sessionAbortController = new AbortController();\n\n  private readonly eventStreams = new Set<AbortController>();\n\n  private closed = false;\n\n  constructor(options: ProtocolSseTransportOptions) {\n    this.fetchImpl = options.fetch ?? fetch;\n    this.apiUrl = options.apiUrl;\n    this.defaultHeaders = options.defaultHeaders ?? {};\n    this.onRequest = options.onRequest;\n    this.fetchFactory = options.fetchFactory;\n    this.asyncCaller = options.asyncCaller;\n    // Custom `fetch` (auth shims, proxies) must keep reconnect enabled — that is\n    // the production path for tenant-aware browsers. Tests that need fail-fast\n    // mocks should pass `maxReconnectAttempts: 0` (and `idleReconnect: 0`)\n    // explicitly rather than relying on `fetch` presence.\n    this.maxReconnectAttempts =\n      options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n    // Default to heartbeat-adaptive idle reconnect, which stays dormant\n    // unless the server actually emits keep-alive heartbeats. Pass `0` to\n    // disable.\n    this.idleReconnect = options.idleReconnect ?? DEFAULT_IDLE_RECONNECT;\n    this.onReconnect = options.onReconnect;\n    this.onConnected = options.onConnected;\n    this.reconnectDelayMs = options.reconnectDelayMs ?? reconnectDelayMs;\n    this.threadId = options.threadId ?? \"\";\n    this.paths = options.paths;\n  }\n\n  /** {@inheritDoc TransportAdapter.setThreadId} */\n  setThreadId(threadId: string): void {\n    this.threadId = threadId;\n  }\n\n  /**\n   * Command/stream/state URLs derive from the currently-bound thread so a\n   * single adapter can follow {@link setThreadId} re-binds. A fixed\n   * `paths.*` string overrides the default and is used as-is.\n   */\n  private get commandsUrl(): string {\n    return resolveProtocolPath(\n      this.paths?.commands,\n      this.threadId,\n      (id) => `/threads/${id}/commands`\n    );\n  }\n\n  private get streamUrl(): string {\n    return resolveProtocolPath(\n      this.paths?.stream,\n      this.threadId,\n      (id) => `/threads/${id}/stream/events`\n    );\n  }\n\n  private get stateUrl(): string {\n    return resolveProtocolPath(\n      this.paths?.state,\n      this.threadId,\n      (id) => `/threads/${id}/state`\n    );\n  }\n\n  /**\n   * Fetch checkpointed thread state for hydration.\n   *\n   * Uses `GET`, matching `client.threads.getState()` and both LangGraph\n   * Platform and Agent Protocol custom backends (`POST` is reserved for\n   * `updateState`).\n   */\n  async getState<StateType = unknown>(): Promise<{\n    values: StateType;\n    next?: unknown;\n    tasks?: unknown;\n    metadata?: unknown;\n    checkpoint?: { checkpoint_id?: string } | null;\n    parent_checkpoint?: { checkpoint_id?: string } | null;\n  } | null> {\n    const url = toAbsoluteUrl(this.apiUrl, this.stateUrl);\n    let requestInit: RequestInit = {\n      method: \"GET\",\n      headers: mergeHeaders(this.defaultHeaders, {}),\n    };\n\n    if (this.onRequest) {\n      requestInit = await this.onRequest(url, requestInit);\n    }\n\n    const fetchImpl = await this.resolveFetch();\n    const response = await fetchImpl(url.toString(), requestInit);\n    if (response.status === 404) return null;\n    if (!response.ok) {\n      const error = toError(\n        new Error(\n          `Thread state request failed: ${response.status} ${response.statusText}`\n        )\n      ) as Error & { status?: number };\n      error.status = response.status;\n      throw error;\n    }\n\n    return (await response.json()) as {\n      values: StateType;\n      next?: unknown;\n      tasks?: unknown;\n      metadata?: unknown;\n      checkpoint?: { checkpoint_id?: string } | null;\n      parent_checkpoint?: { checkpoint_id?: string } | null;\n    };\n  }\n\n  private async resolveFetch(): Promise<typeof fetch> {\n    if (this.fetchFactory) {\n      return await this.fetchFactory();\n    }\n    return this.fetchImpl;\n  }\n\n  /**\n   * HTTP/SSE transports have no handshake — connections are made\n   * per-command and per-subscription.\n   */\n  async open(): Promise<void> {\n    // no-op\n  }\n\n  async send(\n    command: Command\n  ): Promise<CommandResponse | ErrorResponse | void> {\n    const response = await this.request(this.commandsUrl, {\n      method: \"POST\",\n      headers: { \"content-type\": \"application/json\" },\n      body: JSON.stringify(command),\n      signal: this.sessionAbortController.signal,\n    });\n\n    if (response.status === 202 || response.status === 204) {\n      return undefined;\n    }\n\n    const payload = (await response.json()) as unknown;\n    if (!isProtocolResponse(payload)) {\n      throw new Error(\"Protocol command did not return a valid response.\");\n    }\n    return payload;\n  }\n\n  /**\n   * WebSocket-style single event stream.\n   * For the SSE transport this returns a dummy iterable; real event\n   * delivery happens via {@link openEventStream}.\n   */\n  events(): AsyncIterable<Message> {\n    const queue = this.queue;\n    return {\n      [Symbol.asyncIterator]: () => ({\n        next: async () => await queue.shift(),\n        return: async () => {\n          queue.close();\n          return { done: true, value: undefined };\n        },\n      }),\n    };\n  }\n\n  openEventStream(params: SubscribeParams): EventStreamHandle {\n    if (this.closed) {\n      throw new Error(\"Protocol transport is closed.\");\n    }\n\n    const ac = new AbortController();\n    this.eventStreams.add(ac);\n    const streamQueue = new AsyncQueue<Message>();\n    const streamUrl = this.streamUrl;\n\n    let resolveReady!: () => void;\n    let rejectReady!: (err: unknown) => void;\n    const ready = new Promise<void>((resolve, reject) => {\n      resolveReady = resolve;\n      rejectReady = reject;\n    });\n\n    // Honor an explicit caller `since` until the stream has connected\n    // once. Do not advance it from observed `seq` values — those are\n    // connection-local, and carrying them onto a post-connect reconnect\n    // POST filters out the full Redis replay (heartbeats only). Pre-ready\n    // retries still send the caller cursor; only after a successful open\n    // do reconnects omit `since` and rely on durable `event_id` dedup.\n    const initialSince =\n      typeof (params as SubscribeParams & { since?: unknown }).since ===\n      \"number\"\n        ? (params as SubscribeParams & { since: number }).since\n        : undefined;\n\n    let readySettled = false;\n\n    const startStream = async () => {\n      let attempt = 0;\n      let receivedEvent = false;\n\n      while (!ac.signal.aborted && !this.closed) {\n        try {\n          const response = await this.request(\n            streamUrl,\n            {\n              method: \"POST\",\n              headers: {\n                \"content-type\": \"application/json\",\n                accept: \"text/event-stream\",\n              },\n              body: JSON.stringify({\n                channels: params.channels,\n                ...(params.namespaces ? { namespaces: params.namespaces } : {}),\n                ...(params.depth != null ? { depth: params.depth } : {}),\n                ...(!readySettled && initialSince != null\n                  ? { since: initialSince }\n                  : {}),\n              }),\n              signal: ac.signal,\n            },\n            { stream: true }\n          );\n\n          const contentType = response.headers\n            .get(\"content-type\")\n            ?.split(\";\")[0];\n          if (contentType && !contentType.includes(\"text/event-stream\")) {\n            throw new Error(\n              `Expected response header Content-Type to contain 'text/event-stream', got '${contentType}'`\n            );\n          }\n\n          await this.onConnected?.({\n            kind: attempt === 0 ? \"initial\" : \"reconnected\",\n            attempt,\n          });\n\n          if (!readySettled) {\n            readySettled = true;\n            resolveReady();\n          }\n\n          const readable =\n            response.body ??\n            new ReadableStream<Uint8Array>({\n              start(controller) {\n                controller.close();\n              },\n            });\n\n          // Idle watchdog on the line stream (between byte-line and SSE\n          // decoding) so it can reset on any line and recognise `:` keep-alive\n          // heartbeats to drive `\"auto\"` mode. On idle it errors the stream,\n          // which the catch below treats like any other disconnect and\n          // re-opens the SSE without carrying a connection-local `since`.\n          const enableIdle =\n            this.idleReconnect === \"auto\" ||\n            (typeof this.idleReconnect === \"number\" && this.idleReconnect > 0);\n          const lines = readable.pipeThrough(BytesLineDecoder());\n          const watched = enableIdle\n            ? lines.pipeThrough(\n                idleReconnectStream({ mode: this.idleReconnect! })\n              )\n            : lines;\n          const stream = watched.pipeThrough(SSEDecoder());\n          const iterable = IterableReadableStream.fromReadableStream(stream);\n\n          for await (const event of iterable) {\n            if (ac.signal.aborted || this.closed) {\n              break;\n            }\n            if (isRecord(event.data)) {\n              receivedEvent = true;\n              streamQueue.push(event.data as Message);\n            }\n          }\n          if (\n            ac.signal.aborted ||\n            this.closed ||\n            this.maxReconnectAttempts <= 0\n          ) {\n            streamQueue.close();\n            return;\n          }\n          // The thread stream is open-ended: the server only ends it when\n          // its own upstream consumer died or it is shutting down, so a\n          // clean close is a disconnect, not the end of the thread.\n          throw new Error(\"Event stream closed by the server\");\n        } catch (error) {\n          if (receivedEvent) {\n            attempt = 0;\n            receivedEvent = false;\n          }\n          if (ac.signal.aborted || this.closed) {\n            if (!readySettled) {\n              rejectReady(error);\n            }\n            streamQueue.close();\n            return;\n          }\n          if (this.maxReconnectAttempts <= 0) {\n            if (!readySettled) {\n              rejectReady(error);\n            }\n            streamQueue.close(toError(error));\n            return;\n          }\n          attempt += 1;\n          if (attempt > this.maxReconnectAttempts) {\n            if (!readySettled) {\n              rejectReady(error);\n            }\n            streamQueue.close(toError(error));\n            return;\n          }\n          const delay = this.reconnectDelayMs(attempt);\n          this.onReconnect?.({ attempt, cause: error, delayMs: delay });\n          if (delay > 0) {\n            await new Promise<void>((resolve) => {\n              setTimeout(resolve, delay);\n            });\n          }\n        }\n      }\n    };\n\n    void startStream();\n\n    const cleanup = () => {\n      this.eventStreams.delete(ac);\n      ac.abort();\n      streamQueue.close();\n    };\n\n    return {\n      events: {\n        [Symbol.asyncIterator]: () => ({\n          next: async () => await streamQueue.shift(),\n          return: async () => {\n            cleanup();\n            return { done: true, value: undefined };\n          },\n        }),\n      },\n      ready,\n      close: cleanup,\n    };\n  }\n\n  async close(): Promise<void> {\n    if (this.closed) {\n      return;\n    }\n    this.closed = true;\n    this.sessionAbortController.abort();\n    for (const ac of this.eventStreams) ac.abort();\n    this.eventStreams.clear();\n    this.queue.close();\n  }\n\n  private async request(\n    path: string,\n    init: RequestInit,\n    options?: { stream?: boolean }\n  ): Promise<Response> {\n    const url = toAbsoluteUrl(this.apiUrl, path);\n    let requestInit: RequestInit = {\n      ...init,\n      headers: mergeHeaders(this.defaultHeaders, init.headers),\n    };\n\n    if (this.onRequest) {\n      requestInit = await this.onRequest(url, requestInit);\n    }\n\n    // Long-lived SSE event streams must not run through AsyncCaller: its\n    // p-queue/p-retry semantics are designed for discrete request/response\n    // calls, and wrapping a streaming response stalls the call (and can\n    // leak retries). Stream resilience is handled separately by the\n    // reconnect loop in `openEventStream`.\n    const useAsyncCaller = this.asyncCaller != null && !options?.stream;\n\n    const execute = async (): Promise<Response> => {\n      const fetchImpl = await this.resolveFetch();\n      const response = await fetchImpl(url.toString(), requestInit);\n      if (!response.ok) {\n        // Reject with the Response so AsyncCaller maps it to HTTPError and\n        // applies STATUS_NO_RETRY / retry policy consistently with REST.\n        if (useAsyncCaller) {\n          throw response;\n        }\n        let detail = \"\";\n        try {\n          const body = await response.text();\n          const parsed = JSON.parse(body);\n          if (typeof parsed === \"object\" && parsed != null) {\n            detail =\n              ((parsed as Record<string, unknown>).message as string) ??\n              ((parsed as Record<string, unknown>).error as string) ??\n              \"\";\n          }\n          if (!detail) detail = body;\n        } catch {\n          // body unreadable or not JSON — fall through\n        }\n        const message = detail\n          ? `Protocol request failed: ${response.status} ${response.statusText} — ${detail}`\n          : `Protocol request failed: ${response.status} ${response.statusText}`;\n        throw new Error(message);\n      }\n      return response;\n    };\n\n    try {\n      return useAsyncCaller\n        ? await this.asyncCaller!.call(execute)\n        : await execute();\n    } catch (error) {\n      throw toError(error);\n    }\n  }\n}\n"],"mappings":"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"}