@assistant-ui/react-langchain 0.0.4 → 0.0.7
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/README.md +9 -82
- package/dist/convertMessages.d.ts +1 -0
- package/dist/convertMessages.d.ts.map +1 -1
- package/dist/convertMessages.js +1 -1
- package/dist/convertMessages.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/useStreamRuntime.d.ts +43 -5
- package/dist/useStreamRuntime.d.ts.map +1 -1
- package/dist/useStreamRuntime.js +79 -15
- package/dist/useStreamRuntime.js.map +1 -1
- package/package.json +10 -10
- package/src/convertMessages.ts +1 -1
- package/src/index.ts +2 -0
- package/src/useStreamRuntime.ts +145 -26
package/README.md
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# `@assistant-ui/react-langchain`
|
|
2
2
|
|
|
3
|
-
Adapter that wraps [`useStream`](https://docs.langchain.com/oss/javascript/langgraph-sdk/react-stream) from `@langchain/react` and exposes it as an assistant-ui runtime
|
|
3
|
+
Adapter that wraps [`useStream`](https://docs.langchain.com/oss/javascript/langgraph-sdk/react-stream) from `@langchain/react` and exposes it as an assistant-ui runtime. Bridges LangChain's `useStream` to an `AssistantRuntime` with hooks for interrupts, raw state submission, and reading custom LangGraph state keys.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## When to use this
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- Bridges LangChain's `useStream` to an assistant-ui `AssistantRuntime`
|
|
10
|
-
- Tool invocations flow through assistant-ui's `useToolInvocations`
|
|
11
|
-
- `useLangChainInterruptState` — read the current LangGraph interrupt
|
|
12
|
-
- `useLangChainSubmit` — submit raw state updates (e.g. resume commands)
|
|
13
|
-
- `useLangChainState<T>(key)` — read custom state keys like `todos` / `files` reactively
|
|
14
|
-
- Optional assistant-cloud thread persistence
|
|
7
|
+
assistant-ui also ships `@assistant-ui/react-langgraph`, which integrates with `@langchain/langgraph-sdk` directly and has a broader feature set (subgraph events, UI messages, message metadata, cancellation). The two packages are independent adapters targeting different upstream libraries; pick whichever matches the SDK you already use.
|
|
15
8
|
|
|
16
9
|
## Installation
|
|
17
10
|
|
|
@@ -21,13 +14,12 @@ npm install @assistant-ui/react @assistant-ui/react-langchain @langchain/react
|
|
|
21
14
|
|
|
22
15
|
## Usage
|
|
23
16
|
|
|
24
|
-
### Basic setup
|
|
25
|
-
|
|
26
17
|
```tsx
|
|
27
18
|
import { useStreamRuntime } from "@assistant-ui/react-langchain";
|
|
28
|
-
import { AssistantRuntimeProvider
|
|
19
|
+
import { AssistantRuntimeProvider } from "@assistant-ui/react";
|
|
20
|
+
import { Thread } from "@/components/assistant-ui/thread";
|
|
29
21
|
|
|
30
|
-
function App() {
|
|
22
|
+
export function App() {
|
|
31
23
|
const runtime = useStreamRuntime({
|
|
32
24
|
assistantId: "agent",
|
|
33
25
|
apiUrl: "http://localhost:2024",
|
|
@@ -41,71 +33,6 @@ function App() {
|
|
|
41
33
|
}
|
|
42
34
|
```
|
|
43
35
|
|
|
44
|
-
`useStreamRuntime` accepts every option
|
|
45
|
-
|
|
46
|
-
- `cloud` — an `AssistantCloud` instance for persisting threads
|
|
47
|
-
- `adapters` — `{ attachments, speech, feedback }`
|
|
48
|
-
- `messagesKey` — the state key that holds messages (default `"messages"`)
|
|
49
|
-
|
|
50
|
-
### Reading custom state keys
|
|
51
|
-
|
|
52
|
-
LangGraph agents often expose structured state beyond messages (plans, todos, scratch files, generative-UI artifacts). Read them directly with `useLangChainState` — mirrors `useStream().values[key]` upstream and updates when the stream emits new state.
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
import { useLangChainState } from "@assistant-ui/react-langchain";
|
|
56
|
-
|
|
57
|
-
type Todo = { id: string; title: string; done: boolean };
|
|
58
|
-
|
|
59
|
-
function TodoList() {
|
|
60
|
-
const todos = useLangChainState<Todo[]>("todos", []);
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<ul>
|
|
64
|
-
{todos.map((t) => (
|
|
65
|
-
<li key={t.id}>{t.title}</li>
|
|
66
|
-
))}
|
|
67
|
-
</ul>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Signatures:
|
|
36
|
+
`useStreamRuntime` accepts every option `@langchain/react`'s `useStream` does, plus `cloud` for thread persistence, an `adapters` bag, and a `messagesKey` override.
|
|
73
37
|
|
|
74
|
-
|
|
75
|
-
useLangChainState<T>(key: string): T | undefined;
|
|
76
|
-
useLangChainState<T>(key: string, defaultValue: T): T;
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Interrupts
|
|
80
|
-
|
|
81
|
-
```tsx
|
|
82
|
-
import {
|
|
83
|
-
useLangChainInterruptState,
|
|
84
|
-
useLangChainSubmit,
|
|
85
|
-
} from "@assistant-ui/react-langchain";
|
|
86
|
-
import { Command } from "@langchain/langgraph-sdk";
|
|
87
|
-
|
|
88
|
-
function InterruptPrompt() {
|
|
89
|
-
const interrupt = useLangChainInterruptState();
|
|
90
|
-
const submit = useLangChainSubmit();
|
|
91
|
-
|
|
92
|
-
if (!interrupt) return null;
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<div>
|
|
96
|
-
<pre>{JSON.stringify(interrupt.value, null, 2)}</pre>
|
|
97
|
-
<button onClick={() => submit(null, { command: new Command({ resume: "yes" }) })}>
|
|
98
|
-
Approve
|
|
99
|
-
</button>
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Message conversion
|
|
106
|
-
|
|
107
|
-
The adapter ships `convertLangChainBaseMessage` for cases where you want to reuse the internal converter directly (e.g. when building a custom `ExternalStoreAdapter`).
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
import { convertLangChainBaseMessage } from "@assistant-ui/react-langchain";
|
|
111
|
-
```
|
|
38
|
+
Full reference for `useLangChainState`, `useLangChainInterruptState`, `useLangChainSubmit`, and `convertLangChainBaseMessage` at [assistant-ui.com/docs/runtimes/langchain](https://www.assistant-ui.com/docs/runtimes/langchain).
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { useExternalMessageConverter } from "@assistant-ui/core/react";
|
|
2
2
|
import type { LangChainBaseMessage } from "./types.js";
|
|
3
|
+
export declare const getMessageType: (message: LangChainBaseMessage) => string;
|
|
3
4
|
export declare const convertLangChainBaseMessage: useExternalMessageConverter.Callback<LangChainBaseMessage>;
|
|
4
5
|
//# sourceMappingURL=convertMessages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessages.d.ts","sourceRoot":"","sources":["../src/convertMessages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,EAAE,oBAAoB,EAAyB,mBAAgB;
|
|
1
|
+
{"version":3,"file":"convertMessages.d.ts","sourceRoot":"","sources":["../src/convertMessages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,EAAE,oBAAoB,EAAyB,mBAAgB;AAE3E,eAAO,MAAM,cAAc,GAAI,SAAS,oBAAoB,KAAG,MAK9D,CAAC;AAkDF,eAAO,MAAM,2BAA2B,EAAE,2BAA2B,CAAC,QAAQ,CAC5E,oBAAoB,CA0ErB,CAAC"}
|
package/dist/convertMessages.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessages.js","sourceRoot":"","sources":["../src/convertMessages.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAMb,MAAM,cAAc,GAAG,CAAC,OAA6B,EAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"convertMessages.js","sourceRoot":"","sources":["../src/convertMessages.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useStreamRuntime, useLangChainInterruptState, useLangChainState, useLangChainSubmit, } from "./useStreamRuntime.js";
|
|
1
|
+
export { useStreamRuntime, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, } from "./useStreamRuntime.js";
|
|
2
2
|
export type { UseStreamRuntimeOptions } from "./useStreamRuntime.js";
|
|
3
3
|
export { convertLangChainBaseMessage } from "./convertMessages.js";
|
|
4
4
|
export type { LangChainBaseMessage, LangChainContentBlock, LangChainToolCall, } from "./types.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,iBAAiB,EACjB,kBAAkB,GACnB,8BAA2B;AAC5B,YAAY,EAAE,uBAAuB,EAAE,8BAA2B;AAElE,OAAO,EAAE,2BAA2B,EAAE,6BAA0B;AAEhE,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,GAClB,mBAAgB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,GACnB,8BAA2B;AAC5B,YAAY,EAAE,uBAAuB,EAAE,8BAA2B;AAElE,OAAO,EAAE,2BAA2B,EAAE,6BAA0B;AAEhE,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,GAClB,mBAAgB"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { useStreamRuntime, useLangChainInterruptState, useLangChainState, useLangChainSubmit, } from "./useStreamRuntime.js";
|
|
1
|
+
export { useStreamRuntime, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, } from "./useStreamRuntime.js";
|
|
2
2
|
export { convertLangChainBaseMessage } from "./convertMessages.js";
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,iBAAiB,EACjB,kBAAkB,GACnB,8BAA2B;AAG5B,OAAO,EAAE,2BAA2B,EAAE,6BAA0B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,GACnB,8BAA2B;AAG5B,OAAO,EAAE,2BAA2B,EAAE,6BAA0B"}
|
|
@@ -1,16 +1,39 @@
|
|
|
1
|
-
import type { AttachmentAdapter, FeedbackAdapter, SpeechSynthesisAdapter } from "@assistant-ui/core";
|
|
1
|
+
import type { AttachmentAdapter, FeedbackAdapter, RemoteThreadListAdapter, SpeechSynthesisAdapter } from "@assistant-ui/core";
|
|
2
2
|
import type { AssistantCloud } from "assistant-cloud";
|
|
3
3
|
import { type UseStreamOptions } from "@langchain/react";
|
|
4
|
-
|
|
4
|
+
import type { LangChainBaseMessage } from "./types.js";
|
|
5
|
+
type LangChainRuntimeExtraOptions = {
|
|
5
6
|
cloud?: AssistantCloud | undefined;
|
|
6
7
|
adapters?: {
|
|
7
8
|
attachments?: AttachmentAdapter | undefined;
|
|
8
9
|
speech?: SpeechSynthesisAdapter | undefined;
|
|
9
10
|
feedback?: FeedbackAdapter | undefined;
|
|
10
11
|
} | undefined;
|
|
11
|
-
/**
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* When the user sends a new message while previous tool calls are
|
|
14
|
+
* still pending, automatically submit `tool` messages that cancel
|
|
15
|
+
* them so the agent's tool-call accounting stays consistent.
|
|
16
|
+
* Defaults to `true`.
|
|
17
|
+
*/
|
|
18
|
+
autoCancelPendingToolCalls?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Routes the Cancel button's click to `useStream().stop()`. On by
|
|
21
|
+
* default. Pass `false` to disable the Cancel button.
|
|
22
|
+
*/
|
|
23
|
+
unstable_allowCancellation?: boolean | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Custom `RemoteThreadListAdapter`. When provided, replaces the
|
|
26
|
+
* cloud-backed thread list adapter.
|
|
27
|
+
*/
|
|
28
|
+
unstable_threadListAdapter?: RemoteThreadListAdapter | undefined;
|
|
29
|
+
/** Custom thread-creation hook, forwarded to the cloud adapter. */
|
|
30
|
+
create?: (() => Promise<{
|
|
31
|
+
externalId: string | undefined;
|
|
32
|
+
}>) | undefined;
|
|
33
|
+
/** Custom thread-deletion hook, forwarded to the cloud adapter. */
|
|
34
|
+
delete?: ((threadId: string) => Promise<void>) | undefined;
|
|
13
35
|
};
|
|
36
|
+
export type UseStreamRuntimeOptions = UseStreamOptions extends infer O ? O extends UseStreamOptions ? O & LangChainRuntimeExtraOptions : never : never;
|
|
14
37
|
/**
|
|
15
38
|
* Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
|
|
16
39
|
* Accepts the same options as `useStream` from `@langchain/react`, plus
|
|
@@ -35,7 +58,7 @@ export type UseStreamRuntimeOptions = UseStreamOptions & {
|
|
|
35
58
|
* }
|
|
36
59
|
* ```
|
|
37
60
|
*/
|
|
38
|
-
export declare const useStreamRuntime: (
|
|
61
|
+
export declare const useStreamRuntime: (rawOptions: UseStreamRuntimeOptions) => import("@assistant-ui/core").AssistantRuntime;
|
|
39
62
|
/**
|
|
40
63
|
* Read the current LangGraph interrupt state from the runtime extras.
|
|
41
64
|
*/
|
|
@@ -48,6 +71,20 @@ export declare const useLangChainInterruptState: () => {
|
|
|
48
71
|
* commands.
|
|
49
72
|
*/
|
|
50
73
|
export declare const useLangChainSubmit: () => (values: Record<string, unknown> | null | undefined, options?: Record<string, unknown>) => Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Submit a list of LangChain-shaped messages on the current thread.
|
|
76
|
+
* Parity helper for migrating from `useLangGraphSend`. Routes to
|
|
77
|
+
* `useStream().submit({ [messagesKey]: messages }, options)`.
|
|
78
|
+
*/
|
|
79
|
+
export declare const useLangChainSend: () => (messages: readonly LangChainBaseMessage[], options?: Record<string, unknown>) => Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Submit a `useStream` command (e.g. interrupt resume). Parity helper
|
|
82
|
+
* for migrating from `useLangGraphSendCommand`. Note that v1's command
|
|
83
|
+
* shape (`{ resume?, goto?, update? }`) differs from the legacy
|
|
84
|
+
* `{ resume: string }` form — to carry a payload, use the input or
|
|
85
|
+
* `stream.respond` instead.
|
|
86
|
+
*/
|
|
87
|
+
export declare const useLangChainSendCommand: () => (command: Record<string, unknown>) => Promise<void>;
|
|
51
88
|
/**
|
|
52
89
|
* Read a custom LangGraph state key from the current thread. Mirrors
|
|
53
90
|
* `useStream().values[key]` from `@langchain/react` and updates when the
|
|
@@ -61,4 +98,5 @@ export declare const useLangChainSubmit: () => (values: Record<string, unknown>
|
|
|
61
98
|
*/
|
|
62
99
|
export declare function useLangChainState<T>(key: string): T | undefined;
|
|
63
100
|
export declare function useLangChainState<T>(key: string, defaultValue: T): T;
|
|
101
|
+
export {};
|
|
64
102
|
//# sourceMappingURL=useStreamRuntime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"useStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAqB,mBAAgB;AA6BvE,KAAK,4BAA4B,GAAG;IAClC,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,EACL;QACE,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;QAC5C,MAAM,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;QAC5C,QAAQ,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;KACxC,GACD,SAAS,CAAC;IACd;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD;;;OAGG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD;;;OAGG;IACH,0BAA0B,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAC;IACjE,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAC5D,CAAC;AAqBF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,SAAS,MAAM,CAAC,GAClE,CAAC,SAAS,gBAAgB,GACxB,CAAC,GAAG,4BAA4B,GAChC,KAAK,GACP,KAAK,CAAC;AA8MV;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,GAAI,YAAY,uBAAuB,kDA2BnE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;YAnVhB,OAAO;aAyV7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,SAG3B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAClD,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAMpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,SAGzB,UAAU,SAAS,oBAAoB,EAAE,EACzC,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAOpC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,SAE1B,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBACzC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;AACjE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC"}
|
package/dist/useStreamRuntime.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import { useCloudThreadListAdapter, useExternalStoreRuntime, useExternalMessageConverter, useRemoteThreadListRuntime, useToolInvocations, } from "@assistant-ui/core/react";
|
|
4
4
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
5
5
|
import { useStream } from "@langchain/react";
|
|
6
|
-
import { convertLangChainBaseMessage } from "./convertMessages.js";
|
|
6
|
+
import { convertLangChainBaseMessage, getMessageType } from "./convertMessages.js";
|
|
7
7
|
const symbolLangChainRuntimeExtras = Symbol("langchain-runtime-extras");
|
|
8
8
|
const asLangChainRuntimeExtras = (extras) => {
|
|
9
9
|
if (typeof extras !== "object" ||
|
|
@@ -12,6 +12,20 @@ const asLangChainRuntimeExtras = (extras) => {
|
|
|
12
12
|
throw new Error("This method can only be called when you are using useStreamRuntime");
|
|
13
13
|
return extras;
|
|
14
14
|
};
|
|
15
|
+
const getPendingToolCalls = (messages) => {
|
|
16
|
+
const pending = new Map();
|
|
17
|
+
for (const m of messages) {
|
|
18
|
+
const type = getMessageType(m);
|
|
19
|
+
if (type === "ai") {
|
|
20
|
+
for (const tc of m.tool_calls ?? [])
|
|
21
|
+
pending.set(tc.id, tc);
|
|
22
|
+
}
|
|
23
|
+
else if (type === "tool" && m.tool_call_id) {
|
|
24
|
+
pending.delete(m.tool_call_id);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [...pending.values()];
|
|
28
|
+
};
|
|
15
29
|
const getMessageContent = (msg) => {
|
|
16
30
|
const allContent = [
|
|
17
31
|
...msg.content,
|
|
@@ -50,14 +64,17 @@ const getMessageContent = (msg) => {
|
|
|
50
64
|
}
|
|
51
65
|
return content;
|
|
52
66
|
};
|
|
53
|
-
const useStreamThreadRuntime = (
|
|
67
|
+
const useStreamThreadRuntime = (options) => {
|
|
68
|
+
const { adapters, autoCancelPendingToolCalls, unstable_allowCancellation } = options;
|
|
69
|
+
const messagesKey = options.messagesKey ?? "messages";
|
|
54
70
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
55
71
|
const externalId = useAuiState((s) => s.threadListItem.externalId);
|
|
72
|
+
// Mutate in place rather than `{ ...options, threadId }`: spreading
|
|
73
|
+
// `UseStreamOptions` (a discriminated union on `transport`) into an object
|
|
74
|
+
// literal merges both arms' transport types, breaking arm assignment.
|
|
75
|
+
options.threadId = externalId;
|
|
56
76
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
57
|
-
const stream = useStream(
|
|
58
|
-
...streamOptions,
|
|
59
|
-
threadId: externalId,
|
|
60
|
-
});
|
|
77
|
+
const stream = useStream(options);
|
|
61
78
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
62
79
|
const [toolStatuses, setToolStatuses] = useState({});
|
|
63
80
|
const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
|
|
@@ -108,7 +125,14 @@ const useStreamThreadRuntime = ({ adapters, messagesKey = "messages", ...streamO
|
|
|
108
125
|
interrupts: stream.interrupts,
|
|
109
126
|
submit: stream.submit,
|
|
110
127
|
values: stream.values,
|
|
111
|
-
|
|
128
|
+
messagesKey,
|
|
129
|
+
}), [
|
|
130
|
+
stream.interrupt,
|
|
131
|
+
stream.interrupts,
|
|
132
|
+
stream.submit,
|
|
133
|
+
stream.values,
|
|
134
|
+
messagesKey,
|
|
135
|
+
]);
|
|
112
136
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
113
137
|
const runtime = useExternalStoreRuntime({
|
|
114
138
|
isRunning: effectiveIsRunning,
|
|
@@ -118,8 +142,17 @@ const useStreamThreadRuntime = ({ adapters, messagesKey = "messages", ...streamO
|
|
|
118
142
|
onNew: async (msg) => {
|
|
119
143
|
await toolInvocations.abort();
|
|
120
144
|
const content = getMessageContent(msg);
|
|
145
|
+
const cancellations = autoCancelPendingToolCalls !== false
|
|
146
|
+
? getPendingToolCalls(streamRef.current.messages).map((t) => ({
|
|
147
|
+
type: "tool",
|
|
148
|
+
name: t.name,
|
|
149
|
+
tool_call_id: t.id,
|
|
150
|
+
content: JSON.stringify({ cancelled: true }),
|
|
151
|
+
status: "error",
|
|
152
|
+
}))
|
|
153
|
+
: [];
|
|
121
154
|
await stream.submit({
|
|
122
|
-
[messagesKey]: [{ type: "human", content }],
|
|
155
|
+
[messagesKey]: [...cancellations, { type: "human", content }],
|
|
123
156
|
});
|
|
124
157
|
},
|
|
125
158
|
onAddToolResult: async ({ toolCallId, toolName, result, isError, artifact, }) => {
|
|
@@ -136,10 +169,12 @@ const useStreamThreadRuntime = ({ adapters, messagesKey = "messages", ...streamO
|
|
|
136
169
|
],
|
|
137
170
|
});
|
|
138
171
|
},
|
|
139
|
-
onCancel:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
172
|
+
onCancel: unstable_allowCancellation !== false
|
|
173
|
+
? async () => {
|
|
174
|
+
await stream.stop();
|
|
175
|
+
await toolInvocations.abort();
|
|
176
|
+
}
|
|
177
|
+
: undefined,
|
|
143
178
|
});
|
|
144
179
|
return runtime;
|
|
145
180
|
};
|
|
@@ -167,16 +202,22 @@ const useStreamThreadRuntime = ({ adapters, messagesKey = "messages", ...streamO
|
|
|
167
202
|
* }
|
|
168
203
|
* ```
|
|
169
204
|
*/
|
|
170
|
-
export const useStreamRuntime = (
|
|
205
|
+
export const useStreamRuntime = (rawOptions) => {
|
|
206
|
+
const { cloud, unstable_threadListAdapter, create, delete: deleteFn, ...options } = rawOptions;
|
|
171
207
|
const optionsRef = useRef(options);
|
|
172
208
|
optionsRef.current = options;
|
|
173
|
-
const cloudAdapter = useCloudThreadListAdapter({
|
|
209
|
+
const cloudAdapter = useCloudThreadListAdapter({
|
|
210
|
+
cloud,
|
|
211
|
+
create,
|
|
212
|
+
delete: deleteFn,
|
|
213
|
+
});
|
|
214
|
+
const adapter = unstable_threadListAdapter ?? cloudAdapter;
|
|
174
215
|
return useRemoteThreadListRuntime({
|
|
175
216
|
runtimeHook: function RuntimeHook() {
|
|
176
217
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
177
218
|
return useStreamThreadRuntime(optionsRef.current);
|
|
178
219
|
},
|
|
179
|
-
adapter
|
|
220
|
+
adapter,
|
|
180
221
|
allowNesting: true,
|
|
181
222
|
});
|
|
182
223
|
};
|
|
@@ -204,6 +245,29 @@ export const useLangChainSubmit = () => {
|
|
|
204
245
|
return submit(values, options);
|
|
205
246
|
};
|
|
206
247
|
};
|
|
248
|
+
/**
|
|
249
|
+
* Submit a list of LangChain-shaped messages on the current thread.
|
|
250
|
+
* Parity helper for migrating from `useLangGraphSend`. Routes to
|
|
251
|
+
* `useStream().submit({ [messagesKey]: messages }, options)`.
|
|
252
|
+
*/
|
|
253
|
+
export const useLangChainSend = () => {
|
|
254
|
+
const aui = useAui();
|
|
255
|
+
return (messages, options) => {
|
|
256
|
+
const { submit, messagesKey } = asLangChainRuntimeExtras(aui.thread().getState().extras);
|
|
257
|
+
return submit({ [messagesKey]: messages }, options);
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
/**
|
|
261
|
+
* Submit a `useStream` command (e.g. interrupt resume). Parity helper
|
|
262
|
+
* for migrating from `useLangGraphSendCommand`. Note that v1's command
|
|
263
|
+
* shape (`{ resume?, goto?, update? }`) differs from the legacy
|
|
264
|
+
* `{ resume: string }` form — to carry a payload, use the input or
|
|
265
|
+
* `stream.respond` instead.
|
|
266
|
+
*/
|
|
267
|
+
export const useLangChainSendCommand = () => {
|
|
268
|
+
const submit = useLangChainSubmit();
|
|
269
|
+
return (command) => submit(null, { command });
|
|
270
|
+
};
|
|
207
271
|
export function useLangChainState(key, defaultValue) {
|
|
208
272
|
return useAuiState((s) => {
|
|
209
273
|
const extras = s.thread.extras;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStreamRuntime.js","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useStreamRuntime.js","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-langchain",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "LangChain useStream adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"langchain",
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
],
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@assistant-ui/core": "^0.
|
|
33
|
-
"@assistant-ui/store": "^0.2.
|
|
32
|
+
"@assistant-ui/core": "^0.2.3",
|
|
33
|
+
"@assistant-ui/store": "^0.2.11",
|
|
34
34
|
"assistant-cloud": "*",
|
|
35
|
-
"assistant-stream": "^0.3.
|
|
35
|
+
"assistant-stream": "^0.3.15"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@langchain/react": "^0.
|
|
38
|
+
"@langchain/react": "^1.0.2",
|
|
39
39
|
"@types/react": "*",
|
|
40
40
|
"react": "^18 || ^19"
|
|
41
41
|
},
|
|
@@ -45,15 +45,15 @@
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@langchain/core": "^1.1.
|
|
49
|
-
"@langchain/langgraph-sdk": "^1.
|
|
50
|
-
"@langchain/react": "^0.
|
|
48
|
+
"@langchain/core": "^1.1.44",
|
|
49
|
+
"@langchain/langgraph-sdk": "^1.9.2",
|
|
50
|
+
"@langchain/react": "^1.0.2",
|
|
51
51
|
"@testing-library/react": "^16.3.2",
|
|
52
52
|
"@types/react": "^19.2.14",
|
|
53
|
-
"jsdom": "^29.1.
|
|
53
|
+
"jsdom": "^29.1.1",
|
|
54
54
|
"react": "^19.2.5",
|
|
55
55
|
"vitest": "^4.1.5",
|
|
56
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
56
|
+
"@assistant-ui/x-buildutils": "0.0.8"
|
|
57
57
|
},
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public",
|
package/src/convertMessages.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { useExternalMessageConverter } from "@assistant-ui/core/react";
|
|
|
4
4
|
import type { ReadonlyJSONObject } from "assistant-stream/utils";
|
|
5
5
|
import type { LangChainBaseMessage, LangChainContentBlock } from "./types";
|
|
6
6
|
|
|
7
|
-
const getMessageType = (message: LangChainBaseMessage): string => {
|
|
7
|
+
export const getMessageType = (message: LangChainBaseMessage): string => {
|
|
8
8
|
if (typeof message._getType === "function") return message._getType();
|
|
9
9
|
if ("type" in message)
|
|
10
10
|
return (message as Record<string, unknown>).type as string;
|
package/src/index.ts
CHANGED
package/src/useStreamRuntime.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
AppendMessage,
|
|
6
6
|
AttachmentAdapter,
|
|
7
7
|
FeedbackAdapter,
|
|
8
|
+
RemoteThreadListAdapter,
|
|
8
9
|
SpeechSynthesisAdapter,
|
|
9
10
|
} from "@assistant-ui/core";
|
|
10
11
|
import {
|
|
@@ -18,8 +19,8 @@ import {
|
|
|
18
19
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
19
20
|
import type { AssistantCloud } from "assistant-cloud";
|
|
20
21
|
import { useStream, type UseStreamOptions } from "@langchain/react";
|
|
21
|
-
import type { LangChainBaseMessage } from "./types";
|
|
22
|
-
import { convertLangChainBaseMessage } from "./convertMessages";
|
|
22
|
+
import type { LangChainBaseMessage, LangChainToolCall } from "./types";
|
|
23
|
+
import { convertLangChainBaseMessage, getMessageType } from "./convertMessages";
|
|
23
24
|
|
|
24
25
|
const symbolLangChainRuntimeExtras = Symbol("langchain-runtime-extras");
|
|
25
26
|
|
|
@@ -32,6 +33,7 @@ type LangChainRuntimeExtras = {
|
|
|
32
33
|
options?: Record<string, unknown>,
|
|
33
34
|
) => Promise<void>;
|
|
34
35
|
values: Record<string, unknown>;
|
|
36
|
+
messagesKey: string;
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
const asLangChainRuntimeExtras = (extras: unknown): LangChainRuntimeExtras => {
|
|
@@ -46,7 +48,7 @@ const asLangChainRuntimeExtras = (extras: unknown): LangChainRuntimeExtras => {
|
|
|
46
48
|
return extras as LangChainRuntimeExtras;
|
|
47
49
|
};
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
type LangChainRuntimeExtraOptions = {
|
|
50
52
|
cloud?: AssistantCloud | undefined;
|
|
51
53
|
adapters?:
|
|
52
54
|
| {
|
|
@@ -55,10 +57,54 @@ export type UseStreamRuntimeOptions = UseStreamOptions & {
|
|
|
55
57
|
feedback?: FeedbackAdapter | undefined;
|
|
56
58
|
}
|
|
57
59
|
| undefined;
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
+
/**
|
|
61
|
+
* When the user sends a new message while previous tool calls are
|
|
62
|
+
* still pending, automatically submit `tool` messages that cancel
|
|
63
|
+
* them so the agent's tool-call accounting stays consistent.
|
|
64
|
+
* Defaults to `true`.
|
|
65
|
+
*/
|
|
66
|
+
autoCancelPendingToolCalls?: boolean | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Routes the Cancel button's click to `useStream().stop()`. On by
|
|
69
|
+
* default. Pass `false` to disable the Cancel button.
|
|
70
|
+
*/
|
|
71
|
+
unstable_allowCancellation?: boolean | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Custom `RemoteThreadListAdapter`. When provided, replaces the
|
|
74
|
+
* cloud-backed thread list adapter.
|
|
75
|
+
*/
|
|
76
|
+
unstable_threadListAdapter?: RemoteThreadListAdapter | undefined;
|
|
77
|
+
/** Custom thread-creation hook, forwarded to the cloud adapter. */
|
|
78
|
+
create?: (() => Promise<{ externalId: string | undefined }>) | undefined;
|
|
79
|
+
/** Custom thread-deletion hook, forwarded to the cloud adapter. */
|
|
80
|
+
delete?: ((threadId: string) => Promise<void>) | undefined;
|
|
60
81
|
};
|
|
61
82
|
|
|
83
|
+
const getPendingToolCalls = (
|
|
84
|
+
messages: readonly LangChainBaseMessage[],
|
|
85
|
+
): LangChainToolCall[] => {
|
|
86
|
+
const pending = new Map<string, LangChainToolCall>();
|
|
87
|
+
for (const m of messages) {
|
|
88
|
+
const type = getMessageType(m);
|
|
89
|
+
if (type === "ai") {
|
|
90
|
+
for (const tc of m.tool_calls ?? []) pending.set(tc.id, tc);
|
|
91
|
+
} else if (type === "tool" && m.tool_call_id) {
|
|
92
|
+
pending.delete(m.tool_call_id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [...pending.values()];
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Distribute the intersection through the union arms of `UseStreamOptions`
|
|
99
|
+
// (`AgentServerOptions | CustomAdapterOptions`). Writing `UseStreamOptions & X`
|
|
100
|
+
// directly collapses arm tracking, so `Omit<…, "cloud">` and the like would
|
|
101
|
+
// produce a flattened structural type that no longer matches either arm.
|
|
102
|
+
export type UseStreamRuntimeOptions = UseStreamOptions extends infer O
|
|
103
|
+
? O extends UseStreamOptions
|
|
104
|
+
? O & LangChainRuntimeExtraOptions
|
|
105
|
+
: never
|
|
106
|
+
: never;
|
|
107
|
+
|
|
62
108
|
const getMessageContent = (msg: AppendMessage) => {
|
|
63
109
|
const allContent = [
|
|
64
110
|
...msg.content,
|
|
@@ -106,21 +152,31 @@ const getMessageContent = (msg: AppendMessage) => {
|
|
|
106
152
|
return content;
|
|
107
153
|
};
|
|
108
154
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
155
|
+
type DistributiveOmit<T, K extends keyof any> = T extends unknown
|
|
156
|
+
? Omit<T, K>
|
|
157
|
+
: never;
|
|
158
|
+
|
|
159
|
+
const useStreamThreadRuntime = (
|
|
160
|
+
options: DistributiveOmit<
|
|
161
|
+
UseStreamRuntimeOptions,
|
|
162
|
+
"cloud" | "unstable_threadListAdapter" | "create" | "delete"
|
|
163
|
+
>,
|
|
164
|
+
) => {
|
|
165
|
+
const { adapters, autoCancelPendingToolCalls, unstable_allowCancellation } =
|
|
166
|
+
options;
|
|
167
|
+
const messagesKey = options.messagesKey ?? "messages";
|
|
168
|
+
|
|
114
169
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
115
170
|
const externalId = useAuiState((s) => s.threadListItem.externalId) as
|
|
116
171
|
| string
|
|
117
172
|
| null;
|
|
173
|
+
// Mutate in place rather than `{ ...options, threadId }`: spreading
|
|
174
|
+
// `UseStreamOptions` (a discriminated union on `transport`) into an object
|
|
175
|
+
// literal merges both arms' transport types, breaking arm assignment.
|
|
176
|
+
options.threadId = externalId;
|
|
118
177
|
|
|
119
178
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
120
|
-
const stream = useStream(
|
|
121
|
-
...streamOptions,
|
|
122
|
-
threadId: externalId,
|
|
123
|
-
});
|
|
179
|
+
const stream = useStream(options);
|
|
124
180
|
|
|
125
181
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
126
182
|
const [toolStatuses, setToolStatuses] = useState<
|
|
@@ -185,8 +241,15 @@ const useStreamThreadRuntime = ({
|
|
|
185
241
|
interrupts: stream.interrupts,
|
|
186
242
|
submit: stream.submit,
|
|
187
243
|
values: stream.values,
|
|
244
|
+
messagesKey,
|
|
188
245
|
}),
|
|
189
|
-
[
|
|
246
|
+
[
|
|
247
|
+
stream.interrupt,
|
|
248
|
+
stream.interrupts,
|
|
249
|
+
stream.submit,
|
|
250
|
+
stream.values,
|
|
251
|
+
messagesKey,
|
|
252
|
+
],
|
|
190
253
|
);
|
|
191
254
|
|
|
192
255
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
@@ -198,8 +261,20 @@ const useStreamThreadRuntime = ({
|
|
|
198
261
|
onNew: async (msg) => {
|
|
199
262
|
await toolInvocations.abort();
|
|
200
263
|
const content = getMessageContent(msg);
|
|
264
|
+
const cancellations =
|
|
265
|
+
autoCancelPendingToolCalls !== false
|
|
266
|
+
? getPendingToolCalls(
|
|
267
|
+
streamRef.current.messages as readonly LangChainBaseMessage[],
|
|
268
|
+
).map((t) => ({
|
|
269
|
+
type: "tool" as const,
|
|
270
|
+
name: t.name,
|
|
271
|
+
tool_call_id: t.id,
|
|
272
|
+
content: JSON.stringify({ cancelled: true }),
|
|
273
|
+
status: "error" as const,
|
|
274
|
+
}))
|
|
275
|
+
: [];
|
|
201
276
|
await stream.submit({
|
|
202
|
-
[messagesKey]: [{ type: "human", content }],
|
|
277
|
+
[messagesKey]: [...cancellations, { type: "human", content }],
|
|
203
278
|
});
|
|
204
279
|
},
|
|
205
280
|
onAddToolResult: async ({
|
|
@@ -222,10 +297,13 @@ const useStreamThreadRuntime = ({
|
|
|
222
297
|
],
|
|
223
298
|
});
|
|
224
299
|
},
|
|
225
|
-
onCancel:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
300
|
+
onCancel:
|
|
301
|
+
unstable_allowCancellation !== false
|
|
302
|
+
? async () => {
|
|
303
|
+
await stream.stop();
|
|
304
|
+
await toolInvocations.abort();
|
|
305
|
+
}
|
|
306
|
+
: undefined,
|
|
229
307
|
});
|
|
230
308
|
|
|
231
309
|
return runtime;
|
|
@@ -255,20 +333,31 @@ const useStreamThreadRuntime = ({
|
|
|
255
333
|
* }
|
|
256
334
|
* ```
|
|
257
335
|
*/
|
|
258
|
-
export const useStreamRuntime = ({
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
336
|
+
export const useStreamRuntime = (rawOptions: UseStreamRuntimeOptions) => {
|
|
337
|
+
const {
|
|
338
|
+
cloud,
|
|
339
|
+
unstable_threadListAdapter,
|
|
340
|
+
create,
|
|
341
|
+
delete: deleteFn,
|
|
342
|
+
...options
|
|
343
|
+
} = rawOptions;
|
|
344
|
+
|
|
262
345
|
const optionsRef = useRef(options);
|
|
263
346
|
optionsRef.current = options;
|
|
264
347
|
|
|
265
|
-
const cloudAdapter = useCloudThreadListAdapter({
|
|
348
|
+
const cloudAdapter = useCloudThreadListAdapter({
|
|
349
|
+
cloud,
|
|
350
|
+
create,
|
|
351
|
+
delete: deleteFn,
|
|
352
|
+
});
|
|
353
|
+
const adapter = unstable_threadListAdapter ?? cloudAdapter;
|
|
354
|
+
|
|
266
355
|
return useRemoteThreadListRuntime({
|
|
267
356
|
runtimeHook: function RuntimeHook() {
|
|
268
357
|
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
269
358
|
return useStreamThreadRuntime(optionsRef.current);
|
|
270
359
|
},
|
|
271
|
-
adapter
|
|
360
|
+
adapter,
|
|
272
361
|
allowNesting: true,
|
|
273
362
|
});
|
|
274
363
|
};
|
|
@@ -301,6 +390,36 @@ export const useLangChainSubmit = () => {
|
|
|
301
390
|
};
|
|
302
391
|
};
|
|
303
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Submit a list of LangChain-shaped messages on the current thread.
|
|
395
|
+
* Parity helper for migrating from `useLangGraphSend`. Routes to
|
|
396
|
+
* `useStream().submit({ [messagesKey]: messages }, options)`.
|
|
397
|
+
*/
|
|
398
|
+
export const useLangChainSend = () => {
|
|
399
|
+
const aui = useAui();
|
|
400
|
+
return (
|
|
401
|
+
messages: readonly LangChainBaseMessage[],
|
|
402
|
+
options?: Record<string, unknown>,
|
|
403
|
+
) => {
|
|
404
|
+
const { submit, messagesKey } = asLangChainRuntimeExtras(
|
|
405
|
+
aui.thread().getState().extras,
|
|
406
|
+
);
|
|
407
|
+
return submit({ [messagesKey]: messages }, options);
|
|
408
|
+
};
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Submit a `useStream` command (e.g. interrupt resume). Parity helper
|
|
413
|
+
* for migrating from `useLangGraphSendCommand`. Note that v1's command
|
|
414
|
+
* shape (`{ resume?, goto?, update? }`) differs from the legacy
|
|
415
|
+
* `{ resume: string }` form — to carry a payload, use the input or
|
|
416
|
+
* `stream.respond` instead.
|
|
417
|
+
*/
|
|
418
|
+
export const useLangChainSendCommand = () => {
|
|
419
|
+
const submit = useLangChainSubmit();
|
|
420
|
+
return (command: Record<string, unknown>) => submit(null, { command });
|
|
421
|
+
};
|
|
422
|
+
|
|
304
423
|
/**
|
|
305
424
|
* Read a custom LangGraph state key from the current thread. Mirrors
|
|
306
425
|
* `useStream().values[key]` from `@langchain/react` and updates when the
|