@assistant-ui/react-langchain 0.0.35 → 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.map +1 -1
- package/dist/convertMessages.js +6 -11
- 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 +152 -139
- package/dist/useStreamRuntime.js.map +1 -1
- package/dist/useSubagentTranscripts.js +1 -1
- package/package.json +8 -8
- package/src/LangChainThreadController.ts +24 -0
- package/src/convertMessages.test.ts +23 -0
- package/src/convertMessages.ts +9 -16
- 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 +227 -1
- package/src/useStreamRuntime.ts +210 -239
|
@@ -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":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,EAC1B,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,qBAAqB,EAAE,uBAAoB;AAEzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,CACnB,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9D;IACF,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACxD,2BAA2B;IAC3B,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,CAAC;IACtD,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,oEAAoE;IACpE,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACzD,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAC3C,UAAU,EAAE,SAAS;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IACxD,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACxC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAC1D,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAC1D,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,CACN,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAClD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,EAAE,CACP,QAAQ,EAAE,OAAO,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,UAAU,EAAE,CACV,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,0BAA0B,GAAG;IACtE;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACxE,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EACL;QACE,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;QAC5C,MAAM,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;QAC5C,SAAS,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;QACzC,KAAK,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;QACzC,QAAQ,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;KACxC,GACD,SAAS,CAAC;IACd;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD;;;;;OAKG;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;IAC3D;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,CAAC;AAMF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,SAAS,MAAM,CAAC,GAClE,CAAC,SAAS,gBAAgB,GACxB,CAAC,GAAG,4BAA4B,GAChC,KAAK,GACP,KAAK,CAAC"}
|
|
@@ -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
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,7 +62,7 @@ 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
68
|
const [getConverterMetadataKey] = useState(createLangChainMetadataKey);
|
|
@@ -128,48 +126,35 @@ const useStreamThreadRuntime = (options) => {
|
|
|
128
126
|
useInsertionEffect(() => {
|
|
129
127
|
visibleMessagesRef.current = visibleMessages;
|
|
130
128
|
}, [visibleMessages]);
|
|
129
|
+
const dispatchStaging = useCallback((action, fallback = visibleMessagesRef.current) => {
|
|
130
|
+
threadController.dispatch(action);
|
|
131
|
+
visibleMessagesRef.current = threadController.getState().visibleStagedMessages ?? fallback;
|
|
132
|
+
}, [threadController]);
|
|
131
133
|
const threadMessagesRef = useRef(messagesWithTranscripts);
|
|
132
134
|
useInsertionEffect(() => {
|
|
133
135
|
threadMessagesRef.current = messagesWithTranscripts;
|
|
134
136
|
}, [messagesWithTranscripts]);
|
|
135
|
-
const stagedMessagesRef = useRef(/* @__PURE__ */ new Map());
|
|
136
|
-
const stagedBaseMessagesRef = useRef(null);
|
|
137
137
|
useEffect(() => {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (!staged.reconcileOnEcho || index < staged.baseMessageCount || getMessageType(message) !== "human" || !hasSameMessageContent(message, staged.message)) return false;
|
|
152
|
-
matchedBaseMessageIndexes.add(index);
|
|
153
|
-
return true;
|
|
154
|
-
})) stagedMessagesRef.current.delete(id);
|
|
155
|
-
else remainingStagedMessages.push(staged.message);
|
|
156
|
-
}
|
|
157
|
-
if (remainingStagedMessages.length === 0) {
|
|
158
|
-
stagedBaseMessagesRef.current = null;
|
|
159
|
-
visibleMessagesRef.current = baseMessages;
|
|
160
|
-
setStagedMessages(null);
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
const nextMessages = [...baseMessages, ...remainingStagedMessages];
|
|
164
|
-
visibleMessagesRef.current = nextMessages;
|
|
165
|
-
setStagedMessages(nextMessages);
|
|
166
|
-
}, [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
|
+
]);
|
|
167
151
|
const getStagedRun = (parentId) => {
|
|
168
|
-
const
|
|
152
|
+
const stagedEntries = threadController.getState().stagedEntries;
|
|
153
|
+
const parent = parentId ? stagedEntries.get(parentId) : void 0;
|
|
169
154
|
if (!parent || parent.transcriptStatus === "sent") return null;
|
|
170
155
|
const staged = [];
|
|
171
156
|
for (const message of visibleMessagesRef.current) {
|
|
172
|
-
const entry = message.id ?
|
|
157
|
+
const entry = message.id ? stagedEntries.get(message.id) : void 0;
|
|
173
158
|
if (entry && entry.transcriptStatus !== "sent") staged.push(entry.message);
|
|
174
159
|
if (message.id === parentId) break;
|
|
175
160
|
}
|
|
@@ -185,23 +170,28 @@ const useStreamThreadRuntime = (options) => {
|
|
|
185
170
|
content: getThreadMessageText(message),
|
|
186
171
|
...message.metadata.modality && { additional_kwargs: { modality: message.metadata.modality } }
|
|
187
172
|
};
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
|
194
183
|
});
|
|
195
|
-
const nextMessages = [...visibleMessagesRef.current, transcript];
|
|
196
|
-
visibleMessagesRef.current = nextMessages;
|
|
197
|
-
setStagedMessages(nextMessages);
|
|
198
184
|
};
|
|
199
|
-
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
|
+
};
|
|
200
189
|
const setTranscriptStatus = (messages, status) => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
190
|
+
dispatchStaging({
|
|
191
|
+
type: "markTranscript",
|
|
192
|
+
messages,
|
|
193
|
+
status
|
|
194
|
+
});
|
|
205
195
|
};
|
|
206
196
|
const submitCarryingTranscripts = async (transcripts, submit) => {
|
|
207
197
|
setTranscriptStatus(transcripts, "sent");
|
|
@@ -213,10 +203,10 @@ const useStreamThreadRuntime = (options) => {
|
|
|
213
203
|
}
|
|
214
204
|
};
|
|
215
205
|
const dropTranscripts = (messages) => {
|
|
216
|
-
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);
|
|
217
207
|
};
|
|
218
208
|
const isTranscriptMessage = (message) => {
|
|
219
|
-
if ((message.id ?
|
|
209
|
+
if ((message.id ? threadController.getState().stagedEntries.get(message.id) : void 0)?.transcriptStatus === "unsent") return true;
|
|
220
210
|
const type = getMessageType(message);
|
|
221
211
|
return (type === "human" || type === "ai") && getMessageModality(message.additional_kwargs) !== void 0;
|
|
222
212
|
};
|
|
@@ -238,25 +228,31 @@ const useStreamThreadRuntime = (options) => {
|
|
|
238
228
|
};
|
|
239
229
|
const stageUserMessage = (msg, reconcileOnEcho = false) => {
|
|
240
230
|
const stagedMessage = toStagedHumanMessage(msg);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
|
246
240
|
});
|
|
247
|
-
const nextMessages = [...visibleMessagesRef.current, stagedMessage];
|
|
248
|
-
visibleMessagesRef.current = nextMessages;
|
|
249
|
-
setStagedMessages(nextMessages);
|
|
250
241
|
return stagedMessage;
|
|
251
242
|
};
|
|
252
243
|
const removeStagedMessage = (id) => {
|
|
253
|
-
if (!
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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;
|
|
260
256
|
};
|
|
261
257
|
const extras = useMemo(() => langChainExtras.provide({
|
|
262
258
|
interrupt: stream.interrupt,
|
|
@@ -281,7 +277,7 @@ const useStreamThreadRuntime = (options) => {
|
|
|
281
277
|
]);
|
|
282
278
|
return useExternalStoreRuntime({
|
|
283
279
|
...pickExternalStoreSharedOptions(options),
|
|
284
|
-
isRunning: stream.isLoading,
|
|
280
|
+
isRunning: stream.isLoading || forkPending,
|
|
285
281
|
isLoading: stream.isThreadLoading,
|
|
286
282
|
messages: messagesWithTranscripts,
|
|
287
283
|
adapters,
|
|
@@ -330,73 +326,89 @@ const useStreamThreadRuntime = (options) => {
|
|
|
330
326
|
}] }, runConfig === void 0 ? void 0 : { config: runConfig });
|
|
331
327
|
},
|
|
332
328
|
onReload: async (parentId, config) => {
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
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;
|
|
341
345
|
}
|
|
342
|
-
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
+
});
|
|
352
364
|
}
|
|
353
|
-
const threadId = externalId;
|
|
354
|
-
if (!threadId || parentId == null) return;
|
|
355
|
-
const s = streamRef.current;
|
|
356
|
-
const fork = planForkTranscripts(parentId);
|
|
357
|
-
const checkpointId = await resolveForkCheckpoint(s.client, threadId, s.messages, fork.forkParentId, config.sourceId, s[STREAM_CONTROLLER]?.messageMetadataStore?.getSnapshot?.(), messagesKey);
|
|
358
|
-
if (!checkpointId) return;
|
|
359
|
-
dropTranscripts(fork.truncated);
|
|
360
|
-
setActiveRunConfig(config.runConfig);
|
|
361
|
-
await submitCarryingTranscripts(fork.transcripts, () => s.submit(fork.transcripts.length > 0 ? { [messagesKey]: fork.transcripts.map(toStagedMessageInput) } : null, {
|
|
362
|
-
forkFrom: checkpointId,
|
|
363
|
-
...runConfigToSubmitOptions(config.runConfig)
|
|
364
|
-
}));
|
|
365
365
|
},
|
|
366
366
|
onEdit: async (message) => {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
|
375
407
|
});
|
|
376
|
-
stagedBaseMessagesRef.current = truncated;
|
|
377
|
-
const nextMessages = [...truncated, stagedMessage];
|
|
378
|
-
visibleMessagesRef.current = nextMessages;
|
|
379
|
-
setStagedMessages(nextMessages);
|
|
380
|
-
return;
|
|
381
408
|
}
|
|
382
|
-
const threadId = externalId;
|
|
383
|
-
if (!threadId) return;
|
|
384
|
-
const s = streamRef.current;
|
|
385
|
-
const fork = planForkTranscripts(message.parentId);
|
|
386
|
-
const checkpointId = await resolveForkCheckpoint(s.client, threadId, s.messages, fork.forkParentId, message.sourceId, s[STREAM_CONTROLLER]?.messageMetadataStore?.getSnapshot?.(), messagesKey);
|
|
387
|
-
if (!checkpointId) return;
|
|
388
|
-
dropTranscripts(fork.truncated);
|
|
389
|
-
const content = getMessageContent(message);
|
|
390
|
-
setActiveRunConfig(message.runConfig);
|
|
391
|
-
await submitCarryingTranscripts(fork.transcripts, () => s.submit({ [messagesKey]: [...fork.transcripts.map(toStagedMessageInput), {
|
|
392
|
-
type: "human",
|
|
393
|
-
content
|
|
394
|
-
}] }, {
|
|
395
|
-
forkFrom: checkpointId,
|
|
396
|
-
...runConfigToSubmitOptions(message.runConfig)
|
|
397
|
-
}));
|
|
398
409
|
},
|
|
399
410
|
onCancel: unstable_allowCancellation !== false ? async () => {
|
|
411
|
+
threadController.dispatch({ type: "cancelFork" });
|
|
400
412
|
activeRunConfigRef.current = void 0;
|
|
401
413
|
await stream.stop();
|
|
402
414
|
} : void 0
|
|
@@ -405,7 +417,7 @@ const useStreamThreadRuntime = (options) => {
|
|
|
405
417
|
/**
|
|
406
418
|
* Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
|
|
407
419
|
* Accepts the same options as `useStream` from `@langchain/react`, plus
|
|
408
|
-
* `cloud` and `adapters`.
|
|
420
|
+
* `cloud`, `scopeId`, and `adapters`.
|
|
409
421
|
*
|
|
410
422
|
* @example
|
|
411
423
|
* ```tsx
|
|
@@ -427,11 +439,12 @@ const useStreamThreadRuntime = (options) => {
|
|
|
427
439
|
* ```
|
|
428
440
|
*/
|
|
429
441
|
const useStreamRuntime = (rawOptions) => {
|
|
430
|
-
const { cloud, unstable_threadListAdapter, create, delete: deleteFn, onThreadIdChange, ...options } = rawOptions;
|
|
442
|
+
const { cloud, scopeId, unstable_threadListAdapter, create, delete: deleteFn, onThreadIdChange, ...options } = rawOptions;
|
|
431
443
|
const aui = useAui();
|
|
432
444
|
const cloudAdapter = useCloudThreadListAdapter({
|
|
433
445
|
sdk: LANGCHAIN_SDK,
|
|
434
446
|
cloud,
|
|
447
|
+
scopeId,
|
|
435
448
|
create: createCloudThreadListAdapterCreateFallback(create, aui.threadListItem),
|
|
436
449
|
delete: deleteFn
|
|
437
450
|
});
|
|
@@ -445,6 +458,6 @@ const useStreamRuntime = (rawOptions) => {
|
|
|
445
458
|
});
|
|
446
459
|
};
|
|
447
460
|
//#endregion
|
|
448
|
-
export { groupUIMessagesByParent, runConfigToSubmitOptions, useStreamRuntime };
|
|
461
|
+
export { getPendingToolCalls, groupUIMessagesByParent, runConfigToSubmitOptions, useStreamRuntime };
|
|
449
462
|
|
|
450
463
|
//# sourceMappingURL=useStreamRuntime.js.map
|