@assistant-ui/react-langchain 0.0.34 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LangChainThreadController.d.ts +9 -0
- package/dist/LangChainThreadController.d.ts.map +1 -0
- package/dist/LangChainThreadController.js +21 -0
- package/dist/LangChainThreadController.js.map +1 -0
- package/dist/convertMessages.d.ts +2 -1
- package/dist/convertMessages.d.ts.map +1 -1
- package/dist/convertMessages.js +12 -12
- package/dist/convertMessages.js.map +1 -1
- package/dist/converter.d.ts +24 -1
- package/dist/converter.d.ts.map +1 -1
- package/dist/converter.js +84 -18
- package/dist/converter.js.map +1 -1
- package/dist/langChainThreadState.d.ts +54 -0
- package/dist/langChainThreadState.d.ts.map +1 -0
- package/dist/langChainThreadState.js +135 -0
- package/dist/langChainThreadState.js.map +1 -0
- package/dist/sdkIdentity.js +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useStreamRuntime.d.ts +3 -2
- package/dist/useStreamRuntime.d.ts.map +1 -1
- package/dist/useStreamRuntime.js +159 -144
- package/dist/useStreamRuntime.js.map +1 -1
- package/dist/useSubagentTranscripts.js +1 -1
- package/package.json +9 -8
- package/src/LangChainThreadController.ts +24 -0
- package/src/convertMessages.test.ts +23 -0
- package/src/convertMessages.ts +43 -17
- package/src/converter.test.ts +322 -0
- package/src/converter.ts +138 -27
- package/src/getPendingToolCalls.test.ts +35 -0
- package/src/langChainThreadState.test.ts +203 -0
- package/src/langChainThreadState.ts +239 -0
- package/src/types.ts +9 -0
- package/src/useStreamRuntime.cloud-options.test.tsx +61 -0
- package/src/useStreamRuntime.test.tsx +296 -8
- package/src/useStreamRuntime.ts +221 -249
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"langChainThreadState.js","names":[],"sources":["../src/langChainThreadState.ts"],"sourcesContent":["import type { AppendMessage } from \"@assistant-ui/core\";\nimport type { LangChainBaseMessage } from \"./types\";\nimport { getMessageType } from \"./convertMessages\";\n\nexport type StagedMessage = LangChainBaseMessage & { id: string };\n\nexport type StagedEntry = {\n message: StagedMessage;\n runConfig: AppendMessage[\"runConfig\"];\n reconcileOnEcho: boolean;\n baseMessageCount: number;\n transcriptStatus?: \"unsent\" | \"sent\";\n};\n\nexport type LangChainThreadState = {\n forkGeneration: number;\n forkPending: boolean;\n stagedEntries: ReadonlyMap<string, StagedEntry>;\n stagedBaseMessages: LangChainBaseMessage[] | null;\n visibleStagedMessages: LangChainBaseMessage[] | null;\n};\n\nexport type LangChainThreadAction =\n | { type: \"supersedeFork\" }\n | { type: \"finishFork\"; generation: number }\n | { type: \"cancelFork\" }\n | {\n type: \"stage\";\n entry: StagedEntry;\n visibleMessages: readonly LangChainBaseMessage[];\n }\n | {\n type: \"stageEdit\";\n entry: StagedEntry;\n baseMessages: LangChainBaseMessage[];\n }\n | {\n type: \"reconcile\";\n messages: LangChainBaseMessage[];\n visibleMessages: readonly LangChainBaseMessage[];\n }\n | {\n type: \"markTranscript\";\n messages: readonly LangChainBaseMessage[];\n status: \"unsent\" | \"sent\";\n }\n | {\n type: \"remove\";\n id: string;\n visibleMessages: readonly LangChainBaseMessage[];\n }\n | {\n type: \"promote\";\n messages: readonly LangChainBaseMessage[];\n visibleMessages: readonly LangChainBaseMessage[];\n };\n\nexport const createLangChainThreadState = (): LangChainThreadState => ({\n forkGeneration: 0,\n forkPending: false,\n stagedEntries: new Map(),\n stagedBaseMessages: null,\n visibleStagedMessages: null,\n});\n\nconst humanContentText = (content: LangChainBaseMessage[\"content\"]) => {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n return content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n typeof part === \"object\" &&\n part !== null &&\n part.type === \"text\" &&\n typeof part.text === \"string\",\n )\n .map((part) => part.text)\n .join(\"\");\n};\n\nconst hasSameMessageContent = (\n a: LangChainBaseMessage,\n b: LangChainBaseMessage,\n) => humanContentText(a.content) === humanContentText(b.content);\n\nexport const reduceLangChainThreadState = (\n state: LangChainThreadState,\n action: LangChainThreadAction,\n): LangChainThreadState => {\n switch (action.type) {\n case \"supersedeFork\":\n return {\n ...state,\n forkGeneration: state.forkGeneration + 1,\n forkPending: true,\n };\n case \"finishFork\":\n return state.forkGeneration === action.generation\n ? { ...state, forkPending: false }\n : state;\n case \"cancelFork\":\n return {\n ...state,\n forkGeneration: state.forkGeneration + 1,\n forkPending: false,\n };\n case \"stage\": {\n const stagedEntries = new Map(state.stagedEntries);\n stagedEntries.set(action.entry.message.id, action.entry);\n return {\n ...state,\n stagedEntries,\n visibleStagedMessages: [\n ...action.visibleMessages,\n action.entry.message,\n ],\n };\n }\n case \"stageEdit\": {\n const stagedEntries = new Map(state.stagedEntries);\n stagedEntries.set(action.entry.message.id, action.entry);\n return {\n ...state,\n stagedEntries,\n stagedBaseMessages: action.baseMessages,\n visibleStagedMessages: [...action.baseMessages, action.entry.message],\n };\n }\n case \"reconcile\": {\n if (state.stagedEntries.size === 0) return state;\n // Staged edits must keep their truncated base while stream updates arrive before promotion.\n const baseMessages = state.stagedBaseMessages ?? action.messages;\n const stagedEntries = new Map(state.stagedEntries);\n const remainingStagedMessages: LangChainBaseMessage[] = [];\n const matchedBaseMessageIndexes = new Set<number>();\n const visibleStagedIds = new Set(\n action.visibleMessages.flatMap((message) =>\n message.id ? [message.id] : [],\n ),\n );\n for (const [id, staged] of state.stagedEntries) {\n if (!visibleStagedIds.has(id)) continue;\n const echoed = baseMessages.some((message, index) => {\n if (matchedBaseMessageIndexes.has(index)) return false;\n if (message.id === id) {\n matchedBaseMessageIndexes.add(index);\n return true;\n }\n if (\n !staged.reconcileOnEcho ||\n index < staged.baseMessageCount ||\n getMessageType(message) !== \"human\" ||\n !hasSameMessageContent(message, staged.message)\n ) {\n return false;\n }\n matchedBaseMessageIndexes.add(index);\n return true;\n });\n if (echoed) stagedEntries.delete(id);\n else remainingStagedMessages.push(staged.message);\n }\n if (remainingStagedMessages.length === 0) {\n if (\n stagedEntries.size === state.stagedEntries.size &&\n state.stagedBaseMessages === null &&\n state.visibleStagedMessages === null\n ) {\n return state;\n }\n return {\n ...state,\n stagedEntries,\n stagedBaseMessages: null,\n visibleStagedMessages: null,\n };\n }\n return {\n ...state,\n stagedEntries,\n visibleStagedMessages: [...baseMessages, ...remainingStagedMessages],\n };\n }\n case \"markTranscript\": {\n let stagedEntries: Map<string, StagedEntry> | null = null;\n for (const message of action.messages) {\n const entry = message.id\n ? (stagedEntries ?? state.stagedEntries).get(message.id)\n : undefined;\n if (entry?.transcriptStatus) {\n stagedEntries ??= new Map(state.stagedEntries);\n stagedEntries.set(message.id!, {\n ...entry,\n transcriptStatus: action.status,\n });\n }\n }\n return stagedEntries ? { ...state, stagedEntries } : state;\n }\n case \"remove\": {\n if (!state.stagedEntries.has(action.id)) return state;\n const stagedEntries = new Map(state.stagedEntries);\n stagedEntries.delete(action.id);\n return {\n ...state,\n stagedEntries,\n stagedBaseMessages:\n stagedEntries.size === 0 ? null : state.stagedBaseMessages,\n visibleStagedMessages:\n stagedEntries.size === 0\n ? null\n : action.visibleMessages.filter(\n (message) => message.id !== action.id,\n ),\n };\n }\n case \"promote\": {\n const stagedEntries = new Map(state.stagedEntries);\n const promotedIds = new Set<string>();\n for (const message of action.messages) {\n if (!message.id || stagedEntries.get(message.id)?.transcriptStatus)\n continue;\n promotedIds.add(message.id);\n stagedEntries.delete(message.id);\n }\n return {\n ...state,\n stagedEntries,\n stagedBaseMessages: null,\n visibleStagedMessages:\n stagedEntries.size > 0\n ? action.visibleMessages.filter(\n (message) => !message.id || !promotedIds.has(message.id),\n )\n : null,\n };\n }\n }\n};\n"],"mappings":"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"}
|
package/dist/sdkIdentity.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -89,6 +89,11 @@ export type LangChainRuntimeExtraOptions = ExternalStoreSharedOptions & {
|
|
|
89
89
|
*/
|
|
90
90
|
onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;
|
|
91
91
|
cloud?: AssistantCloud | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Stable identity for the account or workspace owning Cloud runtime state.
|
|
94
|
+
* Provide it from the first render and change it when that scope changes.
|
|
95
|
+
*/
|
|
96
|
+
scopeId?: string | undefined;
|
|
92
97
|
adapters?: {
|
|
93
98
|
attachments?: AttachmentAdapter | undefined;
|
|
94
99
|
speech?: SpeechSynthesisAdapter | undefined;
|
|
@@ -106,11 +111,15 @@ export type LangChainRuntimeExtraOptions = ExternalStoreSharedOptions & {
|
|
|
106
111
|
/**
|
|
107
112
|
* Routes the Cancel button's click to `useStream().stop()`. On by
|
|
108
113
|
* default. Pass `false` to disable the Cancel button.
|
|
114
|
+
*
|
|
115
|
+
* @deprecated Experimental since 2025-01-03. Not scheduled for removal; the API may change in any release.
|
|
109
116
|
*/
|
|
110
117
|
unstable_allowCancellation?: boolean | undefined;
|
|
111
118
|
/**
|
|
112
119
|
* Custom `RemoteThreadListAdapter`. When provided, replaces the
|
|
113
120
|
* cloud-backed thread list adapter.
|
|
121
|
+
*
|
|
122
|
+
* @deprecated Experimental since 2026-04-16. Not scheduled for removal; the API may change in any release.
|
|
114
123
|
*/
|
|
115
124
|
unstable_threadListAdapter?: RemoteThreadListAdapter | undefined;
|
|
116
125
|
/** Custom thread-creation hook, forwarded to the cloud adapter. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/// <reference types="@assistant-ui/core/store" preserve="true" />
|
|
2
2
|
import type { AppendMessage } from "@assistant-ui/core";
|
|
3
|
-
import type { UseStreamRuntimeOptions } from "./types.js";
|
|
3
|
+
import type { LangChainBaseMessage, LangChainToolCall, UseStreamRuntimeOptions } from "./types.js";
|
|
4
4
|
export { groupUIMessagesByParent } from "./converter.js";
|
|
5
5
|
export declare const runConfigToSubmitOptions: (runConfig: AppendMessage["runConfig"]) => {
|
|
6
6
|
config: {
|
|
7
7
|
configurable: Record<string, unknown>;
|
|
8
8
|
};
|
|
9
9
|
} | undefined;
|
|
10
|
+
export declare const getPendingToolCalls: (messages: readonly LangChainBaseMessage[]) => LangChainToolCall[];
|
|
10
11
|
/**
|
|
11
12
|
* Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
|
|
12
13
|
* Accepts the same options as `useStream` from `@langchain/react`, plus
|
|
13
|
-
* `cloud` and `adapters`.
|
|
14
|
+
* `cloud`, `scopeId`, and `adapters`.
|
|
14
15
|
*
|
|
15
16
|
* @example
|
|
16
17
|
* ```tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"useStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":";AAYA,OAAO,KAAK,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AAqB7E,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EAEjB,uBAAuB,EACxB,mBAAgB;AAEjB,OAAO,EAAE,uBAAuB,EAAE,uBAAoB;AA4BtD,eAAO,MAAM,wBAAwB,GACnC,WAAW,aAAa,CAAC,WAAW,CAAC;;;;aAIxB,CAAC;AAMhB,eAAO,MAAM,mBAAmB,GAC9B,UAAU,SAAS,oBAAoB,EAAE,KACxC,iBAAiB,EAkBjB,CAAC;AAmoBJ;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,GAAI,YAAY,uBAAuB,kDAgCnE,CAAC"}
|
package/dist/useStreamRuntime.js
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { attachSubagentTranscripts, createAttachMemo } from "./attachSubagentTranscripts.js";
|
|
3
2
|
import { getMessageContent, getMessageModality, groupUIMessagesByParent } from "./converter.js";
|
|
4
|
-
import { convertLangChainBaseMessage, getMessageType } from "./convertMessages.js";
|
|
3
|
+
import { convertLangChainBaseMessage, createLangChainMetadataKey, getMessageType } from "./convertMessages.js";
|
|
4
|
+
import { LangChainThreadController } from "./LangChainThreadController.js";
|
|
5
|
+
import { attachSubagentTranscripts, createAttachMemo } from "./attachSubagentTranscripts.js";
|
|
5
6
|
import { langChainExtras } from "./runtimeExtras.js";
|
|
6
7
|
import { useLangChainStreamingTiming } from "./streamingTiming.js";
|
|
7
8
|
import { UI_CUSTOM_CHANNELS, createUIFoldMemo, createUISnapshotMemo, foldUIUpdates, mergeUIMessages, reconcileUISnapshot } from "./uiMessages.js";
|
|
8
9
|
import { useSubagentTranscripts } from "./useSubagentTranscripts.js";
|
|
9
10
|
import { resolveForkCheckpoint } from "./resolveForkCheckpoint.js";
|
|
10
11
|
import { LANGCHAIN_SDK } from "./sdkIdentity.js";
|
|
11
|
-
import { generateId, getExternalStoreMessages, pickExternalStoreSharedOptions } from "@assistant-ui/core";
|
|
12
12
|
import { createCloudThreadListAdapterCreateFallback, createToolCallCancellationStub, getThreadMessageText, scanPendingToolCalls } from "@assistant-ui/core/internal";
|
|
13
|
+
import { generateId, getExternalStoreMessages, pickExternalStoreSharedOptions } from "@assistant-ui/core";
|
|
13
14
|
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
14
15
|
import { useCloudThreadListAdapter, useExternalMessageConverter, useExternalStoreRuntime, useRemoteThreadListRuntime } from "@assistant-ui/core/react";
|
|
15
|
-
import { useCallback, useEffect, useInsertionEffect, useMemo, useRef, useState } from "react";
|
|
16
|
+
import { useCallback, useEffect, useInsertionEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
16
17
|
import { STREAM_CONTROLLER, useChannel, useStream } from "@langchain/react";
|
|
17
18
|
//#region src/useStreamRuntime.ts
|
|
18
19
|
const runConfigToSubmitOptions = (runConfig) => runConfig?.custom ? { config: { configurable: runConfig.custom } } : void 0;
|
|
19
20
|
const getPendingToolCalls = (messages) => scanPendingToolCalls(messages, (message) => {
|
|
20
21
|
const type = getMessageType(message);
|
|
21
|
-
if (type === "ai") return { toolCalls: message.tool_calls ?? [] };
|
|
22
|
+
if (type === "ai") return { toolCalls: (message.tool_calls ?? []).filter((toolCall) => typeof toolCall === "object" && toolCall !== null) };
|
|
22
23
|
if (type === "tool" && message.tool_call_id) return { toolCallId: message.tool_call_id };
|
|
23
24
|
}, (toolCall) => toolCall.id);
|
|
24
25
|
const toStagedHumanMessage = (msg, id = generateId()) => ({
|
|
@@ -32,12 +33,6 @@ const toStagedMessageInput = (message) => ({
|
|
|
32
33
|
content: message.content,
|
|
33
34
|
...message.additional_kwargs && { additional_kwargs: message.additional_kwargs }
|
|
34
35
|
});
|
|
35
|
-
const humanContentText = (content) => {
|
|
36
|
-
if (typeof content === "string") return content;
|
|
37
|
-
if (!Array.isArray(content)) return "";
|
|
38
|
-
return content.filter((part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
|
|
39
|
-
};
|
|
40
|
-
const hasSameMessageContent = (a, b) => humanContentText(a.content) === humanContentText(b.content);
|
|
41
36
|
const truncateLangChainBaseMessages = (threadMessages, parentId) => {
|
|
42
37
|
if (parentId === null) return [];
|
|
43
38
|
const parentIndex = threadMessages.findIndex((m) => m.id === parentId);
|
|
@@ -53,7 +48,10 @@ const useStreamThreadRuntime = (options) => {
|
|
|
53
48
|
const uiStateKey = options.uiStateKey ?? "ui";
|
|
54
49
|
const externalId = useAuiState((s) => s.threadListItem.externalId);
|
|
55
50
|
const stream = useStream(Object.assign({}, options, { threadId: externalId }));
|
|
56
|
-
const [
|
|
51
|
+
const [threadController] = useState(() => new LangChainThreadController());
|
|
52
|
+
const getVisibleStagedMessages = () => threadController.getState().visibleStagedMessages;
|
|
53
|
+
const visibleStagedMessages = useSyncExternalStore(threadController.subscribe, getVisibleStagedMessages, getVisibleStagedMessages);
|
|
54
|
+
const forkPending = useSyncExternalStore(threadController.subscribe, () => threadController.getState().forkPending, () => threadController.getState().forkPending);
|
|
57
55
|
const [toolStatuses, setToolStatuses] = useState({});
|
|
58
56
|
const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
|
|
59
57
|
const effectiveIsRunning = stream.isLoading || hasExecutingTools;
|
|
@@ -64,18 +62,20 @@ const useStreamThreadRuntime = (options) => {
|
|
|
64
62
|
const liveUiMessages = useMemo(() => foldUIUpdates(customEvents, uiFoldMemo), [customEvents, uiFoldMemo]);
|
|
65
63
|
const mergedUiMessages = useMemo(() => mergeUIMessages(liveUiMessages, uiStateValue), [liveUiMessages, uiStateValue]);
|
|
66
64
|
const uiMessagesByParent = useMemo(() => groupUIMessagesByParent(mergedUiMessages), [mergedUiMessages]);
|
|
67
|
-
const visibleMessages =
|
|
65
|
+
const visibleMessages = visibleStagedMessages ?? stream.messages;
|
|
68
66
|
const messageTiming = useLangChainStreamingTiming(visibleMessages, effectiveIsRunning);
|
|
69
67
|
const subagentTranscripts = useSubagentTranscripts(stream, uiMessagesByParent);
|
|
70
|
-
const
|
|
71
|
-
|
|
68
|
+
const [getConverterMetadataKey] = useState(createLangChainMetadataKey);
|
|
69
|
+
const converterMetadata = useMemo(() => ({
|
|
72
70
|
uiMessagesByParent,
|
|
73
71
|
messageTiming
|
|
74
72
|
}), [uiMessagesByParent, messageTiming]);
|
|
75
73
|
const threadMessages = useExternalMessageConverter({
|
|
76
|
-
callback:
|
|
74
|
+
callback: convertLangChainBaseMessage,
|
|
77
75
|
messages: visibleMessages,
|
|
78
|
-
isRunning: effectiveIsRunning
|
|
76
|
+
isRunning: effectiveIsRunning,
|
|
77
|
+
metadata: converterMetadata,
|
|
78
|
+
getMetadataKey: getConverterMetadataKey
|
|
79
79
|
});
|
|
80
80
|
const [memo] = useState(createAttachMemo);
|
|
81
81
|
const messagesWithTranscripts = useMemo(() => attachSubagentTranscripts(threadMessages, subagentTranscripts, memo), [
|
|
@@ -126,48 +126,35 @@ const useStreamThreadRuntime = (options) => {
|
|
|
126
126
|
useInsertionEffect(() => {
|
|
127
127
|
visibleMessagesRef.current = visibleMessages;
|
|
128
128
|
}, [visibleMessages]);
|
|
129
|
+
const dispatchStaging = useCallback((action, fallback = visibleMessagesRef.current) => {
|
|
130
|
+
threadController.dispatch(action);
|
|
131
|
+
visibleMessagesRef.current = threadController.getState().visibleStagedMessages ?? fallback;
|
|
132
|
+
}, [threadController]);
|
|
129
133
|
const threadMessagesRef = useRef(messagesWithTranscripts);
|
|
130
134
|
useInsertionEffect(() => {
|
|
131
135
|
threadMessagesRef.current = messagesWithTranscripts;
|
|
132
136
|
}, [messagesWithTranscripts]);
|
|
133
|
-
const stagedMessagesRef = useRef(/* @__PURE__ */ new Map());
|
|
134
|
-
const stagedBaseMessagesRef = useRef(null);
|
|
135
137
|
useEffect(() => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (!staged.reconcileOnEcho || index < staged.baseMessageCount || getMessageType(message) !== "human" || !hasSameMessageContent(message, staged.message)) return false;
|
|
150
|
-
matchedBaseMessageIndexes.add(index);
|
|
151
|
-
return true;
|
|
152
|
-
})) stagedMessagesRef.current.delete(id);
|
|
153
|
-
else remainingStagedMessages.push(staged.message);
|
|
154
|
-
}
|
|
155
|
-
if (remainingStagedMessages.length === 0) {
|
|
156
|
-
stagedBaseMessagesRef.current = null;
|
|
157
|
-
visibleMessagesRef.current = baseMessages;
|
|
158
|
-
setStagedMessages(null);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const nextMessages = [...baseMessages, ...remainingStagedMessages];
|
|
162
|
-
visibleMessagesRef.current = nextMessages;
|
|
163
|
-
setStagedMessages(nextMessages);
|
|
164
|
-
}, [stream.messages]);
|
|
138
|
+
const state = threadController.getState();
|
|
139
|
+
if (state.stagedEntries.size === 0) return;
|
|
140
|
+
const messages = stream.messages;
|
|
141
|
+
dispatchStaging({
|
|
142
|
+
type: "reconcile",
|
|
143
|
+
messages,
|
|
144
|
+
visibleMessages: visibleMessagesRef.current
|
|
145
|
+
}, state.stagedBaseMessages ?? messages);
|
|
146
|
+
}, [
|
|
147
|
+
stream.messages,
|
|
148
|
+
threadController,
|
|
149
|
+
dispatchStaging
|
|
150
|
+
]);
|
|
165
151
|
const getStagedRun = (parentId) => {
|
|
166
|
-
const
|
|
152
|
+
const stagedEntries = threadController.getState().stagedEntries;
|
|
153
|
+
const parent = parentId ? stagedEntries.get(parentId) : void 0;
|
|
167
154
|
if (!parent || parent.transcriptStatus === "sent") return null;
|
|
168
155
|
const staged = [];
|
|
169
156
|
for (const message of visibleMessagesRef.current) {
|
|
170
|
-
const entry = message.id ?
|
|
157
|
+
const entry = message.id ? stagedEntries.get(message.id) : void 0;
|
|
171
158
|
if (entry && entry.transcriptStatus !== "sent") staged.push(entry.message);
|
|
172
159
|
if (message.id === parentId) break;
|
|
173
160
|
}
|
|
@@ -183,23 +170,28 @@ const useStreamThreadRuntime = (options) => {
|
|
|
183
170
|
content: getThreadMessageText(message),
|
|
184
171
|
...message.metadata.modality && { additional_kwargs: { modality: message.metadata.modality } }
|
|
185
172
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
173
|
+
dispatchStaging({
|
|
174
|
+
type: "stage",
|
|
175
|
+
entry: {
|
|
176
|
+
message: transcript,
|
|
177
|
+
runConfig: void 0,
|
|
178
|
+
reconcileOnEcho: false,
|
|
179
|
+
baseMessageCount: streamRef.current.messages.length,
|
|
180
|
+
transcriptStatus: "unsent"
|
|
181
|
+
},
|
|
182
|
+
visibleMessages: visibleMessagesRef.current
|
|
192
183
|
});
|
|
193
|
-
const nextMessages = [...visibleMessagesRef.current, transcript];
|
|
194
|
-
visibleMessagesRef.current = nextMessages;
|
|
195
|
-
setStagedMessages(nextMessages);
|
|
196
184
|
};
|
|
197
|
-
const getUnsentTranscripts = () =>
|
|
185
|
+
const getUnsentTranscripts = () => {
|
|
186
|
+
const stagedEntries = threadController.getState().stagedEntries;
|
|
187
|
+
return visibleMessagesRef.current.filter((message) => message.id !== void 0 && stagedEntries.get(message.id)?.transcriptStatus === "unsent");
|
|
188
|
+
};
|
|
198
189
|
const setTranscriptStatus = (messages, status) => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
190
|
+
dispatchStaging({
|
|
191
|
+
type: "markTranscript",
|
|
192
|
+
messages,
|
|
193
|
+
status
|
|
194
|
+
});
|
|
203
195
|
};
|
|
204
196
|
const submitCarryingTranscripts = async (transcripts, submit) => {
|
|
205
197
|
setTranscriptStatus(transcripts, "sent");
|
|
@@ -211,10 +203,10 @@ const useStreamThreadRuntime = (options) => {
|
|
|
211
203
|
}
|
|
212
204
|
};
|
|
213
205
|
const dropTranscripts = (messages) => {
|
|
214
|
-
for (const message of messages) if (message.id &&
|
|
206
|
+
for (const message of messages) if (message.id && threadController.getState().stagedEntries.get(message.id)?.transcriptStatus) removeStagedMessage(message.id);
|
|
215
207
|
};
|
|
216
208
|
const isTranscriptMessage = (message) => {
|
|
217
|
-
if ((message.id ?
|
|
209
|
+
if ((message.id ? threadController.getState().stagedEntries.get(message.id) : void 0)?.transcriptStatus === "unsent") return true;
|
|
218
210
|
const type = getMessageType(message);
|
|
219
211
|
return (type === "human" || type === "ai") && getMessageModality(message.additional_kwargs) !== void 0;
|
|
220
212
|
};
|
|
@@ -236,25 +228,31 @@ const useStreamThreadRuntime = (options) => {
|
|
|
236
228
|
};
|
|
237
229
|
const stageUserMessage = (msg, reconcileOnEcho = false) => {
|
|
238
230
|
const stagedMessage = toStagedHumanMessage(msg);
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
231
|
+
dispatchStaging({
|
|
232
|
+
type: "stage",
|
|
233
|
+
entry: {
|
|
234
|
+
message: stagedMessage,
|
|
235
|
+
runConfig: msg.runConfig,
|
|
236
|
+
reconcileOnEcho,
|
|
237
|
+
baseMessageCount: streamRef.current.messages.length
|
|
238
|
+
},
|
|
239
|
+
visibleMessages: visibleMessagesRef.current
|
|
244
240
|
});
|
|
245
|
-
const nextMessages = [...visibleMessagesRef.current, stagedMessage];
|
|
246
|
-
visibleMessagesRef.current = nextMessages;
|
|
247
|
-
setStagedMessages(nextMessages);
|
|
248
241
|
return stagedMessage;
|
|
249
242
|
};
|
|
250
243
|
const removeStagedMessage = (id) => {
|
|
251
|
-
if (!
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
244
|
+
if (!threadController.getState().stagedEntries.has(id)) return;
|
|
245
|
+
const visible = visibleMessagesRef.current;
|
|
246
|
+
const nextMessages = visible.filter((message) => message.id !== id);
|
|
247
|
+
dispatchStaging({
|
|
248
|
+
type: "remove",
|
|
249
|
+
id,
|
|
250
|
+
visibleMessages: visible
|
|
251
|
+
}, nextMessages);
|
|
252
|
+
};
|
|
253
|
+
const supersedeFork = () => {
|
|
254
|
+
threadController.dispatch({ type: "supersedeFork" });
|
|
255
|
+
return threadController.getState().forkGeneration;
|
|
258
256
|
};
|
|
259
257
|
const extras = useMemo(() => langChainExtras.provide({
|
|
260
258
|
interrupt: stream.interrupt,
|
|
@@ -279,7 +277,7 @@ const useStreamThreadRuntime = (options) => {
|
|
|
279
277
|
]);
|
|
280
278
|
return useExternalStoreRuntime({
|
|
281
279
|
...pickExternalStoreSharedOptions(options),
|
|
282
|
-
isRunning: stream.isLoading,
|
|
280
|
+
isRunning: stream.isLoading || forkPending,
|
|
283
281
|
isLoading: stream.isThreadLoading,
|
|
284
282
|
messages: messagesWithTranscripts,
|
|
285
283
|
adapters,
|
|
@@ -328,73 +326,89 @@ const useStreamThreadRuntime = (options) => {
|
|
|
328
326
|
}] }, runConfig === void 0 ? void 0 : { config: runConfig });
|
|
329
327
|
},
|
|
330
328
|
onReload: async (parentId, config) => {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
329
|
+
const forkGeneration = supersedeFork();
|
|
330
|
+
try {
|
|
331
|
+
await streamRef.current.stop();
|
|
332
|
+
if (threadController.getState().forkGeneration !== forkGeneration) return;
|
|
333
|
+
const stagedRun = getStagedRun(parentId);
|
|
334
|
+
if (stagedRun) {
|
|
335
|
+
if (config.sourceId && threadController.getState().stagedEntries.get(config.sourceId)?.transcriptStatus) removeStagedMessage(config.sourceId);
|
|
336
|
+
dispatchStaging({
|
|
337
|
+
type: "promote",
|
|
338
|
+
messages: stagedRun.messages,
|
|
339
|
+
visibleMessages: visibleMessagesRef.current
|
|
340
|
+
});
|
|
341
|
+
const runConfig = config.runConfig ?? stagedRun.runConfig;
|
|
342
|
+
setActiveRunConfig(runConfig);
|
|
343
|
+
await submitCarryingTranscripts(stagedRun.messages, () => stream.submit({ [messagesKey]: stagedRun.messages.map(toStagedMessageInput) }, runConfigToSubmitOptions(runConfig)));
|
|
344
|
+
return;
|
|
339
345
|
}
|
|
340
|
-
|
|
341
|
-
if (
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
346
|
+
const threadId = externalId;
|
|
347
|
+
if (!threadId || parentId == null) return;
|
|
348
|
+
const s = streamRef.current;
|
|
349
|
+
const fork = planForkTranscripts(parentId);
|
|
350
|
+
const checkpointId = await resolveForkCheckpoint(s.client, threadId, s.messages, fork.forkParentId, config.sourceId, s[STREAM_CONTROLLER]?.messageMetadataStore?.getSnapshot?.(), messagesKey);
|
|
351
|
+
if (threadController.getState().forkGeneration !== forkGeneration) return;
|
|
352
|
+
if (!checkpointId) return;
|
|
353
|
+
dropTranscripts(fork.truncated);
|
|
354
|
+
setActiveRunConfig(config.runConfig);
|
|
355
|
+
await submitCarryingTranscripts(fork.transcripts, () => s.submit(fork.transcripts.length > 0 ? { [messagesKey]: fork.transcripts.map(toStagedMessageInput) } : null, {
|
|
356
|
+
forkFrom: checkpointId,
|
|
357
|
+
...runConfigToSubmitOptions(config.runConfig)
|
|
358
|
+
}));
|
|
359
|
+
} finally {
|
|
360
|
+
threadController.dispatch({
|
|
361
|
+
type: "finishFork",
|
|
362
|
+
generation: forkGeneration
|
|
363
|
+
});
|
|
350
364
|
}
|
|
351
|
-
const threadId = externalId;
|
|
352
|
-
if (!threadId || parentId == null) return;
|
|
353
|
-
const s = streamRef.current;
|
|
354
|
-
const fork = planForkTranscripts(parentId);
|
|
355
|
-
const checkpointId = await resolveForkCheckpoint(s.client, threadId, s.messages, fork.forkParentId, config.sourceId, s[STREAM_CONTROLLER]?.messageMetadataStore?.getSnapshot?.(), messagesKey);
|
|
356
|
-
if (!checkpointId) return;
|
|
357
|
-
dropTranscripts(fork.truncated);
|
|
358
|
-
setActiveRunConfig(config.runConfig);
|
|
359
|
-
await submitCarryingTranscripts(fork.transcripts, () => s.submit(fork.transcripts.length > 0 ? { [messagesKey]: fork.transcripts.map(toStagedMessageInput) } : null, {
|
|
360
|
-
forkFrom: checkpointId,
|
|
361
|
-
...runConfigToSubmitOptions(config.runConfig)
|
|
362
|
-
}));
|
|
363
365
|
},
|
|
364
366
|
onEdit: async (message) => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
367
|
+
const forkGeneration = supersedeFork();
|
|
368
|
+
try {
|
|
369
|
+
await streamRef.current.stop();
|
|
370
|
+
if (threadController.getState().forkGeneration !== forkGeneration) return;
|
|
371
|
+
if (!(message.startRun ?? message.role === "user")) {
|
|
372
|
+
const truncated = truncateLangChainBaseMessages(threadMessagesRef.current, message.parentId);
|
|
373
|
+
const stagedMessage = toStagedHumanMessage(message);
|
|
374
|
+
dispatchStaging({
|
|
375
|
+
type: "stageEdit",
|
|
376
|
+
entry: {
|
|
377
|
+
message: stagedMessage,
|
|
378
|
+
runConfig: message.runConfig,
|
|
379
|
+
reconcileOnEcho: false,
|
|
380
|
+
baseMessageCount: 0
|
|
381
|
+
},
|
|
382
|
+
baseMessages: truncated
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const threadId = externalId;
|
|
387
|
+
if (!threadId) return;
|
|
388
|
+
const s = streamRef.current;
|
|
389
|
+
const fork = planForkTranscripts(message.parentId);
|
|
390
|
+
const checkpointId = await resolveForkCheckpoint(s.client, threadId, s.messages, fork.forkParentId, message.sourceId, s[STREAM_CONTROLLER]?.messageMetadataStore?.getSnapshot?.(), messagesKey);
|
|
391
|
+
if (threadController.getState().forkGeneration !== forkGeneration) return;
|
|
392
|
+
if (!checkpointId) return;
|
|
393
|
+
dropTranscripts(fork.truncated);
|
|
394
|
+
const content = getMessageContent(message);
|
|
395
|
+
setActiveRunConfig(message.runConfig);
|
|
396
|
+
await submitCarryingTranscripts(fork.transcripts, () => s.submit({ [messagesKey]: [...fork.transcripts.map(toStagedMessageInput), {
|
|
397
|
+
type: "human",
|
|
398
|
+
content
|
|
399
|
+
}] }, {
|
|
400
|
+
forkFrom: checkpointId,
|
|
401
|
+
...runConfigToSubmitOptions(message.runConfig)
|
|
402
|
+
}));
|
|
403
|
+
} finally {
|
|
404
|
+
threadController.dispatch({
|
|
405
|
+
type: "finishFork",
|
|
406
|
+
generation: forkGeneration
|
|
373
407
|
});
|
|
374
|
-
stagedBaseMessagesRef.current = truncated;
|
|
375
|
-
const nextMessages = [...truncated, stagedMessage];
|
|
376
|
-
visibleMessagesRef.current = nextMessages;
|
|
377
|
-
setStagedMessages(nextMessages);
|
|
378
|
-
return;
|
|
379
408
|
}
|
|
380
|
-
const threadId = externalId;
|
|
381
|
-
if (!threadId) return;
|
|
382
|
-
const s = streamRef.current;
|
|
383
|
-
const fork = planForkTranscripts(message.parentId);
|
|
384
|
-
const checkpointId = await resolveForkCheckpoint(s.client, threadId, s.messages, fork.forkParentId, message.sourceId, s[STREAM_CONTROLLER]?.messageMetadataStore?.getSnapshot?.(), messagesKey);
|
|
385
|
-
if (!checkpointId) return;
|
|
386
|
-
dropTranscripts(fork.truncated);
|
|
387
|
-
const content = getMessageContent(message);
|
|
388
|
-
setActiveRunConfig(message.runConfig);
|
|
389
|
-
await submitCarryingTranscripts(fork.transcripts, () => s.submit({ [messagesKey]: [...fork.transcripts.map(toStagedMessageInput), {
|
|
390
|
-
type: "human",
|
|
391
|
-
content
|
|
392
|
-
}] }, {
|
|
393
|
-
forkFrom: checkpointId,
|
|
394
|
-
...runConfigToSubmitOptions(message.runConfig)
|
|
395
|
-
}));
|
|
396
409
|
},
|
|
397
410
|
onCancel: unstable_allowCancellation !== false ? async () => {
|
|
411
|
+
threadController.dispatch({ type: "cancelFork" });
|
|
398
412
|
activeRunConfigRef.current = void 0;
|
|
399
413
|
await stream.stop();
|
|
400
414
|
} : void 0
|
|
@@ -403,7 +417,7 @@ const useStreamThreadRuntime = (options) => {
|
|
|
403
417
|
/**
|
|
404
418
|
* Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
|
|
405
419
|
* Accepts the same options as `useStream` from `@langchain/react`, plus
|
|
406
|
-
* `cloud` and `adapters`.
|
|
420
|
+
* `cloud`, `scopeId`, and `adapters`.
|
|
407
421
|
*
|
|
408
422
|
* @example
|
|
409
423
|
* ```tsx
|
|
@@ -425,11 +439,12 @@ const useStreamThreadRuntime = (options) => {
|
|
|
425
439
|
* ```
|
|
426
440
|
*/
|
|
427
441
|
const useStreamRuntime = (rawOptions) => {
|
|
428
|
-
const { cloud, unstable_threadListAdapter, create, delete: deleteFn, onThreadIdChange, ...options } = rawOptions;
|
|
442
|
+
const { cloud, scopeId, unstable_threadListAdapter, create, delete: deleteFn, onThreadIdChange, ...options } = rawOptions;
|
|
429
443
|
const aui = useAui();
|
|
430
444
|
const cloudAdapter = useCloudThreadListAdapter({
|
|
431
445
|
sdk: LANGCHAIN_SDK,
|
|
432
446
|
cloud,
|
|
447
|
+
scopeId,
|
|
433
448
|
create: createCloudThreadListAdapterCreateFallback(create, aui.threadListItem),
|
|
434
449
|
delete: deleteFn
|
|
435
450
|
});
|
|
@@ -443,6 +458,6 @@ const useStreamRuntime = (rawOptions) => {
|
|
|
443
458
|
});
|
|
444
459
|
};
|
|
445
460
|
//#endregion
|
|
446
|
-
export { groupUIMessagesByParent, runConfigToSubmitOptions, useStreamRuntime };
|
|
461
|
+
export { getPendingToolCalls, groupUIMessagesByParent, runConfigToSubmitOptions, useStreamRuntime };
|
|
447
462
|
|
|
448
463
|
//# sourceMappingURL=useStreamRuntime.js.map
|