@langgraph-js/sdk 3.7.1 → 3.8.0
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/History.d.ts +115 -0
- package/dist/History.js +226 -0
- package/dist/LangGraphClient.d.ts +10 -1
- package/dist/LangGraphClient.js +17 -3
- package/dist/TestKit.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/react/ChatContext.d.ts +28 -20
- package/dist/react/ChatContext.js +3 -2
- package/dist/ui-store/createChatStore.d.ts +33 -66
- package/dist/ui-store/createChatStore.js +255 -225
- package/dist/vue/ChatContext.d.ts +38 -21
- package/dist/vue/ChatContext.js +5 -0
- package/package.json +1 -1
- package/src/History.ts +294 -0
- package/src/LangGraphClient.ts +25 -3
- package/src/index.ts +1 -0
- package/src/react/ChatContext.ts +5 -1
- package/src/ui-store/createChatStore.ts +310 -236
- package/src/vue/ChatContext.ts +7 -0
|
@@ -1,27 +1,12 @@
|
|
|
1
1
|
import { atom } from "nanostores";
|
|
2
|
-
import { LangGraphClient } from "../LangGraphClient.js";
|
|
3
2
|
import { debounce } from "ts-debounce";
|
|
4
3
|
import { ToolRenderData } from "../tool/ToolUI.js";
|
|
5
4
|
import { createLangGraphServerClient } from "../client/LanggraphServer.js";
|
|
6
5
|
import { useArtifacts } from "../artifacts/index.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export const formatTime = (date) => {
|
|
12
|
-
return date.toLocaleTimeString();
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
* @zh 格式化数字为带千位分隔符的字符串。
|
|
16
|
-
* @en Formats a number into a string with thousand separators.
|
|
17
|
-
*/
|
|
18
|
-
export const formatTokens = (tokens) => {
|
|
19
|
-
return tokens.toLocaleString("en");
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* @zh 获取消息内容的文本表示,处理不同类型的消息内容。
|
|
23
|
-
* @en Gets the text representation of message content, handling different types of message content.
|
|
24
|
-
*/
|
|
6
|
+
import { History } from "../History.js";
|
|
7
|
+
// ============ 工具函数 ============
|
|
8
|
+
export const formatTime = (date) => date.toLocaleTimeString();
|
|
9
|
+
export const formatTokens = (tokens) => tokens.toLocaleString("en");
|
|
25
10
|
export const getMessageContent = (content) => {
|
|
26
11
|
if (typeof content === "string")
|
|
27
12
|
return content;
|
|
@@ -40,43 +25,56 @@ export const getMessageContent = (content) => {
|
|
|
40
25
|
}
|
|
41
26
|
return JSON.stringify(content);
|
|
42
27
|
};
|
|
43
|
-
/**
|
|
44
|
-
* @zh 获取历史记录中 Thread 内容的文本表示。
|
|
45
|
-
* @en Gets the text representation of Thread content in history.
|
|
46
|
-
*/
|
|
47
28
|
export const getHistoryContent = (thread) => {
|
|
48
29
|
/** @ts-ignore */
|
|
49
30
|
const content = thread.title || thread.name || thread?.values?.messages?.[0]?.content;
|
|
50
31
|
if (content && Array.isArray(content)) {
|
|
51
|
-
return content.map((item) =>
|
|
52
|
-
if (item.type === "text") {
|
|
53
|
-
return item.text;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
else if (typeof content === "string") {
|
|
58
|
-
return content;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
return "";
|
|
32
|
+
return content.map((item) => (item.type === "text" ? item.text : undefined)).filter(Boolean);
|
|
62
33
|
}
|
|
34
|
+
return typeof content === "string" ? content : "";
|
|
63
35
|
};
|
|
64
|
-
|
|
65
|
-
* @zh 创建一个用于聊天界面的状态管理器 (store)。
|
|
66
|
-
* @en Creates a state manager (store) for the chat interface.
|
|
67
|
-
*/
|
|
36
|
+
// ============ Store 创建函数 ============
|
|
68
37
|
export const createChatStore = (initClientName, config, context = {}) => {
|
|
38
|
+
// ============ 状态原子 ============
|
|
39
|
+
// 会话管理
|
|
40
|
+
const history = atom(null);
|
|
41
|
+
const sessions = atom([]);
|
|
69
42
|
const client = atom(null);
|
|
43
|
+
const historyList = atom([]);
|
|
44
|
+
// UI 状态
|
|
70
45
|
const renderMessages = atom([]);
|
|
71
46
|
const userInput = atom("");
|
|
72
|
-
const loading = atom(false);
|
|
73
|
-
const collapsedTools = atom([]);
|
|
74
47
|
const inChatError = atom(null);
|
|
75
|
-
const showHistory = atom(context.showHistory ?? false);
|
|
76
48
|
const currentAgent = atom(initClientName);
|
|
77
49
|
const currentChatId = atom(null);
|
|
78
50
|
const currentNodeName = atom("__start__");
|
|
51
|
+
// 工具和图表
|
|
79
52
|
const tools = atom([]);
|
|
53
|
+
const collapsedTools = atom([]);
|
|
54
|
+
const showHistory = atom(context.showHistory ?? false);
|
|
55
|
+
const showGraph = atom(context.showGraph ?? false);
|
|
56
|
+
const graphVisualize = atom(null);
|
|
57
|
+
// ============ 内部状态 ============
|
|
58
|
+
let cleanupCurrentClient = null;
|
|
59
|
+
// ============ 计算属性 ============
|
|
60
|
+
/** 基于 client.status 的 loading 状态 */
|
|
61
|
+
const loading = atom(false);
|
|
62
|
+
const updateLoadingFromClientStatus = () => {
|
|
63
|
+
const c = client.get();
|
|
64
|
+
if (c) {
|
|
65
|
+
loading.set(c.status === "busy");
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
// ============ UI 更新逻辑 ============
|
|
69
|
+
const updateUI = debounce((newClient) => {
|
|
70
|
+
if (client.get() !== newClient)
|
|
71
|
+
return;
|
|
72
|
+
const messages = newClient.renderMessage;
|
|
73
|
+
const lastMessage = messages[messages.length - 1];
|
|
74
|
+
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
75
|
+
renderMessages.set(messages);
|
|
76
|
+
}, 10);
|
|
77
|
+
// ============ 工具和图表辅助函数 ============
|
|
80
78
|
const refreshTools = async () => {
|
|
81
79
|
const c = client.get();
|
|
82
80
|
if (!c)
|
|
@@ -84,87 +82,174 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
84
82
|
c.tools.clearTools();
|
|
85
83
|
c.tools.bindTools(tools.get());
|
|
86
84
|
};
|
|
87
|
-
// 显示 langgraph 可视化图
|
|
88
|
-
const showGraph = atom(context.showGraph ?? false);
|
|
89
|
-
const graphVisualize = atom(null);
|
|
90
85
|
const refreshGraph = async () => {
|
|
91
|
-
if (showGraph.get())
|
|
86
|
+
if (showGraph.get()) {
|
|
92
87
|
graphVisualize.set((await client.get()?.graphVisualize()) || null);
|
|
88
|
+
}
|
|
93
89
|
};
|
|
94
|
-
|
|
95
|
-
const messages = newClient.renderMessage;
|
|
96
|
-
const lastMessage = messages[messages.length - 1];
|
|
97
|
-
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
98
|
-
renderMessages.set(messages);
|
|
99
|
-
}, 10);
|
|
100
|
-
/**
|
|
101
|
-
* @zh 初始化 LangGraph 客户端。
|
|
102
|
-
* @en Initializes the LangGraph client.
|
|
103
|
-
*/
|
|
90
|
+
// ============ 会话管理核心逻辑 ============
|
|
104
91
|
async function initClient() {
|
|
105
|
-
const
|
|
92
|
+
const historyManager = new History({
|
|
106
93
|
...config,
|
|
107
94
|
client: config.client ?? (await createLangGraphServerClient(config)),
|
|
108
95
|
});
|
|
109
|
-
await
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
96
|
+
await historyManager.init(currentAgent.get());
|
|
97
|
+
history.set(historyManager);
|
|
98
|
+
// 同步远程会话列表
|
|
99
|
+
await refreshSessionList();
|
|
100
|
+
// 根据配置决定初始化行为
|
|
101
|
+
const syncedSessions = sessions.get();
|
|
102
|
+
if (context.autoRestoreLastSession && syncedSessions.length > 0) {
|
|
103
|
+
// 自动激活最近的历史会话
|
|
104
|
+
await activateSession(syncedSessions[0].sessionId);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// 创建新会话
|
|
108
|
+
await createNewSession();
|
|
109
|
+
}
|
|
110
|
+
return historyManager;
|
|
111
|
+
}
|
|
112
|
+
async function refreshSessionList() {
|
|
113
|
+
const historyManager = history.get();
|
|
114
|
+
if (!historyManager)
|
|
115
|
+
return;
|
|
116
|
+
try {
|
|
117
|
+
const syncedSessions = await historyManager.syncFromRemote({ limit: 100 });
|
|
118
|
+
sessions.set(syncedSessions);
|
|
119
|
+
historyList.set(syncedSessions.filter((s) => s.thread).map((s) => s.thread));
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error("Failed to sync sessions:", error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async function createNewSession() {
|
|
126
|
+
const historyManager = history.get();
|
|
127
|
+
if (!historyManager)
|
|
128
|
+
return;
|
|
129
|
+
try {
|
|
130
|
+
const session = await historyManager.createSession();
|
|
131
|
+
await refreshSessionList();
|
|
132
|
+
await activateSession(session.sessionId);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error("Failed to create new session:", error);
|
|
136
|
+
inChatError.set(error.message);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ============ 客户端事件监听器 ============
|
|
140
|
+
function setupClientListeners(newClient) {
|
|
141
|
+
const isActiveClient = () => client.get() === newClient;
|
|
142
|
+
const onStart = () => {
|
|
143
|
+
if (isActiveClient())
|
|
144
|
+
updateLoadingFromClientStatus();
|
|
145
|
+
};
|
|
146
|
+
const onThread = () => {
|
|
147
|
+
if (!isActiveClient())
|
|
148
|
+
return;
|
|
149
|
+
const thread = newClient.getCurrentThread();
|
|
150
|
+
currentChatId.set(thread?.thread_id || null);
|
|
122
151
|
currentNodeName.set("__start__");
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
const historyManager = history.get();
|
|
153
|
+
const activeSession = historyManager?.getActiveSession();
|
|
154
|
+
if (activeSession && thread) {
|
|
155
|
+
activeSession.thread = thread;
|
|
156
|
+
}
|
|
157
|
+
refreshSessionList();
|
|
158
|
+
};
|
|
159
|
+
const onDone = () => {
|
|
160
|
+
if (isActiveClient()) {
|
|
161
|
+
updateLoadingFromClientStatus();
|
|
162
|
+
updateUI(newClient);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const onError = (event) => {
|
|
166
|
+
if (isActiveClient()) {
|
|
167
|
+
updateLoadingFromClientStatus();
|
|
168
|
+
inChatError.set(event.data);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const onMessage = () => {
|
|
172
|
+
if (isActiveClient()) {
|
|
173
|
+
currentChatId.set(newClient.getCurrentThread()?.thread_id || null);
|
|
174
|
+
updateLoadingFromClientStatus();
|
|
175
|
+
updateUI(newClient);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
const onValue = () => {
|
|
179
|
+
if (isActiveClient()) {
|
|
180
|
+
currentChatId.set(newClient.getCurrentThread()?.thread_id || null);
|
|
181
|
+
updateLoadingFromClientStatus();
|
|
182
|
+
updateUI(newClient);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
newClient.on("start", onStart);
|
|
186
|
+
newClient.on("thread", onThread);
|
|
187
|
+
newClient.on("done", onDone);
|
|
188
|
+
newClient.on("error", onError);
|
|
189
|
+
newClient.on("message", onMessage);
|
|
190
|
+
newClient.on("value", onValue);
|
|
191
|
+
return () => {
|
|
192
|
+
newClient.off("start", onStart);
|
|
193
|
+
newClient.off("thread", onThread);
|
|
194
|
+
newClient.off("done", onDone);
|
|
195
|
+
newClient.off("error", onError);
|
|
196
|
+
newClient.off("message", onMessage);
|
|
197
|
+
newClient.off("value", onValue);
|
|
198
|
+
};
|
|
151
199
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
200
|
+
// ============ 会话激活逻辑 ============
|
|
201
|
+
async function activateSession(sessionId) {
|
|
202
|
+
const historyManager = history.get();
|
|
203
|
+
if (!historyManager)
|
|
204
|
+
return;
|
|
205
|
+
try {
|
|
206
|
+
if (cleanupCurrentClient) {
|
|
207
|
+
cleanupCurrentClient();
|
|
208
|
+
cleanupCurrentClient = null;
|
|
209
|
+
}
|
|
210
|
+
inChatError.set(null);
|
|
211
|
+
const session = await historyManager.activateSession(sessionId);
|
|
212
|
+
const activeClient = session.client;
|
|
213
|
+
if (activeClient) {
|
|
214
|
+
cleanupCurrentClient = setupClientListeners(activeClient);
|
|
215
|
+
context.onInit?.(activeClient);
|
|
216
|
+
client.set(activeClient);
|
|
217
|
+
currentChatId.set(sessionId);
|
|
218
|
+
const messages = activeClient.renderMessage;
|
|
219
|
+
renderMessages.set(messages);
|
|
220
|
+
const lastMessage = messages[messages.length - 1];
|
|
221
|
+
currentNodeName.set(lastMessage?.node_name || lastMessage?.name || "__start__");
|
|
222
|
+
updateLoadingFromClientStatus();
|
|
223
|
+
if (showGraph.get())
|
|
224
|
+
refreshGraph();
|
|
225
|
+
refreshTools();
|
|
226
|
+
const currentThread = activeClient.getCurrentThread();
|
|
227
|
+
if (currentThread && (currentThread.status === "running" || currentThread.status === "pending")) {
|
|
228
|
+
await activeClient.resetStream();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
console.error("Failed to activate session:", error);
|
|
234
|
+
inChatError.set(error.message);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// ============ 消息和交互逻辑 ============
|
|
238
|
+
async function sendMessage(message, extraData, withoutCheck = false) {
|
|
239
|
+
const c = client.get();
|
|
240
|
+
if ((!withoutCheck && !userInput.get().trim() && !message?.length) || !c)
|
|
241
|
+
return;
|
|
242
|
+
// 使用 client.status 判断是否正在加载
|
|
243
|
+
if (c.status === "busy")
|
|
158
244
|
return;
|
|
159
|
-
loading.set(true);
|
|
160
245
|
inChatError.set(null);
|
|
161
246
|
try {
|
|
162
|
-
await
|
|
247
|
+
await c.sendMessage(message || userInput.get(), extraData);
|
|
163
248
|
}
|
|
164
249
|
catch (e) {
|
|
165
250
|
const isThreadRunning = e.message.includes("422");
|
|
166
251
|
if (isThreadRunning) {
|
|
167
|
-
await
|
|
252
|
+
await c.resetStream();
|
|
168
253
|
}
|
|
169
254
|
else {
|
|
170
255
|
throw e;
|
|
@@ -172,105 +257,74 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
172
257
|
}
|
|
173
258
|
finally {
|
|
174
259
|
userInput.set("");
|
|
175
|
-
|
|
260
|
+
updateLoadingFromClientStatus();
|
|
176
261
|
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
* @zh 停止当前的消息生成。
|
|
180
|
-
* @en Stops the current message generation.
|
|
181
|
-
*/
|
|
182
|
-
const stopGeneration = () => {
|
|
262
|
+
}
|
|
263
|
+
function stopGeneration() {
|
|
183
264
|
client.get()?.cancelRun();
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
* @zh 切换工具消息的折叠状态。
|
|
187
|
-
* @en Toggles the collapsed state of a tool message.
|
|
188
|
-
*/
|
|
189
|
-
const toggleToolCollapse = (toolId) => {
|
|
265
|
+
}
|
|
266
|
+
function toggleToolCollapse(toolId) {
|
|
190
267
|
const prev = collapsedTools.get();
|
|
191
268
|
collapsedTools.set(prev.includes(toolId) ? prev.filter((id) => id !== toolId) : [...prev, toolId]);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
* @zh 切换历史记录面板的可见性。
|
|
195
|
-
* @en Toggles the visibility of the history panel.
|
|
196
|
-
*/
|
|
197
|
-
const toggleHistoryVisible = () => {
|
|
269
|
+
}
|
|
270
|
+
function toggleHistoryVisible() {
|
|
198
271
|
showHistory.set(!showHistory.get());
|
|
199
272
|
if (showHistory.get()) {
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
const historyList = atom([]);
|
|
204
|
-
/**
|
|
205
|
-
* @zh 刷新历史记录列表。
|
|
206
|
-
* @en Refreshes the history list.
|
|
207
|
-
*/
|
|
208
|
-
const refreshHistoryList = async () => {
|
|
209
|
-
if (!client.get() || !showHistory.get())
|
|
210
|
-
return;
|
|
211
|
-
try {
|
|
212
|
-
const response = await client.get()?.listThreads();
|
|
213
|
-
historyList.set(response || []);
|
|
273
|
+
refreshSessionList();
|
|
214
274
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
/**
|
|
220
|
-
* @zh 将一个 Thread 添加到历史记录列表的开头。
|
|
221
|
-
* @en Adds a Thread to the beginning of the history list.
|
|
222
|
-
*/
|
|
223
|
-
const addToHistory = (thread) => {
|
|
275
|
+
}
|
|
276
|
+
function addToHistory(thread) {
|
|
224
277
|
const prev = historyList.get();
|
|
225
278
|
historyList.set([thread, ...prev]);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const
|
|
279
|
+
}
|
|
280
|
+
function getToolUIRender(tool_name) {
|
|
281
|
+
const c = client.get();
|
|
282
|
+
if (!c)
|
|
283
|
+
return null;
|
|
284
|
+
const toolsDefine = c.tools.getAllTools();
|
|
229
285
|
const tool = toolsDefine.find((i) => i.name === tool_name)?.render;
|
|
230
|
-
return tool ? (message) => tool(new ToolRenderData(message,
|
|
231
|
-
}
|
|
286
|
+
return tool ? (message) => tool(new ToolRenderData(message, c)) : null;
|
|
287
|
+
}
|
|
288
|
+
// ============ 返回 Store API ============
|
|
232
289
|
const artifactHook = useArtifacts(renderMessages, client);
|
|
233
290
|
return {
|
|
234
291
|
data: {
|
|
292
|
+
// 核心客户端
|
|
235
293
|
client,
|
|
294
|
+
history,
|
|
295
|
+
sessions,
|
|
296
|
+
// UI 状态
|
|
236
297
|
renderMessages,
|
|
237
298
|
userInput,
|
|
238
299
|
loading,
|
|
239
300
|
inChatError,
|
|
240
301
|
currentAgent,
|
|
241
|
-
collapsedTools,
|
|
242
|
-
showHistory,
|
|
243
|
-
historyList,
|
|
244
302
|
currentChatId,
|
|
245
|
-
showGraph,
|
|
246
|
-
graphVisualize,
|
|
247
303
|
currentNodeName,
|
|
304
|
+
// 工具和图表
|
|
248
305
|
tools,
|
|
306
|
+
collapsedTools,
|
|
307
|
+
showGraph,
|
|
308
|
+
graphVisualize,
|
|
309
|
+
// 历史记录
|
|
310
|
+
showHistory,
|
|
311
|
+
historyList,
|
|
249
312
|
...artifactHook.data,
|
|
250
313
|
},
|
|
251
314
|
mutations: {
|
|
252
|
-
|
|
253
|
-
setTools(new_tools) {
|
|
254
|
-
tools.set(new_tools);
|
|
255
|
-
refreshTools();
|
|
256
|
-
},
|
|
257
|
-
isFELocking() {
|
|
258
|
-
return client.get()?.isFELocking(renderMessages.get());
|
|
259
|
-
},
|
|
260
|
-
getClient() {
|
|
261
|
-
return client.get();
|
|
262
|
-
},
|
|
315
|
+
// 初始化
|
|
263
316
|
initClient,
|
|
317
|
+
getClient: () => client.get(),
|
|
318
|
+
getHistory: () => history.get(),
|
|
319
|
+
// 会话管理
|
|
320
|
+
activateSession,
|
|
321
|
+
createNewSession,
|
|
322
|
+
refreshSessionList,
|
|
323
|
+
refreshHistoryList: refreshSessionList, // 向后兼容
|
|
324
|
+
// 消息操作
|
|
264
325
|
sendMessage,
|
|
265
326
|
stopGeneration,
|
|
266
|
-
|
|
267
|
-
toggleHistoryVisible,
|
|
268
|
-
refreshHistoryList,
|
|
269
|
-
addToHistory,
|
|
270
|
-
/**
|
|
271
|
-
* @zh 回滚到指定的消息。
|
|
272
|
-
* @en Reverts to the specified message.
|
|
273
|
-
*/
|
|
327
|
+
setUserInput: (input) => userInput.set(input),
|
|
274
328
|
async revertChatTo(messageId, resend = false, sendOptions) {
|
|
275
329
|
await client.get()?.revertChatTo(messageId, sendOptions || {});
|
|
276
330
|
if (resend) {
|
|
@@ -280,63 +334,39 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
280
334
|
updateUI(client.get());
|
|
281
335
|
}
|
|
282
336
|
},
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
userInput.set(input);
|
|
289
|
-
},
|
|
290
|
-
/**
|
|
291
|
-
* @zh 设置当前的 Agent 并重新初始化客户端。
|
|
292
|
-
* @en Sets the current Agent and reinitializes the client.
|
|
293
|
-
*/
|
|
294
|
-
setCurrentAgent(agent) {
|
|
295
|
-
currentAgent.set(agent);
|
|
296
|
-
return initClient().then(() => {
|
|
297
|
-
if (showHistory.get()) {
|
|
298
|
-
refreshHistoryList();
|
|
299
|
-
}
|
|
300
|
-
});
|
|
337
|
+
// 工具操作
|
|
338
|
+
refreshTools,
|
|
339
|
+
setTools(new_tools) {
|
|
340
|
+
tools.set(new_tools);
|
|
341
|
+
refreshTools();
|
|
301
342
|
},
|
|
343
|
+
toggleToolCollapse,
|
|
344
|
+
getToolUIRender,
|
|
345
|
+
isFELocking: () => client.get()?.isFELocking(renderMessages.get()),
|
|
346
|
+
// UI 切换
|
|
347
|
+
toggleHistoryVisible,
|
|
302
348
|
toggleGraphVisible() {
|
|
303
349
|
showGraph.set(!showGraph.get());
|
|
304
|
-
if (showGraph.get())
|
|
350
|
+
if (showGraph.get())
|
|
305
351
|
refreshGraph();
|
|
306
|
-
}
|
|
307
352
|
},
|
|
308
353
|
refreshGraph,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
createNewChat() {
|
|
314
|
-
client.get()?.reset();
|
|
315
|
-
inChatError.set(null);
|
|
316
|
-
loading.set(false);
|
|
317
|
-
},
|
|
318
|
-
/**
|
|
319
|
-
* @zh 切换到指定的历史聊天会话。
|
|
320
|
-
* @en Switches to the specified historical chat session.
|
|
321
|
-
*/
|
|
322
|
-
async toHistoryChat(thread) {
|
|
323
|
-
inChatError.set(null);
|
|
324
|
-
loading.set(false);
|
|
325
|
-
const nowThread = await client.get()?.resetThread(thread.metadata?.graph_id, thread.thread_id);
|
|
326
|
-
if (nowThread) {
|
|
327
|
-
client.get()?.resetStream();
|
|
328
|
-
}
|
|
329
|
-
return nowThread;
|
|
354
|
+
// Agent 切换
|
|
355
|
+
setCurrentAgent(agent) {
|
|
356
|
+
currentAgent.set(agent);
|
|
357
|
+
return initClient();
|
|
330
358
|
},
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
359
|
+
// 历史记录(兼容旧 API)
|
|
360
|
+
addToHistory,
|
|
361
|
+
createNewChat: createNewSession,
|
|
362
|
+
toHistoryChat: (thread) => activateSession(thread.thread_id),
|
|
335
363
|
async deleteHistoryChat(thread) {
|
|
336
|
-
|
|
337
|
-
|
|
364
|
+
const historyManager = history.get();
|
|
365
|
+
if (historyManager) {
|
|
366
|
+
await historyManager.deleteSession(thread.thread_id);
|
|
367
|
+
await refreshSessionList();
|
|
368
|
+
}
|
|
338
369
|
},
|
|
339
|
-
getToolUIRender,
|
|
340
370
|
...artifactHook.mutation,
|
|
341
371
|
},
|
|
342
372
|
};
|