@langgraph-js/sdk 1.7.6 → 1.7.10
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/LICENSE +201 -201
- package/README.md +163 -163
- package/dist/LangGraphClient.js +1 -1
- package/dist/ToolManager.d.ts +1 -1
- package/dist/ToolManager.js +2 -1
- package/dist/tool/createTool.d.ts +4 -0
- package/dist/ui-store/createChatStore.js +0 -3
- package/package.json +1 -1
- package/src/LangGraphClient.ts +655 -655
- package/src/SpendTime.ts +60 -60
- package/src/ToolManager.ts +132 -131
- package/src/index.ts +5 -5
- package/src/tool/ToolUI.ts +55 -55
- package/src/tool/copilotkit-actions.ts +72 -72
- package/src/tool/createTool.ts +104 -102
- package/src/tool/index.ts +3 -3
- package/src/tool/utils.ts +158 -158
- package/src/ui-store/UnionStore.ts +29 -29
- package/src/ui-store/createChatStore.ts +295 -298
- package/src/ui-store/index.ts +2 -2
- package/src/ui-store/rafDebounce.ts +29 -29
- package/test/testResponse.json +5418 -5418
- package/tsconfig.json +112 -112
- package/.env +0 -0
- package/.turbo/turbo-build.log +0 -5
- package/dist/server/createState.d.ts +0 -13
- package/dist/server/createState.js +0 -20
- package/dist/server/feTools.d.ts +0 -16
- package/dist/server/feTools.js +0 -37
- package/dist/server/index.d.ts +0 -3
- package/dist/server/index.js +0 -3
- package/dist/server/interrupt/index.d.ts +0 -23
- package/dist/server/interrupt/index.js +0 -36
- package/dist/server/swarm/handoff.d.ts +0 -11
- package/dist/server/swarm/handoff.js +0 -84
- package/dist/server/swarm/keepState.d.ts +0 -6
- package/dist/server/swarm/keepState.js +0 -21
- package/dist/server/tools/index.d.ts +0 -1
- package/dist/server/tools/index.js +0 -1
- package/dist/server/tools/sequential-thinking.d.ts +0 -52
- package/dist/server/tools/sequential-thinking.js +0 -69
- package/dist/server/utils.d.ts +0 -3
- package/dist/server/utils.js +0 -24
|
@@ -1,298 +1,295 @@
|
|
|
1
|
-
import { atom, computed } from "nanostores";
|
|
2
|
-
import { LangGraphClient, LangGraphClientConfig, RenderMessage, SendMessageOptions } from "../LangGraphClient.js";
|
|
3
|
-
import { AssistantGraph, Message, Thread } from "@langchain/langgraph-sdk";
|
|
4
|
-
import { rafDebounce } from "./rafDebounce.js";
|
|
5
|
-
import { ToolRenderData } from "../tool/ToolUI.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @zh 格式化日期对象为时间字符串。
|
|
9
|
-
* @en Formats a Date object into a time string.
|
|
10
|
-
*/
|
|
11
|
-
export const formatTime = (date: Date) => {
|
|
12
|
-
return date.toLocaleTimeString("en-US");
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @zh 格式化数字为带千位分隔符的字符串。
|
|
17
|
-
* @en Formats a number into a string with thousand separators.
|
|
18
|
-
*/
|
|
19
|
-
export const formatTokens = (tokens: number) => {
|
|
20
|
-
return tokens.toLocaleString("en");
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @zh 获取消息内容的文本表示,处理不同类型的消息内容。
|
|
25
|
-
* @en Gets the text representation of message content, handling different types of message content.
|
|
26
|
-
*/
|
|
27
|
-
export const getMessageContent = (content: any) => {
|
|
28
|
-
if (typeof content === "string") return content;
|
|
29
|
-
if (Array.isArray(content)) {
|
|
30
|
-
return content
|
|
31
|
-
.map((item) => {
|
|
32
|
-
if (typeof item === "string") return item;
|
|
33
|
-
if (item.type === "text") return item.text;
|
|
34
|
-
if (item.type === "image_url") return `[图片]`;
|
|
35
|
-
return JSON.stringify(item);
|
|
36
|
-
})
|
|
37
|
-
.join("");
|
|
38
|
-
}
|
|
39
|
-
return JSON.stringify(content);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @zh 获取历史记录中 Thread 内容的文本表示。
|
|
44
|
-
* @en Gets the text representation of Thread content in history.
|
|
45
|
-
*/
|
|
46
|
-
export const getHistoryContent = (thread: Thread) => {
|
|
47
|
-
const content = (thread?.values as any)?.messages?.[0]?.content;
|
|
48
|
-
if (content && Array.isArray(content)) {
|
|
49
|
-
return content.map((item: any) => {
|
|
50
|
-
if (item.type === "text") {
|
|
51
|
-
return item.text;
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
} else if (typeof content === "string") {
|
|
55
|
-
return content;
|
|
56
|
-
} else {
|
|
57
|
-
return "";
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @zh 创建一个用于聊天界面的状态管理器 (store)。
|
|
63
|
-
* @en Creates a state manager (store) for the chat interface.
|
|
64
|
-
*/
|
|
65
|
-
export const createChatStore = (
|
|
66
|
-
initClientName: string,
|
|
67
|
-
config: LangGraphClientConfig,
|
|
68
|
-
context: {
|
|
69
|
-
showHistory?: boolean;
|
|
70
|
-
showGraph?: boolean;
|
|
71
|
-
onInit?: (client: LangGraphClient) => void;
|
|
72
|
-
} = {}
|
|
73
|
-
) => {
|
|
74
|
-
const client = atom<LangGraphClient | null>(null);
|
|
75
|
-
const renderMessages = atom<RenderMessage[]>([]);
|
|
76
|
-
const userInput = atom<string>("");
|
|
77
|
-
const loading = atom<boolean>(false);
|
|
78
|
-
const collapsedTools = atom<string[]>([]);
|
|
79
|
-
const inChatError = atom<string | null>(null);
|
|
80
|
-
const showHistory = atom<boolean>(context.showHistory ?? false);
|
|
81
|
-
const currentAgent = atom<string>(initClientName);
|
|
82
|
-
const currentChatId = atom<string | null>(null);
|
|
83
|
-
const currentNodeName = atom<string>("__start__");
|
|
84
|
-
|
|
85
|
-
// 显示 langgraph 可视化图
|
|
86
|
-
const showGraph = atom<boolean>(context.showGraph ?? false);
|
|
87
|
-
const graphVisualize = atom<AssistantGraph | null>(null);
|
|
88
|
-
const refreshGraph = async () => {
|
|
89
|
-
if (showGraph.get()) graphVisualize.set((await client.get()?.graphVisualize()) || null);
|
|
90
|
-
};
|
|
91
|
-
const updateUI = rafDebounce((newClient: LangGraphClient) => {
|
|
92
|
-
const messages = newClient.renderMessage;
|
|
93
|
-
const lastMessage = messages[messages.length - 1];
|
|
94
|
-
|
|
95
|
-
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
96
|
-
|
|
97
|
-
renderMessages.set(messages);
|
|
98
|
-
});
|
|
99
|
-
/**
|
|
100
|
-
* @zh 初始化 LangGraph 客户端。
|
|
101
|
-
* @en Initializes the LangGraph client.
|
|
102
|
-
*/
|
|
103
|
-
async function initClient() {
|
|
104
|
-
const newClient = new LangGraphClient(config);
|
|
105
|
-
await newClient.initAssistant(currentAgent.get());
|
|
106
|
-
currentAgent.set(newClient.getCurrentAssistant()!.graph_id);
|
|
107
|
-
// 不再需要创建,sendMessage 会自动创建
|
|
108
|
-
// await newClient.createThread();
|
|
109
|
-
inChatError.set(null);
|
|
110
|
-
newClient.onStreamingUpdate((event) => {
|
|
111
|
-
if (event.type === "start") loading.set(true);
|
|
112
|
-
if (event.type === "thread" || event.type === "done") {
|
|
113
|
-
// console.log(event.data);
|
|
114
|
-
// 创建新流程时,默认为 __start__
|
|
115
|
-
currentNodeName.set("__start__");
|
|
116
|
-
if (event.type === "done") loading.set(false);
|
|
117
|
-
// 创建新会话时,需要自动刷新历史面板
|
|
118
|
-
return refreshHistoryList();
|
|
119
|
-
}
|
|
120
|
-
if (event.type === "error") {
|
|
121
|
-
loading.set(false);
|
|
122
|
-
inChatError.set(event.data);
|
|
123
|
-
}
|
|
124
|
-
// console.log(newClient.renderMessage);
|
|
125
|
-
|
|
126
|
-
updateUI(newClient);
|
|
127
|
-
});
|
|
128
|
-
context.onInit?.(newClient);
|
|
129
|
-
newClient.graphState = {};
|
|
130
|
-
client.set(newClient);
|
|
131
|
-
if (showGraph.get()) refreshGraph();
|
|
132
|
-
return newClient;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* @zh 发送消息。
|
|
137
|
-
* @en Sends a message.
|
|
138
|
-
*/
|
|
139
|
-
const sendMessage = async (message?: Message[], extraData?: SendMessageOptions) => {
|
|
140
|
-
if ((!userInput.get().trim() && !message?.length) || loading.get() || !client.get()) return;
|
|
141
|
-
|
|
142
|
-
loading.set(true);
|
|
143
|
-
inChatError.set(null);
|
|
144
|
-
|
|
145
|
-
await client.get()?.sendMessage(message || userInput.get(), extraData);
|
|
146
|
-
|
|
147
|
-
userInput.set("");
|
|
148
|
-
loading.set(false);
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @zh 停止当前的消息生成。
|
|
153
|
-
* @en Stops the current message generation.
|
|
154
|
-
*/
|
|
155
|
-
const stopGeneration = () => {
|
|
156
|
-
client.get()?.cancelRun();
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @zh 切换工具消息的折叠状态。
|
|
161
|
-
* @en Toggles the collapsed state of a tool message.
|
|
162
|
-
*/
|
|
163
|
-
const toggleToolCollapse = (toolId: string) => {
|
|
164
|
-
const prev = collapsedTools.get();
|
|
165
|
-
collapsedTools.set(prev.includes(toolId) ? prev.filter((id) => id !== toolId) : [...prev, toolId]);
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @zh 切换历史记录面板的可见性。
|
|
170
|
-
* @en Toggles the visibility of the history panel.
|
|
171
|
-
*/
|
|
172
|
-
const toggleHistoryVisible = () => {
|
|
173
|
-
showHistory.set(!showHistory.get());
|
|
174
|
-
if (showHistory.get()) {
|
|
175
|
-
refreshHistoryList();
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const historyList = atom<Thread<{ messages: Message[] }>[]>([]);
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* @zh 刷新历史记录列表。
|
|
183
|
-
* @en Refreshes the history list.
|
|
184
|
-
*/
|
|
185
|
-
const refreshHistoryList = async () => {
|
|
186
|
-
if (!client.get() || !showHistory.get()) return;
|
|
187
|
-
try {
|
|
188
|
-
const response = await client.get()?.listThreads<{ messages: Message[] }>();
|
|
189
|
-
historyList.set(response || []);
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.error("Failed to fetch threads:", error);
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* @zh 将一个 Thread 添加到历史记录列表的开头。
|
|
197
|
-
* @en Adds a Thread to the beginning of the history list.
|
|
198
|
-
*/
|
|
199
|
-
const addToHistory = (thread: Thread<{ messages: Message[] }>) => {
|
|
200
|
-
const prev = historyList.get();
|
|
201
|
-
historyList.set([thread, ...prev]);
|
|
202
|
-
};
|
|
203
|
-
const getToolUIRender = (tool_name: string) => {
|
|
204
|
-
const toolsDefine = client.get()!.tools.getAllTools();
|
|
205
|
-
const tool = toolsDefine.find((i) => i.name === tool_name!)?.render;
|
|
206
|
-
return tool ? (message: RenderMessage) => tool(new ToolRenderData(message, client.get()!)) : null;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
data: {
|
|
211
|
-
client,
|
|
212
|
-
renderMessages,
|
|
213
|
-
userInput,
|
|
214
|
-
loading,
|
|
215
|
-
inChatError,
|
|
216
|
-
currentAgent,
|
|
217
|
-
collapsedTools,
|
|
218
|
-
showHistory,
|
|
219
|
-
historyList,
|
|
220
|
-
currentChatId,
|
|
221
|
-
showGraph,
|
|
222
|
-
graphVisualize,
|
|
223
|
-
currentNodeName,
|
|
224
|
-
},
|
|
225
|
-
mutations: {
|
|
226
|
-
isFELocking() {
|
|
227
|
-
return client.get()?.isFELocking(renderMessages.get());
|
|
228
|
-
},
|
|
229
|
-
initClient,
|
|
230
|
-
sendMessage,
|
|
231
|
-
stopGeneration,
|
|
232
|
-
toggleToolCollapse,
|
|
233
|
-
toggleHistoryVisible,
|
|
234
|
-
refreshHistoryList,
|
|
235
|
-
addToHistory,
|
|
236
|
-
/**
|
|
237
|
-
* @zh 设置用户输入内容。
|
|
238
|
-
* @en Sets the user input content.
|
|
239
|
-
*/
|
|
240
|
-
setUserInput(input: string) {
|
|
241
|
-
userInput.set(input);
|
|
242
|
-
},
|
|
243
|
-
/**
|
|
244
|
-
* @zh 设置当前的 Agent 并重新初始化客户端。
|
|
245
|
-
* @en Sets the current Agent and reinitializes the client.
|
|
246
|
-
*/
|
|
247
|
-
setCurrentAgent(agent: string) {
|
|
248
|
-
currentAgent.set(agent);
|
|
249
|
-
return initClient().then(() => {
|
|
250
|
-
if (showHistory.get()) {
|
|
251
|
-
refreshHistoryList();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
},
|
|
297
|
-
};
|
|
298
|
-
};
|
|
1
|
+
import { atom, computed } from "nanostores";
|
|
2
|
+
import { LangGraphClient, LangGraphClientConfig, RenderMessage, SendMessageOptions } from "../LangGraphClient.js";
|
|
3
|
+
import { AssistantGraph, Message, Thread } from "@langchain/langgraph-sdk";
|
|
4
|
+
import { rafDebounce } from "./rafDebounce.js";
|
|
5
|
+
import { ToolRenderData } from "../tool/ToolUI.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @zh 格式化日期对象为时间字符串。
|
|
9
|
+
* @en Formats a Date object into a time string.
|
|
10
|
+
*/
|
|
11
|
+
export const formatTime = (date: Date) => {
|
|
12
|
+
return date.toLocaleTimeString("en-US");
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @zh 格式化数字为带千位分隔符的字符串。
|
|
17
|
+
* @en Formats a number into a string with thousand separators.
|
|
18
|
+
*/
|
|
19
|
+
export const formatTokens = (tokens: number) => {
|
|
20
|
+
return tokens.toLocaleString("en");
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @zh 获取消息内容的文本表示,处理不同类型的消息内容。
|
|
25
|
+
* @en Gets the text representation of message content, handling different types of message content.
|
|
26
|
+
*/
|
|
27
|
+
export const getMessageContent = (content: any) => {
|
|
28
|
+
if (typeof content === "string") return content;
|
|
29
|
+
if (Array.isArray(content)) {
|
|
30
|
+
return content
|
|
31
|
+
.map((item) => {
|
|
32
|
+
if (typeof item === "string") return item;
|
|
33
|
+
if (item.type === "text") return item.text;
|
|
34
|
+
if (item.type === "image_url") return `[图片]`;
|
|
35
|
+
return JSON.stringify(item);
|
|
36
|
+
})
|
|
37
|
+
.join("");
|
|
38
|
+
}
|
|
39
|
+
return JSON.stringify(content);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @zh 获取历史记录中 Thread 内容的文本表示。
|
|
44
|
+
* @en Gets the text representation of Thread content in history.
|
|
45
|
+
*/
|
|
46
|
+
export const getHistoryContent = (thread: Thread) => {
|
|
47
|
+
const content = (thread?.values as any)?.messages?.[0]?.content;
|
|
48
|
+
if (content && Array.isArray(content)) {
|
|
49
|
+
return content.map((item: any) => {
|
|
50
|
+
if (item.type === "text") {
|
|
51
|
+
return item.text;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
} else if (typeof content === "string") {
|
|
55
|
+
return content;
|
|
56
|
+
} else {
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @zh 创建一个用于聊天界面的状态管理器 (store)。
|
|
63
|
+
* @en Creates a state manager (store) for the chat interface.
|
|
64
|
+
*/
|
|
65
|
+
export const createChatStore = (
|
|
66
|
+
initClientName: string,
|
|
67
|
+
config: LangGraphClientConfig,
|
|
68
|
+
context: {
|
|
69
|
+
showHistory?: boolean;
|
|
70
|
+
showGraph?: boolean;
|
|
71
|
+
onInit?: (client: LangGraphClient) => void;
|
|
72
|
+
} = {}
|
|
73
|
+
) => {
|
|
74
|
+
const client = atom<LangGraphClient | null>(null);
|
|
75
|
+
const renderMessages = atom<RenderMessage[]>([]);
|
|
76
|
+
const userInput = atom<string>("");
|
|
77
|
+
const loading = atom<boolean>(false);
|
|
78
|
+
const collapsedTools = atom<string[]>([]);
|
|
79
|
+
const inChatError = atom<string | null>(null);
|
|
80
|
+
const showHistory = atom<boolean>(context.showHistory ?? false);
|
|
81
|
+
const currentAgent = atom<string>(initClientName);
|
|
82
|
+
const currentChatId = atom<string | null>(null);
|
|
83
|
+
const currentNodeName = atom<string>("__start__");
|
|
84
|
+
|
|
85
|
+
// 显示 langgraph 可视化图
|
|
86
|
+
const showGraph = atom<boolean>(context.showGraph ?? false);
|
|
87
|
+
const graphVisualize = atom<AssistantGraph | null>(null);
|
|
88
|
+
const refreshGraph = async () => {
|
|
89
|
+
if (showGraph.get()) graphVisualize.set((await client.get()?.graphVisualize()) || null);
|
|
90
|
+
};
|
|
91
|
+
const updateUI = rafDebounce((newClient: LangGraphClient) => {
|
|
92
|
+
const messages = newClient.renderMessage;
|
|
93
|
+
const lastMessage = messages[messages.length - 1];
|
|
94
|
+
|
|
95
|
+
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
96
|
+
|
|
97
|
+
renderMessages.set(messages);
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* @zh 初始化 LangGraph 客户端。
|
|
101
|
+
* @en Initializes the LangGraph client.
|
|
102
|
+
*/
|
|
103
|
+
async function initClient() {
|
|
104
|
+
const newClient = new LangGraphClient(config);
|
|
105
|
+
await newClient.initAssistant(currentAgent.get());
|
|
106
|
+
currentAgent.set(newClient.getCurrentAssistant()!.graph_id);
|
|
107
|
+
// 不再需要创建,sendMessage 会自动创建
|
|
108
|
+
// await newClient.createThread();
|
|
109
|
+
inChatError.set(null);
|
|
110
|
+
newClient.onStreamingUpdate((event) => {
|
|
111
|
+
if (event.type === "start") loading.set(true);
|
|
112
|
+
if (event.type === "thread" || event.type === "done") {
|
|
113
|
+
// console.log(event.data);
|
|
114
|
+
// 创建新流程时,默认为 __start__
|
|
115
|
+
currentNodeName.set("__start__");
|
|
116
|
+
if (event.type === "done") loading.set(false);
|
|
117
|
+
// 创建新会话时,需要自动刷新历史面板
|
|
118
|
+
return refreshHistoryList();
|
|
119
|
+
}
|
|
120
|
+
if (event.type === "error") {
|
|
121
|
+
loading.set(false);
|
|
122
|
+
inChatError.set(event.data);
|
|
123
|
+
}
|
|
124
|
+
// console.log(newClient.renderMessage);
|
|
125
|
+
|
|
126
|
+
updateUI(newClient);
|
|
127
|
+
});
|
|
128
|
+
context.onInit?.(newClient);
|
|
129
|
+
newClient.graphState = {};
|
|
130
|
+
client.set(newClient);
|
|
131
|
+
if (showGraph.get()) refreshGraph();
|
|
132
|
+
return newClient;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @zh 发送消息。
|
|
137
|
+
* @en Sends a message.
|
|
138
|
+
*/
|
|
139
|
+
const sendMessage = async (message?: Message[], extraData?: SendMessageOptions) => {
|
|
140
|
+
if ((!userInput.get().trim() && !message?.length) || loading.get() || !client.get()) return;
|
|
141
|
+
|
|
142
|
+
loading.set(true);
|
|
143
|
+
inChatError.set(null);
|
|
144
|
+
|
|
145
|
+
await client.get()?.sendMessage(message || userInput.get(), extraData);
|
|
146
|
+
|
|
147
|
+
userInput.set("");
|
|
148
|
+
loading.set(false);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @zh 停止当前的消息生成。
|
|
153
|
+
* @en Stops the current message generation.
|
|
154
|
+
*/
|
|
155
|
+
const stopGeneration = () => {
|
|
156
|
+
client.get()?.cancelRun();
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @zh 切换工具消息的折叠状态。
|
|
161
|
+
* @en Toggles the collapsed state of a tool message.
|
|
162
|
+
*/
|
|
163
|
+
const toggleToolCollapse = (toolId: string) => {
|
|
164
|
+
const prev = collapsedTools.get();
|
|
165
|
+
collapsedTools.set(prev.includes(toolId) ? prev.filter((id) => id !== toolId) : [...prev, toolId]);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @zh 切换历史记录面板的可见性。
|
|
170
|
+
* @en Toggles the visibility of the history panel.
|
|
171
|
+
*/
|
|
172
|
+
const toggleHistoryVisible = () => {
|
|
173
|
+
showHistory.set(!showHistory.get());
|
|
174
|
+
if (showHistory.get()) {
|
|
175
|
+
refreshHistoryList();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const historyList = atom<Thread<{ messages: Message[] }>[]>([]);
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @zh 刷新历史记录列表。
|
|
183
|
+
* @en Refreshes the history list.
|
|
184
|
+
*/
|
|
185
|
+
const refreshHistoryList = async () => {
|
|
186
|
+
if (!client.get() || !showHistory.get()) return;
|
|
187
|
+
try {
|
|
188
|
+
const response = await client.get()?.listThreads<{ messages: Message[] }>();
|
|
189
|
+
historyList.set(response || []);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error("Failed to fetch threads:", error);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @zh 将一个 Thread 添加到历史记录列表的开头。
|
|
197
|
+
* @en Adds a Thread to the beginning of the history list.
|
|
198
|
+
*/
|
|
199
|
+
const addToHistory = (thread: Thread<{ messages: Message[] }>) => {
|
|
200
|
+
const prev = historyList.get();
|
|
201
|
+
historyList.set([thread, ...prev]);
|
|
202
|
+
};
|
|
203
|
+
const getToolUIRender = (tool_name: string) => {
|
|
204
|
+
const toolsDefine = client.get()!.tools.getAllTools();
|
|
205
|
+
const tool = toolsDefine.find((i) => i.name === tool_name!)?.render;
|
|
206
|
+
return tool ? (message: RenderMessage) => tool(new ToolRenderData(message, client.get()!)) : null;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
data: {
|
|
211
|
+
client,
|
|
212
|
+
renderMessages,
|
|
213
|
+
userInput,
|
|
214
|
+
loading,
|
|
215
|
+
inChatError,
|
|
216
|
+
currentAgent,
|
|
217
|
+
collapsedTools,
|
|
218
|
+
showHistory,
|
|
219
|
+
historyList,
|
|
220
|
+
currentChatId,
|
|
221
|
+
showGraph,
|
|
222
|
+
graphVisualize,
|
|
223
|
+
currentNodeName,
|
|
224
|
+
},
|
|
225
|
+
mutations: {
|
|
226
|
+
isFELocking() {
|
|
227
|
+
return client.get()?.isFELocking(renderMessages.get());
|
|
228
|
+
},
|
|
229
|
+
initClient,
|
|
230
|
+
sendMessage,
|
|
231
|
+
stopGeneration,
|
|
232
|
+
toggleToolCollapse,
|
|
233
|
+
toggleHistoryVisible,
|
|
234
|
+
refreshHistoryList,
|
|
235
|
+
addToHistory,
|
|
236
|
+
/**
|
|
237
|
+
* @zh 设置用户输入内容。
|
|
238
|
+
* @en Sets the user input content.
|
|
239
|
+
*/
|
|
240
|
+
setUserInput(input: string) {
|
|
241
|
+
userInput.set(input);
|
|
242
|
+
},
|
|
243
|
+
/**
|
|
244
|
+
* @zh 设置当前的 Agent 并重新初始化客户端。
|
|
245
|
+
* @en Sets the current Agent and reinitializes the client.
|
|
246
|
+
*/
|
|
247
|
+
setCurrentAgent(agent: string) {
|
|
248
|
+
currentAgent.set(agent);
|
|
249
|
+
return initClient().then(() => {
|
|
250
|
+
if (showHistory.get()) {
|
|
251
|
+
refreshHistoryList();
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
toggleGraphVisible() {
|
|
256
|
+
showGraph.set(!showGraph.get());
|
|
257
|
+
if (showGraph.get()) {
|
|
258
|
+
refreshGraph();
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
refreshGraph,
|
|
262
|
+
/**
|
|
263
|
+
* @zh 创建一个新的聊天会话。
|
|
264
|
+
* @en Creates a new chat session.
|
|
265
|
+
*/
|
|
266
|
+
createNewChat() {
|
|
267
|
+
client.get()?.reset();
|
|
268
|
+
inChatError.set(null);
|
|
269
|
+
loading.set(false);
|
|
270
|
+
},
|
|
271
|
+
/**
|
|
272
|
+
* @zh 切换到指定的历史聊天会话。
|
|
273
|
+
* @en Switches to the specified historical chat session.
|
|
274
|
+
*/
|
|
275
|
+
toHistoryChat(
|
|
276
|
+
thread: Thread<{
|
|
277
|
+
messages: Message[];
|
|
278
|
+
}>
|
|
279
|
+
) {
|
|
280
|
+
inChatError.set(null);
|
|
281
|
+
loading.set(false);
|
|
282
|
+
client.get()?.resetThread(thread.metadata?.graph_id as string, thread.thread_id);
|
|
283
|
+
},
|
|
284
|
+
/**
|
|
285
|
+
* @zh 删除指定的历史聊天会话。
|
|
286
|
+
* @en Deletes the specified historical chat session.
|
|
287
|
+
*/
|
|
288
|
+
async deleteHistoryChat(thread: Thread<{ messages: Message[] }>) {
|
|
289
|
+
await client.get()?.threads.delete(thread.thread_id);
|
|
290
|
+
await refreshHistoryList();
|
|
291
|
+
},
|
|
292
|
+
getToolUIRender,
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
};
|
package/src/ui-store/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./createChatStore.js";
|
|
2
|
-
export * from "./UnionStore.js";
|
|
1
|
+
export * from "./createChatStore.js";
|
|
2
|
+
export * from "./UnionStore.js";
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a debounced function that executes once per animation frame
|
|
3
|
-
* @param callback - The function to debounce
|
|
4
|
-
* @returns A function that executes the callback on the next animation frame
|
|
5
|
-
*/
|
|
6
|
-
export function rafDebounce<T extends (...args: any[]) => any>(callback: T): (...args: Parameters<T>) => void {
|
|
7
|
-
let rafId: number | null = null;
|
|
8
|
-
let lastArgs: Parameters<T> | null = null;
|
|
9
|
-
|
|
10
|
-
// Return the debounced function
|
|
11
|
-
return function (...args: Parameters<T>): void {
|
|
12
|
-
// Store the most recent arguments
|
|
13
|
-
lastArgs = args;
|
|
14
|
-
|
|
15
|
-
// Cancel any pending animation frame
|
|
16
|
-
if (rafId !== null) {
|
|
17
|
-
cancelAnimationFrame(rafId);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Schedule execution on the next animation frame
|
|
21
|
-
rafId = requestAnimationFrame(() => {
|
|
22
|
-
if (lastArgs !== null) {
|
|
23
|
-
callback(...lastArgs);
|
|
24
|
-
lastArgs = null;
|
|
25
|
-
}
|
|
26
|
-
rafId = null;
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Creates a debounced function that executes once per animation frame
|
|
3
|
+
* @param callback - The function to debounce
|
|
4
|
+
* @returns A function that executes the callback on the next animation frame
|
|
5
|
+
*/
|
|
6
|
+
export function rafDebounce<T extends (...args: any[]) => any>(callback: T): (...args: Parameters<T>) => void {
|
|
7
|
+
let rafId: number | null = null;
|
|
8
|
+
let lastArgs: Parameters<T> | null = null;
|
|
9
|
+
|
|
10
|
+
// Return the debounced function
|
|
11
|
+
return function (...args: Parameters<T>): void {
|
|
12
|
+
// Store the most recent arguments
|
|
13
|
+
lastArgs = args;
|
|
14
|
+
|
|
15
|
+
// Cancel any pending animation frame
|
|
16
|
+
if (rafId !== null) {
|
|
17
|
+
cancelAnimationFrame(rafId);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Schedule execution on the next animation frame
|
|
21
|
+
rafId = requestAnimationFrame(() => {
|
|
22
|
+
if (lastArgs !== null) {
|
|
23
|
+
callback(...lastArgs);
|
|
24
|
+
lastArgs = null;
|
|
25
|
+
}
|
|
26
|
+
rafId = null;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|