@langgraph-js/sdk 4.6.3 → 4.6.5
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/LangGraphClient.d.ts +2 -0
- package/dist/LangGraphClient.js +17 -2
- package/dist/react/ChatContext.d.ts +6 -4
- package/dist/react/ChatContext.js +3 -2
- package/dist/solid/ChatContext.d.ts +6 -3
- package/dist/solid/ChatContext.js +1 -0
- package/dist/tool/ToolUI.d.ts +1 -0
- package/dist/tool/ToolUI.js +2 -1
- package/dist/ui-store/createChatStore.d.ts +2 -0
- package/dist/ui-store/createChatStore.js +1 -1
- package/dist/vue/ChatContext.d.ts +15 -4
- package/dist/vue/ChatContext.js +5 -0
- package/package.json +1 -1
- package/src/LangGraphClient.ts +18 -2
- package/src/react/ChatContext.ts +7 -3
- package/src/solid/ChatContext.ts +5 -2
- package/src/tool/ToolUI.ts +2 -1
- package/src/ui-store/createChatStore.ts +3 -1
- package/src/vue/ChatContext.ts +9 -2
|
@@ -284,6 +284,8 @@ export declare class LangGraphClient<TStateType = unknown> extends EventEmitter<
|
|
|
284
284
|
* @deprecated 请使用 doneHumanInTheLoopWaiting 和规范的 humanInTheLoop 协议定义状态
|
|
285
285
|
*/
|
|
286
286
|
doneFEToolWaiting(id: string, result: CallToolResult): void;
|
|
287
|
+
/** 尝试强制跳过工具调用 */
|
|
288
|
+
private forceSkipToolLock?;
|
|
287
289
|
/**
|
|
288
290
|
* @zh 标记人机交互等待已完成。
|
|
289
291
|
* @en Marks the human in the loop waiting as completed.
|
package/dist/LangGraphClient.js
CHANGED
|
@@ -324,7 +324,13 @@ export class LangGraphClient extends EventEmitter {
|
|
|
324
324
|
this.processStreamChunk(chunk, command);
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
|
-
const data = await
|
|
327
|
+
const data = (await Promise.race([
|
|
328
|
+
this.runFETool(),
|
|
329
|
+
new Promise((res) => {
|
|
330
|
+
this.forceSkipToolLock = () => res(null);
|
|
331
|
+
}),
|
|
332
|
+
]));
|
|
333
|
+
this.forceSkipToolLock = undefined;
|
|
328
334
|
await this.responseHumanInTheLoop();
|
|
329
335
|
if (data)
|
|
330
336
|
streamRecord.push(...data);
|
|
@@ -421,7 +427,6 @@ export class LangGraphClient extends EventEmitter {
|
|
|
421
427
|
// json 校验
|
|
422
428
|
return this.callFETool(toolMessage, tool.args).catch((e) => console.warn(e));
|
|
423
429
|
});
|
|
424
|
-
console.log("batch call tools", result.length);
|
|
425
430
|
// 只有当卡住流程时,才改变状态为 interrupted
|
|
426
431
|
this._status = "interrupted";
|
|
427
432
|
this.currentThread.status = "interrupted"; // 修复某些机制下,状态不为 interrupted 与后端有差异
|
|
@@ -511,6 +516,8 @@ export class LangGraphClient extends EventEmitter {
|
|
|
511
516
|
this.resume(result);
|
|
512
517
|
}
|
|
513
518
|
}
|
|
519
|
+
/** 尝试强制跳过工具调用 */
|
|
520
|
+
forceSkipToolLock;
|
|
514
521
|
/**
|
|
515
522
|
* @zh 标记人机交互等待已完成。
|
|
516
523
|
* @en Marks the human in the loop waiting as completed.
|
|
@@ -520,6 +527,14 @@ export class LangGraphClient extends EventEmitter {
|
|
|
520
527
|
this.tools.doneWaiting(tool_id, result);
|
|
521
528
|
if (this.humanInTheLoop) {
|
|
522
529
|
this.humanInTheLoop.result[action_request_id] = result;
|
|
530
|
+
if (Object.keys(this.humanInTheLoop.result).length === this.humanInTheLoop.interruptData.length) {
|
|
531
|
+
setTimeout(() => {
|
|
532
|
+
if (this.forceSkipToolLock) {
|
|
533
|
+
console.warn("force kill tool lock");
|
|
534
|
+
this.forceSkipToolLock();
|
|
535
|
+
}
|
|
536
|
+
}, 100);
|
|
537
|
+
}
|
|
523
538
|
}
|
|
524
539
|
}
|
|
525
540
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
|
-
import { UnionStore } from "../ui-store/index.js";
|
|
2
|
+
import { HistoryFilter, UnionStore } from "../ui-store/index.js";
|
|
3
3
|
import { ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
4
4
|
export declare const useChat: () => UnionStore<{
|
|
5
5
|
data: {
|
|
@@ -28,7 +28,7 @@ export declare const useChat: () => UnionStore<{
|
|
|
28
28
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
29
29
|
}, unknown>[]> & object;
|
|
30
30
|
historyPagination: import("nanostores").PreinitializedWritableAtom<import("../ui-store/createChatStore.js").HistoryPagination> & object;
|
|
31
|
-
historyFilter: import("nanostores").PreinitializedWritableAtom<
|
|
31
|
+
historyFilter: import("nanostores").PreinitializedWritableAtom<HistoryFilter> & object;
|
|
32
32
|
};
|
|
33
33
|
mutations: {
|
|
34
34
|
setCurrentArtifactById: (id: string, tool_id: string) => void;
|
|
@@ -66,7 +66,7 @@ export declare const useChat: () => UnionStore<{
|
|
|
66
66
|
}>): Promise<void>;
|
|
67
67
|
setHistoryPage(page: number): void;
|
|
68
68
|
setHistoryPageSize(pageSize: number): void;
|
|
69
|
-
setHistoryFilter(filter: Partial<
|
|
69
|
+
setHistoryFilter(filter: Partial<HistoryFilter>): void;
|
|
70
70
|
resetHistoryFilter(): void;
|
|
71
71
|
};
|
|
72
72
|
}>;
|
|
@@ -86,7 +86,9 @@ interface ChatProviderProps {
|
|
|
86
86
|
client?: ILangGraphClient;
|
|
87
87
|
legacyMode?: boolean;
|
|
88
88
|
/** 历史记录筛选的默认参数 */
|
|
89
|
-
historyFilter?:
|
|
89
|
+
historyFilter?: HistoryFilter;
|
|
90
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
91
|
+
debounceTime?: number;
|
|
90
92
|
}
|
|
91
93
|
export declare const ChatProvider: React.FC<ChatProviderProps>;
|
|
92
94
|
export {};
|
|
@@ -9,7 +9,7 @@ export const useChat = () => {
|
|
|
9
9
|
}
|
|
10
10
|
return context;
|
|
11
11
|
};
|
|
12
|
-
export const ChatProvider = ({ children, defaultAgent = "", apiUrl = "http://localhost:8123", defaultHeaders, withCredentials = false, fetch, showHistory = false, showGraph = false, fallbackToAvailableAssistants = false, autoRestoreLastSession = false, onInitError, client, legacyMode = false, historyFilter, }) => {
|
|
12
|
+
export const ChatProvider = ({ children, defaultAgent = "", apiUrl = "http://localhost:8123", defaultHeaders, withCredentials = false, fetch, showHistory = false, showGraph = false, fallbackToAvailableAssistants = false, autoRestoreLastSession = false, onInitError, client, legacyMode = false, historyFilter, debounceTime, }) => {
|
|
13
13
|
// 使用 useMemo 稳定 defaultHeaders 的引用
|
|
14
14
|
const stableHeaders = useMemo(() => defaultHeaders || {}, [defaultHeaders]);
|
|
15
15
|
// 使用 useRef 保存 onInitError 的最新引用
|
|
@@ -43,8 +43,9 @@ export const ChatProvider = ({ children, defaultAgent = "", apiUrl = "http://loc
|
|
|
43
43
|
fallbackToAvailableAssistants,
|
|
44
44
|
autoRestoreLastSession,
|
|
45
45
|
historyFilter,
|
|
46
|
+
debounceTime,
|
|
46
47
|
});
|
|
47
|
-
}, [defaultAgent, apiUrl, stableHeaders, withCredentials, fetch, showHistory, showGraph, fallbackToAvailableAssistants, autoRestoreLastSession, client, legacyMode, historyFilter]);
|
|
48
|
+
}, [defaultAgent, apiUrl, stableHeaders, withCredentials, fetch, showHistory, showGraph, fallbackToAvailableAssistants, autoRestoreLastSession, client, legacyMode, historyFilter, debounceTime]);
|
|
48
49
|
const unionStore = useUnionStore(store, useStore);
|
|
49
50
|
// 使用 ref 标记是否已初始化
|
|
50
51
|
const initializedRef = useRef(false);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type JSX, Accessor } from "solid-js";
|
|
2
|
+
import { HistoryFilter } from "../ui-store/index.js";
|
|
2
3
|
import { ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
3
4
|
import { PreinitializedWritableAtom, StoreValue } from "nanostores";
|
|
4
5
|
export declare const useChat: () => UnionStoreSolid<{
|
|
@@ -28,7 +29,7 @@ export declare const useChat: () => UnionStoreSolid<{
|
|
|
28
29
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
29
30
|
}, unknown>[]> & object;
|
|
30
31
|
historyPagination: PreinitializedWritableAtom<import("../ui-store/createChatStore.js").HistoryPagination> & object;
|
|
31
|
-
historyFilter: PreinitializedWritableAtom<
|
|
32
|
+
historyFilter: PreinitializedWritableAtom<HistoryFilter> & object;
|
|
32
33
|
};
|
|
33
34
|
mutations: {
|
|
34
35
|
setCurrentArtifactById: (id: string, tool_id: string) => void;
|
|
@@ -66,7 +67,7 @@ export declare const useChat: () => UnionStoreSolid<{
|
|
|
66
67
|
}>): Promise<void>;
|
|
67
68
|
setHistoryPage(page: number): void;
|
|
68
69
|
setHistoryPageSize(pageSize: number): void;
|
|
69
|
-
setHistoryFilter(filter: Partial<
|
|
70
|
+
setHistoryFilter(filter: Partial<HistoryFilter>): void;
|
|
70
71
|
resetHistoryFilter(): void;
|
|
71
72
|
};
|
|
72
73
|
}>;
|
|
@@ -86,7 +87,9 @@ interface ChatProviderProps {
|
|
|
86
87
|
client?: ILangGraphClient;
|
|
87
88
|
legacyMode?: boolean;
|
|
88
89
|
/** 历史记录筛选的默认参数 */
|
|
89
|
-
historyFilter?:
|
|
90
|
+
historyFilter?: HistoryFilter;
|
|
91
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
92
|
+
debounceTime?: number;
|
|
90
93
|
}
|
|
91
94
|
/**
|
|
92
95
|
* @zh UnionStore 类型用于合并 store 的 data 和 mutations,使其可以直接访问。
|
|
@@ -54,6 +54,7 @@ export const ChatProvider = (props) => {
|
|
|
54
54
|
fallbackToAvailableAssistants: props.fallbackToAvailableAssistants || false,
|
|
55
55
|
autoRestoreLastSession: props.autoRestoreLastSession || false,
|
|
56
56
|
historyFilter: props.historyFilter,
|
|
57
|
+
debounceTime: props.debounceTime,
|
|
57
58
|
});
|
|
58
59
|
});
|
|
59
60
|
const unionStore = useUnionStoreSolid(store(), useStore);
|
package/dist/tool/ToolUI.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class ToolRenderData<I, D> {
|
|
|
8
8
|
message: RenderMessage;
|
|
9
9
|
client: LangGraphClient;
|
|
10
10
|
constructor(message: RenderMessage, client: LangGraphClient);
|
|
11
|
+
/** 这个 id 需要联系到 tool call id, 但是很悲哀langgraph 的 hitl interrupt 没有传递任何 id,非常蠢 */
|
|
11
12
|
private getToolActionRequestID;
|
|
12
13
|
/**
|
|
13
14
|
* 获取人机交互数据
|
package/dist/tool/ToolUI.js
CHANGED
|
@@ -8,6 +8,7 @@ export class ToolRenderData {
|
|
|
8
8
|
this.message = message;
|
|
9
9
|
this.client = client;
|
|
10
10
|
}
|
|
11
|
+
/** 这个 id 需要联系到 tool call id, 但是很悲哀langgraph 的 hitl interrupt 没有传递任何 id,非常蠢 */
|
|
11
12
|
getToolActionRequestID() {
|
|
12
13
|
return createActionRequestID({
|
|
13
14
|
name: this.message.name,
|
|
@@ -43,7 +44,7 @@ export class ToolRenderData {
|
|
|
43
44
|
/**@ts-ignore 修复 sb 的 langchain 官方的命名不统一,我们一致采用下划线版本,而非驼峰版本 */
|
|
44
45
|
response.editedAction = response.edited_action;
|
|
45
46
|
}
|
|
46
|
-
return this.client.doneHumanInTheLoopWaiting(this.message.id, this.getToolActionRequestID(), response);
|
|
47
|
+
return this.client.doneHumanInTheLoopWaiting(this.message.id || this.message.tool_call_id, this.getToolActionRequestID(), response);
|
|
47
48
|
}
|
|
48
49
|
get state() {
|
|
49
50
|
if (this.message.type === "tool" && this.message?.additional_kwargs?.done) {
|
|
@@ -105,7 +105,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
105
105
|
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
106
106
|
renderMessages.set(messages);
|
|
107
107
|
currentStatus.set(newClient.status);
|
|
108
|
-
}, 10);
|
|
108
|
+
}, context.debounceTime ?? 10);
|
|
109
109
|
// ============ 工具和图表辅助函数 ============
|
|
110
110
|
const refreshTools = async () => {
|
|
111
111
|
const c = client.get();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type PropType, Ref } from "vue";
|
|
2
|
-
import { createChatStore } from "../ui-store/index.js";
|
|
2
|
+
import { createChatStore, HistoryFilter } from "../ui-store/index.js";
|
|
3
3
|
import { PreinitializedWritableAtom, StoreValue } from "nanostores";
|
|
4
4
|
import { ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
5
5
|
/**
|
|
@@ -40,7 +40,9 @@ export interface ChatProviderProps {
|
|
|
40
40
|
client?: ILangGraphClient;
|
|
41
41
|
legacyMode?: boolean;
|
|
42
42
|
/** 历史记录筛选的默认参数 */
|
|
43
|
-
historyFilter?:
|
|
43
|
+
historyFilter?: HistoryFilter;
|
|
44
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
45
|
+
debounceTime?: number;
|
|
44
46
|
}
|
|
45
47
|
/**
|
|
46
48
|
* @zh Chat Provider Hook,用于在 setup 中直接使用
|
|
@@ -74,7 +76,7 @@ export declare const useChatProvider: (props: ChatProviderProps) => {
|
|
|
74
76
|
messages: import("@langchain/langgraph-sdk").Message[];
|
|
75
77
|
}, unknown>[]> & object;
|
|
76
78
|
historyPagination: PreinitializedWritableAtom<import("../ui-store/createChatStore.js").HistoryPagination> & object;
|
|
77
|
-
historyFilter: PreinitializedWritableAtom<
|
|
79
|
+
historyFilter: PreinitializedWritableAtom<HistoryFilter> & object;
|
|
78
80
|
};
|
|
79
81
|
mutations: {
|
|
80
82
|
setCurrentArtifactById: (id: string, tool_id: string) => void;
|
|
@@ -112,7 +114,7 @@ export declare const useChatProvider: (props: ChatProviderProps) => {
|
|
|
112
114
|
}>): Promise<void>;
|
|
113
115
|
setHistoryPage(page: number): void;
|
|
114
116
|
setHistoryPageSize(pageSize: number): void;
|
|
115
|
-
setHistoryFilter(filter: Partial<
|
|
117
|
+
setHistoryFilter(filter: Partial<HistoryFilter>): void;
|
|
116
118
|
resetHistoryFilter(): void;
|
|
117
119
|
};
|
|
118
120
|
}>;
|
|
@@ -162,6 +164,10 @@ export declare const ChatProvider: import("vue").DefineComponent<import("vue").E
|
|
|
162
164
|
type: PropType<any>;
|
|
163
165
|
default: undefined;
|
|
164
166
|
};
|
|
167
|
+
debounceTime: {
|
|
168
|
+
type: PropType<number>;
|
|
169
|
+
default: undefined;
|
|
170
|
+
};
|
|
165
171
|
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
166
172
|
[key: string]: any;
|
|
167
173
|
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
@@ -205,6 +211,10 @@ export declare const ChatProvider: import("vue").DefineComponent<import("vue").E
|
|
|
205
211
|
type: PropType<any>;
|
|
206
212
|
default: undefined;
|
|
207
213
|
};
|
|
214
|
+
debounceTime: {
|
|
215
|
+
type: PropType<number>;
|
|
216
|
+
default: undefined;
|
|
217
|
+
};
|
|
208
218
|
}>> & Readonly<{}>, {
|
|
209
219
|
apiUrl: string;
|
|
210
220
|
defaultHeaders: Record<string, string>;
|
|
@@ -216,4 +226,5 @@ export declare const ChatProvider: import("vue").DefineComponent<import("vue").E
|
|
|
216
226
|
fetch: typeof fetch;
|
|
217
227
|
autoRestoreLastSession: boolean;
|
|
218
228
|
onInitError: (error: any, currentAgent: string) => void;
|
|
229
|
+
debounceTime: number;
|
|
219
230
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vue/ChatContext.js
CHANGED
|
@@ -54,6 +54,7 @@ export const useChatProvider = (props) => {
|
|
|
54
54
|
fallbackToAvailableAssistants: props.fallbackToAvailableAssistants,
|
|
55
55
|
autoRestoreLastSession: props.autoRestoreLastSession,
|
|
56
56
|
historyFilter: props.historyFilter,
|
|
57
|
+
debounceTime: props.debounceTime,
|
|
57
58
|
});
|
|
58
59
|
const unionStore = useUnionStoreVue(store, useStore);
|
|
59
60
|
// 提供 store 给子组件
|
|
@@ -118,6 +119,10 @@ export const ChatProvider = defineComponent({
|
|
|
118
119
|
type: Object,
|
|
119
120
|
default: undefined,
|
|
120
121
|
},
|
|
122
|
+
debounceTime: {
|
|
123
|
+
type: Number,
|
|
124
|
+
default: undefined,
|
|
125
|
+
},
|
|
121
126
|
},
|
|
122
127
|
setup(props, { slots }) {
|
|
123
128
|
const { unionStore } = useChatProvider(props);
|
package/package.json
CHANGED
package/src/LangGraphClient.ts
CHANGED
|
@@ -443,7 +443,13 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
|
|
|
443
443
|
this.processStreamChunk(chunk, command);
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
|
-
const data = await
|
|
446
|
+
const data = (await Promise.race([
|
|
447
|
+
this.runFETool(),
|
|
448
|
+
new Promise((res) => {
|
|
449
|
+
this.forceSkipToolLock = () => res(null);
|
|
450
|
+
}),
|
|
451
|
+
])) as any[] | null;
|
|
452
|
+
this.forceSkipToolLock = undefined;
|
|
447
453
|
await this.responseHumanInTheLoop();
|
|
448
454
|
if (data) streamRecord.push(...data);
|
|
449
455
|
this._status = "idle";
|
|
@@ -538,7 +544,7 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
|
|
|
538
544
|
// json 校验
|
|
539
545
|
return this.callFETool(toolMessage, tool.args).catch((e) => console.warn(e));
|
|
540
546
|
});
|
|
541
|
-
|
|
547
|
+
|
|
542
548
|
// 只有当卡住流程时,才改变状态为 interrupted
|
|
543
549
|
this._status = "interrupted";
|
|
544
550
|
this.currentThread!.status = "interrupted"; // 修复某些机制下,状态不为 interrupted 与后端有差异
|
|
@@ -632,6 +638,8 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
|
|
|
632
638
|
}
|
|
633
639
|
}
|
|
634
640
|
|
|
641
|
+
/** 尝试强制跳过工具调用 */
|
|
642
|
+
private forceSkipToolLock?: () => void;
|
|
635
643
|
/**
|
|
636
644
|
* @zh 标记人机交互等待已完成。
|
|
637
645
|
* @en Marks the human in the loop waiting as completed.
|
|
@@ -641,6 +649,14 @@ export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGrap
|
|
|
641
649
|
this.tools.doneWaiting(tool_id, result);
|
|
642
650
|
if (this.humanInTheLoop) {
|
|
643
651
|
this.humanInTheLoop.result[action_request_id] = result;
|
|
652
|
+
if (Object.keys(this.humanInTheLoop.result).length === this.humanInTheLoop.interruptData.length) {
|
|
653
|
+
setTimeout(() => {
|
|
654
|
+
if (this.forceSkipToolLock) {
|
|
655
|
+
console.warn("force kill tool lock");
|
|
656
|
+
this.forceSkipToolLock();
|
|
657
|
+
}
|
|
658
|
+
}, 100);
|
|
659
|
+
}
|
|
644
660
|
}
|
|
645
661
|
}
|
|
646
662
|
|
package/src/react/ChatContext.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createElement, createContext, useContext, useMemo, ReactNode, useEffect, useRef } from "react";
|
|
2
2
|
|
|
3
|
-
import { createChatStore, UnionStore, useUnionStore } from "../ui-store/index.js";
|
|
3
|
+
import { createChatStore, HistoryFilter, UnionStore, useUnionStore } from "../ui-store/index.js";
|
|
4
4
|
import { useStore } from "@nanostores/react";
|
|
5
5
|
import { ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
6
6
|
|
|
@@ -30,7 +30,9 @@ interface ChatProviderProps {
|
|
|
30
30
|
client?: ILangGraphClient;
|
|
31
31
|
legacyMode?: boolean;
|
|
32
32
|
/** 历史记录筛选的默认参数 */
|
|
33
|
-
historyFilter?:
|
|
33
|
+
historyFilter?: HistoryFilter;
|
|
34
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
35
|
+
debounceTime?: number;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
@@ -48,6 +50,7 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
48
50
|
client,
|
|
49
51
|
legacyMode = false,
|
|
50
52
|
historyFilter,
|
|
53
|
+
debounceTime,
|
|
51
54
|
}) => {
|
|
52
55
|
// 使用 useMemo 稳定 defaultHeaders 的引用
|
|
53
56
|
const stableHeaders = useMemo(() => defaultHeaders || {}, [defaultHeaders]);
|
|
@@ -84,8 +87,9 @@ export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
|
84
87
|
fallbackToAvailableAssistants,
|
|
85
88
|
autoRestoreLastSession,
|
|
86
89
|
historyFilter,
|
|
90
|
+
debounceTime,
|
|
87
91
|
});
|
|
88
|
-
}, [defaultAgent, apiUrl, stableHeaders, withCredentials, fetch, showHistory, showGraph, fallbackToAvailableAssistants, autoRestoreLastSession, client, legacyMode, historyFilter]);
|
|
92
|
+
}, [defaultAgent, apiUrl, stableHeaders, withCredentials, fetch, showHistory, showGraph, fallbackToAvailableAssistants, autoRestoreLastSession, client, legacyMode, historyFilter, debounceTime]);
|
|
89
93
|
|
|
90
94
|
const unionStore = useUnionStore(store, useStore);
|
|
91
95
|
|
package/src/solid/ChatContext.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, useContext, createMemo, onMount, type JSX, type Component, createComponent, Accessor } from "solid-js";
|
|
2
|
-
import { createChatStore, UnionStore } from "../ui-store/index.js";
|
|
2
|
+
import { createChatStore, HistoryFilter, UnionStore } from "../ui-store/index.js";
|
|
3
3
|
import { useStore } from "@nanostores/solid";
|
|
4
4
|
import { ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
5
5
|
import { PreinitializedWritableAtom, StoreValue } from "nanostores";
|
|
@@ -30,7 +30,9 @@ interface ChatProviderProps {
|
|
|
30
30
|
client?: ILangGraphClient;
|
|
31
31
|
legacyMode?: boolean;
|
|
32
32
|
/** 历史记录筛选的默认参数 */
|
|
33
|
-
historyFilter?:
|
|
33
|
+
historyFilter?: HistoryFilter;
|
|
34
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
35
|
+
debounceTime?: number;
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* @zh UnionStore 类型用于合并 store 的 data 和 mutations,使其可以直接访问。
|
|
@@ -93,6 +95,7 @@ export const ChatProvider = (props: ChatProviderProps) => {
|
|
|
93
95
|
fallbackToAvailableAssistants: props.fallbackToAvailableAssistants || false,
|
|
94
96
|
autoRestoreLastSession: props.autoRestoreLastSession || false,
|
|
95
97
|
historyFilter: props.historyFilter,
|
|
98
|
+
debounceTime: props.debounceTime,
|
|
96
99
|
});
|
|
97
100
|
});
|
|
98
101
|
|
package/src/tool/ToolUI.ts
CHANGED
|
@@ -13,6 +13,7 @@ export class ToolRenderData<I, D> {
|
|
|
13
13
|
public message: RenderMessage,
|
|
14
14
|
public client: LangGraphClient
|
|
15
15
|
) {}
|
|
16
|
+
/** 这个 id 需要联系到 tool call id, 但是很悲哀langgraph 的 hitl interrupt 没有传递任何 id,非常蠢 */
|
|
16
17
|
private getToolActionRequestID() {
|
|
17
18
|
return createActionRequestID({
|
|
18
19
|
name: this.message.name!,
|
|
@@ -48,7 +49,7 @@ export class ToolRenderData<I, D> {
|
|
|
48
49
|
response.editedAction = response.edited_action;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
return this.client.doneHumanInTheLoopWaiting(this.message.id!, this.getToolActionRequestID(), response);
|
|
52
|
+
return this.client.doneHumanInTheLoopWaiting(this.message.id || this.message.tool_call_id!, this.getToolActionRequestID(), response);
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
get state() {
|
|
@@ -61,6 +61,8 @@ interface ChatStoreContext {
|
|
|
61
61
|
autoRestoreLastSession?: boolean;
|
|
62
62
|
/** 历史记录筛选的默认参数 */
|
|
63
63
|
historyFilter?: Partial<HistoryFilter>;
|
|
64
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
65
|
+
debounceTime?: number;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
// 分页状态类型
|
|
@@ -153,7 +155,7 @@ export const createChatStore = (initClientName: string, config: Partial<LangGrap
|
|
|
153
155
|
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
154
156
|
renderMessages.set(messages);
|
|
155
157
|
currentStatus.set(newClient.status);
|
|
156
|
-
}, 10);
|
|
158
|
+
}, context.debounceTime ?? 10);
|
|
157
159
|
// ============ 工具和图表辅助函数 ============
|
|
158
160
|
|
|
159
161
|
const refreshTools = async () => {
|
package/src/vue/ChatContext.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent, inject, provide, onMounted, defineExpose, type InjectionKey, type PropType, Ref } from "vue";
|
|
2
|
-
import { createChatStore } from "../ui-store/index.js";
|
|
2
|
+
import { createChatStore, HistoryFilter } from "../ui-store/index.js";
|
|
3
3
|
import { useStore } from "@nanostores/vue";
|
|
4
4
|
import { PreinitializedWritableAtom, StoreValue } from "nanostores";
|
|
5
5
|
import { ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
@@ -62,7 +62,9 @@ export interface ChatProviderProps {
|
|
|
62
62
|
client?: ILangGraphClient;
|
|
63
63
|
legacyMode?: boolean;
|
|
64
64
|
/** 历史记录筛选的默认参数 */
|
|
65
|
-
historyFilter?:
|
|
65
|
+
historyFilter?: HistoryFilter;
|
|
66
|
+
/** UI 更新的防抖时间(毫秒,默认 10) */
|
|
67
|
+
debounceTime?: number;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
/**
|
|
@@ -96,6 +98,7 @@ export const useChatProvider = (props: ChatProviderProps) => {
|
|
|
96
98
|
fallbackToAvailableAssistants: props.fallbackToAvailableAssistants,
|
|
97
99
|
autoRestoreLastSession: props.autoRestoreLastSession,
|
|
98
100
|
historyFilter: props.historyFilter,
|
|
101
|
+
debounceTime: props.debounceTime,
|
|
99
102
|
}
|
|
100
103
|
);
|
|
101
104
|
|
|
@@ -166,6 +169,10 @@ export const ChatProvider = defineComponent({
|
|
|
166
169
|
type: Object as PropType<any>,
|
|
167
170
|
default: undefined,
|
|
168
171
|
},
|
|
172
|
+
debounceTime: {
|
|
173
|
+
type: Number as PropType<number>,
|
|
174
|
+
default: undefined,
|
|
175
|
+
},
|
|
169
176
|
},
|
|
170
177
|
setup(props, { slots }) {
|
|
171
178
|
const { unionStore } = useChatProvider(props);
|