{"version":3,"file":"manager.cjs","names":["StreamError","values","toMessageDict"],"sources":["../../src/ui/manager.ts"],"sourcesContent":["import type {\n  CheckpointsStreamEvent,\n  CustomStreamEvent,\n  DebugStreamEvent,\n  ErrorStreamEvent,\n  EventsStreamEvent,\n  FeedbackStreamEvent,\n  MessagesTupleStreamEvent,\n  MetadataStreamEvent,\n  TasksStreamEvent,\n  UpdatesStreamEvent,\n  ValuesStreamEvent,\n} from \"../types.stream.js\";\nimport { MessageTupleManager, toMessageDict } from \"./messages.js\";\nimport { StreamError } from \"./errors.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { BagTemplate } from \"../types.template.js\";\n\n/**\n * Special ID used by LangGraph's messagesStateReducer to signal\n * that all messages should be removed from the state.\n */\nexport const REMOVE_ALL_MESSAGES = \"__remove_all__\";\n\ntype GetUpdateType<\n  Bag extends BagTemplate,\n  StateType extends Record<string, unknown>\n> = Bag extends { UpdateType: unknown }\n  ? Bag[\"UpdateType\"]\n  : Partial<StateType>;\n\ntype GetCustomEventType<Bag extends BagTemplate> = Bag extends {\n  CustomEventType: unknown;\n}\n  ? Bag[\"CustomEventType\"]\n  : unknown;\n\ntype EventStreamMap<StateType, UpdateType, CustomType> = {\n  values: ValuesStreamEvent<StateType>;\n  updates: UpdatesStreamEvent<UpdateType>;\n  custom: CustomStreamEvent<CustomType>;\n  debug: DebugStreamEvent;\n  messages: MessagesTupleStreamEvent;\n  events: EventsStreamEvent;\n  metadata: MetadataStreamEvent;\n  checkpoints: CheckpointsStreamEvent<StateType>;\n  tasks: TasksStreamEvent<StateType, UpdateType>;\n  error: ErrorStreamEvent;\n  feedback: FeedbackStreamEvent;\n};\n\nexport type EventStreamEvent<StateType, UpdateType, CustomType> =\n  EventStreamMap<StateType, UpdateType, CustomType>[keyof EventStreamMap<\n    StateType,\n    UpdateType,\n    CustomType\n  >];\n\ninterface StreamManagerEventCallbacks<\n  StateType extends Record<string, unknown>,\n  Bag extends BagTemplate = BagTemplate\n> {\n  onUpdateEvent?: (\n    data: UpdatesStreamEvent<GetUpdateType<Bag, StateType>>[\"data\"],\n    options: {\n      namespace: string[] | undefined;\n      mutate: (\n        update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n      ) => void;\n    }\n  ) => void;\n  onCustomEvent?: (\n    data: GetCustomEventType<Bag>,\n    options: {\n      namespace: string[] | undefined;\n      mutate: (\n        update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n      ) => void;\n    }\n  ) => void;\n  onMetadataEvent?: (data: MetadataStreamEvent[\"data\"]) => void;\n  onLangChainEvent?: (data: EventsStreamEvent[\"data\"]) => void;\n  onDebugEvent?: (\n    data: DebugStreamEvent[\"data\"],\n    options: { namespace: string[] | undefined }\n  ) => void;\n  onCheckpointEvent?: (\n    data: CheckpointsStreamEvent<StateType>[\"data\"],\n    options: { namespace: string[] | undefined }\n  ) => void;\n  onTaskEvent?: (\n    data: TasksStreamEvent<StateType, GetUpdateType<Bag, StateType>>[\"data\"],\n    options: { namespace: string[] | undefined }\n  ) => void;\n}\n\nexport class StreamManager<\n  StateType extends Record<string, unknown>,\n  Bag extends BagTemplate = BagTemplate\n> {\n  private abortRef = new AbortController();\n\n  private messages: MessageTupleManager;\n\n  private listeners = new Set<() => void>();\n\n  private throttle: number | boolean;\n\n  private queue: Promise<unknown> = Promise.resolve();\n\n  private queueSize: number = 0;\n\n  private state: {\n    isLoading: boolean;\n    values: [values: StateType, kind: \"stream\" | \"stop\"] | null;\n    error: unknown;\n  };\n\n  constructor(\n    messages: MessageTupleManager,\n    options: { throttle: number | boolean }\n  ) {\n    this.messages = messages;\n    this.state = { isLoading: false, values: null, error: undefined };\n    this.throttle = options.throttle;\n  }\n\n  private setState = (newState: Partial<typeof this.state>) => {\n    this.state = { ...this.state, ...newState };\n    this.notifyListeners();\n  };\n\n  private notifyListeners = () => {\n    this.listeners.forEach((listener) => listener());\n  };\n\n  subscribe = (listener: () => void): (() => void) => {\n    if (this.throttle === false) {\n      this.listeners.add(listener);\n      return () => this.listeners.delete(listener);\n    }\n\n    const timeoutMs = this.throttle === true ? 0 : this.throttle;\n    let timeoutId: NodeJS.Timeout | number | undefined;\n\n    const throttledListener = () => {\n      clearTimeout(timeoutId);\n      timeoutId = setTimeout(() => {\n        clearTimeout(timeoutId);\n        listener();\n      }, timeoutMs);\n    };\n\n    this.listeners.add(throttledListener);\n    return () => {\n      clearTimeout(timeoutId);\n      this.listeners.delete(throttledListener);\n    };\n  };\n\n  getSnapshot = () => this.state;\n\n  get isLoading() {\n    return this.state.isLoading;\n  }\n\n  get values() {\n    return this.state.values?.[0] ?? null;\n  }\n\n  get error() {\n    return this.state.error;\n  }\n\n  setStreamValues = (\n    values:\n      | (StateType | null)\n      | ((prev: StateType | null, kind: \"stream\" | \"stop\") => StateType | null),\n    kind: \"stream\" | \"stop\" = \"stream\"\n  ) => {\n    if (typeof values === \"function\") {\n      const [prevValues, prevKind] = this.state.values ?? [null, \"stream\"];\n      const nextValues = values(prevValues, prevKind);\n      this.setState({ values: nextValues != null ? [nextValues, kind] : null });\n    } else {\n      const nextValues = values != null ? [values, kind] : null;\n      this.setState({ values: nextValues as [StateType, \"stream\" | \"stop\"] });\n    }\n  };\n\n  private getMutateFn = (kind: \"stream\" | \"stop\", historyValues: StateType) => {\n    return (\n      update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n    ) => {\n      const prev = {\n        ...historyValues,\n        ...(this.state.values ?? [null, \"stream\"])[0],\n      };\n      const next = typeof update === \"function\" ? update(prev) : update;\n      this.setStreamValues({ ...prev, ...next }, kind);\n    };\n  };\n\n  private matchEventType = <\n    T extends keyof EventStreamMap<\n      StateType,\n      GetUpdateType<Bag, StateType>,\n      GetCustomEventType<Bag>\n    >\n  >(\n    expected: T,\n    actual: EventStreamEvent<\n      StateType,\n      GetUpdateType<Bag, StateType>,\n      GetCustomEventType<Bag>\n    >[\"event\"],\n    _data: EventStreamEvent<\n      StateType,\n      GetUpdateType<Bag, StateType>,\n      GetCustomEventType<Bag>\n    >[\"data\"]\n  ): _data is EventStreamMap<\n    StateType,\n    GetUpdateType<Bag, StateType>,\n    GetCustomEventType<Bag>\n  >[T][\"data\"] => {\n    return expected === actual || actual.startsWith(`${expected}|`);\n  };\n\n  protected enqueue = async (\n    action: (\n      signal: AbortSignal\n    ) => Promise<\n      AsyncGenerator<\n        EventStreamEvent<\n          StateType,\n          GetUpdateType<Bag, StateType>,\n          GetCustomEventType<Bag>\n        >\n      >\n    >,\n    options: {\n      getMessages: (values: StateType) => Message[];\n\n      setMessages: (current: StateType, messages: Message[]) => StateType;\n\n      initialValues: StateType;\n\n      callbacks: StreamManagerEventCallbacks<StateType, Bag>;\n\n      onSuccess: () =>\n        | StateType\n        | null\n        | undefined\n        | void\n        | Promise<StateType | null | undefined | void>;\n\n      onError: (error: unknown) => void | Promise<void>;\n\n      onFinish?: () => void;\n    }\n  ) => {\n    try {\n      this.queueSize = Math.max(0, this.queueSize - 1);\n      this.setState({ isLoading: true, error: undefined });\n      this.abortRef = new AbortController();\n\n      const run = await action(this.abortRef.signal);\n\n      let streamError: StreamError | undefined;\n      for await (const { event, data } of run) {\n        if (event === \"error\") {\n          streamError = new StreamError(data);\n          break;\n        }\n\n        const namespace = event.includes(\"|\")\n          ? event.split(\"|\").slice(1)\n          : undefined;\n\n        const mutate = this.getMutateFn(\"stream\", options.initialValues);\n\n        if (event === \"metadata\") options.callbacks.onMetadataEvent?.(data);\n        if (event === \"events\") options.callbacks.onLangChainEvent?.(data);\n\n        if (this.matchEventType(\"updates\", event, data)) {\n          options.callbacks.onUpdateEvent?.(data, { namespace, mutate });\n        }\n\n        if (this.matchEventType(\"custom\", event, data)) {\n          options.callbacks.onCustomEvent?.(data, { namespace, mutate });\n        }\n\n        if (this.matchEventType(\"checkpoints\", event, data)) {\n          options.callbacks.onCheckpointEvent?.(data, { namespace });\n        }\n\n        if (this.matchEventType(\"tasks\", event, data)) {\n          options.callbacks.onTaskEvent?.(data, { namespace });\n        }\n\n        if (this.matchEventType(\"debug\", event, data)) {\n          options.callbacks.onDebugEvent?.(data, { namespace });\n        }\n\n        if (event === \"values\") {\n          if (\"__interrupt__\" in data) {\n            this.setStreamValues((prev) => ({ ...prev, ...data }));\n          } else {\n            this.setStreamValues(data);\n          }\n        }\n\n        if (this.matchEventType(\"messages\", event, data)) {\n          const [serialized, metadata] = data;\n\n          const messageId = this.messages.add(serialized, metadata);\n          if (!messageId) {\n            console.warn(\n              \"Failed to add message to manager, no message ID found\"\n            );\n            continue;\n          }\n\n          this.setStreamValues((streamValues) => {\n            const values = { ...options.initialValues, ...streamValues };\n\n            // Assumption: we're concatenating the message\n            let messages = options.getMessages(values).slice();\n            const { chunk, index } =\n              this.messages.get(messageId, messages.length) ?? {};\n\n            if (!chunk || index == null) return values;\n            if (chunk.getType() === \"remove\") {\n              // Check for special REMOVE_ALL_MESSAGES sentinel\n              if (chunk.id === REMOVE_ALL_MESSAGES) {\n                // Clear all messages when __remove_all__ is received\n                messages = [];\n              } else {\n                messages.splice(index, 1);\n              }\n            } else {\n              messages[index] = toMessageDict(chunk);\n            }\n\n            return options.setMessages(values, messages);\n          });\n        }\n      }\n\n      if (streamError != null) throw streamError;\n\n      const values = await options.onSuccess?.();\n      if (typeof values !== \"undefined\" && this.queueSize === 0) {\n        this.setStreamValues(values);\n      }\n    } catch (error) {\n      if (\n        !(\n          error instanceof Error && // eslint-disable-line no-instanceof/no-instanceof\n          (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n        )\n      ) {\n        console.error(error);\n        this.setState({ error });\n        await options.onError?.(error);\n      }\n    } finally {\n      this.setState({ isLoading: false });\n      this.abortRef = new AbortController();\n      options.onFinish?.();\n    }\n  };\n\n  start = async (\n    action: (\n      signal: AbortSignal\n    ) => Promise<\n      AsyncGenerator<\n        EventStreamEvent<\n          StateType,\n          GetUpdateType<Bag, StateType>,\n          GetCustomEventType<Bag>\n        >\n      >\n    >,\n    options: {\n      getMessages: (values: StateType) => Message[];\n\n      setMessages: (current: StateType, messages: Message[]) => StateType;\n\n      initialValues: StateType;\n\n      callbacks: StreamManagerEventCallbacks<StateType, Bag>;\n\n      onSuccess: () =>\n        | StateType\n        | null\n        | undefined\n        | void\n        | Promise<StateType | null | undefined | void>;\n\n      onError: (error: unknown) => void | Promise<void>;\n\n      onFinish?: () => void;\n    }\n  ): Promise<void> => {\n    this.queueSize += 1;\n    this.queue = this.queue.then(() => this.enqueue(action, options));\n  };\n\n  stop = async (\n    historyValues: StateType,\n    options: {\n      onStop?: (options: {\n        mutate: (\n          update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n        ) => void;\n      }) => void;\n    }\n  ): Promise<void> => {\n    this.abortRef.abort();\n    this.abortRef = new AbortController();\n\n    options.onStop?.({ mutate: this.getMutateFn(\"stop\", historyValues) });\n  };\n\n  clear = () => {\n    // Cancel any running streams\n    this.abortRef.abort();\n    this.abortRef = new AbortController();\n\n    // Set the stream state to null\n    this.setState({ error: undefined, values: null, isLoading: false });\n\n    // Clear any pending messages\n    this.messages.clear();\n  };\n}\n"],"mappings":"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"}