@assistant-ui/react-langgraph 0.6.10 → 0.7.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.
@@ -12,6 +12,10 @@ export type LangGraphMessagesEvent<TMessage> = {
12
12
  };
13
13
  export type LangGraphStreamCallback<TMessage> = (messages: TMessage[], config: LangGraphSendMessageConfig & {
14
14
  abortSignal: AbortSignal;
15
+ initialize: () => Promise<{
16
+ remoteId: string;
17
+ externalId: string | undefined;
18
+ }>;
15
19
  }) => Promise<AsyncGenerator<LangGraphMessagesEvent<TMessage>>> | AsyncGenerator<LangGraphMessagesEvent<TMessage>>;
16
20
  export type LangGraphInterruptState = {
17
21
  value?: any;
@@ -1 +1 @@
1
- {"version":3,"file":"useLangGraphMessages.d.ts","sourceRoot":"","sources":["../src/useLangGraphMessages.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EAIT,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,QAAQ,IAAI;IAC7C,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,QAAQ,IAAI,CAC9C,QAAQ,EAAE,QAAQ,EAAE,EACpB,MAAM,EAAE,0BAA0B,GAAG;IAAE,WAAW,EAAE,WAAW,CAAA;CAAE,KAE/D,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC,GACzD,cAAc,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAErD,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;CACf,CAAC;AAuBF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,2CAIpE;IACD,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC;IACzE,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,uBAAuB,CAAC;QACrC,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B,OAAO,CAAC,EAAE,oBAAoB,CAAC;QAC/B,aAAa,CAAC,EAAE,qBAAqB,CAAC;KACvC,CAAC;CACH;;;+BAauB,QAAQ,EAAE,UAAU,0BAA0B;;;;CA8GrE,CAAC"}
1
+ {"version":3,"file":"useLangGraphMessages.d.ts","sourceRoot":"","sources":["../src/useLangGraphMessages.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EAIT,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAGjB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,QAAQ,IAAI;IAC7C,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,QAAQ,IAAI,CAC9C,QAAQ,EAAE,QAAQ,EAAE,EACpB,MAAM,EAAE,0BAA0B,GAAG;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,OAAO,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;KAChC,CAAC,CAAC;CACJ,KAEC,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC,GACzD,cAAc,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAErD,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;CACf,CAAC;AAuBF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,2CAIpE;IACD,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC;IACzE,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,uBAAuB,CAAC;QACrC,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B,OAAO,CAAC,EAAE,oBAAoB,CAAC;QAC/B,aAAa,CAAC,EAAE,qBAAqB,CAAC;KACvC,CAAC;CACH;;;+BAcuB,QAAQ,EAAE,UAAU,0BAA0B;;;;CAiHrE,CAAC"}
@@ -5,6 +5,7 @@ import { LangGraphMessageAccumulator } from "./LangGraphMessageAccumulator.js";
5
5
  import {
6
6
  LangGraphKnownEventTypes
7
7
  } from "./types.js";
8
+ import { useAssistantApi } from "@assistant-ui/react";
8
9
  var DEFAULT_APPEND_MESSAGE = (_, curr) => curr;
9
10
  var isLangChainMessageChunk = (value) => {
10
11
  if (!value || typeof value !== "object") return false;
@@ -23,6 +24,7 @@ var useLangGraphMessages = ({
23
24
  () => eventHandlers ?? {},
24
25
  [eventHandlers]
25
26
  );
27
+ const api = useAssistantApi();
26
28
  const sendMessage = useCallback(
27
29
  async (newMessages, config) => {
28
30
  const newMessagesWithId = newMessages.map(
@@ -37,7 +39,10 @@ var useLangGraphMessages = ({
37
39
  abortControllerRef.current = abortController;
38
40
  const response = await stream(newMessagesWithId, {
39
41
  ...config,
40
- abortSignal: abortController.signal
42
+ abortSignal: abortController.signal,
43
+ initialize: async () => {
44
+ return await api.threadListItem().initialize();
45
+ }
41
46
  });
42
47
  for await (const chunk of response) {
43
48
  switch (chunk.event) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useLangGraphMessages.ts"],"sourcesContent":["import { useState, useCallback, useRef, useMemo } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { LangGraphMessageAccumulator } from \"./LangGraphMessageAccumulator\";\nimport {\n EventType,\n LangChainMessageTupleEvent,\n LangGraphKnownEventTypes,\n LangChainMessageChunk,\n OnCustomEventCallback,\n OnErrorEventCallback,\n OnInfoEventCallback,\n OnMetadataEventCallback,\n} from \"./types\";\n\nexport type LangGraphCommand = {\n resume: string;\n};\n\nexport type LangGraphSendMessageConfig = {\n command?: LangGraphCommand;\n runConfig?: unknown;\n};\n\nexport type LangGraphMessagesEvent<TMessage> = {\n event: EventType;\n data: TMessage[] | any;\n};\n\nexport type LangGraphStreamCallback<TMessage> = (\n messages: TMessage[],\n config: LangGraphSendMessageConfig & { abortSignal: AbortSignal },\n) =>\n | Promise<AsyncGenerator<LangGraphMessagesEvent<TMessage>>>\n | AsyncGenerator<LangGraphMessagesEvent<TMessage>>;\n\nexport type LangGraphInterruptState = {\n value?: any;\n resumable?: boolean;\n when?: string;\n ns?: string[];\n};\n\nconst DEFAULT_APPEND_MESSAGE = <TMessage>(\n _: TMessage | undefined,\n curr: TMessage,\n) => curr;\n\nconst isLangChainMessageChunk = (\n value: unknown,\n): value is LangChainMessageChunk => {\n if (!value || typeof value !== \"object\") return false;\n const chunk = value as any;\n return (\n \"type\" in chunk &&\n chunk.type === \"AIMessageChunk\" &&\n (chunk.content === undefined ||\n typeof chunk.content === \"string\" ||\n Array.isArray(chunk.content)) &&\n (chunk.tool_call_chunks === undefined ||\n Array.isArray(chunk.tool_call_chunks))\n );\n};\n\nexport const useLangGraphMessages = <TMessage extends { id?: string }>({\n stream,\n appendMessage = DEFAULT_APPEND_MESSAGE,\n eventHandlers,\n}: {\n stream: LangGraphStreamCallback<TMessage>;\n appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;\n eventHandlers?: {\n onMetadata?: OnMetadataEventCallback;\n onInfo?: OnInfoEventCallback;\n onError?: OnErrorEventCallback;\n onCustomEvent?: OnCustomEventCallback;\n };\n}) => {\n const [interrupt, setInterrupt] = useState<\n LangGraphInterruptState | undefined\n >();\n const [messages, setMessages] = useState<TMessage[]>([]);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onMetadata, onInfo, onError, onCustomEvent } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const sendMessage = useCallback(\n async (newMessages: TMessage[], config: LangGraphSendMessageConfig) => {\n // ensure all messages have an ID\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n );\n\n const accumulator = new LangGraphMessageAccumulator({\n initialMessages: messages,\n appendMessage,\n });\n setMessages(accumulator.addMessages(newMessagesWithId));\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n });\n\n for await (const chunk of response) {\n switch (chunk.event) {\n case LangGraphKnownEventTypes.MessagesPartial:\n case LangGraphKnownEventTypes.MessagesComplete:\n setMessages(accumulator.addMessages(chunk.data));\n break;\n case LangGraphKnownEventTypes.Updates:\n setInterrupt(chunk.data.__interrupt__?.[0]);\n break;\n case LangGraphKnownEventTypes.Messages: {\n const [messageChunk] = (chunk as LangChainMessageTupleEvent).data;\n if (!isLangChainMessageChunk(messageChunk)) {\n console.warn(\n \"Received invalid message chunk format:\",\n messageChunk,\n );\n break;\n }\n const updatedMessages = accumulator.addMessages([\n messageChunk as unknown as TMessage,\n ]);\n setMessages(updatedMessages);\n break;\n }\n case LangGraphKnownEventTypes.Metadata:\n onMetadata?.(chunk.data);\n break;\n case LangGraphKnownEventTypes.Info:\n onInfo?.(chunk.data);\n break;\n case LangGraphKnownEventTypes.Error: {\n onError?.(chunk.data);\n // Update the last AI message with error status\n // Assumes last AI message is the one the error relates to\n const messages = accumulator.getMessages();\n const lastAiMessage = messages.findLast(\n (m): m is TMessage & { type: string; id: string } =>\n m != null && \"type\" in m && m.type === \"ai\" && m.id != null,\n );\n if (lastAiMessage) {\n const errorMessage = {\n ...lastAiMessage,\n status: {\n type: \"incomplete\" as const,\n reason: \"error\" as const,\n error: chunk.data,\n },\n };\n setMessages(accumulator.addMessages([errorMessage]));\n }\n break;\n }\n default:\n if (onCustomEvent) {\n onCustomEvent(chunk.event, chunk.data);\n } else {\n console.warn(\n \"Unhandled event received:\",\n chunk.event,\n chunk.data,\n );\n }\n break;\n }\n }\n },\n [\n messages,\n appendMessage,\n stream,\n onMetadata,\n onInfo,\n onError,\n onCustomEvent,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, [abortControllerRef]);\n\n return {\n interrupt,\n messages,\n sendMessage,\n cancel,\n setInterrupt,\n setMessages,\n };\n};\n"],"mappings":"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","names":["messages"]}
1
+ {"version":3,"sources":["../src/useLangGraphMessages.ts"],"sourcesContent":["import { useState, useCallback, useRef, useMemo } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { LangGraphMessageAccumulator } from \"./LangGraphMessageAccumulator\";\nimport {\n EventType,\n LangChainMessageTupleEvent,\n LangGraphKnownEventTypes,\n LangChainMessageChunk,\n OnCustomEventCallback,\n OnErrorEventCallback,\n OnInfoEventCallback,\n OnMetadataEventCallback,\n} from \"./types\";\nimport { useAssistantApi } from \"@assistant-ui/react\";\n\nexport type LangGraphCommand = {\n resume: string;\n};\n\nexport type LangGraphSendMessageConfig = {\n command?: LangGraphCommand;\n runConfig?: unknown;\n};\n\nexport type LangGraphMessagesEvent<TMessage> = {\n event: EventType;\n data: TMessage[] | any;\n};\n\nexport type LangGraphStreamCallback<TMessage> = (\n messages: TMessage[],\n config: LangGraphSendMessageConfig & {\n abortSignal: AbortSignal;\n initialize: () => Promise<{\n remoteId: string;\n externalId: string | undefined;\n }>;\n },\n) =>\n | Promise<AsyncGenerator<LangGraphMessagesEvent<TMessage>>>\n | AsyncGenerator<LangGraphMessagesEvent<TMessage>>;\n\nexport type LangGraphInterruptState = {\n value?: any;\n resumable?: boolean;\n when?: string;\n ns?: string[];\n};\n\nconst DEFAULT_APPEND_MESSAGE = <TMessage>(\n _: TMessage | undefined,\n curr: TMessage,\n) => curr;\n\nconst isLangChainMessageChunk = (\n value: unknown,\n): value is LangChainMessageChunk => {\n if (!value || typeof value !== \"object\") return false;\n const chunk = value as any;\n return (\n \"type\" in chunk &&\n chunk.type === \"AIMessageChunk\" &&\n (chunk.content === undefined ||\n typeof chunk.content === \"string\" ||\n Array.isArray(chunk.content)) &&\n (chunk.tool_call_chunks === undefined ||\n Array.isArray(chunk.tool_call_chunks))\n );\n};\n\nexport const useLangGraphMessages = <TMessage extends { id?: string }>({\n stream,\n appendMessage = DEFAULT_APPEND_MESSAGE,\n eventHandlers,\n}: {\n stream: LangGraphStreamCallback<TMessage>;\n appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;\n eventHandlers?: {\n onMetadata?: OnMetadataEventCallback;\n onInfo?: OnInfoEventCallback;\n onError?: OnErrorEventCallback;\n onCustomEvent?: OnCustomEventCallback;\n };\n}) => {\n const [interrupt, setInterrupt] = useState<\n LangGraphInterruptState | undefined\n >();\n const [messages, setMessages] = useState<TMessage[]>([]);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onMetadata, onInfo, onError, onCustomEvent } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const api = useAssistantApi();\n const sendMessage = useCallback(\n async (newMessages: TMessage[], config: LangGraphSendMessageConfig) => {\n // ensure all messages have an ID\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n );\n\n const accumulator = new LangGraphMessageAccumulator({\n initialMessages: messages,\n appendMessage,\n });\n setMessages(accumulator.addMessages(newMessagesWithId));\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n initialize: async () => {\n return await api.threadListItem().initialize();\n },\n });\n\n for await (const chunk of response) {\n switch (chunk.event) {\n case LangGraphKnownEventTypes.MessagesPartial:\n case LangGraphKnownEventTypes.MessagesComplete:\n setMessages(accumulator.addMessages(chunk.data));\n break;\n case LangGraphKnownEventTypes.Updates:\n setInterrupt(chunk.data.__interrupt__?.[0]);\n break;\n case LangGraphKnownEventTypes.Messages: {\n const [messageChunk] = (chunk as LangChainMessageTupleEvent).data;\n if (!isLangChainMessageChunk(messageChunk)) {\n console.warn(\n \"Received invalid message chunk format:\",\n messageChunk,\n );\n break;\n }\n const updatedMessages = accumulator.addMessages([\n messageChunk as unknown as TMessage,\n ]);\n setMessages(updatedMessages);\n break;\n }\n case LangGraphKnownEventTypes.Metadata:\n onMetadata?.(chunk.data);\n break;\n case LangGraphKnownEventTypes.Info:\n onInfo?.(chunk.data);\n break;\n case LangGraphKnownEventTypes.Error: {\n onError?.(chunk.data);\n // Update the last AI message with error status\n // Assumes last AI message is the one the error relates to\n const messages = accumulator.getMessages();\n const lastAiMessage = messages.findLast(\n (m): m is TMessage & { type: string; id: string } =>\n m != null && \"type\" in m && m.type === \"ai\" && m.id != null,\n );\n if (lastAiMessage) {\n const errorMessage = {\n ...lastAiMessage,\n status: {\n type: \"incomplete\" as const,\n reason: \"error\" as const,\n error: chunk.data,\n },\n };\n setMessages(accumulator.addMessages([errorMessage]));\n }\n break;\n }\n default:\n if (onCustomEvent) {\n onCustomEvent(chunk.event, chunk.data);\n } else {\n console.warn(\n \"Unhandled event received:\",\n chunk.event,\n chunk.data,\n );\n }\n break;\n }\n }\n },\n [\n messages,\n appendMessage,\n stream,\n onMetadata,\n onInfo,\n onError,\n onCustomEvent,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, [abortControllerRef]);\n\n return {\n interrupt,\n messages,\n sendMessage,\n cancel,\n setInterrupt,\n setMessages,\n };\n};\n"],"mappings":"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","names":["messages"]}
@@ -1,4 +1,5 @@
1
1
  import { LangChainMessage, OnCustomEventCallback, OnErrorEventCallback, OnInfoEventCallback, OnMetadataEventCallback } from "./types";
2
+ import { AssistantCloud } from "@assistant-ui/react";
2
3
  import { LangGraphCommand, LangGraphInterruptState, LangGraphSendMessageConfig, LangGraphStreamCallback } from "./useLangGraphMessages";
3
4
  import { AttachmentAdapter } from "@assistant-ui/react";
4
5
  import { FeedbackAdapter } from "@assistant-ui/react";
@@ -6,30 +7,30 @@ import { SpeechSynthesisAdapter } from "@assistant-ui/react";
6
7
  export declare const useLangGraphInterruptState: () => LangGraphInterruptState | undefined;
7
8
  export declare const useLangGraphSend: () => (messages: LangChainMessage[], config: LangGraphSendMessageConfig) => Promise<void>;
8
9
  export declare const useLangGraphSendCommand: () => (command: LangGraphCommand) => Promise<void>;
9
- export declare const useLangGraphRuntime: ({ autoCancelPendingToolCalls, adapters: { attachments, feedback, speech }, unstable_allowCancellation, stream, threadId, onSwitchToNewThread, onSwitchToThread, eventHandlers, }: {
10
- /**
11
- * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.
12
- */
13
- threadId?: string | undefined;
10
+ type UseLangGraphRuntimeOptions = {
14
11
  autoCancelPendingToolCalls?: boolean | undefined;
15
12
  unstable_allowCancellation?: boolean | undefined;
16
13
  stream: LangGraphStreamCallback<LangChainMessage>;
17
14
  /**
18
- * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.
15
+ * @deprecated This method has been renamed to `load`. Use `load` instead.
19
16
  */
20
- onSwitchToNewThread?: () => Promise<void> | void;
21
17
  onSwitchToThread?: (threadId: string) => Promise<{
22
18
  messages: LangChainMessage[];
23
19
  interrupts?: LangGraphInterruptState[];
24
20
  }>;
21
+ load?: (threadId: string) => Promise<{
22
+ messages: LangChainMessage[];
23
+ interrupts?: LangGraphInterruptState[];
24
+ }>;
25
+ create?: () => Promise<{
26
+ externalId: string;
27
+ }>;
28
+ delete?: (threadId: string) => Promise<void>;
25
29
  adapters?: {
26
30
  attachments?: AttachmentAdapter;
27
31
  speech?: SpeechSynthesisAdapter;
28
32
  feedback?: FeedbackAdapter;
29
33
  } | undefined;
30
- /**
31
- * Event handlers for various LangGraph stream events
32
- */
33
34
  eventHandlers?: {
34
35
  /**
35
36
  * Called when metadata is received from the LangGraph stream
@@ -48,5 +49,8 @@ export declare const useLangGraphRuntime: ({ autoCancelPendingToolCalls, adapter
48
49
  */
49
50
  onCustomEvent?: OnCustomEventCallback;
50
51
  } | undefined;
51
- }) => import("@assistant-ui/react").AssistantRuntime;
52
+ cloud?: AssistantCloud | undefined;
53
+ };
54
+ export declare const useLangGraphRuntime: ({ cloud, create, delete: deleteFn, ...options }: UseLangGraphRuntimeOptions) => import("@assistant-ui/react").AssistantRuntime;
55
+ export {};
52
56
  //# sourceMappingURL=useLangGraphRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useLangGraphRuntime.d.ts","sourceRoot":"","sources":["../src/useLangGraphRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAEhB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAQjB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,0BAA0B,EAC1B,uBAAuB,EAExB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA0E7D,eAAO,MAAM,0BAA0B,2CAOtC,CAAC;AAEF,eAAO,MAAM,gBAAgB,SAGnB,UAAU,gBAAgB,EAAE,EAAE,QAAQ,0BAA0B,kBAKzE,CAAC;AAEF,eAAO,MAAM,uBAAuB,SAE1B,SAAS,gBAAgB,kBAClC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,kLASjC;IACD;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,MAAM,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;IAClD;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACjD,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;QAC/C,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;KACxC,CAAC,CAAC;IACH,QAAQ,CAAC,EACL;QACE,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,MAAM,CAAC,EAAE,sBAAsB,CAAC;QAChC,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B,GACD,SAAS,CAAC;IACd;;OAEG;IACH,aAAa,CAAC,EACV;QACE;;WAEG;QACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;QACrC;;WAEG;QACH,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B;;WAEG;QACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;QAC/B;;WAEG;QACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;KACvC,GACD,SAAS,CAAC;CACf,mDAgJA,CAAC"}
1
+ {"version":3,"file":"useLangGraphRuntime.d.ts","sourceRoot":"","sources":["../src/useLangGraphRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAEhB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,cAAc,EAOf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,0BAA0B,EAC1B,uBAAuB,EAExB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA0E7D,eAAO,MAAM,0BAA0B,2CAOtC,CAAC;AAEF,eAAO,MAAM,gBAAgB,SAGnB,UAAU,gBAAgB,EAAE,EAAE,QAAQ,0BAA0B,kBAKzE,CAAC;AAEF,eAAO,MAAM,uBAAuB,SAE1B,SAAS,gBAAgB,kBAClC,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAChC,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,MAAM,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;IAClD;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;QAC/C,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;KACxC,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;QACnC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;KACxC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,EACL;QACE,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,MAAM,CAAC,EAAE,sBAAsB,CAAC;QAChC,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B,GACD,SAAS,CAAC;IACd,aAAa,CAAC,EACV;QACE;;WAEG;QACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;QACrC;;WAEG;QACH,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B;;WAEG;QACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;QAC/B;;WAEG;QACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;KACvC,GACD,SAAS,CAAC;IACd,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACpC,CAAC;AA4IF,eAAO,MAAM,mBAAmB,GAAI,iDAKjC,0BAA0B,mDAyB5B,CAAC"}
@@ -1,6 +1,8 @@
1
1
  // src/useLangGraphRuntime.ts
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import {
4
+ unstable_useCloudThreadListAdapter,
5
+ unstable_useRemoteThreadListRuntime,
4
6
  useAssistantApi,
5
7
  useAssistantState,
6
8
  useExternalMessageConverter,
@@ -79,14 +81,13 @@ var useLangGraphSendCommand = () => {
79
81
  const send = useLangGraphSend();
80
82
  return (command) => send([], { command });
81
83
  };
82
- var useLangGraphRuntime = ({
84
+ var useLangGraphRuntimeImpl = ({
83
85
  autoCancelPendingToolCalls,
84
86
  adapters: { attachments, feedback, speech } = {},
85
87
  unstable_allowCancellation,
86
88
  stream,
87
- threadId,
88
- onSwitchToNewThread,
89
- onSwitchToThread,
89
+ onSwitchToThread: _onSwitchToThread,
90
+ load = _onSwitchToThread,
90
91
  eventHandlers
91
92
  }) => {
92
93
  const {
@@ -117,27 +118,18 @@ var useLangGraphRuntime = ({
117
118
  messages,
118
119
  isRunning
119
120
  });
120
- const switchToThread = !onSwitchToThread ? void 0 : async (externalId) => {
121
- const { messages: messages2, interrupts } = await onSwitchToThread(externalId);
121
+ const loadThread = !load ? void 0 : async (externalId) => {
122
+ const { messages: messages2, interrupts } = await load(externalId);
122
123
  setMessages(messages2);
123
124
  setInterrupt(interrupts?.[0]);
124
125
  };
125
- const threadList = {
126
- threadId,
127
- onSwitchToNewThread: !onSwitchToNewThread ? void 0 : async () => {
128
- await onSwitchToNewThread();
129
- setMessages([]);
130
- setInterrupt(void 0);
131
- },
132
- onSwitchToThread: switchToThread
133
- };
134
126
  const loadingRef = useRef(false);
135
127
  useEffect(() => {
136
- if (!switchToThread || loadingRef.current) return;
128
+ if (!loadThread || loadingRef.current) return;
137
129
  const externalId = runtime.threads.mainItem.getState().externalId;
138
130
  if (externalId) {
139
131
  loadingRef.current = true;
140
- switchToThread(externalId).finally(() => {
132
+ loadThread(externalId).finally(() => {
141
133
  loadingRef.current = false;
142
134
  });
143
135
  }
@@ -148,8 +140,7 @@ var useLangGraphRuntime = ({
148
140
  adapters: {
149
141
  attachments,
150
142
  feedback,
151
- speech,
152
- threadList
143
+ speech
153
144
  },
154
145
  extras: {
155
146
  [symbolLangGraphRuntimeExtras]: true,
@@ -207,6 +198,35 @@ var useLangGraphRuntime = ({
207
198
  });
208
199
  return runtime;
209
200
  };
201
+ var useLangGraphRuntime = ({
202
+ cloud,
203
+ create,
204
+ delete: deleteFn,
205
+ ...options
206
+ }) => {
207
+ const api = useAssistantApi();
208
+ const cloudAdapter = unstable_useCloudThreadListAdapter({
209
+ cloud,
210
+ create: async () => {
211
+ if (create) {
212
+ return create();
213
+ }
214
+ if (api.threadListItem.source) {
215
+ return api.threadListItem().initialize();
216
+ }
217
+ throw new Error(
218
+ "initialize function requires you to pass a create function to the useLangGraphRuntime hook"
219
+ );
220
+ },
221
+ delete: deleteFn
222
+ });
223
+ return unstable_useRemoteThreadListRuntime({
224
+ runtimeHook: function RuntimeHook() {
225
+ return useLangGraphRuntimeImpl(options);
226
+ },
227
+ adapter: cloudAdapter
228
+ });
229
+ };
210
230
  export {
211
231
  useLangGraphInterruptState,
212
232
  useLangGraphRuntime,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useLangGraphRuntime.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n LangChainMessage,\n LangChainToolCall,\n OnCustomEventCallback,\n OnErrorEventCallback,\n OnInfoEventCallback,\n OnMetadataEventCallback,\n} from \"./types\";\nimport {\n useAssistantApi,\n useAssistantState,\n useExternalMessageConverter,\n useExternalStoreRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangChainMessages } from \"./convertLangChainMessages\";\nimport {\n LangGraphCommand,\n LangGraphInterruptState,\n LangGraphSendMessageConfig,\n LangGraphStreamCallback,\n useLangGraphMessages,\n} from \"./useLangGraphMessages\";\nimport { AttachmentAdapter } from \"@assistant-ui/react\";\nimport { AppendMessage } from \"@assistant-ui/react\";\nimport { ExternalStoreAdapter } from \"@assistant-ui/react\";\nimport { FeedbackAdapter } from \"@assistant-ui/react\";\nimport { SpeechSynthesisAdapter } from \"@assistant-ui/react\";\nimport { appendLangChainChunk } from \"./appendLangChainChunk\";\n\nconst getPendingToolCalls = (messages: LangChainMessage[]) => {\n const pendingToolCalls = new Map<string, LangChainToolCall>();\n for (const message of messages) {\n if (message.type === \"ai\") {\n for (const toolCall of message.tool_calls ?? []) {\n pendingToolCalls.set(toolCall.id, toolCall);\n }\n }\n if (message.type === \"tool\") {\n pendingToolCalls.delete(message.tool_call_id);\n }\n }\n\n return [...pendingToolCalls.values()];\n};\n\nconst getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\n ];\n const content = allContent.map((part) => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\" as const, text: part.text };\n case \"image\":\n return { type: \"image_url\" as const, image_url: { url: part.image } };\n\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n\n default:\n const _exhaustiveCheck: \"reasoning\" | \"source\" | \"file\" | \"audio\" =\n type;\n throw new Error(\n `Unsupported append message part type: ${_exhaustiveCheck}`,\n );\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n\n return content;\n};\n\nconst symbolLangGraphRuntimeExtras = Symbol(\"langgraph-runtime-extras\");\ntype LangGraphRuntimeExtras = {\n [symbolLangGraphRuntimeExtras]: true;\n send: (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => Promise<void>;\n interrupt: LangGraphInterruptState | undefined;\n};\n\nconst asLangGraphRuntimeExtras = (extras: unknown): LangGraphRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolLangGraphRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useLangGraphRuntime\",\n );\n\n return extras as LangGraphRuntimeExtras;\n};\n\nexport const useLangGraphInterruptState = () => {\n const interrupt = useAssistantState(({ thread }) => {\n const extras = thread.extras;\n if (!extras) return undefined;\n return asLangGraphRuntimeExtras(extras).interrupt;\n });\n return interrupt;\n};\n\nexport const useLangGraphSend = () => {\n const api = useAssistantApi();\n\n return (messages: LangChainMessage[], config: LangGraphSendMessageConfig) => {\n const extras = api.thread().getState().extras;\n const { send } = asLangGraphRuntimeExtras(extras);\n return send(messages, config);\n };\n};\n\nexport const useLangGraphSendCommand = () => {\n const send = useLangGraphSend();\n return (command: LangGraphCommand) => send([], { command });\n};\n\nexport const useLangGraphRuntime = ({\n autoCancelPendingToolCalls,\n adapters: { attachments, feedback, speech } = {},\n unstable_allowCancellation,\n stream,\n threadId,\n onSwitchToNewThread,\n onSwitchToThread,\n eventHandlers,\n}: {\n /**\n * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.\n */\n threadId?: string | undefined;\n autoCancelPendingToolCalls?: boolean | undefined;\n unstable_allowCancellation?: boolean | undefined;\n stream: LangGraphStreamCallback<LangChainMessage>;\n /**\n * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.\n */\n onSwitchToNewThread?: () => Promise<void> | void;\n onSwitchToThread?: (threadId: string) => Promise<{\n messages: LangChainMessage[];\n interrupts?: LangGraphInterruptState[];\n }>;\n adapters?:\n | {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n feedback?: FeedbackAdapter;\n }\n | undefined;\n /**\n * Event handlers for various LangGraph stream events\n */\n eventHandlers?:\n | {\n /**\n * Called when metadata is received from the LangGraph stream\n */\n onMetadata?: OnMetadataEventCallback;\n /**\n * Called when informational messages are received from the LangGraph stream\n */\n onInfo?: OnInfoEventCallback;\n /**\n * Called when errors occur during LangGraph stream processing\n */\n onError?: OnErrorEventCallback;\n /**\n * Called when custom events are received from the LangGraph stream\n */\n onCustomEvent?: OnCustomEventCallback;\n }\n | undefined;\n}) => {\n const {\n interrupt,\n setInterrupt,\n messages,\n sendMessage,\n cancel,\n setMessages,\n } = useLangGraphMessages({\n appendMessage: appendLangChainChunk,\n stream,\n ...(eventHandlers && { eventHandlers }),\n });\n\n const [isRunning, setIsRunning] = useState(false);\n const handleSendMessage = async (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => {\n try {\n setIsRunning(true);\n await sendMessage(messages, config);\n } catch (error) {\n console.error(\"Error streaming messages:\", error);\n } finally {\n setIsRunning(false);\n }\n };\n\n const threadMessages = useExternalMessageConverter({\n callback: convertLangChainMessages,\n messages,\n isRunning,\n });\n\n const switchToThread = !onSwitchToThread\n ? undefined\n : async (externalId: string) => {\n const { messages, interrupts } = await onSwitchToThread(externalId);\n setMessages(messages);\n setInterrupt(interrupts?.[0]);\n };\n\n const threadList: NonNullable<\n ExternalStoreAdapter[\"adapters\"]\n >[\"threadList\"] = {\n threadId,\n onSwitchToNewThread: !onSwitchToNewThread\n ? undefined\n : async () => {\n await onSwitchToNewThread();\n setMessages([]);\n setInterrupt(undefined);\n },\n onSwitchToThread: switchToThread,\n };\n\n const loadingRef = useRef(false);\n useEffect(() => {\n if (!switchToThread || loadingRef.current) return;\n\n const externalId = runtime.threads.mainItem.getState().externalId;\n if (externalId) {\n loadingRef.current = true;\n switchToThread(externalId).finally(() => {\n loadingRef.current = false;\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const runtime = useExternalStoreRuntime({\n isRunning,\n messages: threadMessages,\n adapters: {\n attachments,\n feedback,\n speech,\n threadList,\n },\n extras: {\n [symbolLangGraphRuntimeExtras]: true,\n interrupt,\n send: handleSendMessage,\n } satisfies LangGraphRuntimeExtras,\n onNew: (msg) => {\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingToolCalls(messages).map(\n (t) =>\n ({\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\",\n }) satisfies LangChainMessage & { type: \"tool\" },\n )\n : [];\n\n return handleSendMessage(\n [\n ...cancellations,\n {\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n {\n runConfig: msg.runConfig,\n },\n );\n },\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n // TODO parallel human in the loop calls\n await handleSendMessage(\n [\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n artifact,\n status: isError ? \"error\" : \"success\",\n },\n ],\n // TODO reuse runconfig here!\n {},\n );\n },\n onCancel: unstable_allowCancellation\n ? async () => {\n cancel();\n }\n : undefined,\n });\n\n return runtime;\n};\n"],"mappings":"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","names":["messages"]}
1
+ {"version":3,"sources":["../src/useLangGraphRuntime.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n LangChainMessage,\n LangChainToolCall,\n OnCustomEventCallback,\n OnErrorEventCallback,\n OnInfoEventCallback,\n OnMetadataEventCallback,\n} from \"./types\";\nimport {\n AssistantCloud,\n unstable_useCloudThreadListAdapter,\n unstable_useRemoteThreadListRuntime,\n useAssistantApi,\n useAssistantState,\n useExternalMessageConverter,\n useExternalStoreRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangChainMessages } from \"./convertLangChainMessages\";\nimport {\n LangGraphCommand,\n LangGraphInterruptState,\n LangGraphSendMessageConfig,\n LangGraphStreamCallback,\n useLangGraphMessages,\n} from \"./useLangGraphMessages\";\nimport { AttachmentAdapter } from \"@assistant-ui/react\";\nimport { AppendMessage } from \"@assistant-ui/react\";\nimport { FeedbackAdapter } from \"@assistant-ui/react\";\nimport { SpeechSynthesisAdapter } from \"@assistant-ui/react\";\nimport { appendLangChainChunk } from \"./appendLangChainChunk\";\n\nconst getPendingToolCalls = (messages: LangChainMessage[]) => {\n const pendingToolCalls = new Map<string, LangChainToolCall>();\n for (const message of messages) {\n if (message.type === \"ai\") {\n for (const toolCall of message.tool_calls ?? []) {\n pendingToolCalls.set(toolCall.id, toolCall);\n }\n }\n if (message.type === \"tool\") {\n pendingToolCalls.delete(message.tool_call_id);\n }\n }\n\n return [...pendingToolCalls.values()];\n};\n\nconst getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\n ];\n const content = allContent.map((part) => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\" as const, text: part.text };\n case \"image\":\n return { type: \"image_url\" as const, image_url: { url: part.image } };\n\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n\n default:\n const _exhaustiveCheck: \"reasoning\" | \"source\" | \"file\" | \"audio\" =\n type;\n throw new Error(\n `Unsupported append message part type: ${_exhaustiveCheck}`,\n );\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n\n return content;\n};\n\nconst symbolLangGraphRuntimeExtras = Symbol(\"langgraph-runtime-extras\");\ntype LangGraphRuntimeExtras = {\n [symbolLangGraphRuntimeExtras]: true;\n send: (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => Promise<void>;\n interrupt: LangGraphInterruptState | undefined;\n};\n\nconst asLangGraphRuntimeExtras = (extras: unknown): LangGraphRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolLangGraphRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useLangGraphRuntime\",\n );\n\n return extras as LangGraphRuntimeExtras;\n};\n\nexport const useLangGraphInterruptState = () => {\n const interrupt = useAssistantState(({ thread }) => {\n const extras = thread.extras;\n if (!extras) return undefined;\n return asLangGraphRuntimeExtras(extras).interrupt;\n });\n return interrupt;\n};\n\nexport const useLangGraphSend = () => {\n const api = useAssistantApi();\n\n return (messages: LangChainMessage[], config: LangGraphSendMessageConfig) => {\n const extras = api.thread().getState().extras;\n const { send } = asLangGraphRuntimeExtras(extras);\n return send(messages, config);\n };\n};\n\nexport const useLangGraphSendCommand = () => {\n const send = useLangGraphSend();\n return (command: LangGraphCommand) => send([], { command });\n};\n\ntype UseLangGraphRuntimeOptions = {\n autoCancelPendingToolCalls?: boolean | undefined;\n unstable_allowCancellation?: boolean | undefined;\n stream: LangGraphStreamCallback<LangChainMessage>;\n /**\n * @deprecated This method has been renamed to `load`. Use `load` instead.\n */\n onSwitchToThread?: (threadId: string) => Promise<{\n messages: LangChainMessage[];\n interrupts?: LangGraphInterruptState[];\n }>;\n load?: (threadId: string) => Promise<{\n messages: LangChainMessage[];\n interrupts?: LangGraphInterruptState[];\n }>;\n create?: () => Promise<{\n externalId: string;\n }>;\n delete?: (threadId: string) => Promise<void>;\n adapters?:\n | {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n feedback?: FeedbackAdapter;\n }\n | undefined;\n eventHandlers?:\n | {\n /**\n * Called when metadata is received from the LangGraph stream\n */\n onMetadata?: OnMetadataEventCallback;\n /**\n * Called when informational messages are received from the LangGraph stream\n */\n onInfo?: OnInfoEventCallback;\n /**\n * Called when errors occur during LangGraph stream processing\n */\n onError?: OnErrorEventCallback;\n /**\n * Called when custom events are received from the LangGraph stream\n */\n onCustomEvent?: OnCustomEventCallback;\n }\n | undefined;\n cloud?: AssistantCloud | undefined;\n};\n\nconst useLangGraphRuntimeImpl = ({\n autoCancelPendingToolCalls,\n adapters: { attachments, feedback, speech } = {},\n unstable_allowCancellation,\n stream,\n onSwitchToThread: _onSwitchToThread,\n load = _onSwitchToThread,\n eventHandlers,\n}: UseLangGraphRuntimeOptions) => {\n const {\n interrupt,\n setInterrupt,\n messages,\n sendMessage,\n cancel,\n setMessages,\n } = useLangGraphMessages({\n appendMessage: appendLangChainChunk,\n stream,\n ...(eventHandlers && { eventHandlers }),\n });\n\n const [isRunning, setIsRunning] = useState(false);\n const handleSendMessage = async (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => {\n try {\n setIsRunning(true);\n await sendMessage(messages, config);\n } catch (error) {\n console.error(\"Error streaming messages:\", error);\n } finally {\n setIsRunning(false);\n }\n };\n\n const threadMessages = useExternalMessageConverter({\n callback: convertLangChainMessages,\n messages,\n isRunning,\n });\n\n const loadThread = !load\n ? undefined\n : async (externalId: string) => {\n const { messages, interrupts } = await load(externalId);\n setMessages(messages);\n setInterrupt(interrupts?.[0]);\n };\n\n const loadingRef = useRef(false);\n useEffect(() => {\n if (!loadThread || loadingRef.current) return;\n\n const externalId = runtime.threads.mainItem.getState().externalId;\n if (externalId) {\n loadingRef.current = true;\n loadThread(externalId).finally(() => {\n loadingRef.current = false;\n });\n }\n }, []);\n\n const runtime = useExternalStoreRuntime({\n isRunning,\n messages: threadMessages,\n adapters: {\n attachments,\n feedback,\n speech,\n },\n extras: {\n [symbolLangGraphRuntimeExtras]: true,\n interrupt,\n send: handleSendMessage,\n } satisfies LangGraphRuntimeExtras,\n onNew: (msg) => {\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingToolCalls(messages).map(\n (t) =>\n ({\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\",\n }) satisfies LangChainMessage & { type: \"tool\" },\n )\n : [];\n\n return handleSendMessage(\n [\n ...cancellations,\n {\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n {\n runConfig: msg.runConfig,\n },\n );\n },\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n // TODO parallel human in the loop calls\n await handleSendMessage(\n [\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n artifact,\n status: isError ? \"error\" : \"success\",\n },\n ],\n // TODO reuse runconfig here!\n {},\n );\n },\n onCancel: unstable_allowCancellation\n ? async () => {\n cancel();\n }\n : undefined,\n });\n\n return runtime;\n};\n\nexport const useLangGraphRuntime = ({\n cloud,\n create,\n delete: deleteFn,\n ...options\n}: UseLangGraphRuntimeOptions) => {\n const api = useAssistantApi();\n const cloudAdapter = unstable_useCloudThreadListAdapter({\n cloud,\n create: async () => {\n if (create) {\n return create();\n }\n\n if (api.threadListItem.source) {\n return api.threadListItem().initialize();\n }\n\n throw new Error(\n \"initialize function requires you to pass a create function to the useLangGraphRuntime hook\",\n );\n },\n delete: deleteFn,\n });\n return unstable_useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useLangGraphRuntimeImpl(options);\n },\n adapter: cloudAdapter,\n });\n};\n"],"mappings":"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","names":["messages"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-langgraph",
3
- "version": "0.6.10",
3
+ "version": "0.7.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,12 +18,12 @@
18
18
  ],
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
- "assistant-stream": "^0.2.29",
22
- "uuid": "^11.1.0",
23
- "zod": "^4.0.17"
21
+ "assistant-stream": "^0.2.30",
22
+ "uuid": "^13.0.0",
23
+ "zod": "^4.1.11"
24
24
  },
25
25
  "peerDependencies": {
26
- "@assistant-ui/react": "^0.11.20",
26
+ "@assistant-ui/react": "^0.11.21",
27
27
  "@types/react": "*",
28
28
  "react": "^18 || ^19 || ^19.0.0-rc"
29
29
  },
@@ -35,16 +35,16 @@
35
35
  "devDependencies": {
36
36
  "@testing-library/dom": "^10.4.1",
37
37
  "@testing-library/react": "^16.3.0",
38
- "@types/node": "^24.3.0",
39
- "@types/react": "^19.1.10",
40
- "@types/uuid": "^10.0.0",
38
+ "@types/node": "^24.5.2",
39
+ "@types/react": "^19.1.15",
40
+ "@types/uuid": "^11.0.0",
41
41
  "eslint": "^9",
42
- "eslint-config-next": "15.4.6",
43
- "jsdom": "^26.1.0",
42
+ "eslint-config-next": "15.5.4",
43
+ "jsdom": "^27.0.0",
44
44
  "react": "19.1.1",
45
- "tsx": "^4.20.4",
45
+ "tsx": "^4.20.6",
46
46
  "vitest": "^3.2.4",
47
- "@assistant-ui/react": "0.11.20",
47
+ "@assistant-ui/react": "0.11.21",
48
48
  "@assistant-ui/x-buildutils": "0.0.1"
49
49
  },
50
50
  "publishConfig": {
@@ -11,6 +11,7 @@ import {
11
11
  OnInfoEventCallback,
12
12
  OnMetadataEventCallback,
13
13
  } from "./types";
14
+ import { useAssistantApi } from "@assistant-ui/react";
14
15
 
15
16
  export type LangGraphCommand = {
16
17
  resume: string;
@@ -28,7 +29,13 @@ export type LangGraphMessagesEvent<TMessage> = {
28
29
 
29
30
  export type LangGraphStreamCallback<TMessage> = (
30
31
  messages: TMessage[],
31
- config: LangGraphSendMessageConfig & { abortSignal: AbortSignal },
32
+ config: LangGraphSendMessageConfig & {
33
+ abortSignal: AbortSignal;
34
+ initialize: () => Promise<{
35
+ remoteId: string;
36
+ externalId: string | undefined;
37
+ }>;
38
+ },
32
39
  ) =>
33
40
  | Promise<AsyncGenerator<LangGraphMessagesEvent<TMessage>>>
34
41
  | AsyncGenerator<LangGraphMessagesEvent<TMessage>>;
@@ -86,6 +93,7 @@ export const useLangGraphMessages = <TMessage extends { id?: string }>({
86
93
  [eventHandlers],
87
94
  );
88
95
 
96
+ const api = useAssistantApi();
89
97
  const sendMessage = useCallback(
90
98
  async (newMessages: TMessage[], config: LangGraphSendMessageConfig) => {
91
99
  // ensure all messages have an ID
@@ -104,6 +112,9 @@ export const useLangGraphMessages = <TMessage extends { id?: string }>({
104
112
  const response = await stream(newMessagesWithId, {
105
113
  ...config,
106
114
  abortSignal: abortController.signal,
115
+ initialize: async () => {
116
+ return await api.threadListItem().initialize();
117
+ },
107
118
  });
108
119
 
109
120
  for await (const chunk of response) {
@@ -39,14 +39,15 @@ const customEvent = {
39
39
  };
40
40
 
41
41
  describe("useLangGraphRuntime", () => {
42
- const wrapperFactory =
43
- (runtime: AssistantRuntime) =>
44
- // eslint-disable-next-line react/display-name
45
- ({ children }: { children: ReactNode }) => (
42
+ const wrapperFactory = (runtime: AssistantRuntime) => {
43
+ const Wrapper = ({ children }: { children: ReactNode }) => (
46
44
  <AssistantRuntimeProvider runtime={runtime}>
47
45
  {children}
48
46
  </AssistantRuntimeProvider>
49
47
  );
48
+ Wrapper.displayName = "TestWrapper";
49
+ return Wrapper;
50
+ };
50
51
 
51
52
  it("should handle metadata events", async () => {
52
53
  const onMetadata = vi.fn();
@@ -72,6 +73,9 @@ describe("useLangGraphRuntime", () => {
72
73
  wrapper,
73
74
  });
74
75
 
76
+ // Wait a tick for the runtime to be fully mounted
77
+ await Promise.resolve();
78
+
75
79
  act(() => {
76
80
  sendResult.current(
77
81
  [
@@ -108,16 +112,17 @@ describe("useLangGraphRuntime", () => {
108
112
  {},
109
113
  );
110
114
 
111
- const wrapper = ({ children }: { children: ReactNode }) => (
112
- <AssistantRuntimeProvider runtime={runtimeResult.current}>
113
- {children}
114
- </AssistantRuntimeProvider>
115
- );
115
+ const wrapper = wrapperFactory(runtimeResult.current);
116
116
 
117
117
  const { result: sendResult } = renderHook(() => useLangGraphSend(), {
118
118
  wrapper,
119
119
  });
120
120
 
121
+ // Wait a tick for the runtime to be fully mounted
122
+ await waitFor(() => {
123
+ expect(sendResult.current).toBeDefined();
124
+ });
125
+
121
126
  act(() => {
122
127
  sendResult.current(
123
128
  [
@@ -154,16 +159,17 @@ describe("useLangGraphRuntime", () => {
154
159
  {},
155
160
  );
156
161
 
157
- const wrapper = ({ children }: { children: ReactNode }) => (
158
- <AssistantRuntimeProvider runtime={runtimeResult.current}>
159
- {children}
160
- </AssistantRuntimeProvider>
161
- );
162
+ const wrapper = wrapperFactory(runtimeResult.current);
162
163
 
163
164
  const { result: sendResult } = renderHook(() => useLangGraphSend(), {
164
165
  wrapper,
165
166
  });
166
167
 
168
+ // Wait a tick for the runtime to be fully mounted
169
+ await waitFor(() => {
170
+ expect(sendResult.current).toBeDefined();
171
+ });
172
+
167
173
  act(() => {
168
174
  sendResult.current(
169
175
  [
@@ -206,6 +212,11 @@ describe("useLangGraphRuntime", () => {
206
212
  wrapper,
207
213
  });
208
214
 
215
+ // Wait a tick for the runtime to be fully mounted
216
+ await waitFor(() => {
217
+ expect(sendResult.current).toBeDefined();
218
+ });
219
+
209
220
  act(() => {
210
221
  sendResult.current(
211
222
  [
@@ -254,6 +265,11 @@ describe("useLangGraphRuntime", () => {
254
265
  wrapper,
255
266
  });
256
267
 
268
+ // Wait a tick for the runtime to be fully mounted
269
+ await waitFor(() => {
270
+ expect(sendResult.current).toBeDefined();
271
+ });
272
+
257
273
  act(() => {
258
274
  sendResult.current(
259
275
  [
@@ -8,6 +8,9 @@ import {
8
8
  OnMetadataEventCallback,
9
9
  } from "./types";
10
10
  import {
11
+ AssistantCloud,
12
+ unstable_useCloudThreadListAdapter,
13
+ unstable_useRemoteThreadListRuntime,
11
14
  useAssistantApi,
12
15
  useAssistantState,
13
16
  useExternalMessageConverter,
@@ -23,7 +26,6 @@ import {
23
26
  } from "./useLangGraphMessages";
24
27
  import { AttachmentAdapter } from "@assistant-ui/react";
25
28
  import { AppendMessage } from "@assistant-ui/react";
26
- import { ExternalStoreAdapter } from "@assistant-ui/react";
27
29
  import { FeedbackAdapter } from "@assistant-ui/react";
28
30
  import { SpeechSynthesisAdapter } from "@assistant-ui/react";
29
31
  import { appendLangChainChunk } from "./appendLangChainChunk";
@@ -123,31 +125,25 @@ export const useLangGraphSendCommand = () => {
123
125
  return (command: LangGraphCommand) => send([], { command });
124
126
  };
125
127
 
126
- export const useLangGraphRuntime = ({
127
- autoCancelPendingToolCalls,
128
- adapters: { attachments, feedback, speech } = {},
129
- unstable_allowCancellation,
130
- stream,
131
- threadId,
132
- onSwitchToNewThread,
133
- onSwitchToThread,
134
- eventHandlers,
135
- }: {
136
- /**
137
- * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.
138
- */
139
- threadId?: string | undefined;
128
+ type UseLangGraphRuntimeOptions = {
140
129
  autoCancelPendingToolCalls?: boolean | undefined;
141
130
  unstable_allowCancellation?: boolean | undefined;
142
131
  stream: LangGraphStreamCallback<LangChainMessage>;
143
132
  /**
144
- * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.
133
+ * @deprecated This method has been renamed to `load`. Use `load` instead.
145
134
  */
146
- onSwitchToNewThread?: () => Promise<void> | void;
147
135
  onSwitchToThread?: (threadId: string) => Promise<{
148
136
  messages: LangChainMessage[];
149
137
  interrupts?: LangGraphInterruptState[];
150
138
  }>;
139
+ load?: (threadId: string) => Promise<{
140
+ messages: LangChainMessage[];
141
+ interrupts?: LangGraphInterruptState[];
142
+ }>;
143
+ create?: () => Promise<{
144
+ externalId: string;
145
+ }>;
146
+ delete?: (threadId: string) => Promise<void>;
151
147
  adapters?:
152
148
  | {
153
149
  attachments?: AttachmentAdapter;
@@ -155,9 +151,6 @@ export const useLangGraphRuntime = ({
155
151
  feedback?: FeedbackAdapter;
156
152
  }
157
153
  | undefined;
158
- /**
159
- * Event handlers for various LangGraph stream events
160
- */
161
154
  eventHandlers?:
162
155
  | {
163
156
  /**
@@ -178,7 +171,18 @@ export const useLangGraphRuntime = ({
178
171
  onCustomEvent?: OnCustomEventCallback;
179
172
  }
180
173
  | undefined;
181
- }) => {
174
+ cloud?: AssistantCloud | undefined;
175
+ };
176
+
177
+ const useLangGraphRuntimeImpl = ({
178
+ autoCancelPendingToolCalls,
179
+ adapters: { attachments, feedback, speech } = {},
180
+ unstable_allowCancellation,
181
+ stream,
182
+ onSwitchToThread: _onSwitchToThread,
183
+ load = _onSwitchToThread,
184
+ eventHandlers,
185
+ }: UseLangGraphRuntimeOptions) => {
182
186
  const {
183
187
  interrupt,
184
188
  setInterrupt,
@@ -213,40 +217,25 @@ export const useLangGraphRuntime = ({
213
217
  isRunning,
214
218
  });
215
219
 
216
- const switchToThread = !onSwitchToThread
220
+ const loadThread = !load
217
221
  ? undefined
218
222
  : async (externalId: string) => {
219
- const { messages, interrupts } = await onSwitchToThread(externalId);
223
+ const { messages, interrupts } = await load(externalId);
220
224
  setMessages(messages);
221
225
  setInterrupt(interrupts?.[0]);
222
226
  };
223
227
 
224
- const threadList: NonNullable<
225
- ExternalStoreAdapter["adapters"]
226
- >["threadList"] = {
227
- threadId,
228
- onSwitchToNewThread: !onSwitchToNewThread
229
- ? undefined
230
- : async () => {
231
- await onSwitchToNewThread();
232
- setMessages([]);
233
- setInterrupt(undefined);
234
- },
235
- onSwitchToThread: switchToThread,
236
- };
237
-
238
228
  const loadingRef = useRef(false);
239
229
  useEffect(() => {
240
- if (!switchToThread || loadingRef.current) return;
230
+ if (!loadThread || loadingRef.current) return;
241
231
 
242
232
  const externalId = runtime.threads.mainItem.getState().externalId;
243
233
  if (externalId) {
244
234
  loadingRef.current = true;
245
- switchToThread(externalId).finally(() => {
235
+ loadThread(externalId).finally(() => {
246
236
  loadingRef.current = false;
247
237
  });
248
238
  }
249
- // eslint-disable-next-line react-hooks/exhaustive-deps
250
239
  }, []);
251
240
 
252
241
  const runtime = useExternalStoreRuntime({
@@ -256,7 +245,6 @@ export const useLangGraphRuntime = ({
256
245
  attachments,
257
246
  feedback,
258
247
  speech,
259
- threadList,
260
248
  },
261
249
  extras: {
262
250
  [symbolLangGraphRuntimeExtras]: true,
@@ -323,3 +311,35 @@ export const useLangGraphRuntime = ({
323
311
 
324
312
  return runtime;
325
313
  };
314
+
315
+ export const useLangGraphRuntime = ({
316
+ cloud,
317
+ create,
318
+ delete: deleteFn,
319
+ ...options
320
+ }: UseLangGraphRuntimeOptions) => {
321
+ const api = useAssistantApi();
322
+ const cloudAdapter = unstable_useCloudThreadListAdapter({
323
+ cloud,
324
+ create: async () => {
325
+ if (create) {
326
+ return create();
327
+ }
328
+
329
+ if (api.threadListItem.source) {
330
+ return api.threadListItem().initialize();
331
+ }
332
+
333
+ throw new Error(
334
+ "initialize function requires you to pass a create function to the useLangGraphRuntime hook",
335
+ );
336
+ },
337
+ delete: deleteFn,
338
+ });
339
+ return unstable_useRemoteThreadListRuntime({
340
+ runtimeHook: function RuntimeHook() {
341
+ return useLangGraphRuntimeImpl(options);
342
+ },
343
+ adapter: cloudAdapter,
344
+ });
345
+ };