@assistant-ui/react-langchain 0.0.30 → 0.0.32
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 +1 -1
- package/dist/attachSubagentTranscripts.d.ts +24 -0
- package/dist/attachSubagentTranscripts.d.ts.map +1 -0
- package/dist/attachSubagentTranscripts.js +43 -0
- package/dist/attachSubagentTranscripts.js.map +1 -0
- package/dist/convertMessages.d.ts +4 -4
- package/dist/convertMessages.d.ts.map +1 -1
- package/dist/converter.d.ts +10 -11
- package/dist/converter.d.ts.map +1 -1
- package/dist/findForkCheckpointInHistory.d.ts +2 -3
- package/dist/findForkCheckpointInHistory.d.ts.map +1 -1
- package/dist/hooks.d.ts +14 -15
- package/dist/hooks.d.ts.map +1 -1
- package/dist/resolveForkCheckpoint.d.ts +1 -2
- package/dist/resolveForkCheckpoint.d.ts.map +1 -1
- package/dist/runtimeExtras.d.ts +1 -2
- package/dist/runtimeExtras.d.ts.map +1 -1
- package/dist/sdkIdentity.d.ts +5 -0
- package/dist/sdkIdentity.d.ts.map +1 -0
- package/dist/sdkIdentity.js +9 -0
- package/dist/sdkIdentity.js.map +1 -0
- package/dist/streamingTiming.d.ts +2 -3
- package/dist/streamingTiming.d.ts.map +1 -1
- package/dist/types.d.ts +8 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/uiMessages.d.ts +22 -7
- package/dist/uiMessages.d.ts.map +1 -1
- package/dist/uiMessages.js +23 -5
- package/dist/uiMessages.js.map +1 -1
- package/dist/useStreamRuntime.d.ts +3 -3
- package/dist/useStreamRuntime.d.ts.map +1 -1
- package/dist/useStreamRuntime.js +26 -17
- package/dist/useStreamRuntime.js.map +1 -1
- package/dist/useSubagentTranscripts.d.ts +8 -0
- package/dist/useSubagentTranscripts.d.ts.map +1 -0
- package/dist/useSubagentTranscripts.js +265 -0
- package/dist/useSubagentTranscripts.js.map +1 -0
- package/package.json +17 -12
- package/src/attachSubagentTranscripts.test.ts +198 -0
- package/src/attachSubagentTranscripts.ts +91 -0
- package/src/sdkIdentity.ts +9 -0
- package/src/uiMessages.test.ts +43 -0
- package/src/uiMessages.ts +36 -4
- package/src/useStreamRuntime.test.tsx +218 -7
- package/src/useStreamRuntime.ts +40 -16
- package/src/useSubagentTranscripts.test.tsx +1258 -0
- package/src/useSubagentTranscripts.ts +526 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
|
|
3
3
|
import { act, render, renderHook, waitFor } from "@testing-library/react";
|
|
4
|
-
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import { AssistantRuntimeProvider } from "@assistant-ui/core/react";
|
|
6
6
|
import type {
|
|
7
7
|
AssistantRuntime,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "./hooks";
|
|
21
21
|
|
|
22
22
|
const { mockUseChannel, mockUseStream, streamController } = vi.hoisted(() => ({
|
|
23
|
-
mockUseChannel: vi.fn(() => []),
|
|
23
|
+
mockUseChannel: vi.fn((): unknown[] => []),
|
|
24
24
|
mockUseStream: vi.fn(),
|
|
25
25
|
streamController: Symbol("STREAM_CONTROLLER"),
|
|
26
26
|
}));
|
|
@@ -40,7 +40,7 @@ type MockStream = {
|
|
|
40
40
|
values: Record<string, unknown>;
|
|
41
41
|
interrupts: unknown[];
|
|
42
42
|
toolCalls: unknown[];
|
|
43
|
-
subagents: unknown
|
|
43
|
+
subagents: ReadonlyMap<string, unknown>;
|
|
44
44
|
subgraphs: unknown[];
|
|
45
45
|
error: unknown;
|
|
46
46
|
submit: ReturnType<typeof vi.fn>;
|
|
@@ -53,6 +53,10 @@ type MockStream = {
|
|
|
53
53
|
messageMetadataStore: {
|
|
54
54
|
getSnapshot: ReturnType<typeof vi.fn>;
|
|
55
55
|
};
|
|
56
|
+
resolveSubagentNamespace: ReturnType<typeof vi.fn>;
|
|
57
|
+
registry: {
|
|
58
|
+
acquire: ReturnType<typeof vi.fn>;
|
|
59
|
+
};
|
|
56
60
|
};
|
|
57
61
|
};
|
|
58
62
|
|
|
@@ -75,7 +79,7 @@ const createMockStream = (
|
|
|
75
79
|
values: {},
|
|
76
80
|
interrupts: [],
|
|
77
81
|
toolCalls: [],
|
|
78
|
-
subagents:
|
|
82
|
+
subagents: new Map(),
|
|
79
83
|
subgraphs: [],
|
|
80
84
|
error: undefined,
|
|
81
85
|
submit: vi.fn(async () => {}),
|
|
@@ -88,6 +92,10 @@ const createMockStream = (
|
|
|
88
92
|
messageMetadataStore: {
|
|
89
93
|
getSnapshot: vi.fn(),
|
|
90
94
|
},
|
|
95
|
+
resolveSubagentNamespace: vi.fn(async () => {}),
|
|
96
|
+
registry: {
|
|
97
|
+
acquire: vi.fn(),
|
|
98
|
+
},
|
|
91
99
|
},
|
|
92
100
|
});
|
|
93
101
|
|
|
@@ -177,7 +185,11 @@ describe("useStreamRuntime thread options", () => {
|
|
|
177
185
|
unstable_threadListAdapter: threadListAdapter,
|
|
178
186
|
} as never);
|
|
179
187
|
capture.runtime = runtime;
|
|
180
|
-
return
|
|
188
|
+
return (
|
|
189
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
190
|
+
{null}
|
|
191
|
+
</AssistantRuntimeProvider>
|
|
192
|
+
);
|
|
181
193
|
};
|
|
182
194
|
|
|
183
195
|
const view = render(<TestRuntime />);
|
|
@@ -286,7 +298,11 @@ describe("useStreamRuntime thread options", () => {
|
|
|
286
298
|
const TestRuntime = () => {
|
|
287
299
|
const runtime = useStreamRuntime({ apiUrl: "/api" } as never);
|
|
288
300
|
capture.runtime = runtime;
|
|
289
|
-
return
|
|
301
|
+
return (
|
|
302
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
303
|
+
{null}
|
|
304
|
+
</AssistantRuntimeProvider>
|
|
305
|
+
);
|
|
290
306
|
};
|
|
291
307
|
const view = render(<TestRuntime />);
|
|
292
308
|
await waitFor(() => expect(capture.runtime).not.toBeNull());
|
|
@@ -721,7 +737,9 @@ describe("useStreamRuntime run configuration", () => {
|
|
|
721
737
|
});
|
|
722
738
|
|
|
723
739
|
await act(async () => {
|
|
724
|
-
await capture.send!([
|
|
740
|
+
await capture.send!([
|
|
741
|
+
{ type: "human", content: "next" } as unknown as LangChainBaseMessage,
|
|
742
|
+
]);
|
|
725
743
|
});
|
|
726
744
|
|
|
727
745
|
expect(stream.submit).toHaveBeenLastCalledWith(
|
|
@@ -971,3 +989,196 @@ describe("useStreamRuntime committed refs", () => {
|
|
|
971
989
|
host.unmount();
|
|
972
990
|
});
|
|
973
991
|
});
|
|
992
|
+
|
|
993
|
+
describe("useStreamRuntime subagent transcripts", () => {
|
|
994
|
+
afterEach(() => {
|
|
995
|
+
mockUseChannel.mockReset();
|
|
996
|
+
});
|
|
997
|
+
|
|
998
|
+
it("renders live UI messages inside the transcript of the subagent that pushed them", async () => {
|
|
999
|
+
const stream = createMockStream([
|
|
1000
|
+
message("human-1", "human", "delegate"),
|
|
1001
|
+
{
|
|
1002
|
+
id: "root-ai",
|
|
1003
|
+
_getType: () => "ai",
|
|
1004
|
+
content: "",
|
|
1005
|
+
tool_calls: [{ id: "task-one", name: "task", args: {} }],
|
|
1006
|
+
},
|
|
1007
|
+
]);
|
|
1008
|
+
const transcript = [message("nested-ai", "ai", "nested answer")];
|
|
1009
|
+
stream.subagents = new Map([
|
|
1010
|
+
[
|
|
1011
|
+
"task-one",
|
|
1012
|
+
{
|
|
1013
|
+
id: "task-one",
|
|
1014
|
+
namespace: ["tools:task-one"],
|
|
1015
|
+
status: "running",
|
|
1016
|
+
parentId: null,
|
|
1017
|
+
depth: 1,
|
|
1018
|
+
startedAt: new Date(1_000),
|
|
1019
|
+
completedAt: null,
|
|
1020
|
+
},
|
|
1021
|
+
],
|
|
1022
|
+
]);
|
|
1023
|
+
stream[streamController]!.registry.acquire.mockReturnValue({
|
|
1024
|
+
store: { getSnapshot: () => transcript, subscribe: () => () => {} },
|
|
1025
|
+
release: vi.fn(),
|
|
1026
|
+
});
|
|
1027
|
+
const uiEvent = {
|
|
1028
|
+
method: "custom",
|
|
1029
|
+
params: {
|
|
1030
|
+
namespace: ["tools:task-one"],
|
|
1031
|
+
data: {
|
|
1032
|
+
type: "ui",
|
|
1033
|
+
id: "ui-1",
|
|
1034
|
+
name: "chart",
|
|
1035
|
+
props: { points: [1, 2] },
|
|
1036
|
+
metadata: { message_id: "nested-ai" },
|
|
1037
|
+
},
|
|
1038
|
+
},
|
|
1039
|
+
};
|
|
1040
|
+
mockUseChannel.mockReturnValue([uiEvent]);
|
|
1041
|
+
const { auiResult, rerender } = renderAui(stream);
|
|
1042
|
+
const nestedTranscript = () => {
|
|
1043
|
+
const { messages } = auiResult.current.thread.getState();
|
|
1044
|
+
for (const threadMessage of messages) {
|
|
1045
|
+
for (const part of threadMessage.content) {
|
|
1046
|
+
if (part.type === "tool-call" && part.toolCallId === "task-one")
|
|
1047
|
+
return part.messages;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return undefined;
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
await waitFor(() =>
|
|
1054
|
+
expect(nestedTranscript()?.[0]?.content).toMatchObject([
|
|
1055
|
+
{ type: "text", text: "nested answer" },
|
|
1056
|
+
{ type: "data", name: "chart", data: { points: [1, 2] } },
|
|
1057
|
+
]),
|
|
1058
|
+
);
|
|
1059
|
+
const rendered = nestedTranscript();
|
|
1060
|
+
|
|
1061
|
+
mockUseChannel.mockReturnValue([
|
|
1062
|
+
uiEvent,
|
|
1063
|
+
{
|
|
1064
|
+
method: "custom",
|
|
1065
|
+
params: { namespace: [], data: { name: "progress", payload: 1 } },
|
|
1066
|
+
},
|
|
1067
|
+
]);
|
|
1068
|
+
await act(async () => {
|
|
1069
|
+
rerender();
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
expect(nestedTranscript()).toBe(rendered);
|
|
1073
|
+
});
|
|
1074
|
+
|
|
1075
|
+
it("keeps messages and transcripts when custom events carry no UI update", async () => {
|
|
1076
|
+
const stream = createMockStream([
|
|
1077
|
+
message("human-1", "human", "delegate"),
|
|
1078
|
+
{
|
|
1079
|
+
id: "root-ai",
|
|
1080
|
+
_getType: () => "ai",
|
|
1081
|
+
content: "",
|
|
1082
|
+
tool_calls: [{ id: "task-one", name: "task", args: {} }],
|
|
1083
|
+
},
|
|
1084
|
+
]);
|
|
1085
|
+
const transcript = [message("nested-ai", "ai", "nested answer")];
|
|
1086
|
+
stream.subagents = new Map([
|
|
1087
|
+
[
|
|
1088
|
+
"task-one",
|
|
1089
|
+
{
|
|
1090
|
+
id: "task-one",
|
|
1091
|
+
namespace: ["tools:task-one"],
|
|
1092
|
+
status: "running",
|
|
1093
|
+
parentId: null,
|
|
1094
|
+
depth: 1,
|
|
1095
|
+
startedAt: new Date(1_000),
|
|
1096
|
+
completedAt: null,
|
|
1097
|
+
},
|
|
1098
|
+
],
|
|
1099
|
+
]);
|
|
1100
|
+
stream[streamController]!.registry.acquire.mockReturnValue({
|
|
1101
|
+
store: { getSnapshot: () => transcript, subscribe: () => () => {} },
|
|
1102
|
+
release: vi.fn(),
|
|
1103
|
+
});
|
|
1104
|
+
const chartEvent = (
|
|
1105
|
+
props: Record<string, unknown>,
|
|
1106
|
+
metadata: Record<string, unknown> = {},
|
|
1107
|
+
) => ({
|
|
1108
|
+
method: "custom",
|
|
1109
|
+
params: {
|
|
1110
|
+
namespace: ["tools:task-one"],
|
|
1111
|
+
data: {
|
|
1112
|
+
type: "ui",
|
|
1113
|
+
id: "ui-1",
|
|
1114
|
+
name: "chart",
|
|
1115
|
+
props,
|
|
1116
|
+
metadata: { message_id: "nested-ai", ...metadata },
|
|
1117
|
+
},
|
|
1118
|
+
},
|
|
1119
|
+
});
|
|
1120
|
+
const events = [
|
|
1121
|
+
chartEvent({ points: [1, 2] }),
|
|
1122
|
+
chartEvent({ label: "first" }, { merge: true }),
|
|
1123
|
+
];
|
|
1124
|
+
mockUseChannel.mockReturnValue(events);
|
|
1125
|
+
const { auiResult, rerender } = renderAui(stream);
|
|
1126
|
+
const nestedTranscript = () => {
|
|
1127
|
+
const { messages } = auiResult.current.thread.getState();
|
|
1128
|
+
for (const threadMessage of messages) {
|
|
1129
|
+
for (const part of threadMessage.content) {
|
|
1130
|
+
if (part.type === "tool-call" && part.toolCallId === "task-one")
|
|
1131
|
+
return part.messages;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return undefined;
|
|
1135
|
+
};
|
|
1136
|
+
|
|
1137
|
+
await waitFor(() =>
|
|
1138
|
+
expect(nestedTranscript()?.[0]?.content).toMatchObject([
|
|
1139
|
+
{ type: "text", text: "nested answer" },
|
|
1140
|
+
{
|
|
1141
|
+
type: "data",
|
|
1142
|
+
name: "chart",
|
|
1143
|
+
data: { points: [1, 2], label: "first" },
|
|
1144
|
+
},
|
|
1145
|
+
]),
|
|
1146
|
+
);
|
|
1147
|
+
const [human, ai] = auiResult.current.thread.getState().messages;
|
|
1148
|
+
const rendered = nestedTranscript();
|
|
1149
|
+
|
|
1150
|
+
const withProgress = [
|
|
1151
|
+
...events,
|
|
1152
|
+
{
|
|
1153
|
+
method: "custom",
|
|
1154
|
+
params: { namespace: [], data: { name: "progress", payload: 1 } },
|
|
1155
|
+
},
|
|
1156
|
+
];
|
|
1157
|
+
mockUseChannel.mockReturnValue(withProgress);
|
|
1158
|
+
await act(async () => {
|
|
1159
|
+
rerender();
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1162
|
+
const messages = auiResult.current.thread.getState().messages;
|
|
1163
|
+
expect(messages[0]).toBe(human);
|
|
1164
|
+
expect(messages[1]).toBe(ai);
|
|
1165
|
+
expect(nestedTranscript()).toBe(rendered);
|
|
1166
|
+
|
|
1167
|
+
mockUseChannel.mockReturnValue([
|
|
1168
|
+
...withProgress,
|
|
1169
|
+
chartEvent({ label: "second" }, { merge: true }),
|
|
1170
|
+
]);
|
|
1171
|
+
await act(async () => {
|
|
1172
|
+
rerender();
|
|
1173
|
+
});
|
|
1174
|
+
|
|
1175
|
+
expect(nestedTranscript()?.[0]?.content).toMatchObject([
|
|
1176
|
+
{ type: "text", text: "nested answer" },
|
|
1177
|
+
{
|
|
1178
|
+
type: "data",
|
|
1179
|
+
name: "chart",
|
|
1180
|
+
data: { points: [1, 2], label: "second" },
|
|
1181
|
+
},
|
|
1182
|
+
]);
|
|
1183
|
+
});
|
|
1184
|
+
});
|
package/src/useStreamRuntime.ts
CHANGED
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
} from "@assistant-ui/core/react";
|
|
30
30
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
31
31
|
import { STREAM_CONTROLLER, useChannel, useStream } from "@langchain/react";
|
|
32
|
-
import type { Channel } from "@langchain/react";
|
|
33
32
|
import type {
|
|
34
33
|
LangChainBaseMessage,
|
|
35
34
|
LangChainToolCall,
|
|
@@ -43,12 +42,21 @@ import {
|
|
|
43
42
|
getMessageContent,
|
|
44
43
|
getMessageType,
|
|
45
44
|
} from "./convertMessages";
|
|
46
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
attachSubagentTranscripts,
|
|
47
|
+
createAttachMemo,
|
|
48
|
+
} from "./attachSubagentTranscripts";
|
|
49
|
+
import { useSubagentTranscripts } from "./useSubagentTranscripts";
|
|
50
|
+
import {
|
|
51
|
+
createUIFoldMemo,
|
|
52
|
+
foldUIUpdates,
|
|
53
|
+
mergeUIMessages,
|
|
54
|
+
UI_CUSTOM_CHANNELS,
|
|
55
|
+
} from "./uiMessages";
|
|
47
56
|
import { langChainExtras } from "./runtimeExtras";
|
|
48
57
|
import { resolveForkCheckpoint } from "./resolveForkCheckpoint";
|
|
49
58
|
import { useLangChainStreamingTiming } from "./streamingTiming";
|
|
50
|
-
|
|
51
|
-
const UI_CUSTOM_CHANNELS: readonly Channel[] = ["custom"];
|
|
59
|
+
import { LANGCHAIN_SDK } from "./sdkIdentity";
|
|
52
60
|
|
|
53
61
|
export const runConfigToSubmitOptions = (
|
|
54
62
|
runConfig: AppendMessage["runConfig"],
|
|
@@ -161,9 +169,10 @@ const useStreamThreadRuntime = (
|
|
|
161
169
|
const uiStateValue = stream.values[uiStateKey];
|
|
162
170
|
|
|
163
171
|
const customEvents = useChannel(stream, UI_CUSTOM_CHANNELS);
|
|
172
|
+
const [uiFoldMemo] = useState(createUIFoldMemo);
|
|
164
173
|
const liveUiMessages = useMemo(
|
|
165
|
-
() => foldUIUpdates(customEvents),
|
|
166
|
-
[customEvents],
|
|
174
|
+
() => foldUIUpdates(customEvents, uiFoldMemo),
|
|
175
|
+
[customEvents, uiFoldMemo],
|
|
167
176
|
);
|
|
168
177
|
|
|
169
178
|
const mergedUiMessages = useMemo(
|
|
@@ -171,6 +180,11 @@ const useStreamThreadRuntime = (
|
|
|
171
180
|
[liveUiMessages, uiStateValue],
|
|
172
181
|
);
|
|
173
182
|
|
|
183
|
+
const uiMessagesByParent = useMemo(
|
|
184
|
+
() => groupUIMessagesByParent<UIMessage>(mergedUiMessages),
|
|
185
|
+
[mergedUiMessages],
|
|
186
|
+
);
|
|
187
|
+
|
|
174
188
|
const visibleMessages =
|
|
175
189
|
stagedMessages ?? (stream.messages as LangChainBaseMessage[]);
|
|
176
190
|
|
|
@@ -179,24 +193,33 @@ const useStreamThreadRuntime = (
|
|
|
179
193
|
effectiveIsRunning,
|
|
180
194
|
);
|
|
181
195
|
|
|
196
|
+
const subagentTranscripts = useSubagentTranscripts(
|
|
197
|
+
stream,
|
|
198
|
+
uiMessagesByParent,
|
|
199
|
+
);
|
|
200
|
+
|
|
182
201
|
const convertWithUI = useMemo<
|
|
183
202
|
useExternalMessageConverter.Callback<LangChainBaseMessage>
|
|
184
|
-
>(
|
|
185
|
-
|
|
186
|
-
groupUIMessagesByParent<UIMessage>(mergedUiMessages);
|
|
187
|
-
return (message, metadata) =>
|
|
203
|
+
>(
|
|
204
|
+
() => (message, metadata) =>
|
|
188
205
|
convertLangChainBaseMessage(message, {
|
|
189
206
|
...metadata,
|
|
190
207
|
uiMessagesByParent,
|
|
191
208
|
messageTiming,
|
|
192
|
-
})
|
|
193
|
-
|
|
209
|
+
}),
|
|
210
|
+
[uiMessagesByParent, messageTiming],
|
|
211
|
+
);
|
|
194
212
|
|
|
195
213
|
const threadMessages = useExternalMessageConverter({
|
|
196
214
|
callback: convertWithUI,
|
|
197
215
|
messages: visibleMessages,
|
|
198
216
|
isRunning: effectiveIsRunning,
|
|
199
217
|
});
|
|
218
|
+
const [memo] = useState(createAttachMemo);
|
|
219
|
+
const messagesWithTranscripts = useMemo(
|
|
220
|
+
() => attachSubagentTranscripts(threadMessages, subagentTranscripts, memo),
|
|
221
|
+
[threadMessages, subagentTranscripts, memo],
|
|
222
|
+
);
|
|
200
223
|
|
|
201
224
|
const streamRef = useRef(stream);
|
|
202
225
|
useInsertionEffect(() => {
|
|
@@ -269,10 +292,10 @@ const useStreamThreadRuntime = (
|
|
|
269
292
|
visibleMessagesRef.current = visibleMessages;
|
|
270
293
|
}, [visibleMessages]);
|
|
271
294
|
|
|
272
|
-
const threadMessagesRef = useRef(
|
|
295
|
+
const threadMessagesRef = useRef(messagesWithTranscripts);
|
|
273
296
|
useInsertionEffect(() => {
|
|
274
|
-
threadMessagesRef.current =
|
|
275
|
-
}, [
|
|
297
|
+
threadMessagesRef.current = messagesWithTranscripts;
|
|
298
|
+
}, [messagesWithTranscripts]);
|
|
276
299
|
|
|
277
300
|
const stagedMessagesRef = useRef(
|
|
278
301
|
new Map<
|
|
@@ -412,7 +435,7 @@ const useStreamThreadRuntime = (
|
|
|
412
435
|
...pickExternalStoreSharedOptions(options),
|
|
413
436
|
isRunning: stream.isLoading,
|
|
414
437
|
isLoading: stream.isThreadLoading,
|
|
415
|
-
messages:
|
|
438
|
+
messages: messagesWithTranscripts,
|
|
416
439
|
adapters,
|
|
417
440
|
extras,
|
|
418
441
|
unstable_enableToolInvocations: true,
|
|
@@ -631,6 +654,7 @@ export const useStreamRuntime = (rawOptions: UseStreamRuntimeOptions) => {
|
|
|
631
654
|
|
|
632
655
|
const aui = useAui();
|
|
633
656
|
const cloudAdapter = useCloudThreadListAdapter({
|
|
657
|
+
sdk: LANGCHAIN_SDK,
|
|
634
658
|
cloud,
|
|
635
659
|
create: createCloudThreadListAdapterCreateFallback(
|
|
636
660
|
create,
|