@langchain/langgraph-sdk 1.3.1 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/rolldown_runtime.cjs +10 -6
- package/dist/auth/error.cjs.map +1 -1
- package/dist/auth/error.d.cts.map +1 -1
- package/dist/auth/error.d.ts.map +1 -1
- package/dist/auth/error.js.map +1 -1
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +1 -3
- package/dist/auth/index.d.cts.map +1 -1
- package/dist/auth/index.d.ts +1 -3
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/types.d.cts +1 -1
- package/dist/auth/types.d.cts.map +1 -1
- package/dist/auth/types.d.ts +1 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/client.cjs +15 -24
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -6
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.ts +2 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +15 -24
- package/dist/client.js.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/logging/index.cjs.map +1 -1
- package/dist/logging/index.d.cts +0 -1
- package/dist/logging/index.d.cts.map +1 -1
- package/dist/logging/index.d.ts +0 -1
- package/dist/logging/index.d.ts.map +1 -1
- package/dist/logging/index.js.map +1 -1
- package/dist/react/index.d.cts +3 -2
- package/dist/react/index.d.ts +3 -2
- package/dist/react/stream.cjs +1 -1
- package/dist/react/stream.cjs.map +1 -1
- package/dist/react/stream.custom.cjs +12 -6
- package/dist/react/stream.custom.cjs.map +1 -1
- package/dist/react/stream.custom.d.cts +3 -2
- package/dist/react/stream.custom.d.cts.map +1 -1
- package/dist/react/stream.custom.d.ts +3 -2
- package/dist/react/stream.custom.d.ts.map +1 -1
- package/dist/react/stream.custom.js +11 -5
- package/dist/react/stream.custom.js.map +1 -1
- package/dist/react/stream.d.cts +116 -34
- package/dist/react/stream.d.cts.map +1 -1
- package/dist/react/stream.d.ts +116 -34
- package/dist/react/stream.d.ts.map +1 -1
- package/dist/react/stream.js.map +1 -1
- package/dist/react/stream.lgp.cjs +15 -13
- package/dist/react/stream.lgp.cjs.map +1 -1
- package/dist/react/stream.lgp.js +14 -12
- package/dist/react/stream.lgp.js.map +1 -1
- package/dist/react/thread.cjs +1 -2
- package/dist/react/thread.cjs.map +1 -1
- package/dist/react/thread.js +0 -1
- package/dist/react/thread.js.map +1 -1
- package/dist/react/types.d.cts +73 -284
- package/dist/react/types.d.cts.map +1 -1
- package/dist/react/types.d.ts +73 -284
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react-ui/client.cjs +8 -7
- package/dist/react-ui/client.cjs.map +1 -1
- package/dist/react-ui/client.d.cts +4 -21
- package/dist/react-ui/client.d.cts.map +1 -1
- package/dist/react-ui/client.d.ts +4 -21
- package/dist/react-ui/client.d.ts.map +1 -1
- package/dist/react-ui/client.js +2 -4
- package/dist/react-ui/client.js.map +1 -1
- package/dist/react-ui/index.cjs.map +1 -1
- package/dist/react-ui/index.js.map +1 -1
- package/dist/react-ui/server/server.cjs +1 -1
- package/dist/react-ui/server/server.cjs.map +1 -1
- package/dist/react-ui/server/server.d.cts.map +1 -1
- package/dist/react-ui/server/server.d.ts.map +1 -1
- package/dist/react-ui/server/server.js.map +1 -1
- package/dist/react-ui/types.cjs.map +1 -1
- package/dist/react-ui/types.d.cts.map +1 -1
- package/dist/react-ui/types.d.ts.map +1 -1
- package/dist/react-ui/types.js.map +1 -1
- package/dist/schema.d.cts +6 -6
- package/dist/schema.d.cts.map +1 -1
- package/dist/schema.d.ts +6 -6
- package/dist/schema.d.ts.map +1 -1
- package/dist/singletons/fetch.cjs.map +1 -1
- package/dist/singletons/fetch.js.map +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.messages.d.cts +207 -34
- package/dist/types.messages.d.cts.map +1 -1
- package/dist/types.messages.d.ts +207 -34
- package/dist/types.messages.d.ts.map +1 -1
- package/dist/types.stream.d.cts +1 -3
- package/dist/types.stream.d.cts.map +1 -1
- package/dist/types.stream.d.ts +1 -3
- package/dist/types.stream.d.ts.map +1 -1
- package/dist/types.template.d.cts +19 -0
- package/dist/types.template.d.cts.map +1 -0
- package/dist/types.template.d.ts +19 -0
- package/dist/types.template.d.ts.map +1 -0
- package/dist/ui/branching.cjs.map +1 -1
- package/dist/ui/branching.d.cts +0 -3
- package/dist/ui/branching.d.cts.map +1 -1
- package/dist/ui/branching.d.ts +0 -3
- package/dist/ui/branching.d.ts.map +1 -1
- package/dist/ui/branching.js.map +1 -1
- package/dist/ui/errors.cjs.map +1 -1
- package/dist/ui/errors.js.map +1 -1
- package/dist/ui/manager.cjs +8 -2
- package/dist/ui/manager.cjs.map +1 -1
- package/dist/ui/manager.js +8 -2
- package/dist/ui/manager.js.map +1 -1
- package/dist/ui/messages.cjs +10 -10
- package/dist/ui/messages.cjs.map +1 -1
- package/dist/ui/messages.js.map +1 -1
- package/dist/ui/types.d.cts +420 -0
- package/dist/ui/types.d.cts.map +1 -0
- package/dist/ui/types.d.ts +420 -0
- package/dist/ui/types.d.ts.map +1 -0
- package/dist/ui/utils.cjs +0 -1
- package/dist/ui/utils.cjs.map +1 -1
- package/dist/ui/utils.js +0 -1
- package/dist/ui/utils.js.map +1 -1
- package/dist/utils/async_caller.cjs +12 -4
- package/dist/utils/async_caller.cjs.map +1 -1
- package/dist/utils/async_caller.d.cts +1 -3
- package/dist/utils/async_caller.d.cts.map +1 -1
- package/dist/utils/async_caller.d.ts +1 -3
- package/dist/utils/async_caller.d.ts.map +1 -1
- package/dist/utils/async_caller.js +8 -2
- package/dist/utils/async_caller.js.map +1 -1
- package/dist/utils/env.cjs +1 -1
- package/dist/utils/env.cjs.map +1 -1
- package/dist/utils/env.js +1 -1
- package/dist/utils/env.js.map +1 -1
- package/dist/utils/error.cjs.map +1 -1
- package/dist/utils/error.js.map +1 -1
- package/dist/utils/signals.cjs.map +1 -1
- package/dist/utils/signals.js.map +1 -1
- package/dist/utils/sse.cjs.map +1 -1
- package/dist/utils/sse.js.map +1 -1
- package/dist/utils/stream.cjs +1 -3
- package/dist/utils/stream.cjs.map +1 -1
- package/dist/utils/stream.js +1 -3
- package/dist/utils/stream.js.map +1 -1
- package/dist/utils/tools.cjs +52 -0
- package/dist/utils/tools.cjs.map +1 -0
- package/dist/utils/tools.js +51 -0
- package/dist/utils/tools.js.map +1 -0
- package/package.json +5 -5
- package/CHANGELOG.md +0 -281
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
5
4
|
const require_sse = require('../utils/sse.cjs');
|
|
6
5
|
const require_stream = require('../utils/stream.cjs');
|
|
7
6
|
const require_messages = require('../ui/messages.cjs');
|
|
8
7
|
const require_manager = require('../ui/manager.cjs');
|
|
8
|
+
const require_tools = require('../utils/tools.cjs');
|
|
9
9
|
const require_thread = require('./thread.cjs');
|
|
10
|
-
|
|
10
|
+
let react = require("react");
|
|
11
11
|
|
|
12
12
|
//#region src/react/stream.custom.tsx
|
|
13
13
|
var FetchStreamTransport = class {
|
|
@@ -15,7 +15,7 @@ var FetchStreamTransport = class {
|
|
|
15
15
|
this.options = options;
|
|
16
16
|
}
|
|
17
17
|
async stream(payload) {
|
|
18
|
-
const { signal
|
|
18
|
+
const { signal, ...body } = payload;
|
|
19
19
|
let requestInit = {
|
|
20
20
|
method: "POST",
|
|
21
21
|
headers: {
|
|
@@ -26,8 +26,7 @@ var FetchStreamTransport = class {
|
|
|
26
26
|
signal
|
|
27
27
|
};
|
|
28
28
|
if (this.options.onRequest) requestInit = await this.options.onRequest(this.options.apiUrl, requestInit);
|
|
29
|
-
const
|
|
30
|
-
const response = await fetchFn(this.options.apiUrl, requestInit);
|
|
29
|
+
const response = await (this.options.fetch ?? fetch)(this.options.apiUrl, requestInit);
|
|
31
30
|
if (!response.ok) throw new Error(`Failed to stream: ${response.statusText}`);
|
|
32
31
|
const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })).pipeThrough(require_sse.BytesLineDecoder()).pipeThrough(require_sse.SSEDecoder());
|
|
33
32
|
return require_stream.IterableReadableStream.fromReadableStream(stream);
|
|
@@ -114,11 +113,18 @@ function useStreamCustom(options) {
|
|
|
114
113
|
if (valueInterrupts.length === 1) return valueInterrupts[0];
|
|
115
114
|
return valueInterrupts;
|
|
116
115
|
}
|
|
117
|
-
return void 0;
|
|
118
116
|
},
|
|
119
117
|
get messages() {
|
|
120
118
|
if (!stream.values) return [];
|
|
121
119
|
return getMessages(stream.values);
|
|
120
|
+
},
|
|
121
|
+
get toolCalls() {
|
|
122
|
+
if (!stream.values) return [];
|
|
123
|
+
return require_tools.getToolCallsWithResults(getMessages(stream.values));
|
|
124
|
+
},
|
|
125
|
+
getToolCalls(message) {
|
|
126
|
+
if (!stream.values) return [];
|
|
127
|
+
return require_tools.getToolCallsWithResults(getMessages(stream.values)).filter((tc) => tc.aiMessage.id === message.id);
|
|
122
128
|
}
|
|
123
129
|
};
|
|
124
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.custom.cjs","names":["options: FetchStreamTransportOptions","requestInit: RequestInit","BytesLineDecoder","SSEDecoder","IterableReadableStream","MessageTupleManager","StreamManager","useControllableThreadId","callbackMeta: RunCallbackMeta | undefined"],"sources":["../../src/react/stream.custom.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n BagTemplate,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n RunCallbackMeta,\n GetConfigurableType,\n UseStreamCustomOptions,\n UseStreamCustom,\n UseStreamTransport,\n CustomSubmitOptions,\n} from \"./types.js\";\nimport type { Message } from \"../types.messages.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { Interrupt } from \"../schema.js\";\nimport { BytesLineDecoder, SSEDecoder } from \"../utils/sse.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { useControllableThreadId } from \"./thread.js\";\nimport { Command } from \"../types.js\";\n\ninterface FetchStreamTransportOptions {\n /**\n * The URL of the API to use.\n */\n apiUrl: string;\n\n /**\n * Default headers to send with requests.\n */\n defaultHeaders?: HeadersInit;\n\n /**\n * Specify a custom fetch implementation.\n */\n fetch?: typeof fetch | ((...args: any[]) => any); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n /**\n * Callback that is called before the request is made.\n */\n onRequest?: (\n url: string,\n init: RequestInit\n ) => Promise<RequestInit> | RequestInit;\n}\n\nexport class FetchStreamTransport<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate\n> implements UseStreamTransport<StateType, Bag>\n{\n constructor(private readonly options: FetchStreamTransportOptions) {}\n\n async stream(payload: {\n input: GetUpdateType<Bag, StateType> | null | undefined;\n context: GetConfigurableType<Bag> | undefined;\n command: Command | undefined;\n signal: AbortSignal;\n }): Promise<AsyncGenerator<{ id?: string; event: string; data: unknown }>> {\n const { signal, ...body } = payload;\n\n let requestInit: RequestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.options.defaultHeaders,\n },\n body: JSON.stringify(body),\n signal,\n };\n\n if (this.options.onRequest) {\n requestInit = await this.options.onRequest(\n this.options.apiUrl,\n requestInit\n );\n }\n const fetchFn = this.options.fetch ?? fetch;\n\n const response = await fetchFn(this.options.apiUrl, requestInit);\n if (!response.ok) {\n throw new Error(`Failed to stream: ${response.statusText}`);\n }\n\n const stream = (\n response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })\n )\n .pipeThrough(BytesLineDecoder())\n .pipeThrough(SSEDecoder());\n\n return IterableReadableStream.fromReadableStream(stream);\n }\n}\n\nexport function useStreamCustom<\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>(\n options: UseStreamCustomOptions<StateType, Bag>\n): UseStreamCustom<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n\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 threadIdRef = useRef<string | null>(threadId);\n\n // Cancel the stream if thread ID has changed\n useEffect(() => {\n if (threadIdRef.current !== threadId) {\n threadIdRef.current = threadId;\n stream.clear();\n }\n }, [threadId, stream]);\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey]) ? 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 historyValues = options.initialValues ?? ({} as StateType);\n\n const stop = () => stream.stop(historyValues, { onStop: options.onStop });\n\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: CustomSubmitOptions<StateType, ConfigurableType>\n ) => {\n let callbackMeta: RunCallbackMeta | undefined;\n let usableThreadId = threadId;\n\n stream.setStreamValues(() => {\n if (submitOptions?.optimisticValues != null) {\n return {\n ...historyValues,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(historyValues)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...historyValues };\n });\n\n await stream.start(\n async (signal: AbortSignal) => {\n if (!usableThreadId) {\n // generate random thread id\n usableThreadId = crypto.randomUUID();\n threadIdRef.current = usableThreadId;\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n return options.transport.stream({\n input: values,\n context: submitOptions?.context,\n command: submitOptions?.command,\n signal,\n config: {\n ...submitOptions?.config,\n configurable: {\n thread_id: usableThreadId,\n ...submitOptions?.config?.configurable,\n } as unknown as GetConfigurableType<Bag>,\n },\n }) as Promise<\n AsyncGenerator<EventStreamEvent<StateType, UpdateType, CustomType>>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: {} as StateType,\n callbacks: options,\n\n onSuccess: () => undefined,\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n }\n );\n };\n\n return {\n get values() {\n return stream.values ?? ({} as StateType);\n },\n\n error: stream.error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n get interrupt(): Interrupt<InterruptType> | undefined {\n if (\n stream.values != null &&\n \"__interrupt__\" in stream.values &&\n Array.isArray(stream.values.__interrupt__)\n ) {\n const valueInterrupts = stream.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 as Interrupt<InterruptType>;\n }\n\n return undefined;\n },\n\n get messages() {\n if (!stream.values) return [];\n return getMessages(stream.values);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;AAmDA,IAAa,uBAAb,MAIA;CACE,YAAY,AAAiBA,SAAsC;EAAtC;;CAE7B,MAAM,OAAO,SAK8D;EACzE,MAAM,EAAE,OAAQ,GAAG,SAAS;EAE5B,IAAIC,cAA2B;GAC7B,QAAQ;GACR,SAAS;IACP,gBAAgB;IAChB,GAAG,KAAK,QAAQ;;GAElB,MAAM,KAAK,UAAU;GACrB;;AAGF,MAAI,KAAK,QAAQ,UACf,eAAc,MAAM,KAAK,QAAQ,UAC/B,KAAK,QAAQ,QACb;EAGJ,MAAM,UAAU,KAAK,QAAQ,SAAS;EAEtC,MAAM,WAAW,MAAM,QAAQ,KAAK,QAAQ,QAAQ;AACpD,MAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,qBAAqB,SAAS;EAGhD,MAAM,UACJ,SAAS,QAAQ,IAAI,eAAe,EAAE,QAAQ,SAAS,KAAK,YAE3D,YAAYC,gCACZ,YAAYC;AAEf,SAAOC,sCAAuB,mBAAmB;;;AAIrD,SAAgB,gBASd,SACiC;CAMjC,MAAM,CAAC,4CAAiC,IAAIC;CAC5C,MAAM,CAAC,oCAEH,IAAIC,8BAA8B,gBAAgB,EAChD,UAAU,QAAQ,YAAY;AAIpC,iCACE,OAAO,WACP,OAAO,aACP,OAAO;CAGT,MAAM,CAAC,UAAU,cAAcC,uCAAwB;CACvD,MAAM,gCAAoC;AAG1C,4BAAgB;AACd,MAAI,YAAY,YAAY,UAAU;AACpC,eAAY,UAAU;AACtB,UAAO;;IAER,CAAC,UAAU;CAEd,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,gBAAgB,QAAQ,iBAAkB;CAEhD,MAAM,aAAa,OAAO,KAAK,eAAe,EAAE,QAAQ,QAAQ;CAEhE,MAAM,SAAS,OACb,QACA,kBACG;EACH,IAAIC;EACJ,IAAI,iBAAiB;AAErB,SAAO,sBAAsB;AAC3B,OAAI,eAAe,oBAAoB,KACrC,QAAO;IACL,GAAG;IACH,GAAI,OAAO,cAAc,qBAAqB,aAC1C,cAAc,iBAAiB,iBAC/B,cAAc;;AAItB,UAAO,EAAE,GAAG;;AAGd,QAAM,OAAO,MACX,OAAO,WAAwB;AAC7B,OAAI,CAAC,gBAAgB;AAEnB,qBAAiB,OAAO;AACxB,gBAAY,UAAU;AACtB,eAAW;;AAGb,OAAI,CAAC,eACH,OAAM,IAAI,MAAM;AAGlB,UAAO,QAAQ,UAAU,OAAO;IAC9B,OAAO;IACP,SAAS,eAAe;IACxB,SAAS,eAAe;IACxB;IACA,QAAQ;KACN,GAAG,eAAe;KAClB,cAAc;MACZ,WAAW;MACX,GAAG,eAAe,QAAQ;;;;KAOlC;GACE;GACA;GAEA,eAAe;GACf,WAAW;GAEX,iBAAiB;GACjB,QAAQ,OAAO;AACb,YAAQ,UAAU,OAAO;;;;AAMjC,QAAO;EACL,IAAI,SAAS;AACX,UAAO,OAAO,UAAW;;EAG3B,OAAO,OAAO;EACd,WAAW,OAAO;EAElB;EACA;EAEA,IAAI,YAAkD;AACpD,OACE,OAAO,UAAU,QACjB,mBAAmB,OAAO,UAC1B,MAAM,QAAQ,OAAO,OAAO,gBAC5B;IACA,MAAM,kBAAkB,OAAO,OAAO;AACtC,QAAI,gBAAgB,WAAW,EAAG,QAAO,EAAE,MAAM;AACjD,QAAI,gBAAgB,WAAW,EAAG,QAAO,gBAAgB;AAGzD,WAAO;;AAGT,UAAO;;EAGT,IAAI,WAAW;AACb,OAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,UAAO,YAAY,OAAO"}
|
|
1
|
+
{"version":3,"file":"stream.custom.cjs","names":["BytesLineDecoder","SSEDecoder","IterableReadableStream","MessageTupleManager","StreamManager","useControllableThreadId","getToolCallsWithResults"],"sources":["../../src/react/stream.custom.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetToolCallsType,\n RunCallbackMeta,\n GetConfigurableType,\n UseStreamTransport,\n UseStreamCustomOptions,\n CustomSubmitOptions,\n} from \"../ui/types.js\";\nimport type { UseStreamCustom } from \"./types.js\";\nimport { type Message } from \"../types.messages.js\";\nimport { getToolCallsWithResults } from \"../utils/tools.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { Interrupt } from \"../schema.js\";\nimport { BytesLineDecoder, SSEDecoder } from \"../utils/sse.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { useControllableThreadId } from \"./thread.js\";\nimport { Command } from \"../types.js\";\nimport type { BagTemplate } from \"../types.template.js\";\n\ninterface FetchStreamTransportOptions {\n /**\n * The URL of the API to use.\n */\n apiUrl: string;\n\n /**\n * Default headers to send with requests.\n */\n defaultHeaders?: HeadersInit;\n\n /**\n * Specify a custom fetch implementation.\n */\n fetch?: typeof fetch | ((...args: any[]) => any); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n /**\n * Callback that is called before the request is made.\n */\n onRequest?: (\n url: string,\n init: RequestInit\n ) => Promise<RequestInit> | RequestInit;\n}\n\nexport class FetchStreamTransport<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate\n> implements UseStreamTransport<StateType, Bag>\n{\n constructor(private readonly options: FetchStreamTransportOptions) {}\n\n async stream(payload: {\n input: GetUpdateType<Bag, StateType> | null | undefined;\n context: GetConfigurableType<Bag> | undefined;\n command: Command | undefined;\n signal: AbortSignal;\n }): Promise<AsyncGenerator<{ id?: string; event: string; data: unknown }>> {\n const { signal, ...body } = payload;\n\n let requestInit: RequestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.options.defaultHeaders,\n },\n body: JSON.stringify(body),\n signal,\n };\n\n if (this.options.onRequest) {\n requestInit = await this.options.onRequest(\n this.options.apiUrl,\n requestInit\n );\n }\n const fetchFn = this.options.fetch ?? fetch;\n\n const response = await fetchFn(this.options.apiUrl, requestInit);\n if (!response.ok) {\n throw new Error(`Failed to stream: ${response.statusText}`);\n }\n\n const stream = (\n response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })\n )\n .pipeThrough(BytesLineDecoder())\n .pipeThrough(SSEDecoder());\n\n return IterableReadableStream.fromReadableStream(stream);\n }\n}\n\nexport function useStreamCustom<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate\n>(\n options: UseStreamCustomOptions<StateType, Bag>\n): UseStreamCustom<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n type ToolCallType = GetToolCallsType<StateType>;\n\n const [messageManager] = useState(() => new MessageTupleManager());\n const [stream] = useState(\n () =>\n new StreamManager<StateType, Bag>(messageManager, {\n throttle: options.throttle ?? false,\n })\n );\n\n useSyncExternalStore(\n stream.subscribe,\n stream.getSnapshot,\n stream.getSnapshot\n );\n\n const [threadId, onThreadId] = useControllableThreadId(options);\n const threadIdRef = useRef<string | null>(threadId);\n\n // Cancel the stream if thread ID has changed\n useEffect(() => {\n if (threadIdRef.current !== threadId) {\n threadIdRef.current = threadId;\n stream.clear();\n }\n }, [threadId, stream]);\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey])\n ? (value[messagesKey] as Message[])\n : [];\n };\n\n const setMessages = (current: StateType, messages: Message[]): StateType => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return { ...current, [messagesKey]: messages };\n };\n\n const historyValues = options.initialValues ?? ({} as StateType);\n\n const stop = () => stream.stop(historyValues, { onStop: options.onStop });\n\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: CustomSubmitOptions<StateType, ConfigurableType>\n ) => {\n let callbackMeta: RunCallbackMeta | undefined;\n let usableThreadId = threadId;\n\n stream.setStreamValues(() => {\n if (submitOptions?.optimisticValues != null) {\n return {\n ...historyValues,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(historyValues)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...historyValues };\n });\n\n await stream.start(\n async (signal: AbortSignal) => {\n if (!usableThreadId) {\n // generate random thread id\n usableThreadId = crypto.randomUUID();\n threadIdRef.current = usableThreadId;\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n return options.transport.stream({\n input: values,\n context: submitOptions?.context,\n command: submitOptions?.command,\n signal,\n config: {\n ...submitOptions?.config,\n configurable: {\n thread_id: usableThreadId,\n ...submitOptions?.config?.configurable,\n } as unknown as GetConfigurableType<Bag>,\n },\n }) as Promise<\n AsyncGenerator<EventStreamEvent<StateType, UpdateType, CustomType>>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: {} as StateType,\n callbacks: options,\n\n onSuccess: () => undefined,\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n }\n );\n };\n\n return {\n get values() {\n return stream.values ?? ({} as StateType);\n },\n\n error: stream.error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n get interrupt(): Interrupt<InterruptType> | undefined {\n if (\n stream.values != null &&\n \"__interrupt__\" in stream.values &&\n Array.isArray(stream.values.__interrupt__)\n ) {\n const valueInterrupts = stream.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 as Interrupt<InterruptType>;\n }\n\n return undefined;\n },\n\n get messages(): Message<ToolCallType>[] {\n if (!stream.values) return [];\n return getMessages(stream.values);\n },\n\n get toolCalls() {\n if (!stream.values) return [];\n const msgs = getMessages(stream.values);\n return getToolCallsWithResults<ToolCallType>(msgs);\n },\n\n getToolCalls(message) {\n if (!stream.values) return [];\n const msgs = getMessages(stream.values);\n const allToolCalls = getToolCallsWithResults<ToolCallType>(msgs);\n return allToolCalls.filter((tc) => tc.aiMessage.id === message.id);\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "../types.cjs";
|
|
2
|
-
import { BagTemplate
|
|
2
|
+
import { BagTemplate } from "../types.template.cjs";
|
|
3
|
+
import { GetConfigurableType, GetUpdateType, UseStreamTransport } from "../ui/types.cjs";
|
|
3
4
|
|
|
4
5
|
//#region src/react/stream.custom.d.ts
|
|
5
6
|
interface FetchStreamTransportOptions {
|
|
@@ -14,7 +15,7 @@ interface FetchStreamTransportOptions {
|
|
|
14
15
|
/**
|
|
15
16
|
* Specify a custom fetch implementation.
|
|
16
17
|
*/
|
|
17
|
-
fetch?: typeof fetch | ((...args: any[]) => any);
|
|
18
|
+
fetch?: typeof fetch | ((...args: any[]) => any);
|
|
18
19
|
/**
|
|
19
20
|
* Callback that is called before the request is made.
|
|
20
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.custom.d.cts","names":["
|
|
1
|
+
{"version":3,"file":"stream.custom.d.cts","names":["GetUpdateType","GetConfigurableType","UseStreamTransport","UseStreamCustomOptions","UseStreamCustom","Command","BagTemplate","FetchStreamTransportOptions","HeadersInit","fetch","RequestInit","Promise","FetchStreamTransport","Record","StateType","Bag","AbortSignal","AsyncGenerator","useStreamCustom"],"sources":["../../src/react/stream.custom.d.ts"],"sourcesContent":["import type { GetUpdateType, GetConfigurableType, UseStreamTransport, UseStreamCustomOptions } from \"../ui/types.js\";\nimport type { UseStreamCustom } from \"./types.js\";\nimport { Command } from \"../types.js\";\nimport type { BagTemplate } from \"../types.template.js\";\ninterface FetchStreamTransportOptions {\n /**\n * The URL of the API to use.\n */\n apiUrl: string;\n /**\n * Default headers to send with requests.\n */\n defaultHeaders?: HeadersInit;\n /**\n * Specify a custom fetch implementation.\n */\n fetch?: typeof fetch | ((...args: any[]) => any);\n /**\n * Callback that is called before the request is made.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<RequestInit> | RequestInit;\n}\nexport declare class FetchStreamTransport<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> implements UseStreamTransport<StateType, Bag> {\n private readonly options;\n constructor(options: FetchStreamTransportOptions);\n stream(payload: {\n input: GetUpdateType<Bag, StateType> | null | undefined;\n context: GetConfigurableType<Bag> | undefined;\n command: Command | undefined;\n signal: AbortSignal;\n }): Promise<AsyncGenerator<{\n id?: string;\n event: string;\n data: unknown;\n }>>;\n}\nexport declare function useStreamCustom<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: UseStreamCustomOptions<StateType, Bag>): UseStreamCustom<StateType, Bag>;\nexport {};\n"],"mappings":";;;;;UAIUO,2BAAAA;EAAAA;;;QAYSE,EAAAA,MAAAA;;;;gBAIwDC,CAAAA,EARtDF,WAQsDE;EAAW;AAEtF;;OAA4DG,CAAAA,EAAAA,OANzCJ,KAMyCI,GAAAA,CAAAA,CAAAA,GAAAA,IAAAA,EAAAA,GAAAA,EAAAA,EAAAA,GAAAA,GAAAA,CAAAA;;;;WAAwHC,CAAAA,EAAAA,CAAAA,GAAAA,EAAAA,MAAAA,EAAAA,IAAAA,EAFhJJ,WAEgJI,EAAAA,GAFhIH,OAEgIG,CAFxHJ,WAEwHI,CAAAA,GAFzGJ,WAEyGI;;AAE3JP,cAFJK,oBAEIL,CAAAA,kBAFmCM,MAEnCN,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAF6DM,MAE7DN,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,EAAAA,YAFkGD,WAElGC,GAFgHD,WAEhHC,CAAAA,YAFwIL,kBAExIK,CAF2JO,SAE3JP,EAFsKQ,GAEtKR,CAAAA,CAAAA;mBAEIQ,OAAAA;aAAKD,CAAAA,OAAAA,EAFTP,2BAESO;QAAnBd,CAAAA,OAAAA,EAAAA;IACsBe,KAAAA,EADtBf,aACsBe,CADRA,GACQA,EADHD,SACGC,CAAAA,GAAAA,IAAAA,GAAAA,SAAAA;IAApBd,OAAAA,EAAAA,mBAAAA,CAAoBc,GAApBd,CAAAA,GAAAA,SAAAA;IACAI,OAAAA,EAAAA,OAAAA,GAAAA,SAAAA;IACDW,MAAAA,EAAAA,WAAAA;MACRL,OAAQM,CAAAA,cAAAA,CAAAA;IAARN,EAAAA,CAAAA,EAAAA,MAAAA;IARyJT,KAAAA,EAAAA,MAAAA;IAAkB,IAAA,EAAA,OAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "../types.js";
|
|
2
|
-
import { BagTemplate
|
|
2
|
+
import { BagTemplate } from "../types.template.js";
|
|
3
|
+
import { GetConfigurableType, GetUpdateType, UseStreamTransport } from "../ui/types.js";
|
|
3
4
|
|
|
4
5
|
//#region src/react/stream.custom.d.ts
|
|
5
6
|
interface FetchStreamTransportOptions {
|
|
@@ -14,7 +15,7 @@ interface FetchStreamTransportOptions {
|
|
|
14
15
|
/**
|
|
15
16
|
* Specify a custom fetch implementation.
|
|
16
17
|
*/
|
|
17
|
-
fetch?: typeof fetch | ((...args: any[]) => any);
|
|
18
|
+
fetch?: typeof fetch | ((...args: any[]) => any);
|
|
18
19
|
/**
|
|
19
20
|
* Callback that is called before the request is made.
|
|
20
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.custom.d.ts","names":["
|
|
1
|
+
{"version":3,"file":"stream.custom.d.ts","names":["GetUpdateType","GetConfigurableType","UseStreamTransport","UseStreamCustomOptions","UseStreamCustom","Command","BagTemplate","FetchStreamTransportOptions","HeadersInit","fetch","RequestInit","Promise","FetchStreamTransport","Record","StateType","Bag","AbortSignal","AsyncGenerator","useStreamCustom"],"sources":["../../src/react/stream.custom.d.ts"],"sourcesContent":["import type { GetUpdateType, GetConfigurableType, UseStreamTransport, UseStreamCustomOptions } from \"../ui/types.js\";\nimport type { UseStreamCustom } from \"./types.js\";\nimport { Command } from \"../types.js\";\nimport type { BagTemplate } from \"../types.template.js\";\ninterface FetchStreamTransportOptions {\n /**\n * The URL of the API to use.\n */\n apiUrl: string;\n /**\n * Default headers to send with requests.\n */\n defaultHeaders?: HeadersInit;\n /**\n * Specify a custom fetch implementation.\n */\n fetch?: typeof fetch | ((...args: any[]) => any);\n /**\n * Callback that is called before the request is made.\n */\n onRequest?: (url: string, init: RequestInit) => Promise<RequestInit> | RequestInit;\n}\nexport declare class FetchStreamTransport<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate> implements UseStreamTransport<StateType, Bag> {\n private readonly options;\n constructor(options: FetchStreamTransportOptions);\n stream(payload: {\n input: GetUpdateType<Bag, StateType> | null | undefined;\n context: GetConfigurableType<Bag> | undefined;\n command: Command | undefined;\n signal: AbortSignal;\n }): Promise<AsyncGenerator<{\n id?: string;\n event: string;\n data: unknown;\n }>>;\n}\nexport declare function useStreamCustom<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: UseStreamCustomOptions<StateType, Bag>): UseStreamCustom<StateType, Bag>;\nexport {};\n"],"mappings":";;;;;UAIUO,2BAAAA;EAAAA;;;QAYSE,EAAAA,MAAAA;;;;gBAIwDC,CAAAA,EARtDF,WAQsDE;EAAW;AAEtF;;OAA4DG,CAAAA,EAAAA,OANzCJ,KAMyCI,GAAAA,CAAAA,CAAAA,GAAAA,IAAAA,EAAAA,GAAAA,EAAAA,EAAAA,GAAAA,GAAAA,CAAAA;;;;WAAwHC,CAAAA,EAAAA,CAAAA,GAAAA,EAAAA,MAAAA,EAAAA,IAAAA,EAFhJJ,WAEgJI,EAAAA,GAFhIH,OAEgIG,CAFxHJ,WAEwHI,CAAAA,GAFzGJ,WAEyGI;;AAE3JP,cAFJK,oBAEIL,CAAAA,kBAFmCM,MAEnCN,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAF6DM,MAE7DN,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,EAAAA,YAFkGD,WAElGC,GAFgHD,WAEhHC,CAAAA,YAFwIL,kBAExIK,CAF2JO,SAE3JP,EAFsKQ,GAEtKR,CAAAA,CAAAA;mBAEIQ,OAAAA;aAAKD,CAAAA,OAAAA,EAFTP,2BAESO;QAAnBd,CAAAA,OAAAA,EAAAA;IACsBe,KAAAA,EADtBf,aACsBe,CADRA,GACQA,EADHD,SACGC,CAAAA,GAAAA,IAAAA,GAAAA,SAAAA;IAApBd,OAAAA,EAAAA,mBAAAA,CAAoBc,GAApBd,CAAAA,GAAAA,SAAAA;IACAI,OAAAA,EAAAA,OAAAA,GAAAA,SAAAA;IACDW,MAAAA,EAAAA,WAAAA;MACRL,OAAQM,CAAAA,cAAAA,CAAAA;IAARN,EAAAA,CAAAA,EAAAA,MAAAA;IARyJT,KAAAA,EAAAA,MAAAA;IAAkB,IAAA,EAAA,OAAA"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
import { BytesLineDecoder, SSEDecoder } from "../utils/sse.js";
|
|
5
4
|
import { IterableReadableStream } from "../utils/stream.js";
|
|
6
5
|
import { MessageTupleManager } from "../ui/messages.js";
|
|
7
6
|
import { StreamManager } from "../ui/manager.js";
|
|
7
|
+
import { getToolCallsWithResults } from "../utils/tools.js";
|
|
8
8
|
import { useControllableThreadId } from "./thread.js";
|
|
9
9
|
import { useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ var FetchStreamTransport = class {
|
|
|
14
14
|
this.options = options;
|
|
15
15
|
}
|
|
16
16
|
async stream(payload) {
|
|
17
|
-
const { signal
|
|
17
|
+
const { signal, ...body } = payload;
|
|
18
18
|
let requestInit = {
|
|
19
19
|
method: "POST",
|
|
20
20
|
headers: {
|
|
@@ -25,8 +25,7 @@ var FetchStreamTransport = class {
|
|
|
25
25
|
signal
|
|
26
26
|
};
|
|
27
27
|
if (this.options.onRequest) requestInit = await this.options.onRequest(this.options.apiUrl, requestInit);
|
|
28
|
-
const
|
|
29
|
-
const response = await fetchFn(this.options.apiUrl, requestInit);
|
|
28
|
+
const response = await (this.options.fetch ?? fetch)(this.options.apiUrl, requestInit);
|
|
30
29
|
if (!response.ok) throw new Error(`Failed to stream: ${response.statusText}`);
|
|
31
30
|
const stream = (response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })).pipeThrough(BytesLineDecoder()).pipeThrough(SSEDecoder());
|
|
32
31
|
return IterableReadableStream.fromReadableStream(stream);
|
|
@@ -113,11 +112,18 @@ function useStreamCustom(options) {
|
|
|
113
112
|
if (valueInterrupts.length === 1) return valueInterrupts[0];
|
|
114
113
|
return valueInterrupts;
|
|
115
114
|
}
|
|
116
|
-
return void 0;
|
|
117
115
|
},
|
|
118
116
|
get messages() {
|
|
119
117
|
if (!stream.values) return [];
|
|
120
118
|
return getMessages(stream.values);
|
|
119
|
+
},
|
|
120
|
+
get toolCalls() {
|
|
121
|
+
if (!stream.values) return [];
|
|
122
|
+
return getToolCallsWithResults(getMessages(stream.values));
|
|
123
|
+
},
|
|
124
|
+
getToolCalls(message) {
|
|
125
|
+
if (!stream.values) return [];
|
|
126
|
+
return getToolCallsWithResults(getMessages(stream.values)).filter((tc) => tc.aiMessage.id === message.id);
|
|
121
127
|
}
|
|
122
128
|
};
|
|
123
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.custom.js","names":["options: FetchStreamTransportOptions","requestInit: RequestInit","callbackMeta: RunCallbackMeta | undefined"],"sources":["../../src/react/stream.custom.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n BagTemplate,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n RunCallbackMeta,\n GetConfigurableType,\n UseStreamCustomOptions,\n UseStreamCustom,\n UseStreamTransport,\n CustomSubmitOptions,\n} from \"./types.js\";\nimport type { Message } from \"../types.messages.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { Interrupt } from \"../schema.js\";\nimport { BytesLineDecoder, SSEDecoder } from \"../utils/sse.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { useControllableThreadId } from \"./thread.js\";\nimport { Command } from \"../types.js\";\n\ninterface FetchStreamTransportOptions {\n /**\n * The URL of the API to use.\n */\n apiUrl: string;\n\n /**\n * Default headers to send with requests.\n */\n defaultHeaders?: HeadersInit;\n\n /**\n * Specify a custom fetch implementation.\n */\n fetch?: typeof fetch | ((...args: any[]) => any); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n /**\n * Callback that is called before the request is made.\n */\n onRequest?: (\n url: string,\n init: RequestInit\n ) => Promise<RequestInit> | RequestInit;\n}\n\nexport class FetchStreamTransport<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate\n> implements UseStreamTransport<StateType, Bag>\n{\n constructor(private readonly options: FetchStreamTransportOptions) {}\n\n async stream(payload: {\n input: GetUpdateType<Bag, StateType> | null | undefined;\n context: GetConfigurableType<Bag> | undefined;\n command: Command | undefined;\n signal: AbortSignal;\n }): Promise<AsyncGenerator<{ id?: string; event: string; data: unknown }>> {\n const { signal, ...body } = payload;\n\n let requestInit: RequestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.options.defaultHeaders,\n },\n body: JSON.stringify(body),\n signal,\n };\n\n if (this.options.onRequest) {\n requestInit = await this.options.onRequest(\n this.options.apiUrl,\n requestInit\n );\n }\n const fetchFn = this.options.fetch ?? fetch;\n\n const response = await fetchFn(this.options.apiUrl, requestInit);\n if (!response.ok) {\n throw new Error(`Failed to stream: ${response.statusText}`);\n }\n\n const stream = (\n response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })\n )\n .pipeThrough(BytesLineDecoder())\n .pipeThrough(SSEDecoder());\n\n return IterableReadableStream.fromReadableStream(stream);\n }\n}\n\nexport function useStreamCustom<\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>(\n options: UseStreamCustomOptions<StateType, Bag>\n): UseStreamCustom<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n\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 threadIdRef = useRef<string | null>(threadId);\n\n // Cancel the stream if thread ID has changed\n useEffect(() => {\n if (threadIdRef.current !== threadId) {\n threadIdRef.current = threadId;\n stream.clear();\n }\n }, [threadId, stream]);\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey]) ? 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 historyValues = options.initialValues ?? ({} as StateType);\n\n const stop = () => stream.stop(historyValues, { onStop: options.onStop });\n\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: CustomSubmitOptions<StateType, ConfigurableType>\n ) => {\n let callbackMeta: RunCallbackMeta | undefined;\n let usableThreadId = threadId;\n\n stream.setStreamValues(() => {\n if (submitOptions?.optimisticValues != null) {\n return {\n ...historyValues,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(historyValues)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...historyValues };\n });\n\n await stream.start(\n async (signal: AbortSignal) => {\n if (!usableThreadId) {\n // generate random thread id\n usableThreadId = crypto.randomUUID();\n threadIdRef.current = usableThreadId;\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n return options.transport.stream({\n input: values,\n context: submitOptions?.context,\n command: submitOptions?.command,\n signal,\n config: {\n ...submitOptions?.config,\n configurable: {\n thread_id: usableThreadId,\n ...submitOptions?.config?.configurable,\n } as unknown as GetConfigurableType<Bag>,\n },\n }) as Promise<\n AsyncGenerator<EventStreamEvent<StateType, UpdateType, CustomType>>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: {} as StateType,\n callbacks: options,\n\n onSuccess: () => undefined,\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n }\n );\n };\n\n return {\n get values() {\n return stream.values ?? ({} as StateType);\n },\n\n error: stream.error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n get interrupt(): Interrupt<InterruptType> | undefined {\n if (\n stream.values != null &&\n \"__interrupt__\" in stream.values &&\n Array.isArray(stream.values.__interrupt__)\n ) {\n const valueInterrupts = stream.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 as Interrupt<InterruptType>;\n }\n\n return undefined;\n },\n\n get messages() {\n if (!stream.values) return [];\n return getMessages(stream.values);\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream.custom.js","names":[],"sources":["../../src/react/stream.custom.tsx"],"sourcesContent":["/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */\n\n\"use client\";\n\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { EventStreamEvent, StreamManager } from \"../ui/manager.js\";\nimport type {\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetToolCallsType,\n RunCallbackMeta,\n GetConfigurableType,\n UseStreamTransport,\n UseStreamCustomOptions,\n CustomSubmitOptions,\n} from \"../ui/types.js\";\nimport type { UseStreamCustom } from \"./types.js\";\nimport { type Message } from \"../types.messages.js\";\nimport { getToolCallsWithResults } from \"../utils/tools.js\";\nimport { MessageTupleManager } from \"../ui/messages.js\";\nimport { Interrupt } from \"../schema.js\";\nimport { BytesLineDecoder, SSEDecoder } from \"../utils/sse.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { useControllableThreadId } from \"./thread.js\";\nimport { Command } from \"../types.js\";\nimport type { BagTemplate } from \"../types.template.js\";\n\ninterface FetchStreamTransportOptions {\n /**\n * The URL of the API to use.\n */\n apiUrl: string;\n\n /**\n * Default headers to send with requests.\n */\n defaultHeaders?: HeadersInit;\n\n /**\n * Specify a custom fetch implementation.\n */\n fetch?: typeof fetch | ((...args: any[]) => any); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n /**\n * Callback that is called before the request is made.\n */\n onRequest?: (\n url: string,\n init: RequestInit\n ) => Promise<RequestInit> | RequestInit;\n}\n\nexport class FetchStreamTransport<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate\n> implements UseStreamTransport<StateType, Bag>\n{\n constructor(private readonly options: FetchStreamTransportOptions) {}\n\n async stream(payload: {\n input: GetUpdateType<Bag, StateType> | null | undefined;\n context: GetConfigurableType<Bag> | undefined;\n command: Command | undefined;\n signal: AbortSignal;\n }): Promise<AsyncGenerator<{ id?: string; event: string; data: unknown }>> {\n const { signal, ...body } = payload;\n\n let requestInit: RequestInit = {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.options.defaultHeaders,\n },\n body: JSON.stringify(body),\n signal,\n };\n\n if (this.options.onRequest) {\n requestInit = await this.options.onRequest(\n this.options.apiUrl,\n requestInit\n );\n }\n const fetchFn = this.options.fetch ?? fetch;\n\n const response = await fetchFn(this.options.apiUrl, requestInit);\n if (!response.ok) {\n throw new Error(`Failed to stream: ${response.statusText}`);\n }\n\n const stream = (\n response.body || new ReadableStream({ start: (ctrl) => ctrl.close() })\n )\n .pipeThrough(BytesLineDecoder())\n .pipeThrough(SSEDecoder());\n\n return IterableReadableStream.fromReadableStream(stream);\n }\n}\n\nexport function useStreamCustom<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate\n>(\n options: UseStreamCustomOptions<StateType, Bag>\n): UseStreamCustom<StateType, Bag> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n type InterruptType = GetInterruptType<Bag>;\n type ConfigurableType = GetConfigurableType<Bag>;\n type ToolCallType = GetToolCallsType<StateType>;\n\n const [messageManager] = useState(() => new MessageTupleManager());\n const [stream] = useState(\n () =>\n new StreamManager<StateType, Bag>(messageManager, {\n throttle: options.throttle ?? false,\n })\n );\n\n useSyncExternalStore(\n stream.subscribe,\n stream.getSnapshot,\n stream.getSnapshot\n );\n\n const [threadId, onThreadId] = useControllableThreadId(options);\n const threadIdRef = useRef<string | null>(threadId);\n\n // Cancel the stream if thread ID has changed\n useEffect(() => {\n if (threadIdRef.current !== threadId) {\n threadIdRef.current = threadId;\n stream.clear();\n }\n }, [threadId, stream]);\n\n const getMessages = (value: StateType): Message[] => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return Array.isArray(value[messagesKey])\n ? (value[messagesKey] as Message[])\n : [];\n };\n\n const setMessages = (current: StateType, messages: Message[]): StateType => {\n const messagesKey = options.messagesKey ?? \"messages\";\n return { ...current, [messagesKey]: messages };\n };\n\n const historyValues = options.initialValues ?? ({} as StateType);\n\n const stop = () => stream.stop(historyValues, { onStop: options.onStop });\n\n const submit = async (\n values: UpdateType | null | undefined,\n submitOptions?: CustomSubmitOptions<StateType, ConfigurableType>\n ) => {\n let callbackMeta: RunCallbackMeta | undefined;\n let usableThreadId = threadId;\n\n stream.setStreamValues(() => {\n if (submitOptions?.optimisticValues != null) {\n return {\n ...historyValues,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(historyValues)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...historyValues };\n });\n\n await stream.start(\n async (signal: AbortSignal) => {\n if (!usableThreadId) {\n // generate random thread id\n usableThreadId = crypto.randomUUID();\n threadIdRef.current = usableThreadId;\n onThreadId(usableThreadId);\n }\n\n if (!usableThreadId) {\n throw new Error(\"Failed to obtain valid thread ID.\");\n }\n\n return options.transport.stream({\n input: values,\n context: submitOptions?.context,\n command: submitOptions?.command,\n signal,\n config: {\n ...submitOptions?.config,\n configurable: {\n thread_id: usableThreadId,\n ...submitOptions?.config?.configurable,\n } as unknown as GetConfigurableType<Bag>,\n },\n }) as Promise<\n AsyncGenerator<EventStreamEvent<StateType, UpdateType, CustomType>>\n >;\n },\n {\n getMessages,\n setMessages,\n\n initialValues: {} as StateType,\n callbacks: options,\n\n onSuccess: () => undefined,\n onError(error) {\n options.onError?.(error, callbackMeta);\n },\n }\n );\n };\n\n return {\n get values() {\n return stream.values ?? ({} as StateType);\n },\n\n error: stream.error,\n isLoading: stream.isLoading,\n\n stop,\n submit,\n\n get interrupt(): Interrupt<InterruptType> | undefined {\n if (\n stream.values != null &&\n \"__interrupt__\" in stream.values &&\n Array.isArray(stream.values.__interrupt__)\n ) {\n const valueInterrupts = stream.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 as Interrupt<InterruptType>;\n }\n\n return undefined;\n },\n\n get messages(): Message<ToolCallType>[] {\n if (!stream.values) return [];\n return getMessages(stream.values);\n },\n\n get toolCalls() {\n if (!stream.values) return [];\n const msgs = getMessages(stream.values);\n return getToolCallsWithResults<ToolCallType>(msgs);\n },\n\n getToolCalls(message) {\n if (!stream.values) return [];\n const msgs = getMessages(stream.values);\n const allToolCalls = getToolCallsWithResults<ToolCallType>(msgs);\n return allToolCalls.filter((tc) => tc.aiMessage.id === message.id);\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/react/stream.d.cts
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Message } from "../types.messages.cjs";
|
|
2
|
+
import { BagTemplate } from "../types.template.cjs";
|
|
3
|
+
import { InferAgentToolCalls, UseStreamCustomOptions, UseStreamOptions } from "../ui/types.cjs";
|
|
4
|
+
import { UseStream, UseStreamCustom } from "./types.cjs";
|
|
2
5
|
|
|
3
6
|
//#region src/react/stream.d.ts
|
|
4
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Helper type that infers StateType based on whether T is an agent-like type, a CompiledGraph/Pregel instance, or a state type.
|
|
10
|
+
* - If T has `~agentTypes`, returns a state with typed messages based on the agent's tools
|
|
11
|
+
* - If T has `~RunOutput` (CompiledGraph/CompiledStateGraph), returns the state type
|
|
12
|
+
* - If T has `~OutputType` (Pregel), returns the output type as state
|
|
13
|
+
* - Otherwise, returns T (direct state type)
|
|
14
|
+
*/
|
|
15
|
+
type InferStateType<T> = T extends {
|
|
16
|
+
"~agentTypes": unknown;
|
|
17
|
+
} ? {
|
|
18
|
+
messages: Message<InferAgentToolCalls<T>>[];
|
|
19
|
+
} : T extends {
|
|
20
|
+
"~RunOutput": infer S;
|
|
21
|
+
} ? S extends Record<string, unknown> ? S : Record<string, unknown> : T extends {
|
|
22
|
+
"~OutputType": infer O;
|
|
23
|
+
} ? O extends Record<string, unknown> ? O : Record<string, unknown> : T extends Record<string, unknown> ? T : Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Helper type that infers Bag based on whether T is an agent-like type.
|
|
26
|
+
* - If T has `~agentTypes`, extracts bag from the agent's tools
|
|
27
|
+
* - Otherwise, returns the default BagTemplate
|
|
28
|
+
*/
|
|
29
|
+
type InferBag<T, B extends BagTemplate = BagTemplate> = T extends {
|
|
30
|
+
"~agentTypes": unknown;
|
|
31
|
+
} ? BagTemplate : B;
|
|
5
32
|
/**
|
|
6
33
|
* A React hook that provides seamless integration with LangGraph streaming capabilities.
|
|
7
34
|
*
|
|
@@ -9,29 +36,94 @@ import { BagTemplate, UseStream, UseStreamCustom, UseStreamCustomOptions, UseStr
|
|
|
9
36
|
* letting you focus on building great chat experiences. It provides automatic state management for
|
|
10
37
|
* messages, interrupts, loading states, and errors.
|
|
11
38
|
*
|
|
12
|
-
*
|
|
13
|
-
* @template Bag Type configuration bag containing:
|
|
14
|
-
* - `ConfigurableType`: Type for the `config.configurable` property
|
|
15
|
-
* - `InterruptType`: Type for interrupt values
|
|
16
|
-
* - `CustomEventType`: Type for custom events
|
|
17
|
-
* - `UpdateType`: Type for the submit function updates
|
|
39
|
+
* ## Usage with ReactAgent (recommended for createAgent users)
|
|
18
40
|
*
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
declare function useStream<StateType extends Record<string, unknown> = Record<string, unknown>, Bag extends {
|
|
22
|
-
ConfigurableType?: Record<string, unknown>;
|
|
23
|
-
InterruptType?: unknown;
|
|
24
|
-
CustomEventType?: unknown;
|
|
25
|
-
UpdateType?: unknown;
|
|
26
|
-
} = BagTemplate>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag>;
|
|
27
|
-
/**
|
|
28
|
-
* A React hook that provides seamless integration with LangGraph streaming capabilities.
|
|
41
|
+
* When using `createAgent` from `@langchain/langgraph`, you can pass `typeof agent` as the
|
|
42
|
+
* type parameter to automatically infer tool call types:
|
|
29
43
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* // In your agent file (e.g., agent.ts)
|
|
47
|
+
* import { createAgent, tool } from "@langchain/langgraph";
|
|
48
|
+
* import { z } from "zod";
|
|
49
|
+
*
|
|
50
|
+
* const getWeather = tool(
|
|
51
|
+
* async ({ location }) => `Weather in ${location}`,
|
|
52
|
+
* { name: "get_weather", schema: z.object({ location: z.string() }) }
|
|
53
|
+
* );
|
|
54
|
+
*
|
|
55
|
+
* export const agent = createAgent({
|
|
56
|
+
* model: "openai:gpt-4o",
|
|
57
|
+
* tools: [getWeather],
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* // In your React component
|
|
61
|
+
* import { agent } from "./agent";
|
|
62
|
+
*
|
|
63
|
+
* function Chat() {
|
|
64
|
+
* // Tool calls are automatically typed from the agent's tools!
|
|
65
|
+
* const stream = useStream<typeof agent>({
|
|
66
|
+
* assistantId: "agent",
|
|
67
|
+
* apiUrl: "http://localhost:2024",
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // stream.toolCalls[0].call.name is typed as "get_weather"
|
|
71
|
+
* // stream.toolCalls[0].call.args is typed as { location: string }
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* ## Usage with StateGraph (for custom LangGraph applications)
|
|
76
|
+
*
|
|
77
|
+
* When building custom graphs with `StateGraph`, embed your tool call types directly
|
|
78
|
+
* in your state's messages property using `Message<MyToolCalls>`:
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { Message } from "@langchain/langgraph-sdk";
|
|
83
|
+
*
|
|
84
|
+
* // Define your tool call types as a discriminated union
|
|
85
|
+
* type MyToolCalls =
|
|
86
|
+
* | { name: "search"; args: { query: string }; id?: string }
|
|
87
|
+
* | { name: "calculate"; args: { expression: string }; id?: string };
|
|
88
|
+
*
|
|
89
|
+
* // Embed tool call types in your state's messages
|
|
90
|
+
* interface MyGraphState {
|
|
91
|
+
* messages: Message<MyToolCalls>[];
|
|
92
|
+
* context?: string;
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
95
|
+
* function Chat() {
|
|
96
|
+
* const stream = useStream<MyGraphState>({
|
|
97
|
+
* assistantId: "my-graph",
|
|
98
|
+
* apiUrl: "http://localhost:2024",
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* // stream.values is typed as MyGraphState
|
|
102
|
+
* // stream.toolCalls[0].call.name is typed as "search" | "calculate"
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* // With additional type configuration (interrupts, configurable)
|
|
109
|
+
* interface MyGraphState {
|
|
110
|
+
* messages: Message<MyToolCalls>[];
|
|
111
|
+
* }
|
|
112
|
+
*
|
|
113
|
+
* function Chat() {
|
|
114
|
+
* const stream = useStream<MyGraphState, {
|
|
115
|
+
* InterruptType: { question: string };
|
|
116
|
+
* ConfigurableType: { userId: string };
|
|
117
|
+
* }>({
|
|
118
|
+
* assistantId: "my-graph",
|
|
119
|
+
* apiUrl: "http://localhost:2024",
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* // stream.interrupt is typed as { question: string } | undefined
|
|
123
|
+
* }
|
|
124
|
+
* ```
|
|
33
125
|
*
|
|
34
|
-
* @template
|
|
126
|
+
* @template T Either a ReactAgent type (with `~agentTypes`) or a state type (`Record<string, unknown>`)
|
|
35
127
|
* @template Bag Type configuration bag containing:
|
|
36
128
|
* - `ConfigurableType`: Type for the `config.configurable` property
|
|
37
129
|
* - `InterruptType`: Type for interrupt values
|
|
@@ -40,12 +132,7 @@ declare function useStream<StateType extends Record<string, unknown> = Record<st
|
|
|
40
132
|
*
|
|
41
133
|
* @see {@link https://docs.langchain.com/langgraph-platform/use-stream-react | LangGraph React Integration Guide}
|
|
42
134
|
*/
|
|
43
|
-
declare function useStream<
|
|
44
|
-
ConfigurableType?: Record<string, unknown>;
|
|
45
|
-
InterruptType?: unknown;
|
|
46
|
-
CustomEventType?: unknown;
|
|
47
|
-
UpdateType?: unknown;
|
|
48
|
-
} = BagTemplate>(options: UseStreamCustomOptions<StateType, Bag>): UseStreamCustom<StateType, Bag>;
|
|
135
|
+
declare function useStream<T = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: UseStreamOptions<InferStateType<T>, InferBag<T, Bag>>): UseStream<InferStateType<T>, InferBag<T, Bag>>;
|
|
49
136
|
/**
|
|
50
137
|
* A React hook that provides seamless integration with LangGraph streaming capabilities.
|
|
51
138
|
*
|
|
@@ -53,7 +140,7 @@ declare function useStream<StateType extends Record<string, unknown> = Record<st
|
|
|
53
140
|
* letting you focus on building great chat experiences. It provides automatic state management for
|
|
54
141
|
* messages, interrupts, loading states, and errors.
|
|
55
142
|
*
|
|
56
|
-
* @template
|
|
143
|
+
* @template T Either a ReactAgent type (with `~agentTypes`) or a state type (`Record<string, unknown>`)
|
|
57
144
|
* @template Bag Type configuration bag containing:
|
|
58
145
|
* - `ConfigurableType`: Type for the `config.configurable` property
|
|
59
146
|
* - `InterruptType`: Type for interrupt values
|
|
@@ -62,12 +149,7 @@ declare function useStream<StateType extends Record<string, unknown> = Record<st
|
|
|
62
149
|
*
|
|
63
150
|
* @see {@link https://docs.langchain.com/langgraph-platform/use-stream-react | LangGraph React Integration Guide}
|
|
64
151
|
*/
|
|
65
|
-
declare function useStream<
|
|
66
|
-
ConfigurableType?: Record<string, unknown>;
|
|
67
|
-
InterruptType?: unknown;
|
|
68
|
-
CustomEventType?: unknown;
|
|
69
|
-
UpdateType?: unknown;
|
|
70
|
-
} = BagTemplate>(options: UseStreamOptions<StateType, Bag>): UseStream<StateType, Bag>;
|
|
152
|
+
declare function useStream<T = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: UseStreamCustomOptions<InferStateType<T>, InferBag<T, Bag>>): UseStreamCustom<InferStateType<T>, InferBag<T, Bag>>;
|
|
71
153
|
//#endregion
|
|
72
154
|
export { useStream };
|
|
73
155
|
//# sourceMappingURL=stream.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.cts","names":["BagTemplate","UseStream","UseStreamCustom","UseStreamCustomOptions","
|
|
1
|
+
{"version":3,"file":"stream.d.cts","names":["UseStreamOptions","InferAgentToolCalls","Message","BagTemplate","UseStream","UseStreamCustom","UseStreamCustomOptions","InferStateType","T","S","Record","O","InferBag","B","useStream","Bag"],"sources":["../../src/react/stream.d.ts"],"sourcesContent":["import type { UseStreamOptions, InferAgentToolCalls } from \"../ui/types.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { BagTemplate } from \"../types.template.js\";\nimport type { UseStream, UseStreamCustom, UseStreamCustomOptions } from \"./types.js\";\n/**\n * Helper type that infers StateType based on whether T is an agent-like type, a CompiledGraph/Pregel instance, or a state type.\n * - If T has `~agentTypes`, returns a state with typed messages based on the agent's tools\n * - If T has `~RunOutput` (CompiledGraph/CompiledStateGraph), returns the state type\n * - If T has `~OutputType` (Pregel), returns the output type as state\n * - Otherwise, returns T (direct state type)\n */\ntype InferStateType<T> = T extends {\n \"~agentTypes\": unknown;\n} ? {\n messages: Message<InferAgentToolCalls<T>>[];\n} : T extends {\n \"~RunOutput\": infer S;\n} ? S extends Record<string, unknown> ? S : Record<string, unknown> : T extends {\n \"~OutputType\": infer O;\n} ? O extends Record<string, unknown> ? O : Record<string, unknown> : T extends Record<string, unknown> ? T : Record<string, unknown>;\n/**\n * Helper type that infers Bag based on whether T is an agent-like type.\n * - If T has `~agentTypes`, extracts bag from the agent's tools\n * - Otherwise, returns the default BagTemplate\n */\ntype InferBag<T, B extends BagTemplate = BagTemplate> = T extends {\n \"~agentTypes\": unknown;\n} ? BagTemplate : B;\n/**\n * A React hook that provides seamless integration with LangGraph streaming capabilities.\n *\n * The `useStream` hook handles all the complexities of streaming, state management, and branching logic,\n * letting you focus on building great chat experiences. It provides automatic state management for\n * messages, interrupts, loading states, and errors.\n *\n * ## Usage with ReactAgent (recommended for createAgent users)\n *\n * When using `createAgent` from `@langchain/langgraph`, you can pass `typeof agent` as the\n * type parameter to automatically infer tool call types:\n *\n * @example\n * ```typescript\n * // In your agent file (e.g., agent.ts)\n * import { createAgent, tool } from \"@langchain/langgraph\";\n * import { z } from \"zod\";\n *\n * const getWeather = tool(\n * async ({ location }) => `Weather in ${location}`,\n * { name: \"get_weather\", schema: z.object({ location: z.string() }) }\n * );\n *\n * export const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [getWeather],\n * });\n *\n * // In your React component\n * import { agent } from \"./agent\";\n *\n * function Chat() {\n * // Tool calls are automatically typed from the agent's tools!\n * const stream = useStream<typeof agent>({\n * assistantId: \"agent\",\n * apiUrl: \"http://localhost:2024\",\n * });\n *\n * // stream.toolCalls[0].call.name is typed as \"get_weather\"\n * // stream.toolCalls[0].call.args is typed as { location: string }\n * }\n * ```\n *\n * ## Usage with StateGraph (for custom LangGraph applications)\n *\n * When building custom graphs with `StateGraph`, embed your tool call types directly\n * in your state's messages property using `Message<MyToolCalls>`:\n *\n * @example\n * ```typescript\n * import { Message } from \"@langchain/langgraph-sdk\";\n *\n * // Define your tool call types as a discriminated union\n * type MyToolCalls =\n * | { name: \"search\"; args: { query: string }; id?: string }\n * | { name: \"calculate\"; args: { expression: string }; id?: string };\n *\n * // Embed tool call types in your state's messages\n * interface MyGraphState {\n * messages: Message<MyToolCalls>[];\n * context?: string;\n * }\n *\n * function Chat() {\n * const stream = useStream<MyGraphState>({\n * assistantId: \"my-graph\",\n * apiUrl: \"http://localhost:2024\",\n * });\n *\n * // stream.values is typed as MyGraphState\n * // stream.toolCalls[0].call.name is typed as \"search\" | \"calculate\"\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With additional type configuration (interrupts, configurable)\n * interface MyGraphState {\n * messages: Message<MyToolCalls>[];\n * }\n *\n * function Chat() {\n * const stream = useStream<MyGraphState, {\n * InterruptType: { question: string };\n * ConfigurableType: { userId: string };\n * }>({\n * assistantId: \"my-graph\",\n * apiUrl: \"http://localhost:2024\",\n * });\n *\n * // stream.interrupt is typed as { question: string } | undefined\n * }\n * ```\n *\n * @template T Either a ReactAgent type (with `~agentTypes`) or a state type (`Record<string, unknown>`)\n * @template Bag Type configuration bag containing:\n * - `ConfigurableType`: Type for the `config.configurable` property\n * - `InterruptType`: Type for interrupt values\n * - `CustomEventType`: Type for custom events\n * - `UpdateType`: Type for the submit function updates\n *\n * @see {@link https://docs.langchain.com/langgraph-platform/use-stream-react | LangGraph React Integration Guide}\n */\nexport declare function useStream<T = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: UseStreamOptions<InferStateType<T>, InferBag<T, Bag>>): UseStream<InferStateType<T>, InferBag<T, Bag>>;\n/**\n * A React hook that provides seamless integration with LangGraph streaming capabilities.\n *\n * The `useStream` hook handles all the complexities of streaming, state management, and branching logic,\n * letting you focus on building great chat experiences. It provides automatic state management for\n * messages, interrupts, loading states, and errors.\n *\n * @template T Either a ReactAgent type (with `~agentTypes`) or a state type (`Record<string, unknown>`)\n * @template Bag Type configuration bag containing:\n * - `ConfigurableType`: Type for the `config.configurable` property\n * - `InterruptType`: Type for interrupt values\n * - `CustomEventType`: Type for custom events\n * - `UpdateType`: Type for the submit function updates\n *\n * @see {@link https://docs.langchain.com/langgraph-platform/use-stream-react | LangGraph React Integration Guide}\n */\nexport declare function useStream<T = Record<string, unknown>, Bag extends BagTemplate = BagTemplate>(options: UseStreamCustomOptions<InferStateType<T>, InferBag<T, Bag>>): UseStreamCustom<InferStateType<T>, InferBag<T, Bag>>;\nexport {};\n"],"mappings":";;;;;;;;;AAGqF;;;;;KAQhFO,cAGSL,CAAAA,CAAAA,CAAAA,GAHWM,CAGXN,SAAAA;eACVM,EAAAA,OAAAA;;UAEUE,EAHAR,OAGAQ,CAHQT,mBAGRS,CAH4BF,CAG5BE,CAAAA,CAAAA,EAAAA;IAFVF,UAEoCC;cAAIC,EAAAA,KAAAA,EAAAA;IAAxCD,UAAUC,MAAwDF,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAA9BC,CAA8BD,GAA1BE,MAA0BF,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAAAA,CAAAA,SAAAA;eAElEG,EAAAA,KAAAA,EAAAA;IAAAA,UAAUD,MAAAA,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAA0BC,CAA1BD,GAA8BA,MAA9BA,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAAwDF,CAAxDE,SAAkEA,MAAlEA,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA,GAA4FF,CAA5FE,GAAgGA,MAAhGA,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA;;;;;;KAMTE,QANyGF,CAAAA,CAAAA,EAAAA,UAMnFP,WANmFO,GAMrEP,WANqEO,CAAAA,GAMtDF,CANsDE,SAAAA;EAAM,aAAA,EAAA,OAAA;AAAA,CAAA,GAQhHP,WAFS,GAEKU,CAFL;;;;;;;;AA0Gb;;;;;;;;;;;;;;;;;;AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAjBwBC,cAAcJ,qCAAqCP,cAAcA,sBAAsBH,iBAAiBO,eAAeC,IAAII,SAASJ,GAAGO,QAAQX,UAAUG,eAAeC,IAAII,SAASJ,GAAGO;;;;;;;;;;;;;;;;;iBAiBxLD,cAAcJ,qCAAqCP,cAAcA,sBAAsBG,uBAAuBC,eAAeC,IAAII,SAASJ,GAAGO,QAAQV,gBAAgBE,eAAeC,IAAII,SAASJ,GAAGO"}
|