@langgraph-js/sdk 1.3.2 → 1.5.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/LangGraphClient.d.ts +3 -0
- package/dist/LangGraphClient.js +43 -3
- package/dist/tool/ToolUI.d.ts +10 -0
- package/dist/tool/ToolUI.js +24 -0
- package/dist/tool/createTool.d.ts +20 -2
- package/dist/tool/createTool.js +7 -0
- package/dist/tool/index.d.ts +1 -0
- package/dist/tool/index.js +1 -0
- package/dist/ui-store/createChatStore.d.ts +1 -0
- package/dist/ui-store/createChatStore.js +8 -0
- package/package.json +1 -1
- package/src/LangGraphClient.ts +57 -18
- package/src/tool/ToolUI.ts +26 -0
- package/src/tool/createTool.ts +12 -1
- package/src/tool/index.ts +1 -0
- package/src/ui-store/createChatStore.ts +7 -1
|
@@ -119,6 +119,7 @@ export declare class LangGraphClient extends Client {
|
|
|
119
119
|
/** 图发过来的更新信息 */
|
|
120
120
|
graphMessages: RenderMessage[];
|
|
121
121
|
cloneMessage(message: Message): Message;
|
|
122
|
+
private updateStreamingMessage;
|
|
122
123
|
private replaceMessageWithValuesMessage;
|
|
123
124
|
/**
|
|
124
125
|
* @zh 用于 UI 中的流式渲染中的消息。
|
|
@@ -164,6 +165,8 @@ export declare class LangGraphClient extends Client {
|
|
|
164
165
|
* @en Sends a message to the LangGraph backend.
|
|
165
166
|
*/
|
|
166
167
|
sendMessage(input: string | Message[], { extraParams, _debug, command }?: SendMessageOptions): Promise<any[]>;
|
|
168
|
+
/** 子图的数据需要通过 merge 的方式重新进行合并更新 */
|
|
169
|
+
private mergeSubGraphMessagesToStreamingMessages;
|
|
167
170
|
private runFETool;
|
|
168
171
|
private callFETool;
|
|
169
172
|
/**
|
package/dist/LangGraphClient.js
CHANGED
|
@@ -126,6 +126,14 @@ export class LangGraphClient extends Client {
|
|
|
126
126
|
cloneMessage(message) {
|
|
127
127
|
return JSON.parse(JSON.stringify(message));
|
|
128
128
|
}
|
|
129
|
+
updateStreamingMessage(message) {
|
|
130
|
+
const lastMessage = this.streamingMessage[this.streamingMessage.length - 1];
|
|
131
|
+
if (!(lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.id) || message.id !== lastMessage.id) {
|
|
132
|
+
this.streamingMessage.push(message);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.streamingMessage[this.streamingMessage.length - 1] = message;
|
|
136
|
+
}
|
|
129
137
|
replaceMessageWithValuesMessage(message, isTool = false) {
|
|
130
138
|
const key = (isTool ? "tool_call_id" : "id");
|
|
131
139
|
const valuesMessage = this.graphMessages.find((i) => i[key] === message[key]);
|
|
@@ -145,8 +153,10 @@ export class LangGraphClient extends Client {
|
|
|
145
153
|
get renderMessage() {
|
|
146
154
|
var _a;
|
|
147
155
|
const previousMessage = new Map();
|
|
156
|
+
const closedToolCallIds = new Set();
|
|
148
157
|
const result = [];
|
|
149
158
|
const inputMessages = [...this.graphMessages, ...this.streamingMessage];
|
|
159
|
+
console.log(inputMessages);
|
|
150
160
|
// 从后往前遍历,这样可以保证最新的消息在前面
|
|
151
161
|
for (let i = inputMessages.length - 1; i >= 0; i--) {
|
|
152
162
|
const message = this.cloneMessage(inputMessages[i]);
|
|
@@ -164,7 +174,11 @@ export class LangGraphClient extends Client {
|
|
|
164
174
|
previousMessage.set(message.id, m);
|
|
165
175
|
/** @ts-ignore */
|
|
166
176
|
const tool_calls = ((_a = m.tool_calls) === null || _a === void 0 ? void 0 : _a.length) ? m.tool_calls : m.tool_call_chunks;
|
|
167
|
-
const new_tool_calls = tool_calls
|
|
177
|
+
const new_tool_calls = tool_calls
|
|
178
|
+
.filter((i) => {
|
|
179
|
+
return !closedToolCallIds.has(i.id);
|
|
180
|
+
})
|
|
181
|
+
.map((tool, index) => {
|
|
168
182
|
var _a, _b, _c, _d;
|
|
169
183
|
return this.replaceMessageWithValuesMessage({
|
|
170
184
|
type: "tool",
|
|
@@ -186,6 +200,9 @@ export class LangGraphClient extends Client {
|
|
|
186
200
|
result.unshift(m);
|
|
187
201
|
}
|
|
188
202
|
else {
|
|
203
|
+
if (message.type === "tool" && message.tool_call_id) {
|
|
204
|
+
closedToolCallIds.add(message.tool_call_id);
|
|
205
|
+
}
|
|
189
206
|
// 记录这个 id 的消息,并添加到结果中
|
|
190
207
|
const m = this.replaceMessageWithValuesMessage(message);
|
|
191
208
|
previousMessage.set(message.id, m);
|
|
@@ -364,7 +381,7 @@ export class LangGraphClient extends Client {
|
|
|
364
381
|
}
|
|
365
382
|
else if (chunk.event === "messages/partial") {
|
|
366
383
|
for (const message of chunk.data) {
|
|
367
|
-
this.
|
|
384
|
+
this.updateStreamingMessage(message);
|
|
368
385
|
}
|
|
369
386
|
this.emitStreamingUpdate({
|
|
370
387
|
type: "message",
|
|
@@ -372,7 +389,7 @@ export class LangGraphClient extends Client {
|
|
|
372
389
|
});
|
|
373
390
|
continue;
|
|
374
391
|
}
|
|
375
|
-
else if (chunk.event
|
|
392
|
+
else if (chunk.event === "values") {
|
|
376
393
|
const data = chunk.data;
|
|
377
394
|
if (data.messages) {
|
|
378
395
|
const isResume = !!(command === null || command === void 0 ? void 0 : command.resume);
|
|
@@ -390,6 +407,12 @@ export class LangGraphClient extends Client {
|
|
|
390
407
|
this.streamingMessage = [];
|
|
391
408
|
continue;
|
|
392
409
|
}
|
|
410
|
+
else if (chunk.event.startsWith("values|")) {
|
|
411
|
+
// 这个 values 必然是子 values
|
|
412
|
+
if (chunk.data.messages) {
|
|
413
|
+
this.mergeSubGraphMessagesToStreamingMessages(chunk.data.messages);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
393
416
|
}
|
|
394
417
|
this.streamingMessage = [];
|
|
395
418
|
const data = await this.runFETool();
|
|
@@ -403,6 +426,23 @@ export class LangGraphClient extends Client {
|
|
|
403
426
|
});
|
|
404
427
|
return streamRecord;
|
|
405
428
|
}
|
|
429
|
+
/** 子图的数据需要通过 merge 的方式重新进行合并更新 */
|
|
430
|
+
mergeSubGraphMessagesToStreamingMessages(messages) {
|
|
431
|
+
const map = new Map(messages.filter((i) => i.id).map((i) => [i.id, i]));
|
|
432
|
+
this.streamingMessage.forEach((i) => {
|
|
433
|
+
if (map.has(i.id)) {
|
|
434
|
+
const newValue = map.get(i.id);
|
|
435
|
+
Object.assign(i, newValue);
|
|
436
|
+
map.delete(i.id);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
// 剩余的 message 一定不在 streamMessage 中
|
|
440
|
+
map.forEach((i) => {
|
|
441
|
+
if (i.type === "tool" && i.tool_call_id) {
|
|
442
|
+
this.streamingMessage.push(i);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
406
446
|
runFETool() {
|
|
407
447
|
var _a;
|
|
408
448
|
const data = this.graphMessages;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RenderMessage } from "../LangGraphClient.js";
|
|
2
|
+
import { LangGraphClient } from "../LangGraphClient.js";
|
|
3
|
+
export declare class ToolRenderData<D> {
|
|
4
|
+
message: RenderMessage;
|
|
5
|
+
client: LangGraphClient;
|
|
6
|
+
constructor(message: RenderMessage, client: LangGraphClient);
|
|
7
|
+
get state(): "done" | "idle";
|
|
8
|
+
get input(): any;
|
|
9
|
+
response(data: D): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class ToolRenderData {
|
|
2
|
+
constructor(message, client) {
|
|
3
|
+
this.message = message;
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
get state() {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
if (this.message.type === "tool" && ((_b = (_a = this.message) === null || _a === void 0 ? void 0 : _a.additional_kwargs) === null || _b === void 0 ? void 0 : _b.done)) {
|
|
9
|
+
return "done";
|
|
10
|
+
}
|
|
11
|
+
return "idle";
|
|
12
|
+
}
|
|
13
|
+
get input() {
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(this.message.tool_input);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
response(data) {
|
|
22
|
+
this.client.doneFEToolWaiting(this.message.id, JSON.stringify(data));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z, ZodRawShape, ZodTypeAny } from "zod";
|
|
2
2
|
import { Action, Parameter } from "./copilotkit-actions.js";
|
|
3
3
|
import { Message } from "@langchain/langgraph-sdk";
|
|
4
|
-
|
|
4
|
+
import { ToolRenderData } from "./ToolUI.js";
|
|
5
|
+
export interface UnionTool<Args extends ZodRawShape, Child extends Object = Object> {
|
|
5
6
|
name: string;
|
|
6
7
|
description: string;
|
|
7
8
|
parameters: Args;
|
|
@@ -10,6 +11,8 @@ export interface UnionTool<Args extends ZodRawShape> {
|
|
|
10
11
|
execute: ToolCallback<Args>;
|
|
11
12
|
/** 工具执行成功后触发的附加消息 */
|
|
12
13
|
callbackMessage?: (result: CallToolResult) => Message[];
|
|
14
|
+
render?: <D>(tool: ToolRenderData<D>) => Child;
|
|
15
|
+
onlyRender?: boolean;
|
|
13
16
|
}
|
|
14
17
|
export type ToolCallback<Args extends ZodRawShape> = (args: z.objectOutputType<Args, ZodTypeAny>, context?: any) => CallToolResult | Promise<CallToolResult>;
|
|
15
18
|
export type CallToolResult = string | {
|
|
@@ -17,7 +20,7 @@ export type CallToolResult = string | {
|
|
|
17
20
|
text: string;
|
|
18
21
|
}[];
|
|
19
22
|
/** 用于格式校验 */
|
|
20
|
-
export declare const createTool: <Args extends ZodRawShape>(tool: UnionTool<Args>) => UnionTool<Args>;
|
|
23
|
+
export declare const createTool: <Args extends ZodRawShape>(tool: UnionTool<Args>) => UnionTool<Args, Object>;
|
|
21
24
|
/** 提供一种兼容 copilotkit 的定义方式,简化定义形式
|
|
22
25
|
* 来自 copilotkit 的 frontend action
|
|
23
26
|
*/
|
|
@@ -45,3 +48,18 @@ export declare const createMCPTool: <Args extends ZodRawShape>(tool: UnionTool<A
|
|
|
45
48
|
}[];
|
|
46
49
|
isError: boolean;
|
|
47
50
|
}>))[];
|
|
51
|
+
export declare const createToolUI: <Args extends Parameter[] | [] = [], Child extends Object = {}>(tool: Action<Args> & {
|
|
52
|
+
render?: (tool: ToolRenderData<any>) => Child;
|
|
53
|
+
onlyRender?: boolean;
|
|
54
|
+
}) => {
|
|
55
|
+
render: ((tool: ToolRenderData<any>) => Child) | undefined;
|
|
56
|
+
onlyRender: boolean | undefined;
|
|
57
|
+
name: string;
|
|
58
|
+
description: string;
|
|
59
|
+
parameters: z.ZodRawShape;
|
|
60
|
+
/** 是否直接返回工具结果,而不是通过消息返回 */
|
|
61
|
+
returnDirect?: boolean;
|
|
62
|
+
execute: ToolCallback<z.ZodRawShape>;
|
|
63
|
+
/** 工具执行成功后触发的附加消息 */
|
|
64
|
+
callbackMessage?: (result: CallToolResult) => Message[];
|
|
65
|
+
};
|
package/dist/tool/createTool.js
CHANGED
package/dist/tool/index.d.ts
CHANGED
package/dist/tool/index.js
CHANGED
|
@@ -87,5 +87,6 @@ export declare const createChatStore: (initClientName: string, config: LangGraph
|
|
|
87
87
|
deleteHistoryChat(thread: Thread<{
|
|
88
88
|
messages: Message[];
|
|
89
89
|
}>): Promise<void>;
|
|
90
|
+
getToolUIRender: (tool_name: string) => ((message: RenderMessage) => Object) | null;
|
|
90
91
|
};
|
|
91
92
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { atom } from "nanostores";
|
|
2
2
|
import { LangGraphClient } from "../LangGraphClient.js";
|
|
3
3
|
import { rafDebounce } from "./rafDebounce.js";
|
|
4
|
+
import { ToolRenderData } from "../tool/ToolUI.js";
|
|
4
5
|
/**
|
|
5
6
|
* @zh 格式化日期对象为时间字符串。
|
|
6
7
|
* @en Formats a Date object into a time string.
|
|
@@ -189,6 +190,12 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
189
190
|
const prev = historyList.get();
|
|
190
191
|
historyList.set([thread, ...prev]);
|
|
191
192
|
};
|
|
193
|
+
const getToolUIRender = (tool_name) => {
|
|
194
|
+
var _a;
|
|
195
|
+
const toolsDefine = client.get().tools.getAllTools();
|
|
196
|
+
const tool = (_a = toolsDefine.find((i) => i.name === tool_name)) === null || _a === void 0 ? void 0 : _a.render;
|
|
197
|
+
return tool ? (message) => tool(new ToolRenderData(message, client.get())) : null;
|
|
198
|
+
};
|
|
192
199
|
return {
|
|
193
200
|
data: {
|
|
194
201
|
client,
|
|
@@ -271,6 +278,7 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
271
278
|
await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.threads.delete(thread.thread_id));
|
|
272
279
|
await refreshHistoryList();
|
|
273
280
|
},
|
|
281
|
+
getToolUIRender,
|
|
274
282
|
},
|
|
275
283
|
};
|
|
276
284
|
};
|
package/package.json
CHANGED
package/src/LangGraphClient.ts
CHANGED
|
@@ -172,6 +172,7 @@ export class LangGraphClient extends Client {
|
|
|
172
172
|
sortOrder: "desc",
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
|
+
|
|
175
176
|
/**
|
|
176
177
|
* @zh 从历史中恢复 Thread 数据。
|
|
177
178
|
* @en Resets the Thread data from history.
|
|
@@ -198,6 +199,14 @@ export class LangGraphClient extends Client {
|
|
|
198
199
|
cloneMessage(message: Message): Message {
|
|
199
200
|
return JSON.parse(JSON.stringify(message));
|
|
200
201
|
}
|
|
202
|
+
private updateStreamingMessage(message: RenderMessage) {
|
|
203
|
+
const lastMessage = this.streamingMessage[this.streamingMessage.length - 1];
|
|
204
|
+
if (!lastMessage?.id || message.id !== lastMessage.id) {
|
|
205
|
+
this.streamingMessage.push(message);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
this.streamingMessage[this.streamingMessage.length - 1] = message;
|
|
209
|
+
}
|
|
201
210
|
private replaceMessageWithValuesMessage(message: AIMessage | ToolMessage, isTool = false): Message {
|
|
202
211
|
const key = (isTool ? "tool_call_id" : "id") as any as "id";
|
|
203
212
|
const valuesMessage = this.graphMessages.find((i) => i[key] === message[key]);
|
|
@@ -217,9 +226,10 @@ export class LangGraphClient extends Client {
|
|
|
217
226
|
*/
|
|
218
227
|
get renderMessage() {
|
|
219
228
|
const previousMessage = new Map<string, Message>();
|
|
229
|
+
const closedToolCallIds = new Set<string>();
|
|
220
230
|
const result: Message[] = [];
|
|
221
231
|
const inputMessages = [...this.graphMessages, ...this.streamingMessage];
|
|
222
|
-
|
|
232
|
+
console.log(inputMessages);
|
|
223
233
|
// 从后往前遍历,这样可以保证最新的消息在前面
|
|
224
234
|
for (let i = inputMessages.length - 1; i >= 0; i--) {
|
|
225
235
|
const message = this.cloneMessage(inputMessages[i]);
|
|
@@ -241,21 +251,25 @@ export class LangGraphClient extends Client {
|
|
|
241
251
|
|
|
242
252
|
/** @ts-ignore */
|
|
243
253
|
const tool_calls: NonNullable<AIMessage["tool_calls"]> = (m as AIMessage).tool_calls?.length ? (m as AIMessage).tool_calls : (m as RenderMessage).tool_call_chunks;
|
|
244
|
-
const new_tool_calls = tool_calls
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
254
|
+
const new_tool_calls = tool_calls
|
|
255
|
+
.filter((i) => {
|
|
256
|
+
return !closedToolCallIds.has(i.id!);
|
|
257
|
+
})!
|
|
258
|
+
.map((tool, index) => {
|
|
259
|
+
return this.replaceMessageWithValuesMessage(
|
|
260
|
+
{
|
|
261
|
+
type: "tool",
|
|
262
|
+
additional_kwargs: {},
|
|
263
|
+
/** @ts-ignore */
|
|
264
|
+
tool_input: m.additional_kwargs?.tool_calls?.[index]?.function?.arguments,
|
|
265
|
+
id: tool.id,
|
|
266
|
+
name: tool.name,
|
|
267
|
+
response_metadata: {},
|
|
268
|
+
tool_call_id: tool.id!,
|
|
269
|
+
},
|
|
270
|
+
true
|
|
271
|
+
);
|
|
272
|
+
});
|
|
259
273
|
for (const tool of new_tool_calls) {
|
|
260
274
|
if (!previousMessage.has(tool.id!)) {
|
|
261
275
|
result.unshift(tool);
|
|
@@ -264,6 +278,9 @@ export class LangGraphClient extends Client {
|
|
|
264
278
|
}
|
|
265
279
|
result.unshift(m);
|
|
266
280
|
} else {
|
|
281
|
+
if (message.type === "tool" && message.tool_call_id) {
|
|
282
|
+
closedToolCallIds.add(message.tool_call_id);
|
|
283
|
+
}
|
|
267
284
|
// 记录这个 id 的消息,并添加到结果中
|
|
268
285
|
const m = this.replaceMessageWithValuesMessage(message as AIMessage);
|
|
269
286
|
previousMessage.set(message.id, m);
|
|
@@ -450,14 +467,14 @@ export class LangGraphClient extends Client {
|
|
|
450
467
|
});
|
|
451
468
|
} else if (chunk.event === "messages/partial") {
|
|
452
469
|
for (const message of chunk.data) {
|
|
453
|
-
this.
|
|
470
|
+
this.updateStreamingMessage(message);
|
|
454
471
|
}
|
|
455
472
|
this.emitStreamingUpdate({
|
|
456
473
|
type: "message",
|
|
457
474
|
data: chunk,
|
|
458
475
|
});
|
|
459
476
|
continue;
|
|
460
|
-
} else if (chunk.event
|
|
477
|
+
} else if (chunk.event === "values") {
|
|
461
478
|
const data = chunk.data as { messages: Message[] };
|
|
462
479
|
|
|
463
480
|
if (data.messages) {
|
|
@@ -475,6 +492,11 @@ export class LangGraphClient extends Client {
|
|
|
475
492
|
this.graphState = chunk.data;
|
|
476
493
|
this.streamingMessage = [];
|
|
477
494
|
continue;
|
|
495
|
+
} else if (chunk.event.startsWith("values|")) {
|
|
496
|
+
// 这个 values 必然是子 values
|
|
497
|
+
if (chunk.data.messages) {
|
|
498
|
+
this.mergeSubGraphMessagesToStreamingMessages(chunk.data.messages);
|
|
499
|
+
}
|
|
478
500
|
}
|
|
479
501
|
}
|
|
480
502
|
this.streamingMessage = [];
|
|
@@ -488,6 +510,23 @@ export class LangGraphClient extends Client {
|
|
|
488
510
|
});
|
|
489
511
|
return streamRecord;
|
|
490
512
|
}
|
|
513
|
+
/** 子图的数据需要通过 merge 的方式重新进行合并更新 */
|
|
514
|
+
private mergeSubGraphMessagesToStreamingMessages(messages: Message[]) {
|
|
515
|
+
const map = new Map(messages.filter((i) => i.id).map((i) => [i.id!, i]));
|
|
516
|
+
this.streamingMessage.forEach((i) => {
|
|
517
|
+
if (map.has(i.id!)) {
|
|
518
|
+
const newValue = map.get(i.id!)!;
|
|
519
|
+
Object.assign(i, newValue);
|
|
520
|
+
map.delete(i.id!);
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
// 剩余的 message 一定不在 streamMessage 中
|
|
524
|
+
map.forEach((i) => {
|
|
525
|
+
if (i.type === "tool" && i.tool_call_id) {
|
|
526
|
+
this.streamingMessage.push(i as RenderMessage);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
}
|
|
491
530
|
private runFETool() {
|
|
492
531
|
const data = this.graphMessages;
|
|
493
532
|
const lastMessage = data[data.length - 1];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RenderMessage } from "../LangGraphClient.js";
|
|
2
|
+
|
|
3
|
+
import { LangGraphClient } from "../LangGraphClient.js";
|
|
4
|
+
|
|
5
|
+
export class ToolRenderData<D> {
|
|
6
|
+
constructor(
|
|
7
|
+
public message: RenderMessage,
|
|
8
|
+
public client: LangGraphClient
|
|
9
|
+
) {}
|
|
10
|
+
get state() {
|
|
11
|
+
if (this.message.type === "tool" && this.message?.additional_kwargs?.done) {
|
|
12
|
+
return "done";
|
|
13
|
+
}
|
|
14
|
+
return "idle";
|
|
15
|
+
}
|
|
16
|
+
get input() {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(this.message.tool_input!);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
response(data: D) {
|
|
24
|
+
this.client.doneFEToolWaiting(this.message.id!, JSON.stringify(data));
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/tool/createTool.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { z, ZodRawShape, ZodTypeAny } from "zod";
|
|
|
3
3
|
import { Action, Parameter } from "./copilotkit-actions.js";
|
|
4
4
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
5
5
|
import { Message } from "@langchain/langgraph-sdk";
|
|
6
|
+
import { ToolRenderData } from "./ToolUI.js";
|
|
6
7
|
|
|
7
|
-
export interface UnionTool<Args extends ZodRawShape> {
|
|
8
|
+
export interface UnionTool<Args extends ZodRawShape, Child extends Object = Object> {
|
|
8
9
|
name: string;
|
|
9
10
|
description: string;
|
|
10
11
|
parameters: Args;
|
|
@@ -13,6 +14,8 @@ export interface UnionTool<Args extends ZodRawShape> {
|
|
|
13
14
|
execute: ToolCallback<Args>;
|
|
14
15
|
/** 工具执行成功后触发的附加消息 */
|
|
15
16
|
callbackMessage?: (result: CallToolResult) => Message[];
|
|
17
|
+
render?: <D>(tool: ToolRenderData<D>) => Child;
|
|
18
|
+
onlyRender?: boolean;
|
|
16
19
|
}
|
|
17
20
|
export type ToolCallback<Args extends ZodRawShape> = (args: z.objectOutputType<Args, ZodTypeAny>, context?: any) => CallToolResult | Promise<CallToolResult>;
|
|
18
21
|
|
|
@@ -76,3 +79,11 @@ export const createMCPTool = <Args extends ZodRawShape>(tool: UnionTool<Args>) =
|
|
|
76
79
|
},
|
|
77
80
|
];
|
|
78
81
|
};
|
|
82
|
+
|
|
83
|
+
export const createToolUI = <Args extends Parameter[] | [] = [], Child extends Object = {}>(tool: Action<Args> & { render?: (tool: ToolRenderData<any>) => Child; onlyRender?: boolean }) => {
|
|
84
|
+
return {
|
|
85
|
+
...createFETool(tool),
|
|
86
|
+
render: tool.render,
|
|
87
|
+
onlyRender: tool.onlyRender,
|
|
88
|
+
};
|
|
89
|
+
};
|
package/src/tool/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { atom } from "nanostores";
|
|
|
2
2
|
import { LangGraphClient, LangGraphClientConfig, RenderMessage, SendMessageOptions } from "../LangGraphClient.js";
|
|
3
3
|
import { AssistantGraph, Message, Thread } from "@langchain/langgraph-sdk";
|
|
4
4
|
import { rafDebounce } from "./rafDebounce.js";
|
|
5
|
+
import { ToolRenderData } from "../tool/ToolUI.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @zh 格式化日期对象为时间字符串。
|
|
@@ -198,7 +199,11 @@ export const createChatStore = (
|
|
|
198
199
|
const prev = historyList.get();
|
|
199
200
|
historyList.set([thread, ...prev]);
|
|
200
201
|
};
|
|
201
|
-
|
|
202
|
+
const getToolUIRender = (tool_name: string) => {
|
|
203
|
+
const toolsDefine = client.get()!.tools.getAllTools();
|
|
204
|
+
const tool = toolsDefine.find((i) => i.name === tool_name!)?.render;
|
|
205
|
+
return tool ? (message: RenderMessage) => tool(new ToolRenderData(message, client.get()!)) : null;
|
|
206
|
+
};
|
|
202
207
|
return {
|
|
203
208
|
data: {
|
|
204
209
|
client,
|
|
@@ -282,6 +287,7 @@ export const createChatStore = (
|
|
|
282
287
|
await client.get()?.threads.delete(thread.thread_id);
|
|
283
288
|
await refreshHistoryList();
|
|
284
289
|
},
|
|
290
|
+
getToolUIRender,
|
|
285
291
|
},
|
|
286
292
|
};
|
|
287
293
|
};
|