@langchain/langgraph-sdk 1.2.0 → 1.3.0
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/CHANGELOG.md +6 -0
- package/dist/react/stream.lgp.cjs +11 -13
- package/dist/react/stream.lgp.cjs.map +1 -1
- package/dist/react/stream.lgp.js +11 -13
- package/dist/react/stream.lgp.js.map +1 -1
- package/dist/ui/manager.cjs +9 -3
- package/dist/ui/manager.cjs.map +1 -1
- package/dist/ui/manager.js +9 -3
- package/dist/ui/manager.js.map +1 -1
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -153,8 +153,6 @@ function useStreamLGP(options) {
|
|
|
153
153
|
hasCheckpointListener,
|
|
154
154
|
hasTaskListener
|
|
155
155
|
]);
|
|
156
|
-
const clearCallbackRef = (0, react.useRef)(null);
|
|
157
|
-
clearCallbackRef.current = stream.clear;
|
|
158
156
|
const threadIdRef = (0, react.useRef)(threadId);
|
|
159
157
|
const threadIdStreamingRef = (0, react.useRef)(null);
|
|
160
158
|
(0, react.useEffect)(() => {
|
|
@@ -228,21 +226,21 @@ function useStreamLGP(options) {
|
|
|
228
226
|
setBranch(checkpointId != null ? branchContext.branchByCheckpoint[checkpointId]?.branch ?? "" : "");
|
|
229
227
|
const includeImplicitBranch = historyLimit === true || typeof historyLimit === "number";
|
|
230
228
|
const shouldRefetch = options.onFinish != null || includeImplicitBranch;
|
|
231
|
-
stream.setStreamValues(() => {
|
|
232
|
-
const prev = shouldRefetch ? historyValues : {
|
|
233
|
-
...historyValues,
|
|
234
|
-
...stream.values
|
|
235
|
-
};
|
|
236
|
-
if (submitOptions?.optimisticValues != null) return {
|
|
237
|
-
...prev,
|
|
238
|
-
...typeof submitOptions.optimisticValues === "function" ? submitOptions.optimisticValues(prev) : submitOptions.optimisticValues
|
|
239
|
-
};
|
|
240
|
-
return { ...prev };
|
|
241
|
-
});
|
|
242
229
|
let callbackMeta;
|
|
243
230
|
let rejoinKey;
|
|
244
231
|
let usableThreadId = threadId;
|
|
245
232
|
await stream.start(async (signal) => {
|
|
233
|
+
stream.setStreamValues((values$2) => {
|
|
234
|
+
const prev = {
|
|
235
|
+
...historyValues,
|
|
236
|
+
...values$2 ?? {}
|
|
237
|
+
};
|
|
238
|
+
if (submitOptions?.optimisticValues != null) return {
|
|
239
|
+
...prev,
|
|
240
|
+
...typeof submitOptions.optimisticValues === "function" ? submitOptions.optimisticValues(prev) : submitOptions.optimisticValues
|
|
241
|
+
};
|
|
242
|
+
return { ...prev };
|
|
243
|
+
});
|
|
246
244
|
if (!usableThreadId) {
|
|
247
245
|
const thread = await client.threads.create({
|
|
248
246
|
threadId: submitOptions?.threadId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.lgp.cjs","names":["getClientConfigHash","client","key","threadId","limit","state","Client","MessageTupleManager","StreamManager","useControllableThreadId","modes: Exclude<StreamMode, \"messages\">[]","getBranchContext","error","StreamError","findLast","idx","branch","callbackMeta: RunCallbackMeta | undefined","rejoinKey: `lg:stream:${string}` | undefined","unique","values","callbackMeta: RunCallbackMeta"],"sources":["../../src/react/stream.lgp.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport {\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { findLast, unique } from \"../ui/utils.js\";\nimport { StreamError } from \"../ui/errors.js\";\nimport { getBranchContext } from \"../ui/branching.js\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n BagTemplate,\n UseStreamOptions,\n UseStream,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetConfigurableType,\n RunCallbackMeta,\n SubmitOptions,\n MessageMetadata,\n UseStreamThread,\n} from \"./types.js\";\nimport { Client, getClientConfigHash } from \"../client.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { Interrupt, ThreadState } from \"../schema.js\";\nimport type { StreamMode } from \"../types.stream.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { useControllableThreadId } from \"./thread.js\";\n\nfunction getFetchHistoryKey(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number\n) {\n return [getClientConfigHash(client), threadId, limit].join(\":\");\n}\n\nfunction fetchHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string,\n options?: { limit?: boolean | number }\n) {\n if (options?.limit === false) {\n return client.threads.getState<StateType>(threadId).then((state) => {\n if (state.checkpoint == null) return [];\n return [state];\n });\n }\n\n const limit = typeof options?.limit === \"number\" ? options.limit : 10;\n return client.threads.getHistory<StateType>(threadId, { limit });\n}\n\nfunction useThreadHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number,\n options: {\n passthrough: boolean;\n submittingRef: RefObject<string | null>;\n onError?: (error: unknown, run?: RunCallbackMeta) => void;\n }\n): UseStreamThread<StateType> {\n const key = getFetchHistoryKey(client, threadId, limit);\n const [state, setState] = useState<{\n key: string | undefined;\n data: ThreadState<StateType>[] | undefined;\n error: unknown | undefined;\n isLoading: boolean;\n }>(() => ({\n key: undefined,\n data: undefined,\n error: undefined,\n isLoading: threadId != null,\n }));\n\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const onErrorRef = useRef(options?.onError);\n onErrorRef.current = options?.onError;\n\n const fetcher = useCallback(\n (\n threadId: string | undefined | null,\n limit: boolean | number\n ): Promise<ThreadState<StateType>[]> => {\n // If only passthrough is enabled, don't fetch history\n if (options.passthrough) return Promise.resolve([]);\n\n const client = clientRef.current;\n const key = getFetchHistoryKey(client, threadId, limit);\n\n if (threadId != null) {\n setState((state) => {\n if (state.key === key) return { ...state, isLoading: true };\n return { key, data: undefined, error: undefined, isLoading: true };\n });\n return fetchHistory<StateType>(client, threadId, { limit }).then(\n (data) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data, error: undefined, isLoading: false };\n });\n return data;\n },\n (error) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data: state.data, error, isLoading: false };\n });\n onErrorRef.current?.(error);\n return Promise.reject(error);\n }\n );\n }\n\n setState({ key, data: undefined, error: undefined, isLoading: false });\n return Promise.resolve([]);\n },\n [options.passthrough]\n );\n\n useEffect(() => {\n // Skip if a stream is already in progress, no need to fetch history\n if (\n options.submittingRef.current != null &&\n options.submittingRef.current === threadId\n ) {\n return;\n }\n\n void fetcher(threadId, limit);\n // The `threadId` and `limit` arguments are already present in `key`\n // Thus we don't need to include them in the dependency array\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetcher, key]);\n\n return {\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n mutate: (mutateId?: string) => fetcher(mutateId ?? threadId, limit),\n };\n}\n\nexport function useStreamLGP<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n } = BagTemplate\n>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n\n const reconnectOnMountRef = useRef(options.reconnectOnMount);\n const runMetadataStorage = useMemo(() => {\n if (typeof window === \"undefined\") return null;\n const storage = reconnectOnMountRef.current;\n if (storage === true) return window.sessionStorage;\n if (typeof storage === \"function\") return storage();\n return null;\n }, []);\n\n const client = useMemo(\n () =>\n options.client ??\n new Client({\n apiUrl: options.apiUrl,\n apiKey: options.apiKey,\n callerOptions: options.callerOptions,\n defaultHeaders: options.defaultHeaders,\n }),\n [\n options.client,\n options.apiKey,\n options.apiUrl,\n options.callerOptions,\n options.defaultHeaders,\n ]\n );\n\n const [messageManager] = useState(() => new MessageTupleManager());\n const [stream] = useState(\n () =>\n new StreamManager<StateType, Bag>(messageManager, {\n throttle: options.throttle ?? false,\n })\n );\n\n useSyncExternalStore(\n stream.subscribe,\n stream.getSnapshot,\n stream.getSnapshot\n );\n\n const [threadId, onThreadId] = useControllableThreadId(options);\n const trackStreamModeRef = useRef<Exclude<StreamMode, \"messages\">[]>([]);\n\n const trackStreamMode = useCallback(\n (...mode: Exclude<StreamMode, \"messages\">[]) => {\n const ref = trackStreamModeRef.current;\n for (const m of mode) {\n if (!ref.includes(m)) ref.push(m);\n }\n },\n []\n );\n\n const hasUpdateListener = options.onUpdateEvent != null;\n const hasCustomListener = options.onCustomEvent != null;\n const hasLangChainListener = options.onLangChainEvent != null;\n const hasDebugListener = options.onDebugEvent != null;\n const hasCheckpointListener = options.onCheckpointEvent != null;\n const hasTaskListener = options.onTaskEvent != null;\n\n const callbackStreamMode = useMemo(() => {\n const modes: Exclude<StreamMode, \"messages\">[] = [];\n if (hasUpdateListener) modes.push(\"updates\");\n if (hasCustomListener) modes.push(\"custom\");\n if (hasLangChainListener) modes.push(\"events\");\n if (hasDebugListener) modes.push(\"debug\");\n if (hasCheckpointListener) modes.push(\"checkpoints\");\n if (hasTaskListener) modes.push(\"tasks\");\n return modes;\n }, [\n hasUpdateListener,\n hasCustomListener,\n hasLangChainListener,\n hasDebugListener,\n hasCheckpointListener,\n hasTaskListener,\n ]);\n\n const clearCallbackRef = useRef<() => void>(null!);\n clearCallbackRef.current = stream.clear;\n\n const threadIdRef = useRef<string | null>(threadId);\n const threadIdStreamingRef = useRef<string | null>(null);\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 historyLimit =\n typeof options.fetchStateHistory === \"object\" &&\n options.fetchStateHistory != null\n ? options.fetchStateHistory.limit ?? false\n : options.fetchStateHistory ?? false;\n\n const builtInHistory = useThreadHistory<StateType>(\n client,\n threadId,\n historyLimit,\n {\n passthrough: options.thread != null,\n submittingRef: threadIdStreamingRef,\n onError: options.onError,\n }\n );\n const history = options.thread ?? builtInHistory;\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey]) ? value[messagesKey] : [];\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 [branch, setBranch] = useState<string>(\"\");\n const branchContext = getBranchContext(branch, history.data ?? undefined);\n\n const historyValues =\n branchContext.threadHead?.values ??\n options.initialValues ??\n ({} as StateType);\n\n const historyError = (() => {\n const error = branchContext.threadHead?.tasks?.at(-1)?.error;\n if (error == null) return undefined;\n try {\n const parsed = JSON.parse(error) as unknown;\n if (StreamError.isStructuredError(parsed)) return new StreamError(parsed);\n return parsed;\n } catch {\n // do nothing\n }\n return error;\n })();\n\n const messageMetadata = (() => {\n const alreadyShown = new Set<string>();\n return getMessages(historyValues).map(\n (message, idx): Omit<MessageMetadata<StateType>, \"streamMetadata\"> => {\n const messageId = message.id ?? idx;\n\n // Find the first checkpoint where the message was seen\n const firstSeenState = findLast(history.data ?? [], (state) =>\n getMessages(state.values)\n .map((m, idx) => m.id ?? idx)\n .includes(messageId)\n );\n\n const checkpointId = firstSeenState?.checkpoint?.checkpoint_id;\n let branch =\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]\n : undefined;\n if (!branch?.branch?.length) branch = undefined;\n\n // serialize branches\n const optionsShown = branch?.branchOptions?.flat(2).join(\",\");\n if (optionsShown) {\n if (alreadyShown.has(optionsShown)) branch = undefined;\n alreadyShown.add(optionsShown);\n }\n\n return {\n messageId: messageId.toString(),\n firstSeenState,\n\n branch: branch?.branch,\n branchOptions: branch?.branchOptions,\n };\n }\n );\n })();\n\n const stop = () =>\n stream.stop(historyValues, {\n onStop: (args) => {\n if (runMetadataStorage && threadId) {\n const runId = runMetadataStorage.getItem(`lg:stream:${threadId}`);\n if (runId) void client.runs.cancel(threadId, runId);\n runMetadataStorage.removeItem(`lg:stream:${threadId}`);\n }\n\n options.onStop?.(args);\n },\n });\n\n // --- TRANSPORT ---\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: SubmitOptions<StateType, ConfigurableType>\n ) => {\n // Unbranch things\n const checkpointId = submitOptions?.checkpoint?.checkpoint_id;\n setBranch(\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]?.branch ?? \"\"\n : \"\"\n );\n\n // When `fetchStateHistory` is requested, thus we assume that branching\n // is enabled. We then need to include the implicit branch.\n const includeImplicitBranch =\n historyLimit === true || typeof historyLimit === \"number\";\n\n const shouldRefetch =\n // We're expecting the whole thread state in onFinish\n options.onFinish != null ||\n // We're fetching history, thus we need the latest checkpoint\n // to ensure we're not accidentally submitting to a wrong branch\n includeImplicitBranch;\n\n stream.setStreamValues(() => {\n const prev = shouldRefetch\n ? historyValues\n : { ...historyValues, ...stream.values };\n\n if (submitOptions?.optimisticValues != null) {\n return {\n ...prev,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(prev)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...prev };\n });\n\n let callbackMeta: RunCallbackMeta | undefined;\n let rejoinKey: `lg:stream:${string}` | undefined;\n let usableThreadId = threadId;\n\n await stream.start(\n async (signal: AbortSignal) => {\n if (!usableThreadId) {\n const thread = await client.threads.create({\n threadId: submitOptions?.threadId,\n metadata: submitOptions?.metadata,\n signal,\n });\n\n usableThreadId = thread.thread_id;\n\n // Pre-emptively update the thread ID before\n // stream cancellation is kicked off and thread\n // is being refetched\n threadIdRef.current = usableThreadId;\n threadIdStreamingRef.current = usableThreadId;\n\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n threadIdStreamingRef.current = usableThreadId;\n\n const streamMode = unique([\n ...(submitOptions?.streamMode ?? []),\n ...trackStreamModeRef.current,\n ...callbackStreamMode,\n ]);\n\n let checkpoint =\n submitOptions?.checkpoint ??\n (includeImplicitBranch\n ? branchContext.threadHead?.checkpoint\n : undefined) ??\n undefined;\n\n // Avoid specifying a checkpoint if user explicitly set it to null\n if (submitOptions?.checkpoint === null) checkpoint = undefined;\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (checkpoint != null) delete checkpoint.thread_id;\n const streamResumable =\n submitOptions?.streamResumable ?? !!runMetadataStorage;\n\n return client.runs.stream(usableThreadId, options.assistantId, {\n input: values as Record<string, unknown>,\n config: submitOptions?.config,\n context: submitOptions?.context,\n command: submitOptions?.command,\n\n interruptBefore: submitOptions?.interruptBefore,\n interruptAfter: submitOptions?.interruptAfter,\n metadata: submitOptions?.metadata,\n multitaskStrategy: submitOptions?.multitaskStrategy,\n onCompletion: submitOptions?.onCompletion,\n onDisconnect:\n submitOptions?.onDisconnect ??\n (streamResumable ? \"continue\" : \"cancel\"),\n\n signal,\n\n checkpoint,\n streamMode,\n streamSubgraphs: submitOptions?.streamSubgraphs,\n streamResumable,\n durability: submitOptions?.durability,\n onRunCreated(params) {\n callbackMeta = {\n run_id: params.run_id,\n thread_id: params.thread_id ?? usableThreadId!,\n };\n\n if (runMetadataStorage) {\n rejoinKey = `lg:stream:${usableThreadId}`;\n runMetadataStorage.setItem(rejoinKey, callbackMeta.run_id);\n }\n\n options.onCreated?.(callbackMeta);\n },\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n\n async onSuccess() {\n if (rejoinKey) runMetadataStorage?.removeItem(rejoinKey);\n\n if (shouldRefetch) {\n const newHistory = await history.mutate(usableThreadId!);\n const lastHead = newHistory?.at(0);\n if (lastHead) {\n // We now have the latest update from /history\n // Thus we can clear the local stream state\n options.onFinish?.(lastHead, callbackMeta);\n return null;\n }\n }\n\n return undefined;\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const joinStream = async (\n runId: string,\n lastEventId?: string,\n joinOptions?: { streamMode?: StreamMode | StreamMode[] }\n ) => {\n // eslint-disable-next-line no-param-reassign\n lastEventId ??= \"-1\";\n if (!threadId) return;\n\n const callbackMeta: RunCallbackMeta = {\n thread_id: threadId,\n run_id: runId,\n };\n\n await stream.start(\n async (signal: AbortSignal) => {\n threadIdStreamingRef.current = threadId;\n return client.runs.joinStream(threadId, runId, {\n signal,\n lastEventId,\n streamMode: joinOptions?.streamMode,\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n async onSuccess() {\n runMetadataStorage?.removeItem(`lg:stream:${threadId}`);\n const newHistory = await history.mutate(threadId);\n const lastHead = newHistory?.at(0);\n if (lastHead) options.onFinish?.(lastHead, callbackMeta);\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const reconnectKey = useMemo(() => {\n if (!runMetadataStorage || stream.isLoading) return undefined;\n if (typeof window === \"undefined\") return undefined;\n const runId = runMetadataStorage?.getItem(`lg:stream:${threadId}`);\n if (!runId) return undefined;\n return { runId, threadId };\n }, [runMetadataStorage, stream.isLoading, threadId]);\n\n const shouldReconnect = !!runMetadataStorage;\n const reconnectRef = useRef({ threadId, shouldReconnect });\n\n const joinStreamRef = useRef<typeof joinStream>(joinStream);\n joinStreamRef.current = joinStream;\n\n useEffect(() => {\n // reset shouldReconnect when switching threads\n if (reconnectRef.current.threadId !== threadId) {\n reconnectRef.current = { threadId, shouldReconnect };\n }\n }, [threadId, shouldReconnect]);\n\n useEffect(() => {\n if (reconnectKey && reconnectRef.current.shouldReconnect) {\n reconnectRef.current.shouldReconnect = false;\n void joinStreamRef.current?.(reconnectKey.runId);\n }\n }, [reconnectKey]);\n\n const error = stream.error ?? historyError ?? history.error;\n const values = stream.values ?? historyValues;\n\n return {\n get values() {\n trackStreamMode(\"values\");\n return values;\n },\n\n client,\n assistantId: options.assistantId,\n\n error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n joinStream,\n\n branch,\n setBranch,\n\n get history() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `history`\"\n );\n }\n\n return branchContext.flatHistory;\n },\n\n isThreadLoading: history.isLoading && history.data == null,\n\n get experimental_branchTree() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `experimental_branchTree`\"\n );\n }\n\n return branchContext.branchTree;\n },\n\n get interrupt() {\n if (\n values != null &&\n \"__interrupt__\" in values &&\n Array.isArray(values.__interrupt__)\n ) {\n const valueInterrupts = values.__interrupt__;\n if (valueInterrupts.length === 0) return { when: \"breakpoint\" };\n if (valueInterrupts.length === 1) return valueInterrupts[0];\n\n // TODO: fix the typing of interrupts if multiple interrupts are returned\n return valueInterrupts;\n }\n\n // If we're deferring to old interrupt detection logic, don't show the interrupt if the stream is loading\n if (stream.isLoading) return undefined;\n\n const interrupts = branchContext.threadHead?.tasks?.at(-1)?.interrupts;\n if (interrupts == null || interrupts.length === 0) {\n // check if there's a next task present\n const next = branchContext.threadHead?.next ?? [];\n if (!next.length || error != null) return undefined;\n return { when: \"breakpoint\" };\n }\n\n // Return only the current interrupt\n return interrupts.at(-1) as Interrupt<InterruptType> | undefined;\n },\n\n get messages() {\n trackStreamMode(\"messages-tuple\", \"values\");\n return getMessages(values);\n },\n\n getMessagesMetadata(\n message: Message,\n index?: number\n ): MessageMetadata<StateType> | undefined {\n trackStreamMode(\"values\");\n\n const streamMetadata = messageManager.get(message.id)?.metadata;\n const historyMetadata = messageMetadata?.find(\n (m) => m.messageId === (message.id ?? index)\n );\n\n if (streamMetadata != null || historyMetadata != null) {\n return {\n ...historyMetadata,\n streamMetadata,\n } as MessageMetadata<StateType>;\n }\n\n return undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.lgp.cjs","names":["getClientConfigHash","client","key","threadId","limit","state","Client","MessageTupleManager","StreamManager","useControllableThreadId","modes: Exclude<StreamMode, \"messages\">[]","getBranchContext","error","StreamError","findLast","idx","branch","callbackMeta: RunCallbackMeta | undefined","rejoinKey: `lg:stream:${string}` | undefined","values","unique","callbackMeta: RunCallbackMeta"],"sources":["../../src/react/stream.lgp.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport {\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { findLast, unique } from \"../ui/utils.js\";\nimport { StreamError } from \"../ui/errors.js\";\nimport { getBranchContext } from \"../ui/branching.js\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n BagTemplate,\n UseStreamOptions,\n UseStream,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetConfigurableType,\n RunCallbackMeta,\n SubmitOptions,\n MessageMetadata,\n UseStreamThread,\n} from \"./types.js\";\nimport { Client, getClientConfigHash } from \"../client.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { Interrupt, ThreadState } from \"../schema.js\";\nimport type { StreamMode } from \"../types.stream.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { useControllableThreadId } from \"./thread.js\";\n\nfunction getFetchHistoryKey(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number\n) {\n return [getClientConfigHash(client), threadId, limit].join(\":\");\n}\n\nfunction fetchHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string,\n options?: { limit?: boolean | number }\n) {\n if (options?.limit === false) {\n return client.threads.getState<StateType>(threadId).then((state) => {\n if (state.checkpoint == null) return [];\n return [state];\n });\n }\n\n const limit = typeof options?.limit === \"number\" ? options.limit : 10;\n return client.threads.getHistory<StateType>(threadId, { limit });\n}\n\nfunction useThreadHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number,\n options: {\n passthrough: boolean;\n submittingRef: RefObject<string | null>;\n onError?: (error: unknown, run?: RunCallbackMeta) => void;\n }\n): UseStreamThread<StateType> {\n const key = getFetchHistoryKey(client, threadId, limit);\n const [state, setState] = useState<{\n key: string | undefined;\n data: ThreadState<StateType>[] | undefined;\n error: unknown | undefined;\n isLoading: boolean;\n }>(() => ({\n key: undefined,\n data: undefined,\n error: undefined,\n isLoading: threadId != null,\n }));\n\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const onErrorRef = useRef(options?.onError);\n onErrorRef.current = options?.onError;\n\n const fetcher = useCallback(\n (\n threadId: string | undefined | null,\n limit: boolean | number\n ): Promise<ThreadState<StateType>[]> => {\n // If only passthrough is enabled, don't fetch history\n if (options.passthrough) return Promise.resolve([]);\n\n const client = clientRef.current;\n const key = getFetchHistoryKey(client, threadId, limit);\n\n if (threadId != null) {\n setState((state) => {\n if (state.key === key) return { ...state, isLoading: true };\n return { key, data: undefined, error: undefined, isLoading: true };\n });\n return fetchHistory<StateType>(client, threadId, { limit }).then(\n (data) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data, error: undefined, isLoading: false };\n });\n return data;\n },\n (error) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data: state.data, error, isLoading: false };\n });\n onErrorRef.current?.(error);\n return Promise.reject(error);\n }\n );\n }\n\n setState({ key, data: undefined, error: undefined, isLoading: false });\n return Promise.resolve([]);\n },\n [options.passthrough]\n );\n\n useEffect(() => {\n // Skip if a stream is already in progress, no need to fetch history\n if (\n options.submittingRef.current != null &&\n options.submittingRef.current === threadId\n ) {\n return;\n }\n\n void fetcher(threadId, limit);\n // The `threadId` and `limit` arguments are already present in `key`\n // Thus we don't need to include them in the dependency array\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetcher, key]);\n\n return {\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n mutate: (mutateId?: string) => fetcher(mutateId ?? threadId, limit),\n };\n}\n\nexport function useStreamLGP<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n } = BagTemplate\n>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n\n const reconnectOnMountRef = useRef(options.reconnectOnMount);\n const runMetadataStorage = useMemo(() => {\n if (typeof window === \"undefined\") return null;\n const storage = reconnectOnMountRef.current;\n if (storage === true) return window.sessionStorage;\n if (typeof storage === \"function\") return storage();\n return null;\n }, []);\n\n const client = useMemo(\n () =>\n options.client ??\n new Client({\n apiUrl: options.apiUrl,\n apiKey: options.apiKey,\n callerOptions: options.callerOptions,\n defaultHeaders: options.defaultHeaders,\n }),\n [\n options.client,\n options.apiKey,\n options.apiUrl,\n options.callerOptions,\n options.defaultHeaders,\n ]\n );\n\n const [messageManager] = useState(() => new MessageTupleManager());\n const [stream] = useState(\n () =>\n new StreamManager<StateType, Bag>(messageManager, {\n throttle: options.throttle ?? false,\n })\n );\n\n useSyncExternalStore(\n stream.subscribe,\n stream.getSnapshot,\n stream.getSnapshot\n );\n\n const [threadId, onThreadId] = useControllableThreadId(options);\n const trackStreamModeRef = useRef<Exclude<StreamMode, \"messages\">[]>([]);\n\n const trackStreamMode = useCallback(\n (...mode: Exclude<StreamMode, \"messages\">[]) => {\n const ref = trackStreamModeRef.current;\n for (const m of mode) {\n if (!ref.includes(m)) ref.push(m);\n }\n },\n []\n );\n\n const hasUpdateListener = options.onUpdateEvent != null;\n const hasCustomListener = options.onCustomEvent != null;\n const hasLangChainListener = options.onLangChainEvent != null;\n const hasDebugListener = options.onDebugEvent != null;\n const hasCheckpointListener = options.onCheckpointEvent != null;\n const hasTaskListener = options.onTaskEvent != null;\n\n const callbackStreamMode = useMemo(() => {\n const modes: Exclude<StreamMode, \"messages\">[] = [];\n if (hasUpdateListener) modes.push(\"updates\");\n if (hasCustomListener) modes.push(\"custom\");\n if (hasLangChainListener) modes.push(\"events\");\n if (hasDebugListener) modes.push(\"debug\");\n if (hasCheckpointListener) modes.push(\"checkpoints\");\n if (hasTaskListener) modes.push(\"tasks\");\n return modes;\n }, [\n hasUpdateListener,\n hasCustomListener,\n hasLangChainListener,\n hasDebugListener,\n hasCheckpointListener,\n hasTaskListener,\n ]);\n\n const threadIdRef = useRef<string | null>(threadId);\n const threadIdStreamingRef = useRef<string | null>(null);\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 historyLimit =\n typeof options.fetchStateHistory === \"object\" &&\n options.fetchStateHistory != null\n ? options.fetchStateHistory.limit ?? false\n : options.fetchStateHistory ?? false;\n\n const builtInHistory = useThreadHistory<StateType>(\n client,\n threadId,\n historyLimit,\n {\n passthrough: options.thread != null,\n submittingRef: threadIdStreamingRef,\n onError: options.onError,\n }\n );\n const history = options.thread ?? builtInHistory;\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey]) ? value[messagesKey] : [];\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 [branch, setBranch] = useState<string>(\"\");\n const branchContext = getBranchContext(branch, history.data ?? undefined);\n\n const historyValues =\n branchContext.threadHead?.values ??\n options.initialValues ??\n ({} as StateType);\n\n const historyError = (() => {\n const error = branchContext.threadHead?.tasks?.at(-1)?.error;\n if (error == null) return undefined;\n try {\n const parsed = JSON.parse(error) as unknown;\n if (StreamError.isStructuredError(parsed)) return new StreamError(parsed);\n return parsed;\n } catch {\n // do nothing\n }\n return error;\n })();\n\n const messageMetadata = (() => {\n const alreadyShown = new Set<string>();\n return getMessages(historyValues).map(\n (message, idx): Omit<MessageMetadata<StateType>, \"streamMetadata\"> => {\n const messageId = message.id ?? idx;\n\n // Find the first checkpoint where the message was seen\n const firstSeenState = findLast(history.data ?? [], (state) =>\n getMessages(state.values)\n .map((m, idx) => m.id ?? idx)\n .includes(messageId)\n );\n\n const checkpointId = firstSeenState?.checkpoint?.checkpoint_id;\n let branch =\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]\n : undefined;\n if (!branch?.branch?.length) branch = undefined;\n\n // serialize branches\n const optionsShown = branch?.branchOptions?.flat(2).join(\",\");\n if (optionsShown) {\n if (alreadyShown.has(optionsShown)) branch = undefined;\n alreadyShown.add(optionsShown);\n }\n\n return {\n messageId: messageId.toString(),\n firstSeenState,\n\n branch: branch?.branch,\n branchOptions: branch?.branchOptions,\n };\n }\n );\n })();\n\n const stop = () =>\n stream.stop(historyValues, {\n onStop: (args) => {\n if (runMetadataStorage && threadId) {\n const runId = runMetadataStorage.getItem(`lg:stream:${threadId}`);\n if (runId) void client.runs.cancel(threadId, runId);\n runMetadataStorage.removeItem(`lg:stream:${threadId}`);\n }\n\n options.onStop?.(args);\n },\n });\n\n // --- TRANSPORT ---\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: SubmitOptions<StateType, ConfigurableType>\n ) => {\n // Unbranch things\n const checkpointId = submitOptions?.checkpoint?.checkpoint_id;\n setBranch(\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]?.branch ?? \"\"\n : \"\"\n );\n\n // When `fetchStateHistory` is requested, thus we assume that branching\n // is enabled. We then need to include the implicit branch.\n const includeImplicitBranch =\n historyLimit === true || typeof historyLimit === \"number\";\n\n const shouldRefetch =\n // We're expecting the whole thread state in onFinish\n options.onFinish != null ||\n // We're fetching history, thus we need the latest checkpoint\n // to ensure we're not accidentally submitting to a wrong branch\n includeImplicitBranch;\n\n let callbackMeta: RunCallbackMeta | undefined;\n let rejoinKey: `lg:stream:${string}` | undefined;\n let usableThreadId = threadId;\n\n await stream.start(\n async (signal: AbortSignal) => {\n stream.setStreamValues((values) => {\n const prev = { ...historyValues, ...(values ?? {}) };\n if (submitOptions?.optimisticValues != null) {\n return {\n ...prev,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(prev)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...prev };\n });\n\n if (!usableThreadId) {\n const thread = await client.threads.create({\n threadId: submitOptions?.threadId,\n metadata: submitOptions?.metadata,\n signal,\n });\n\n usableThreadId = thread.thread_id;\n\n // Pre-emptively update the thread ID before\n // stream cancellation is kicked off and thread\n // is being refetched\n threadIdRef.current = usableThreadId;\n threadIdStreamingRef.current = usableThreadId;\n\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n threadIdStreamingRef.current = usableThreadId;\n\n const streamMode = unique([\n ...(submitOptions?.streamMode ?? []),\n ...trackStreamModeRef.current,\n ...callbackStreamMode,\n ]);\n\n let checkpoint =\n submitOptions?.checkpoint ??\n (includeImplicitBranch\n ? branchContext.threadHead?.checkpoint\n : undefined) ??\n undefined;\n\n // Avoid specifying a checkpoint if user explicitly set it to null\n if (submitOptions?.checkpoint === null) checkpoint = undefined;\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (checkpoint != null) delete checkpoint.thread_id;\n const streamResumable =\n submitOptions?.streamResumable ?? !!runMetadataStorage;\n\n return client.runs.stream(usableThreadId, options.assistantId, {\n input: values as Record<string, unknown>,\n config: submitOptions?.config,\n context: submitOptions?.context,\n command: submitOptions?.command,\n\n interruptBefore: submitOptions?.interruptBefore,\n interruptAfter: submitOptions?.interruptAfter,\n metadata: submitOptions?.metadata,\n multitaskStrategy: submitOptions?.multitaskStrategy,\n onCompletion: submitOptions?.onCompletion,\n onDisconnect:\n submitOptions?.onDisconnect ??\n (streamResumable ? \"continue\" : \"cancel\"),\n\n signal,\n\n checkpoint,\n streamMode,\n streamSubgraphs: submitOptions?.streamSubgraphs,\n streamResumable,\n durability: submitOptions?.durability,\n onRunCreated(params) {\n callbackMeta = {\n run_id: params.run_id,\n thread_id: params.thread_id ?? usableThreadId!,\n };\n\n if (runMetadataStorage) {\n rejoinKey = `lg:stream:${usableThreadId}`;\n runMetadataStorage.setItem(rejoinKey, callbackMeta.run_id);\n }\n\n options.onCreated?.(callbackMeta);\n },\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n\n async onSuccess() {\n if (rejoinKey) runMetadataStorage?.removeItem(rejoinKey);\n\n if (shouldRefetch) {\n const newHistory = await history.mutate(usableThreadId!);\n const lastHead = newHistory?.at(0);\n if (lastHead) {\n // We now have the latest update from /history\n // Thus we can clear the local stream state\n options.onFinish?.(lastHead, callbackMeta);\n return null;\n }\n }\n\n return undefined;\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const joinStream = async (\n runId: string,\n lastEventId?: string,\n joinOptions?: { streamMode?: StreamMode | StreamMode[] }\n ) => {\n // eslint-disable-next-line no-param-reassign\n lastEventId ??= \"-1\";\n if (!threadId) return;\n\n const callbackMeta: RunCallbackMeta = {\n thread_id: threadId,\n run_id: runId,\n };\n\n await stream.start(\n async (signal: AbortSignal) => {\n threadIdStreamingRef.current = threadId;\n return client.runs.joinStream(threadId, runId, {\n signal,\n lastEventId,\n streamMode: joinOptions?.streamMode,\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n async onSuccess() {\n runMetadataStorage?.removeItem(`lg:stream:${threadId}`);\n const newHistory = await history.mutate(threadId);\n const lastHead = newHistory?.at(0);\n if (lastHead) options.onFinish?.(lastHead, callbackMeta);\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const reconnectKey = useMemo(() => {\n if (!runMetadataStorage || stream.isLoading) return undefined;\n if (typeof window === \"undefined\") return undefined;\n const runId = runMetadataStorage?.getItem(`lg:stream:${threadId}`);\n if (!runId) return undefined;\n return { runId, threadId };\n }, [runMetadataStorage, stream.isLoading, threadId]);\n\n const shouldReconnect = !!runMetadataStorage;\n const reconnectRef = useRef({ threadId, shouldReconnect });\n\n const joinStreamRef = useRef<typeof joinStream>(joinStream);\n joinStreamRef.current = joinStream;\n\n useEffect(() => {\n // reset shouldReconnect when switching threads\n if (reconnectRef.current.threadId !== threadId) {\n reconnectRef.current = { threadId, shouldReconnect };\n }\n }, [threadId, shouldReconnect]);\n\n useEffect(() => {\n if (reconnectKey && reconnectRef.current.shouldReconnect) {\n reconnectRef.current.shouldReconnect = false;\n void joinStreamRef.current?.(reconnectKey.runId);\n }\n }, [reconnectKey]);\n\n const error = stream.error ?? historyError ?? history.error;\n const values = stream.values ?? historyValues;\n\n return {\n get values() {\n trackStreamMode(\"values\");\n return values;\n },\n\n client,\n assistantId: options.assistantId,\n\n error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n joinStream,\n\n branch,\n setBranch,\n\n get history() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `history`\"\n );\n }\n\n return branchContext.flatHistory;\n },\n\n isThreadLoading: history.isLoading && history.data == null,\n\n get experimental_branchTree() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `experimental_branchTree`\"\n );\n }\n\n return branchContext.branchTree;\n },\n\n get interrupt() {\n if (\n values != null &&\n \"__interrupt__\" in values &&\n Array.isArray(values.__interrupt__)\n ) {\n const valueInterrupts = values.__interrupt__;\n if (valueInterrupts.length === 0) return { when: \"breakpoint\" };\n if (valueInterrupts.length === 1) return valueInterrupts[0];\n\n // TODO: fix the typing of interrupts if multiple interrupts are returned\n return valueInterrupts;\n }\n\n // If we're deferring to old interrupt detection logic, don't show the interrupt if the stream is loading\n if (stream.isLoading) return undefined;\n\n const interrupts = branchContext.threadHead?.tasks?.at(-1)?.interrupts;\n if (interrupts == null || interrupts.length === 0) {\n // check if there's a next task present\n const next = branchContext.threadHead?.next ?? [];\n if (!next.length || error != null) return undefined;\n return { when: \"breakpoint\" };\n }\n\n // Return only the current interrupt\n return interrupts.at(-1) as Interrupt<InterruptType> | undefined;\n },\n\n get messages() {\n trackStreamMode(\"messages-tuple\", \"values\");\n return getMessages(values);\n },\n\n getMessagesMetadata(\n message: Message,\n index?: number\n ): MessageMetadata<StateType> | undefined {\n trackStreamMode(\"values\");\n\n const streamMetadata = messageManager.get(message.id)?.metadata;\n const historyMetadata = messageMetadata?.find(\n (m) => m.messageId === (message.id ?? index)\n );\n\n if (streamMetadata != null || historyMetadata != null) {\n return {\n ...historyMetadata,\n streamMetadata,\n } as MessageMetadata<StateType>;\n }\n\n return undefined;\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/react/stream.lgp.js
CHANGED
|
@@ -152,8 +152,6 @@ function useStreamLGP(options) {
|
|
|
152
152
|
hasCheckpointListener,
|
|
153
153
|
hasTaskListener
|
|
154
154
|
]);
|
|
155
|
-
const clearCallbackRef = useRef(null);
|
|
156
|
-
clearCallbackRef.current = stream.clear;
|
|
157
155
|
const threadIdRef = useRef(threadId);
|
|
158
156
|
const threadIdStreamingRef = useRef(null);
|
|
159
157
|
useEffect(() => {
|
|
@@ -227,21 +225,21 @@ function useStreamLGP(options) {
|
|
|
227
225
|
setBranch(checkpointId != null ? branchContext.branchByCheckpoint[checkpointId]?.branch ?? "" : "");
|
|
228
226
|
const includeImplicitBranch = historyLimit === true || typeof historyLimit === "number";
|
|
229
227
|
const shouldRefetch = options.onFinish != null || includeImplicitBranch;
|
|
230
|
-
stream.setStreamValues(() => {
|
|
231
|
-
const prev = shouldRefetch ? historyValues : {
|
|
232
|
-
...historyValues,
|
|
233
|
-
...stream.values
|
|
234
|
-
};
|
|
235
|
-
if (submitOptions?.optimisticValues != null) return {
|
|
236
|
-
...prev,
|
|
237
|
-
...typeof submitOptions.optimisticValues === "function" ? submitOptions.optimisticValues(prev) : submitOptions.optimisticValues
|
|
238
|
-
};
|
|
239
|
-
return { ...prev };
|
|
240
|
-
});
|
|
241
228
|
let callbackMeta;
|
|
242
229
|
let rejoinKey;
|
|
243
230
|
let usableThreadId = threadId;
|
|
244
231
|
await stream.start(async (signal) => {
|
|
232
|
+
stream.setStreamValues((values$2) => {
|
|
233
|
+
const prev = {
|
|
234
|
+
...historyValues,
|
|
235
|
+
...values$2 ?? {}
|
|
236
|
+
};
|
|
237
|
+
if (submitOptions?.optimisticValues != null) return {
|
|
238
|
+
...prev,
|
|
239
|
+
...typeof submitOptions.optimisticValues === "function" ? submitOptions.optimisticValues(prev) : submitOptions.optimisticValues
|
|
240
|
+
};
|
|
241
|
+
return { ...prev };
|
|
242
|
+
});
|
|
245
243
|
if (!usableThreadId) {
|
|
246
244
|
const thread = await client.threads.create({
|
|
247
245
|
threadId: submitOptions?.threadId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.lgp.js","names":["client","key","threadId","limit","state","modes: Exclude<StreamMode, \"messages\">[]","error","idx","branch","callbackMeta: RunCallbackMeta | undefined","rejoinKey: `lg:stream:${string}` | undefined","values","callbackMeta: RunCallbackMeta"],"sources":["../../src/react/stream.lgp.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport {\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { findLast, unique } from \"../ui/utils.js\";\nimport { StreamError } from \"../ui/errors.js\";\nimport { getBranchContext } from \"../ui/branching.js\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n BagTemplate,\n UseStreamOptions,\n UseStream,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetConfigurableType,\n RunCallbackMeta,\n SubmitOptions,\n MessageMetadata,\n UseStreamThread,\n} from \"./types.js\";\nimport { Client, getClientConfigHash } from \"../client.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { Interrupt, ThreadState } from \"../schema.js\";\nimport type { StreamMode } from \"../types.stream.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { useControllableThreadId } from \"./thread.js\";\n\nfunction getFetchHistoryKey(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number\n) {\n return [getClientConfigHash(client), threadId, limit].join(\":\");\n}\n\nfunction fetchHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string,\n options?: { limit?: boolean | number }\n) {\n if (options?.limit === false) {\n return client.threads.getState<StateType>(threadId).then((state) => {\n if (state.checkpoint == null) return [];\n return [state];\n });\n }\n\n const limit = typeof options?.limit === \"number\" ? options.limit : 10;\n return client.threads.getHistory<StateType>(threadId, { limit });\n}\n\nfunction useThreadHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number,\n options: {\n passthrough: boolean;\n submittingRef: RefObject<string | null>;\n onError?: (error: unknown, run?: RunCallbackMeta) => void;\n }\n): UseStreamThread<StateType> {\n const key = getFetchHistoryKey(client, threadId, limit);\n const [state, setState] = useState<{\n key: string | undefined;\n data: ThreadState<StateType>[] | undefined;\n error: unknown | undefined;\n isLoading: boolean;\n }>(() => ({\n key: undefined,\n data: undefined,\n error: undefined,\n isLoading: threadId != null,\n }));\n\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const onErrorRef = useRef(options?.onError);\n onErrorRef.current = options?.onError;\n\n const fetcher = useCallback(\n (\n threadId: string | undefined | null,\n limit: boolean | number\n ): Promise<ThreadState<StateType>[]> => {\n // If only passthrough is enabled, don't fetch history\n if (options.passthrough) return Promise.resolve([]);\n\n const client = clientRef.current;\n const key = getFetchHistoryKey(client, threadId, limit);\n\n if (threadId != null) {\n setState((state) => {\n if (state.key === key) return { ...state, isLoading: true };\n return { key, data: undefined, error: undefined, isLoading: true };\n });\n return fetchHistory<StateType>(client, threadId, { limit }).then(\n (data) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data, error: undefined, isLoading: false };\n });\n return data;\n },\n (error) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data: state.data, error, isLoading: false };\n });\n onErrorRef.current?.(error);\n return Promise.reject(error);\n }\n );\n }\n\n setState({ key, data: undefined, error: undefined, isLoading: false });\n return Promise.resolve([]);\n },\n [options.passthrough]\n );\n\n useEffect(() => {\n // Skip if a stream is already in progress, no need to fetch history\n if (\n options.submittingRef.current != null &&\n options.submittingRef.current === threadId\n ) {\n return;\n }\n\n void fetcher(threadId, limit);\n // The `threadId` and `limit` arguments are already present in `key`\n // Thus we don't need to include them in the dependency array\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetcher, key]);\n\n return {\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n mutate: (mutateId?: string) => fetcher(mutateId ?? threadId, limit),\n };\n}\n\nexport function useStreamLGP<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n } = BagTemplate\n>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n\n const reconnectOnMountRef = useRef(options.reconnectOnMount);\n const runMetadataStorage = useMemo(() => {\n if (typeof window === \"undefined\") return null;\n const storage = reconnectOnMountRef.current;\n if (storage === true) return window.sessionStorage;\n if (typeof storage === \"function\") return storage();\n return null;\n }, []);\n\n const client = useMemo(\n () =>\n options.client ??\n new Client({\n apiUrl: options.apiUrl,\n apiKey: options.apiKey,\n callerOptions: options.callerOptions,\n defaultHeaders: options.defaultHeaders,\n }),\n [\n options.client,\n options.apiKey,\n options.apiUrl,\n options.callerOptions,\n options.defaultHeaders,\n ]\n );\n\n const [messageManager] = useState(() => new MessageTupleManager());\n const [stream] = useState(\n () =>\n new StreamManager<StateType, Bag>(messageManager, {\n throttle: options.throttle ?? false,\n })\n );\n\n useSyncExternalStore(\n stream.subscribe,\n stream.getSnapshot,\n stream.getSnapshot\n );\n\n const [threadId, onThreadId] = useControllableThreadId(options);\n const trackStreamModeRef = useRef<Exclude<StreamMode, \"messages\">[]>([]);\n\n const trackStreamMode = useCallback(\n (...mode: Exclude<StreamMode, \"messages\">[]) => {\n const ref = trackStreamModeRef.current;\n for (const m of mode) {\n if (!ref.includes(m)) ref.push(m);\n }\n },\n []\n );\n\n const hasUpdateListener = options.onUpdateEvent != null;\n const hasCustomListener = options.onCustomEvent != null;\n const hasLangChainListener = options.onLangChainEvent != null;\n const hasDebugListener = options.onDebugEvent != null;\n const hasCheckpointListener = options.onCheckpointEvent != null;\n const hasTaskListener = options.onTaskEvent != null;\n\n const callbackStreamMode = useMemo(() => {\n const modes: Exclude<StreamMode, \"messages\">[] = [];\n if (hasUpdateListener) modes.push(\"updates\");\n if (hasCustomListener) modes.push(\"custom\");\n if (hasLangChainListener) modes.push(\"events\");\n if (hasDebugListener) modes.push(\"debug\");\n if (hasCheckpointListener) modes.push(\"checkpoints\");\n if (hasTaskListener) modes.push(\"tasks\");\n return modes;\n }, [\n hasUpdateListener,\n hasCustomListener,\n hasLangChainListener,\n hasDebugListener,\n hasCheckpointListener,\n hasTaskListener,\n ]);\n\n const clearCallbackRef = useRef<() => void>(null!);\n clearCallbackRef.current = stream.clear;\n\n const threadIdRef = useRef<string | null>(threadId);\n const threadIdStreamingRef = useRef<string | null>(null);\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 historyLimit =\n typeof options.fetchStateHistory === \"object\" &&\n options.fetchStateHistory != null\n ? options.fetchStateHistory.limit ?? false\n : options.fetchStateHistory ?? false;\n\n const builtInHistory = useThreadHistory<StateType>(\n client,\n threadId,\n historyLimit,\n {\n passthrough: options.thread != null,\n submittingRef: threadIdStreamingRef,\n onError: options.onError,\n }\n );\n const history = options.thread ?? builtInHistory;\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey]) ? value[messagesKey] : [];\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 [branch, setBranch] = useState<string>(\"\");\n const branchContext = getBranchContext(branch, history.data ?? undefined);\n\n const historyValues =\n branchContext.threadHead?.values ??\n options.initialValues ??\n ({} as StateType);\n\n const historyError = (() => {\n const error = branchContext.threadHead?.tasks?.at(-1)?.error;\n if (error == null) return undefined;\n try {\n const parsed = JSON.parse(error) as unknown;\n if (StreamError.isStructuredError(parsed)) return new StreamError(parsed);\n return parsed;\n } catch {\n // do nothing\n }\n return error;\n })();\n\n const messageMetadata = (() => {\n const alreadyShown = new Set<string>();\n return getMessages(historyValues).map(\n (message, idx): Omit<MessageMetadata<StateType>, \"streamMetadata\"> => {\n const messageId = message.id ?? idx;\n\n // Find the first checkpoint where the message was seen\n const firstSeenState = findLast(history.data ?? [], (state) =>\n getMessages(state.values)\n .map((m, idx) => m.id ?? idx)\n .includes(messageId)\n );\n\n const checkpointId = firstSeenState?.checkpoint?.checkpoint_id;\n let branch =\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]\n : undefined;\n if (!branch?.branch?.length) branch = undefined;\n\n // serialize branches\n const optionsShown = branch?.branchOptions?.flat(2).join(\",\");\n if (optionsShown) {\n if (alreadyShown.has(optionsShown)) branch = undefined;\n alreadyShown.add(optionsShown);\n }\n\n return {\n messageId: messageId.toString(),\n firstSeenState,\n\n branch: branch?.branch,\n branchOptions: branch?.branchOptions,\n };\n }\n );\n })();\n\n const stop = () =>\n stream.stop(historyValues, {\n onStop: (args) => {\n if (runMetadataStorage && threadId) {\n const runId = runMetadataStorage.getItem(`lg:stream:${threadId}`);\n if (runId) void client.runs.cancel(threadId, runId);\n runMetadataStorage.removeItem(`lg:stream:${threadId}`);\n }\n\n options.onStop?.(args);\n },\n });\n\n // --- TRANSPORT ---\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: SubmitOptions<StateType, ConfigurableType>\n ) => {\n // Unbranch things\n const checkpointId = submitOptions?.checkpoint?.checkpoint_id;\n setBranch(\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]?.branch ?? \"\"\n : \"\"\n );\n\n // When `fetchStateHistory` is requested, thus we assume that branching\n // is enabled. We then need to include the implicit branch.\n const includeImplicitBranch =\n historyLimit === true || typeof historyLimit === \"number\";\n\n const shouldRefetch =\n // We're expecting the whole thread state in onFinish\n options.onFinish != null ||\n // We're fetching history, thus we need the latest checkpoint\n // to ensure we're not accidentally submitting to a wrong branch\n includeImplicitBranch;\n\n stream.setStreamValues(() => {\n const prev = shouldRefetch\n ? historyValues\n : { ...historyValues, ...stream.values };\n\n if (submitOptions?.optimisticValues != null) {\n return {\n ...prev,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(prev)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...prev };\n });\n\n let callbackMeta: RunCallbackMeta | undefined;\n let rejoinKey: `lg:stream:${string}` | undefined;\n let usableThreadId = threadId;\n\n await stream.start(\n async (signal: AbortSignal) => {\n if (!usableThreadId) {\n const thread = await client.threads.create({\n threadId: submitOptions?.threadId,\n metadata: submitOptions?.metadata,\n signal,\n });\n\n usableThreadId = thread.thread_id;\n\n // Pre-emptively update the thread ID before\n // stream cancellation is kicked off and thread\n // is being refetched\n threadIdRef.current = usableThreadId;\n threadIdStreamingRef.current = usableThreadId;\n\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n threadIdStreamingRef.current = usableThreadId;\n\n const streamMode = unique([\n ...(submitOptions?.streamMode ?? []),\n ...trackStreamModeRef.current,\n ...callbackStreamMode,\n ]);\n\n let checkpoint =\n submitOptions?.checkpoint ??\n (includeImplicitBranch\n ? branchContext.threadHead?.checkpoint\n : undefined) ??\n undefined;\n\n // Avoid specifying a checkpoint if user explicitly set it to null\n if (submitOptions?.checkpoint === null) checkpoint = undefined;\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (checkpoint != null) delete checkpoint.thread_id;\n const streamResumable =\n submitOptions?.streamResumable ?? !!runMetadataStorage;\n\n return client.runs.stream(usableThreadId, options.assistantId, {\n input: values as Record<string, unknown>,\n config: submitOptions?.config,\n context: submitOptions?.context,\n command: submitOptions?.command,\n\n interruptBefore: submitOptions?.interruptBefore,\n interruptAfter: submitOptions?.interruptAfter,\n metadata: submitOptions?.metadata,\n multitaskStrategy: submitOptions?.multitaskStrategy,\n onCompletion: submitOptions?.onCompletion,\n onDisconnect:\n submitOptions?.onDisconnect ??\n (streamResumable ? \"continue\" : \"cancel\"),\n\n signal,\n\n checkpoint,\n streamMode,\n streamSubgraphs: submitOptions?.streamSubgraphs,\n streamResumable,\n durability: submitOptions?.durability,\n onRunCreated(params) {\n callbackMeta = {\n run_id: params.run_id,\n thread_id: params.thread_id ?? usableThreadId!,\n };\n\n if (runMetadataStorage) {\n rejoinKey = `lg:stream:${usableThreadId}`;\n runMetadataStorage.setItem(rejoinKey, callbackMeta.run_id);\n }\n\n options.onCreated?.(callbackMeta);\n },\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n\n async onSuccess() {\n if (rejoinKey) runMetadataStorage?.removeItem(rejoinKey);\n\n if (shouldRefetch) {\n const newHistory = await history.mutate(usableThreadId!);\n const lastHead = newHistory?.at(0);\n if (lastHead) {\n // We now have the latest update from /history\n // Thus we can clear the local stream state\n options.onFinish?.(lastHead, callbackMeta);\n return null;\n }\n }\n\n return undefined;\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const joinStream = async (\n runId: string,\n lastEventId?: string,\n joinOptions?: { streamMode?: StreamMode | StreamMode[] }\n ) => {\n // eslint-disable-next-line no-param-reassign\n lastEventId ??= \"-1\";\n if (!threadId) return;\n\n const callbackMeta: RunCallbackMeta = {\n thread_id: threadId,\n run_id: runId,\n };\n\n await stream.start(\n async (signal: AbortSignal) => {\n threadIdStreamingRef.current = threadId;\n return client.runs.joinStream(threadId, runId, {\n signal,\n lastEventId,\n streamMode: joinOptions?.streamMode,\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n async onSuccess() {\n runMetadataStorage?.removeItem(`lg:stream:${threadId}`);\n const newHistory = await history.mutate(threadId);\n const lastHead = newHistory?.at(0);\n if (lastHead) options.onFinish?.(lastHead, callbackMeta);\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const reconnectKey = useMemo(() => {\n if (!runMetadataStorage || stream.isLoading) return undefined;\n if (typeof window === \"undefined\") return undefined;\n const runId = runMetadataStorage?.getItem(`lg:stream:${threadId}`);\n if (!runId) return undefined;\n return { runId, threadId };\n }, [runMetadataStorage, stream.isLoading, threadId]);\n\n const shouldReconnect = !!runMetadataStorage;\n const reconnectRef = useRef({ threadId, shouldReconnect });\n\n const joinStreamRef = useRef<typeof joinStream>(joinStream);\n joinStreamRef.current = joinStream;\n\n useEffect(() => {\n // reset shouldReconnect when switching threads\n if (reconnectRef.current.threadId !== threadId) {\n reconnectRef.current = { threadId, shouldReconnect };\n }\n }, [threadId, shouldReconnect]);\n\n useEffect(() => {\n if (reconnectKey && reconnectRef.current.shouldReconnect) {\n reconnectRef.current.shouldReconnect = false;\n void joinStreamRef.current?.(reconnectKey.runId);\n }\n }, [reconnectKey]);\n\n const error = stream.error ?? historyError ?? history.error;\n const values = stream.values ?? historyValues;\n\n return {\n get values() {\n trackStreamMode(\"values\");\n return values;\n },\n\n client,\n assistantId: options.assistantId,\n\n error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n joinStream,\n\n branch,\n setBranch,\n\n get history() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `history`\"\n );\n }\n\n return branchContext.flatHistory;\n },\n\n isThreadLoading: history.isLoading && history.data == null,\n\n get experimental_branchTree() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `experimental_branchTree`\"\n );\n }\n\n return branchContext.branchTree;\n },\n\n get interrupt() {\n if (\n values != null &&\n \"__interrupt__\" in values &&\n Array.isArray(values.__interrupt__)\n ) {\n const valueInterrupts = values.__interrupt__;\n if (valueInterrupts.length === 0) return { when: \"breakpoint\" };\n if (valueInterrupts.length === 1) return valueInterrupts[0];\n\n // TODO: fix the typing of interrupts if multiple interrupts are returned\n return valueInterrupts;\n }\n\n // If we're deferring to old interrupt detection logic, don't show the interrupt if the stream is loading\n if (stream.isLoading) return undefined;\n\n const interrupts = branchContext.threadHead?.tasks?.at(-1)?.interrupts;\n if (interrupts == null || interrupts.length === 0) {\n // check if there's a next task present\n const next = branchContext.threadHead?.next ?? [];\n if (!next.length || error != null) return undefined;\n return { when: \"breakpoint\" };\n }\n\n // Return only the current interrupt\n return interrupts.at(-1) as Interrupt<InterruptType> | undefined;\n },\n\n get messages() {\n trackStreamMode(\"messages-tuple\", \"values\");\n return getMessages(values);\n },\n\n getMessagesMetadata(\n message: Message,\n index?: number\n ): MessageMetadata<StateType> | undefined {\n trackStreamMode(\"values\");\n\n const streamMetadata = messageManager.get(message.id)?.metadata;\n const historyMetadata = messageMetadata?.find(\n (m) => m.messageId === (message.id ?? index)\n );\n\n if (streamMetadata != null || historyMetadata != null) {\n return {\n ...historyMetadata,\n streamMetadata,\n } as MessageMetadata<StateType>;\n }\n\n return undefined;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.lgp.js","names":["client","key","threadId","limit","state","modes: Exclude<StreamMode, \"messages\">[]","error","idx","branch","callbackMeta: RunCallbackMeta | undefined","rejoinKey: `lg:stream:${string}` | undefined","values","callbackMeta: RunCallbackMeta"],"sources":["../../src/react/stream.lgp.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport {\n type RefObject,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { findLast, unique } from \"../ui/utils.js\";\nimport { StreamError } from \"../ui/errors.js\";\nimport { getBranchContext } from \"../ui/branching.js\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n BagTemplate,\n UseStreamOptions,\n UseStream,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetConfigurableType,\n RunCallbackMeta,\n SubmitOptions,\n MessageMetadata,\n UseStreamThread,\n} from \"./types.js\";\nimport { Client, getClientConfigHash } from \"../client.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { Interrupt, ThreadState } from \"../schema.js\";\nimport type { StreamMode } from \"../types.stream.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { useControllableThreadId } from \"./thread.js\";\n\nfunction getFetchHistoryKey(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number\n) {\n return [getClientConfigHash(client), threadId, limit].join(\":\");\n}\n\nfunction fetchHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string,\n options?: { limit?: boolean | number }\n) {\n if (options?.limit === false) {\n return client.threads.getState<StateType>(threadId).then((state) => {\n if (state.checkpoint == null) return [];\n return [state];\n });\n }\n\n const limit = typeof options?.limit === \"number\" ? options.limit : 10;\n return client.threads.getHistory<StateType>(threadId, { limit });\n}\n\nfunction useThreadHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string | undefined | null,\n limit: boolean | number,\n options: {\n passthrough: boolean;\n submittingRef: RefObject<string | null>;\n onError?: (error: unknown, run?: RunCallbackMeta) => void;\n }\n): UseStreamThread<StateType> {\n const key = getFetchHistoryKey(client, threadId, limit);\n const [state, setState] = useState<{\n key: string | undefined;\n data: ThreadState<StateType>[] | undefined;\n error: unknown | undefined;\n isLoading: boolean;\n }>(() => ({\n key: undefined,\n data: undefined,\n error: undefined,\n isLoading: threadId != null,\n }));\n\n const clientRef = useRef(client);\n clientRef.current = client;\n\n const onErrorRef = useRef(options?.onError);\n onErrorRef.current = options?.onError;\n\n const fetcher = useCallback(\n (\n threadId: string | undefined | null,\n limit: boolean | number\n ): Promise<ThreadState<StateType>[]> => {\n // If only passthrough is enabled, don't fetch history\n if (options.passthrough) return Promise.resolve([]);\n\n const client = clientRef.current;\n const key = getFetchHistoryKey(client, threadId, limit);\n\n if (threadId != null) {\n setState((state) => {\n if (state.key === key) return { ...state, isLoading: true };\n return { key, data: undefined, error: undefined, isLoading: true };\n });\n return fetchHistory<StateType>(client, threadId, { limit }).then(\n (data) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data, error: undefined, isLoading: false };\n });\n return data;\n },\n (error) => {\n setState((state) => {\n if (state.key !== key) return state;\n return { key, data: state.data, error, isLoading: false };\n });\n onErrorRef.current?.(error);\n return Promise.reject(error);\n }\n );\n }\n\n setState({ key, data: undefined, error: undefined, isLoading: false });\n return Promise.resolve([]);\n },\n [options.passthrough]\n );\n\n useEffect(() => {\n // Skip if a stream is already in progress, no need to fetch history\n if (\n options.submittingRef.current != null &&\n options.submittingRef.current === threadId\n ) {\n return;\n }\n\n void fetcher(threadId, limit);\n // The `threadId` and `limit` arguments are already present in `key`\n // Thus we don't need to include them in the dependency array\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetcher, key]);\n\n return {\n data: state.data,\n error: state.error,\n isLoading: state.isLoading,\n mutate: (mutateId?: string) => fetcher(mutateId ?? threadId, limit),\n };\n}\n\nexport function useStreamLGP<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n } = BagTemplate\n>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n\n const reconnectOnMountRef = useRef(options.reconnectOnMount);\n const runMetadataStorage = useMemo(() => {\n if (typeof window === \"undefined\") return null;\n const storage = reconnectOnMountRef.current;\n if (storage === true) return window.sessionStorage;\n if (typeof storage === \"function\") return storage();\n return null;\n }, []);\n\n const client = useMemo(\n () =>\n options.client ??\n new Client({\n apiUrl: options.apiUrl,\n apiKey: options.apiKey,\n callerOptions: options.callerOptions,\n defaultHeaders: options.defaultHeaders,\n }),\n [\n options.client,\n options.apiKey,\n options.apiUrl,\n options.callerOptions,\n options.defaultHeaders,\n ]\n );\n\n const [messageManager] = useState(() => new MessageTupleManager());\n const [stream] = useState(\n () =>\n new StreamManager<StateType, Bag>(messageManager, {\n throttle: options.throttle ?? false,\n })\n );\n\n useSyncExternalStore(\n stream.subscribe,\n stream.getSnapshot,\n stream.getSnapshot\n );\n\n const [threadId, onThreadId] = useControllableThreadId(options);\n const trackStreamModeRef = useRef<Exclude<StreamMode, \"messages\">[]>([]);\n\n const trackStreamMode = useCallback(\n (...mode: Exclude<StreamMode, \"messages\">[]) => {\n const ref = trackStreamModeRef.current;\n for (const m of mode) {\n if (!ref.includes(m)) ref.push(m);\n }\n },\n []\n );\n\n const hasUpdateListener = options.onUpdateEvent != null;\n const hasCustomListener = options.onCustomEvent != null;\n const hasLangChainListener = options.onLangChainEvent != null;\n const hasDebugListener = options.onDebugEvent != null;\n const hasCheckpointListener = options.onCheckpointEvent != null;\n const hasTaskListener = options.onTaskEvent != null;\n\n const callbackStreamMode = useMemo(() => {\n const modes: Exclude<StreamMode, \"messages\">[] = [];\n if (hasUpdateListener) modes.push(\"updates\");\n if (hasCustomListener) modes.push(\"custom\");\n if (hasLangChainListener) modes.push(\"events\");\n if (hasDebugListener) modes.push(\"debug\");\n if (hasCheckpointListener) modes.push(\"checkpoints\");\n if (hasTaskListener) modes.push(\"tasks\");\n return modes;\n }, [\n hasUpdateListener,\n hasCustomListener,\n hasLangChainListener,\n hasDebugListener,\n hasCheckpointListener,\n hasTaskListener,\n ]);\n\n const threadIdRef = useRef<string | null>(threadId);\n const threadIdStreamingRef = useRef<string | null>(null);\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 historyLimit =\n typeof options.fetchStateHistory === \"object\" &&\n options.fetchStateHistory != null\n ? options.fetchStateHistory.limit ?? false\n : options.fetchStateHistory ?? false;\n\n const builtInHistory = useThreadHistory<StateType>(\n client,\n threadId,\n historyLimit,\n {\n passthrough: options.thread != null,\n submittingRef: threadIdStreamingRef,\n onError: options.onError,\n }\n );\n const history = options.thread ?? builtInHistory;\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey]) ? value[messagesKey] : [];\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 [branch, setBranch] = useState<string>(\"\");\n const branchContext = getBranchContext(branch, history.data ?? undefined);\n\n const historyValues =\n branchContext.threadHead?.values ??\n options.initialValues ??\n ({} as StateType);\n\n const historyError = (() => {\n const error = branchContext.threadHead?.tasks?.at(-1)?.error;\n if (error == null) return undefined;\n try {\n const parsed = JSON.parse(error) as unknown;\n if (StreamError.isStructuredError(parsed)) return new StreamError(parsed);\n return parsed;\n } catch {\n // do nothing\n }\n return error;\n })();\n\n const messageMetadata = (() => {\n const alreadyShown = new Set<string>();\n return getMessages(historyValues).map(\n (message, idx): Omit<MessageMetadata<StateType>, \"streamMetadata\"> => {\n const messageId = message.id ?? idx;\n\n // Find the first checkpoint where the message was seen\n const firstSeenState = findLast(history.data ?? [], (state) =>\n getMessages(state.values)\n .map((m, idx) => m.id ?? idx)\n .includes(messageId)\n );\n\n const checkpointId = firstSeenState?.checkpoint?.checkpoint_id;\n let branch =\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]\n : undefined;\n if (!branch?.branch?.length) branch = undefined;\n\n // serialize branches\n const optionsShown = branch?.branchOptions?.flat(2).join(\",\");\n if (optionsShown) {\n if (alreadyShown.has(optionsShown)) branch = undefined;\n alreadyShown.add(optionsShown);\n }\n\n return {\n messageId: messageId.toString(),\n firstSeenState,\n\n branch: branch?.branch,\n branchOptions: branch?.branchOptions,\n };\n }\n );\n })();\n\n const stop = () =>\n stream.stop(historyValues, {\n onStop: (args) => {\n if (runMetadataStorage && threadId) {\n const runId = runMetadataStorage.getItem(`lg:stream:${threadId}`);\n if (runId) void client.runs.cancel(threadId, runId);\n runMetadataStorage.removeItem(`lg:stream:${threadId}`);\n }\n\n options.onStop?.(args);\n },\n });\n\n // --- TRANSPORT ---\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: SubmitOptions<StateType, ConfigurableType>\n ) => {\n // Unbranch things\n const checkpointId = submitOptions?.checkpoint?.checkpoint_id;\n setBranch(\n checkpointId != null\n ? branchContext.branchByCheckpoint[checkpointId]?.branch ?? \"\"\n : \"\"\n );\n\n // When `fetchStateHistory` is requested, thus we assume that branching\n // is enabled. We then need to include the implicit branch.\n const includeImplicitBranch =\n historyLimit === true || typeof historyLimit === \"number\";\n\n const shouldRefetch =\n // We're expecting the whole thread state in onFinish\n options.onFinish != null ||\n // We're fetching history, thus we need the latest checkpoint\n // to ensure we're not accidentally submitting to a wrong branch\n includeImplicitBranch;\n\n let callbackMeta: RunCallbackMeta | undefined;\n let rejoinKey: `lg:stream:${string}` | undefined;\n let usableThreadId = threadId;\n\n await stream.start(\n async (signal: AbortSignal) => {\n stream.setStreamValues((values) => {\n const prev = { ...historyValues, ...(values ?? {}) };\n if (submitOptions?.optimisticValues != null) {\n return {\n ...prev,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(prev)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...prev };\n });\n\n if (!usableThreadId) {\n const thread = await client.threads.create({\n threadId: submitOptions?.threadId,\n metadata: submitOptions?.metadata,\n signal,\n });\n\n usableThreadId = thread.thread_id;\n\n // Pre-emptively update the thread ID before\n // stream cancellation is kicked off and thread\n // is being refetched\n threadIdRef.current = usableThreadId;\n threadIdStreamingRef.current = usableThreadId;\n\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n threadIdStreamingRef.current = usableThreadId;\n\n const streamMode = unique([\n ...(submitOptions?.streamMode ?? []),\n ...trackStreamModeRef.current,\n ...callbackStreamMode,\n ]);\n\n let checkpoint =\n submitOptions?.checkpoint ??\n (includeImplicitBranch\n ? branchContext.threadHead?.checkpoint\n : undefined) ??\n undefined;\n\n // Avoid specifying a checkpoint if user explicitly set it to null\n if (submitOptions?.checkpoint === null) checkpoint = undefined;\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (checkpoint != null) delete checkpoint.thread_id;\n const streamResumable =\n submitOptions?.streamResumable ?? !!runMetadataStorage;\n\n return client.runs.stream(usableThreadId, options.assistantId, {\n input: values as Record<string, unknown>,\n config: submitOptions?.config,\n context: submitOptions?.context,\n command: submitOptions?.command,\n\n interruptBefore: submitOptions?.interruptBefore,\n interruptAfter: submitOptions?.interruptAfter,\n metadata: submitOptions?.metadata,\n multitaskStrategy: submitOptions?.multitaskStrategy,\n onCompletion: submitOptions?.onCompletion,\n onDisconnect:\n submitOptions?.onDisconnect ??\n (streamResumable ? \"continue\" : \"cancel\"),\n\n signal,\n\n checkpoint,\n streamMode,\n streamSubgraphs: submitOptions?.streamSubgraphs,\n streamResumable,\n durability: submitOptions?.durability,\n onRunCreated(params) {\n callbackMeta = {\n run_id: params.run_id,\n thread_id: params.thread_id ?? usableThreadId!,\n };\n\n if (runMetadataStorage) {\n rejoinKey = `lg:stream:${usableThreadId}`;\n runMetadataStorage.setItem(rejoinKey, callbackMeta.run_id);\n }\n\n options.onCreated?.(callbackMeta);\n },\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n\n async onSuccess() {\n if (rejoinKey) runMetadataStorage?.removeItem(rejoinKey);\n\n if (shouldRefetch) {\n const newHistory = await history.mutate(usableThreadId!);\n const lastHead = newHistory?.at(0);\n if (lastHead) {\n // We now have the latest update from /history\n // Thus we can clear the local stream state\n options.onFinish?.(lastHead, callbackMeta);\n return null;\n }\n }\n\n return undefined;\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const joinStream = async (\n runId: string,\n lastEventId?: string,\n joinOptions?: { streamMode?: StreamMode | StreamMode[] }\n ) => {\n // eslint-disable-next-line no-param-reassign\n lastEventId ??= \"-1\";\n if (!threadId) return;\n\n const callbackMeta: RunCallbackMeta = {\n thread_id: threadId,\n run_id: runId,\n };\n\n await stream.start(\n async (signal: AbortSignal) => {\n threadIdStreamingRef.current = threadId;\n return client.runs.joinStream(threadId, runId, {\n signal,\n lastEventId,\n streamMode: joinOptions?.streamMode,\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: historyValues,\n callbacks: options,\n async onSuccess() {\n runMetadataStorage?.removeItem(`lg:stream:${threadId}`);\n const newHistory = await history.mutate(threadId);\n const lastHead = newHistory?.at(0);\n if (lastHead) options.onFinish?.(lastHead, callbackMeta);\n },\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n onFinish() {\n threadIdStreamingRef.current = null;\n },\n }\n );\n };\n\n const reconnectKey = useMemo(() => {\n if (!runMetadataStorage || stream.isLoading) return undefined;\n if (typeof window === \"undefined\") return undefined;\n const runId = runMetadataStorage?.getItem(`lg:stream:${threadId}`);\n if (!runId) return undefined;\n return { runId, threadId };\n }, [runMetadataStorage, stream.isLoading, threadId]);\n\n const shouldReconnect = !!runMetadataStorage;\n const reconnectRef = useRef({ threadId, shouldReconnect });\n\n const joinStreamRef = useRef<typeof joinStream>(joinStream);\n joinStreamRef.current = joinStream;\n\n useEffect(() => {\n // reset shouldReconnect when switching threads\n if (reconnectRef.current.threadId !== threadId) {\n reconnectRef.current = { threadId, shouldReconnect };\n }\n }, [threadId, shouldReconnect]);\n\n useEffect(() => {\n if (reconnectKey && reconnectRef.current.shouldReconnect) {\n reconnectRef.current.shouldReconnect = false;\n void joinStreamRef.current?.(reconnectKey.runId);\n }\n }, [reconnectKey]);\n\n const error = stream.error ?? historyError ?? history.error;\n const values = stream.values ?? historyValues;\n\n return {\n get values() {\n trackStreamMode(\"values\");\n return values;\n },\n\n client,\n assistantId: options.assistantId,\n\n error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n joinStream,\n\n branch,\n setBranch,\n\n get history() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `history`\"\n );\n }\n\n return branchContext.flatHistory;\n },\n\n isThreadLoading: history.isLoading && history.data == null,\n\n get experimental_branchTree() {\n if (historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `experimental_branchTree`\"\n );\n }\n\n return branchContext.branchTree;\n },\n\n get interrupt() {\n if (\n values != null &&\n \"__interrupt__\" in values &&\n Array.isArray(values.__interrupt__)\n ) {\n const valueInterrupts = values.__interrupt__;\n if (valueInterrupts.length === 0) return { when: \"breakpoint\" };\n if (valueInterrupts.length === 1) return valueInterrupts[0];\n\n // TODO: fix the typing of interrupts if multiple interrupts are returned\n return valueInterrupts;\n }\n\n // If we're deferring to old interrupt detection logic, don't show the interrupt if the stream is loading\n if (stream.isLoading) return undefined;\n\n const interrupts = branchContext.threadHead?.tasks?.at(-1)?.interrupts;\n if (interrupts == null || interrupts.length === 0) {\n // check if there's a next task present\n const next = branchContext.threadHead?.next ?? [];\n if (!next.length || error != null) return undefined;\n return { when: \"breakpoint\" };\n }\n\n // Return only the current interrupt\n return interrupts.at(-1) as Interrupt<InterruptType> | undefined;\n },\n\n get messages() {\n trackStreamMode(\"messages-tuple\", \"values\");\n return getMessages(values);\n },\n\n getMessagesMetadata(\n message: Message,\n index?: number\n ): MessageMetadata<StateType> | undefined {\n trackStreamMode(\"values\");\n\n const streamMetadata = messageManager.get(message.id)?.metadata;\n const historyMetadata = messageMetadata?.find(\n (m) => m.messageId === (message.id ?? index)\n );\n\n if (streamMetadata != null || historyMetadata != null) {\n return {\n ...historyMetadata,\n streamMetadata,\n } as MessageMetadata<StateType>;\n }\n\n return undefined;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAqCA,SAAS,mBACP,QACA,UACA,OACA;AACA,QAAO;EAAC,oBAAoB;EAAS;EAAU;GAAO,KAAK;;AAG7D,SAAS,aACP,QACA,UACA,SACA;AACA,KAAI,SAAS,UAAU,MACrB,QAAO,OAAO,QAAQ,SAAoB,UAAU,MAAM,UAAU;AAClE,MAAI,MAAM,cAAc,KAAM,QAAO;AACrC,SAAO,CAAC;;CAIZ,MAAM,QAAQ,OAAO,SAAS,UAAU,WAAW,QAAQ,QAAQ;AACnE,QAAO,OAAO,QAAQ,WAAsB,UAAU,EAAE;;AAG1D,SAAS,iBACP,QACA,UACA,OACA,SAK4B;CAC5B,MAAM,MAAM,mBAAmB,QAAQ,UAAU;CACjD,MAAM,CAAC,OAAO,YAAY,gBAKhB;EACR,KAAK;EACL,MAAM;EACN,OAAO;EACP,WAAW,YAAY;;CAGzB,MAAM,YAAY,OAAO;AACzB,WAAU,UAAU;CAEpB,MAAM,aAAa,OAAO,SAAS;AACnC,YAAW,UAAU,SAAS;CAE9B,MAAM,UAAU,aAEZ,YACA,YACsC;AAEtC,MAAI,QAAQ,YAAa,QAAO,QAAQ,QAAQ;EAEhD,MAAMA,WAAS,UAAU;EACzB,MAAMC,QAAM,mBAAmBD,UAAQE,YAAUC;AAEjD,MAAID,cAAY,MAAM;AACpB,aAAU,YAAU;AAClB,QAAIE,QAAM,QAAQH,MAAK,QAAO;KAAE,GAAGG;KAAO,WAAW;;AACrD,WAAO;KAAE;KAAK,MAAM;KAAW,OAAO;KAAW,WAAW;;;AAE9D,UAAO,aAAwBJ,UAAQE,YAAU,EAAE,kBAAS,MACzD,SAAS;AACR,cAAU,YAAU;AAClB,SAAIE,QAAM,QAAQH,MAAK,QAAOG;AAC9B,YAAO;MAAE;MAAK;MAAM,OAAO;MAAW,WAAW;;;AAEnD,WAAO;OAER,UAAU;AACT,cAAU,YAAU;AAClB,SAAIA,QAAM,QAAQH,MAAK,QAAOG;AAC9B,YAAO;MAAE;MAAK,MAAMA,QAAM;MAAM;MAAO,WAAW;;;AAEpD,eAAW,UAAU;AACrB,WAAO,QAAQ,OAAO;;;AAK5B,WAAS;GAAE;GAAK,MAAM;GAAW,OAAO;GAAW,WAAW;;AAC9D,SAAO,QAAQ,QAAQ;IAEzB,CAAC,QAAQ;AAGX,iBAAgB;AAEd,MACE,QAAQ,cAAc,WAAW,QACjC,QAAQ,cAAc,YAAY,SAElC;AAGF,EAAK,QAAQ,UAAU;IAItB,CAAC,SAAS;AAEb,QAAO;EACL,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,WAAW,MAAM;EACjB,SAAS,aAAsB,QAAQ,YAAY,UAAU;;;AAIjE,SAAgB,aAQd,SAAsE;CAMtE,MAAM,sBAAsB,OAAO,QAAQ;CAC3C,MAAM,qBAAqB,cAAc;AACvC,MAAI,OAAO,WAAW,YAAa,QAAO;EAC1C,MAAM,UAAU,oBAAoB;AACpC,MAAI,YAAY,KAAM,QAAO,OAAO;AACpC,MAAI,OAAO,YAAY,WAAY,QAAO;AAC1C,SAAO;IACN;CAEH,MAAM,SAAS,cAEX,QAAQ,UACR,IAAI,OAAO;EACT,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,eAAe,QAAQ;EACvB,gBAAgB,QAAQ;KAE5B;EACE,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;;CAIZ,MAAM,CAAC,kBAAkB,eAAe,IAAI;CAC5C,MAAM,CAAC,UAAU,eAEb,IAAI,cAA8B,gBAAgB,EAChD,UAAU,QAAQ,YAAY;AAIpC,sBACE,OAAO,WACP,OAAO,aACP,OAAO;CAGT,MAAM,CAAC,UAAU,cAAc,wBAAwB;CACvD,MAAM,qBAAqB,OAA0C;CAErE,MAAM,kBAAkB,aACrB,GAAG,SAA4C;EAC9C,MAAM,MAAM,mBAAmB;AAC/B,OAAK,MAAM,KAAK,KACd,KAAI,CAAC,IAAI,SAAS,GAAI,KAAI,KAAK;IAGnC;CAGF,MAAM,oBAAoB,QAAQ,iBAAiB;CACnD,MAAM,oBAAoB,QAAQ,iBAAiB;CACnD,MAAM,uBAAuB,QAAQ,oBAAoB;CACzD,MAAM,mBAAmB,QAAQ,gBAAgB;CACjD,MAAM,wBAAwB,QAAQ,qBAAqB;CAC3D,MAAM,kBAAkB,QAAQ,eAAe;CAE/C,MAAM,qBAAqB,cAAc;EACvC,MAAMC,QAA2C;AACjD,MAAI,kBAAmB,OAAM,KAAK;AAClC,MAAI,kBAAmB,OAAM,KAAK;AAClC,MAAI,qBAAsB,OAAM,KAAK;AACrC,MAAI,iBAAkB,OAAM,KAAK;AACjC,MAAI,sBAAuB,OAAM,KAAK;AACtC,MAAI,gBAAiB,OAAM,KAAK;AAChC,SAAO;IACN;EACD;EACA;EACA;EACA;EACA;EACA;;CAGF,MAAM,cAAc,OAAsB;CAC1C,MAAM,uBAAuB,OAAsB;AAGnD,iBAAgB;AACd,MAAI,YAAY,YAAY,UAAU;AACpC,eAAY,UAAU;AACtB,UAAO;;IAER,CAAC,UAAU;CAEd,MAAM,eACJ,OAAO,QAAQ,sBAAsB,YACrC,QAAQ,qBAAqB,OACzB,QAAQ,kBAAkB,SAAS,QACnC,QAAQ,qBAAqB;CAEnC,MAAM,iBAAiB,iBACrB,QACA,UACA,cACA;EACE,aAAa,QAAQ,UAAU;EAC/B,eAAe;EACf,SAAS,QAAQ;;CAGrB,MAAM,UAAU,QAAQ,UAAU;CAElC,MAAM,eAAe,UAAgC;EACnD,MAAM,cAAc,QAAQ,eAAe;AAC3C,SAAO,MAAM,QAAQ,MAAM,gBAAgB,MAAM,eAAe;;CAGlE,MAAM,eAAe,SAAoB,aAAmC;EAC1E,MAAM,cAAc,QAAQ,eAAe;AAC3C,SAAO;GAAE,GAAG;IAAU,cAAc;;;CAGtC,MAAM,CAAC,QAAQ,aAAa,SAAiB;CAC7C,MAAM,gBAAgB,iBAAiB,QAAQ,QAAQ,QAAQ;CAE/D,MAAM,gBACJ,cAAc,YAAY,UAC1B,QAAQ,iBACP;CAEH,MAAM,sBAAsB;EAC1B,MAAMC,UAAQ,cAAc,YAAY,OAAO,GAAG,KAAK;AACvD,MAAIA,WAAS,KAAM,QAAO;AAC1B,MAAI;GACF,MAAM,SAAS,KAAK,MAAMA;AAC1B,OAAI,YAAY,kBAAkB,QAAS,QAAO,IAAI,YAAY;AAClE,UAAO;UACD;AAGR,SAAOA;;CAGT,MAAM,yBAAyB;EAC7B,MAAM,+BAAe,IAAI;AACzB,SAAO,YAAY,eAAe,KAC/B,SAAS,QAA4D;GACpE,MAAM,YAAY,QAAQ,MAAM;GAGhC,MAAM,iBAAiB,SAAS,QAAQ,QAAQ,KAAK,UACnD,YAAY,MAAM,QACf,KAAK,GAAG,UAAQ,EAAE,MAAMC,OACxB,SAAS;GAGd,MAAM,eAAe,gBAAgB,YAAY;GACjD,IAAIC,WACF,gBAAgB,OACZ,cAAc,mBAAmB,gBACjC;AACN,OAAI,CAACA,UAAQ,QAAQ,OAAQ,YAAS;GAGtC,MAAM,eAAeA,UAAQ,eAAe,KAAK,GAAG,KAAK;AACzD,OAAI,cAAc;AAChB,QAAI,aAAa,IAAI,cAAe,YAAS;AAC7C,iBAAa,IAAI;;AAGnB,UAAO;IACL,WAAW,UAAU;IACrB;IAEA,QAAQA,UAAQ;IAChB,eAAeA,UAAQ;;;;CAM/B,MAAM,aACJ,OAAO,KAAK,eAAe,EACzB,SAAS,SAAS;AAChB,MAAI,sBAAsB,UAAU;GAClC,MAAM,QAAQ,mBAAmB,QAAQ,aAAa;AACtD,OAAI,MAAO,CAAK,OAAO,KAAK,OAAO,UAAU;AAC7C,sBAAmB,WAAW,aAAa;;AAG7C,UAAQ,SAAS;;CAKvB,MAAM,SAAS,OACb,UACA,kBACG;EAEH,MAAM,eAAe,eAAe,YAAY;AAChD,YACE,gBAAgB,OACZ,cAAc,mBAAmB,eAAe,UAAU,KAC1D;EAKN,MAAM,wBACJ,iBAAiB,QAAQ,OAAO,iBAAiB;EAEnD,MAAM,gBAEJ,QAAQ,YAAY,QAGpB;EAEF,IAAIC;EACJ,IAAIC;EACJ,IAAI,iBAAiB;AAErB,QAAM,OAAO,MACX,OAAO,WAAwB;AAC7B,UAAO,iBAAiB,aAAW;IACjC,MAAM,OAAO;KAAE,GAAG;KAAe,GAAIC,YAAU;;AAC/C,QAAI,eAAe,oBAAoB,KACrC,QAAO;KACL,GAAG;KACH,GAAI,OAAO,cAAc,qBAAqB,aAC1C,cAAc,iBAAiB,QAC/B,cAAc;;AAItB,WAAO,EAAE,GAAG;;AAGd,OAAI,CAAC,gBAAgB;IACnB,MAAM,SAAS,MAAM,OAAO,QAAQ,OAAO;KACzC,UAAU,eAAe;KACzB,UAAU,eAAe;KACzB;;AAGF,qBAAiB,OAAO;AAKxB,gBAAY,UAAU;AACtB,yBAAqB,UAAU;AAE/B,eAAW;;AAGb,OAAI,CAAC,eACH,OAAM,IAAI,MAAM;AAGlB,wBAAqB,UAAU;GAE/B,MAAM,aAAa,OAAO;IACxB,GAAI,eAAe,cAAc;IACjC,GAAG,mBAAmB;IACtB,GAAG;;GAGL,IAAI,aACF,eAAe,eACd,wBACG,cAAc,YAAY,aAC1B,WACJ;AAGF,OAAI,eAAe,eAAe,KAAM,cAAa;AAIrD,OAAI,cAAc,KAAM,QAAO,WAAW;GAC1C,MAAM,kBACJ,eAAe,mBAAmB,CAAC,CAAC;AAEtC,UAAO,OAAO,KAAK,OAAO,gBAAgB,QAAQ,aAAa;IAC7D,OAAOA;IACP,QAAQ,eAAe;IACvB,SAAS,eAAe;IACxB,SAAS,eAAe;IAExB,iBAAiB,eAAe;IAChC,gBAAgB,eAAe;IAC/B,UAAU,eAAe;IACzB,mBAAmB,eAAe;IAClC,cAAc,eAAe;IAC7B,cACE,eAAe,iBACd,kBAAkB,aAAa;IAElC;IAEA;IACA;IACA,iBAAiB,eAAe;IAChC;IACA,YAAY,eAAe;IAC3B,aAAa,QAAQ;AACnB,oBAAe;MACb,QAAQ,OAAO;MACf,WAAW,OAAO,aAAa;;AAGjC,SAAI,oBAAoB;AACtB,kBAAY,aAAa;AACzB,yBAAmB,QAAQ,WAAW,aAAa;;AAGrD,aAAQ,YAAY;;;KAM1B;GACE;GACA;GAEA,eAAe;GACf,WAAW;GAEX,MAAM,YAAY;AAChB,QAAI,UAAW,qBAAoB,WAAW;AAE9C,QAAI,eAAe;KACjB,MAAM,aAAa,MAAM,QAAQ,OAAO;KACxC,MAAM,WAAW,YAAY,GAAG;AAChC,SAAI,UAAU;AAGZ,cAAQ,WAAW,UAAU;AAC7B,aAAO;;;AAIX,WAAO;;GAET,QAAQ,SAAO;AACb,YAAQ,UAAUL,SAAO;;GAE3B,WAAW;AACT,yBAAqB,UAAU;;;;CAMvC,MAAM,aAAa,OACjB,OACA,aACA,gBACG;AAEH,kBAAgB;AAChB,MAAI,CAAC,SAAU;EAEf,MAAMM,eAAgC;GACpC,WAAW;GACX,QAAQ;;AAGV,QAAM,OAAO,MACX,OAAO,WAAwB;AAC7B,wBAAqB,UAAU;AAC/B,UAAO,OAAO,KAAK,WAAW,UAAU,OAAO;IAC7C;IACA;IACA,YAAY,aAAa;;KAK7B;GACE;GACA;GAEA,eAAe;GACf,WAAW;GACX,MAAM,YAAY;AAChB,wBAAoB,WAAW,aAAa;IAC5C,MAAM,aAAa,MAAM,QAAQ,OAAO;IACxC,MAAM,WAAW,YAAY,GAAG;AAChC,QAAI,SAAU,SAAQ,WAAW,UAAU;;GAE7C,QAAQ,SAAO;AACb,YAAQ,UAAUN,SAAO;;GAE3B,WAAW;AACT,yBAAqB,UAAU;;;;CAMvC,MAAM,eAAe,cAAc;AACjC,MAAI,CAAC,sBAAsB,OAAO,UAAW,QAAO;AACpD,MAAI,OAAO,WAAW,YAAa,QAAO;EAC1C,MAAM,QAAQ,oBAAoB,QAAQ,aAAa;AACvD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO;GAAE;GAAO;;IACf;EAAC;EAAoB,OAAO;EAAW;;CAE1C,MAAM,kBAAkB,CAAC,CAAC;CAC1B,MAAM,eAAe,OAAO;EAAE;EAAU;;CAExC,MAAM,gBAAgB,OAA0B;AAChD,eAAc,UAAU;AAExB,iBAAgB;AAEd,MAAI,aAAa,QAAQ,aAAa,SACpC,cAAa,UAAU;GAAE;GAAU;;IAEpC,CAAC,UAAU;AAEd,iBAAgB;AACd,MAAI,gBAAgB,aAAa,QAAQ,iBAAiB;AACxD,gBAAa,QAAQ,kBAAkB;AACvC,GAAK,cAAc,UAAU,aAAa;;IAE3C,CAAC;CAEJ,MAAM,QAAQ,OAAO,SAAS,gBAAgB,QAAQ;CACtD,MAAM,SAAS,OAAO,UAAU;AAEhC,QAAO;EACL,IAAI,SAAS;AACX,mBAAgB;AAChB,UAAO;;EAGT;EACA,aAAa,QAAQ;EAErB;EACA,WAAW,OAAO;EAElB;EACA;EAEA;EAEA;EACA;EAEA,IAAI,UAAU;AACZ,OAAI,iBAAiB,MACnB,OAAM,IAAI,MACR;AAIJ,UAAO,cAAc;;EAGvB,iBAAiB,QAAQ,aAAa,QAAQ,QAAQ;EAEtD,IAAI,0BAA0B;AAC5B,OAAI,iBAAiB,MACnB,OAAM,IAAI,MACR;AAIJ,UAAO,cAAc;;EAGvB,IAAI,YAAY;AACd,OACE,UAAU,QACV,mBAAmB,UACnB,MAAM,QAAQ,OAAO,gBACrB;IACA,MAAM,kBAAkB,OAAO;AAC/B,QAAI,gBAAgB,WAAW,EAAG,QAAO,EAAE,MAAM;AACjD,QAAI,gBAAgB,WAAW,EAAG,QAAO,gBAAgB;AAGzD,WAAO;;AAIT,OAAI,OAAO,UAAW,QAAO;GAE7B,MAAM,aAAa,cAAc,YAAY,OAAO,GAAG,KAAK;AAC5D,OAAI,cAAc,QAAQ,WAAW,WAAW,GAAG;IAEjD,MAAM,OAAO,cAAc,YAAY,QAAQ;AAC/C,QAAI,CAAC,KAAK,UAAU,SAAS,KAAM,QAAO;AAC1C,WAAO,EAAE,MAAM;;AAIjB,UAAO,WAAW,GAAG;;EAGvB,IAAI,WAAW;AACb,mBAAgB,kBAAkB;AAClC,UAAO,YAAY;;EAGrB,oBACE,SACA,OACwC;AACxC,mBAAgB;GAEhB,MAAM,iBAAiB,eAAe,IAAI,QAAQ,KAAK;GACvD,MAAM,kBAAkB,iBAAiB,MACtC,MAAM,EAAE,eAAe,QAAQ,MAAM;AAGxC,OAAI,kBAAkB,QAAQ,mBAAmB,KAC/C,QAAO;IACL,GAAG;IACH;;AAIJ,UAAO"}
|
package/dist/ui/manager.cjs
CHANGED
|
@@ -7,6 +7,8 @@ var StreamManager = class {
|
|
|
7
7
|
messages;
|
|
8
8
|
listeners = /* @__PURE__ */ new Set();
|
|
9
9
|
throttle;
|
|
10
|
+
queue = Promise.resolve();
|
|
11
|
+
queueSize = 0;
|
|
10
12
|
state;
|
|
11
13
|
constructor(messages, options) {
|
|
12
14
|
this.messages = messages;
|
|
@@ -83,9 +85,9 @@ var StreamManager = class {
|
|
|
83
85
|
matchEventType = (expected, actual, _data) => {
|
|
84
86
|
return expected === actual || actual.startsWith(`${expected}|`);
|
|
85
87
|
};
|
|
86
|
-
|
|
87
|
-
if (this.state.isLoading) return;
|
|
88
|
+
enqueue = async (action, options) => {
|
|
88
89
|
try {
|
|
90
|
+
this.queueSize = Math.max(0, this.queueSize - 1);
|
|
89
91
|
this.setState({
|
|
90
92
|
isLoading: true,
|
|
91
93
|
error: void 0
|
|
@@ -141,7 +143,7 @@ var StreamManager = class {
|
|
|
141
143
|
}
|
|
142
144
|
if (streamError != null) throw streamError;
|
|
143
145
|
const values = await options.onSuccess?.();
|
|
144
|
-
if (typeof values !== "undefined") this.setStreamValues(values);
|
|
146
|
+
if (typeof values !== "undefined" && this.queueSize === 0) this.setStreamValues(values);
|
|
145
147
|
} catch (error) {
|
|
146
148
|
if (!(error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError"))) {
|
|
147
149
|
console.error(error);
|
|
@@ -154,6 +156,10 @@ var StreamManager = class {
|
|
|
154
156
|
options.onFinish?.();
|
|
155
157
|
}
|
|
156
158
|
};
|
|
159
|
+
start = async (action, options) => {
|
|
160
|
+
this.queueSize += 1;
|
|
161
|
+
this.queue = this.queue.then(() => this.enqueue(action, options));
|
|
162
|
+
};
|
|
157
163
|
stop = async (historyValues, options) => {
|
|
158
164
|
this.abortRef.abort();
|
|
159
165
|
this.abortRef = new AbortController();
|
package/dist/ui/manager.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.cjs","names":["timeoutId: NodeJS.Timeout | number | undefined","streamError: StreamError | undefined","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\";\n\ntype BagTemplate = {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n};\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 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 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 if (this.state.isLoading) return;\n\n try {\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 const 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 messages.splice(index, 1);\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.setStreamValues(values);\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 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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"}
|
|
1
|
+
{"version":3,"file":"manager.cjs","names":["timeoutId: NodeJS.Timeout | number | undefined","streamError: StreamError | undefined","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\";\n\ntype BagTemplate = {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n};\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 const 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 messages.splice(index, 1);\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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"}
|
package/dist/ui/manager.js
CHANGED
|
@@ -7,6 +7,8 @@ var StreamManager = class {
|
|
|
7
7
|
messages;
|
|
8
8
|
listeners = /* @__PURE__ */ new Set();
|
|
9
9
|
throttle;
|
|
10
|
+
queue = Promise.resolve();
|
|
11
|
+
queueSize = 0;
|
|
10
12
|
state;
|
|
11
13
|
constructor(messages, options) {
|
|
12
14
|
this.messages = messages;
|
|
@@ -83,9 +85,9 @@ var StreamManager = class {
|
|
|
83
85
|
matchEventType = (expected, actual, _data) => {
|
|
84
86
|
return expected === actual || actual.startsWith(`${expected}|`);
|
|
85
87
|
};
|
|
86
|
-
|
|
87
|
-
if (this.state.isLoading) return;
|
|
88
|
+
enqueue = async (action, options) => {
|
|
88
89
|
try {
|
|
90
|
+
this.queueSize = Math.max(0, this.queueSize - 1);
|
|
89
91
|
this.setState({
|
|
90
92
|
isLoading: true,
|
|
91
93
|
error: void 0
|
|
@@ -141,7 +143,7 @@ var StreamManager = class {
|
|
|
141
143
|
}
|
|
142
144
|
if (streamError != null) throw streamError;
|
|
143
145
|
const values = await options.onSuccess?.();
|
|
144
|
-
if (typeof values !== "undefined") this.setStreamValues(values);
|
|
146
|
+
if (typeof values !== "undefined" && this.queueSize === 0) this.setStreamValues(values);
|
|
145
147
|
} catch (error) {
|
|
146
148
|
if (!(error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError"))) {
|
|
147
149
|
console.error(error);
|
|
@@ -154,6 +156,10 @@ var StreamManager = class {
|
|
|
154
156
|
options.onFinish?.();
|
|
155
157
|
}
|
|
156
158
|
};
|
|
159
|
+
start = async (action, options) => {
|
|
160
|
+
this.queueSize += 1;
|
|
161
|
+
this.queue = this.queue.then(() => this.enqueue(action, options));
|
|
162
|
+
};
|
|
157
163
|
stop = async (historyValues, options) => {
|
|
158
164
|
this.abortRef.abort();
|
|
159
165
|
this.abortRef = new AbortController();
|
package/dist/ui/manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","names":["timeoutId: NodeJS.Timeout | number | undefined","streamError: StreamError | undefined","values"],"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\";\n\ntype BagTemplate = {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n};\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 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 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 if (this.state.isLoading) return;\n\n try {\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 const 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 messages.splice(index, 1);\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.setStreamValues(values);\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 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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"}
|
|
1
|
+
{"version":3,"file":"manager.js","names":["timeoutId: NodeJS.Timeout | number | undefined","streamError: StreamError | undefined","values"],"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\";\n\ntype BagTemplate = {\n ConfigurableType?: Record<string, unknown>;\n InterruptType?: unknown;\n CustomEventType?: unknown;\n UpdateType?: unknown;\n};\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 const 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 messages.splice(index, 1);\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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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/langgraph-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Client library for interacting with the LangGraph API",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+ssh://git@github.com/langchain-ai/langgraphjs.git",
|
|
9
|
+
"directory": "libs/sdk"
|
|
10
|
+
},
|
|
6
11
|
"scripts": {
|
|
7
12
|
"clean": "rm -rf dist/ dist-cjs/",
|
|
8
13
|
"build": "yarn turbo:command build:internal --filter=@langchain/langgraph-sdk",
|