@opentiny/next-sdk 0.1.9 → 0.1.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/WebMcpClient.ts +9 -37
- package/agent/AgentModelProvider.ts +48 -44
- package/agent/type.ts +2 -2
- package/agent/utils/getAISDKTools.ts +2 -2
- package/dist/WebMcpClient.d.ts +1 -4
- package/dist/WebMcpClient.js +9 -33
- package/dist/agent/AgentModelProvider.d.ts +20 -17
- package/dist/agent/AgentModelProvider.js +47 -40
- package/dist/agent/type.d.ts +2 -2
- package/dist/agent/utils/getAISDKTools.d.ts +2 -2
- package/dist/agent/utils/getAISDKTools.js +2 -2
- package/dist/index.es.dev.js +47 -57
- package/dist/index.es.js +9645 -9666
- package/dist/index.umd.dev.js +47 -57
- package/dist/index.umd.js +33 -33
- package/dist/webagent.dev.js +39 -28
- package/dist/webagent.es.dev.js +39 -28
- package/dist/webagent.es.js +38 -30
- package/dist/webagent.js +1 -1
- package/dist/webmcp-full.dev.js +8 -29
- package/dist/webmcp-full.es.dev.js +8 -29
- package/dist/webmcp-full.es.js +1388 -1397
- package/dist/webmcp-full.js +7 -7
- package/dist/webmcp.dev.js +8 -29
- package/dist/webmcp.es.dev.js +8 -29
- package/dist/webmcp.es.js +432 -441
- package/dist/webmcp.js +1 -1
- package/package.json +1 -1
- package/runtime.html +21 -80
package/WebMcpClient.ts
CHANGED
|
@@ -18,11 +18,9 @@ import {
|
|
|
18
18
|
MessageChannelClientTransport,
|
|
19
19
|
sseOptions,
|
|
20
20
|
streamOptions,
|
|
21
|
-
attemptConnection,
|
|
22
21
|
createSseProxy,
|
|
23
22
|
createStreamProxy,
|
|
24
|
-
createSocketProxy
|
|
25
|
-
AuthClientProvider
|
|
23
|
+
createSocketProxy
|
|
26
24
|
} from '@opentiny/next'
|
|
27
25
|
import type {
|
|
28
26
|
Result,
|
|
@@ -61,12 +59,9 @@ export interface ClientConnectOptions {
|
|
|
61
59
|
url: string
|
|
62
60
|
token?: string
|
|
63
61
|
sessionId?: string
|
|
64
|
-
authProvider?: AuthClientProvider
|
|
65
62
|
type?: 'channel' | 'sse' | 'stream' | 'socket'
|
|
66
63
|
agent?: boolean
|
|
67
64
|
onError?: (error: Error) => void
|
|
68
|
-
onUnauthorized?: (connect: () => Promise<void>) => Promise<void>
|
|
69
|
-
onReconnect?: () => Promise<void>
|
|
70
65
|
}
|
|
71
66
|
|
|
72
67
|
type SendRequestT = Request
|
|
@@ -117,13 +112,11 @@ export class WebMcpClient {
|
|
|
117
112
|
return { transport: this.transport, sessionId: this.transport.sessionId as string }
|
|
118
113
|
}
|
|
119
114
|
|
|
120
|
-
const { url, token, sessionId,
|
|
121
|
-
options as ClientConnectOptions
|
|
115
|
+
const { url, token, sessionId, type, agent, onError } = options as ClientConnectOptions
|
|
122
116
|
|
|
123
117
|
if (agent === true) {
|
|
124
|
-
const proxyOptions: ProxyOptions = { client: this.client, url, token, sessionId
|
|
118
|
+
const proxyOptions: ProxyOptions = { client: this.client, url, token, sessionId }
|
|
125
119
|
|
|
126
|
-
let reconnect = false
|
|
127
120
|
let response
|
|
128
121
|
|
|
129
122
|
const connectProxy = async () => {
|
|
@@ -136,17 +129,6 @@ export class WebMcpClient {
|
|
|
136
129
|
|
|
137
130
|
transport.onerror = async (error: Error) => {
|
|
138
131
|
onError?.(error)
|
|
139
|
-
|
|
140
|
-
if (error.message === 'Unauthorized' && !reconnect) {
|
|
141
|
-
if (typeof onUnauthorized === 'function') {
|
|
142
|
-
await onUnauthorized(connectProxy)
|
|
143
|
-
} else {
|
|
144
|
-
reconnect = true
|
|
145
|
-
await connectProxy()
|
|
146
|
-
reconnect = false
|
|
147
|
-
await onReconnect?.()
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
132
|
}
|
|
151
133
|
|
|
152
134
|
response = { transport, sessionId }
|
|
@@ -165,14 +147,9 @@ export class WebMcpClient {
|
|
|
165
147
|
}
|
|
166
148
|
|
|
167
149
|
if (type === 'sse') {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
} else {
|
|
172
|
-
const opts = sseOptions(token, sessionId) as SSEClientTransportOptions
|
|
173
|
-
transport = new SSEClientTransport(endpoint, opts)
|
|
174
|
-
await this.client.connect(transport)
|
|
175
|
-
}
|
|
150
|
+
const opts = sseOptions(token, sessionId) as SSEClientTransportOptions
|
|
151
|
+
transport = new SSEClientTransport(endpoint, opts)
|
|
152
|
+
await this.client.connect(transport)
|
|
176
153
|
}
|
|
177
154
|
|
|
178
155
|
if (type === 'socket') {
|
|
@@ -182,14 +159,9 @@ export class WebMcpClient {
|
|
|
182
159
|
}
|
|
183
160
|
|
|
184
161
|
if (typeof transport === 'undefined') {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
} else {
|
|
189
|
-
const opts = streamOptions(token, sessionId) as StreamableHTTPClientTransportOptions
|
|
190
|
-
transport = new StreamableHTTPClientTransport(endpoint, opts)
|
|
191
|
-
await this.client.connect(transport)
|
|
192
|
-
}
|
|
162
|
+
const opts = streamOptions(token, sessionId) as StreamableHTTPClientTransportOptions
|
|
163
|
+
transport = new StreamableHTTPClientTransport(endpoint, opts)
|
|
164
|
+
await this.client.connect(transport)
|
|
193
165
|
}
|
|
194
166
|
|
|
195
167
|
this.transport = transport
|
|
@@ -15,35 +15,31 @@ export const AIProviderFactories = {
|
|
|
15
15
|
|
|
16
16
|
type ChatMethodFn = typeof streamText | typeof generateText
|
|
17
17
|
|
|
18
|
-
/** 一个通用的ai-sdk的
|
|
18
|
+
/** 一个通用的ai-sdk的Agent封装
|
|
19
19
|
* @summary 内部自动管理了 llm, mcpServer, ai-sdk的clients 和 tools
|
|
20
20
|
* @returns 暴露了 chat, chatStream方法
|
|
21
21
|
*/
|
|
22
22
|
export class AgentModelProvider {
|
|
23
23
|
llm: ProviderV2 | OpenAIProvider
|
|
24
|
-
/** mcpServers
|
|
24
|
+
/** 当前mcpServers对象集合。键为服务器名称,值为 McpServerConfig 或任意的 MCPTransport
|
|
25
25
|
* 参考: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#initializing-an-mcp-client */
|
|
26
|
-
mcpServers: McpServerConfig
|
|
27
|
-
/**
|
|
26
|
+
mcpServers: Record<string, McpServerConfig> = {}
|
|
27
|
+
/** 当前ai-sdk的 mcpClient 数组 */
|
|
28
28
|
mcpClients: any[] = []
|
|
29
|
-
/**
|
|
29
|
+
/** 当前 mcpClients 所对应的tools */
|
|
30
30
|
mcpTools: Array<Record<string, any>> = []
|
|
31
|
-
/**
|
|
31
|
+
/** 需要实时过滤掉的tools name*/
|
|
32
32
|
ignoreToolnames: string[] = []
|
|
33
|
-
|
|
34
|
-
/** chat 时,自动更新 所有的tools 后的事件 */
|
|
33
|
+
/** Agent 自动更新所有的tools 后的事件 */
|
|
35
34
|
onUpdatedTools: (() => void) | undefined
|
|
36
|
-
/**
|
|
35
|
+
/** Agent 内部报错时,抛出的错误事件 */
|
|
37
36
|
onError: ((msg: string, err?: any) => void) | undefined
|
|
38
|
-
|
|
39
|
-
/** 缓存 ai-sdk response 中的 多轮会话 */
|
|
37
|
+
/** 缓存 ai-sdk response 中的 多轮会话的上下文 */
|
|
40
38
|
messages: any[] = []
|
|
41
39
|
|
|
42
40
|
constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption) {
|
|
43
|
-
|
|
44
|
-
this.mcpServers = mcpServers || []
|
|
41
|
+
this.mcpServers = mcpServers || {}
|
|
45
42
|
|
|
46
|
-
// 2、保存 llm
|
|
47
43
|
if (llm) {
|
|
48
44
|
this.llm = llm
|
|
49
45
|
} else if (llmConfig) {
|
|
@@ -63,7 +59,7 @@ export class AgentModelProvider {
|
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
|
|
66
|
-
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回
|
|
62
|
+
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
|
|
67
63
|
private async _createOneClient(serverConfig: McpServerConfig) {
|
|
68
64
|
try {
|
|
69
65
|
let transport: MCPClientConfig['transport']
|
|
@@ -86,22 +82,24 @@ export class AgentModelProvider {
|
|
|
86
82
|
return null
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
|
-
/** 关闭一个
|
|
85
|
+
/** 关闭一个 mcpClient */
|
|
90
86
|
private async _closeOneClient(client: any) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
try {
|
|
88
|
+
await client['__transport__']?.terminateSession?.()
|
|
89
|
+
await client['__transport__']?.close?.()
|
|
90
|
+
await client?.close?.()
|
|
91
|
+
} catch (error) {}
|
|
94
92
|
}
|
|
95
|
-
/**
|
|
93
|
+
/** 创建所有 mcpClients */
|
|
96
94
|
private async _createMpcClients() {
|
|
97
95
|
// 使用 Promise.all 并行处理所有 mcpServer 项
|
|
98
96
|
this.mcpClients = await Promise.all(
|
|
99
|
-
this.mcpServers.map(async (server) => {
|
|
97
|
+
Object.values(this.mcpServers).map(async (server) => {
|
|
100
98
|
return this._createOneClient(server)
|
|
101
99
|
})
|
|
102
100
|
)
|
|
103
101
|
}
|
|
104
|
-
/**
|
|
102
|
+
/** 查询所有 mcpClients 的 tools, 失败则保存为null */
|
|
105
103
|
private async _createMpcTools() {
|
|
106
104
|
this.mcpTools = await Promise.all(
|
|
107
105
|
this.mcpClients.map(async (client) => {
|
|
@@ -133,48 +131,56 @@ export class AgentModelProvider {
|
|
|
133
131
|
)
|
|
134
132
|
}
|
|
135
133
|
|
|
134
|
+
/** 创建所有的 mcpClients,并更新它们的tools */
|
|
136
135
|
async initClientsAndTools() {
|
|
137
136
|
await this._createMpcClients()
|
|
138
137
|
await this._createMpcTools()
|
|
138
|
+
this.onUpdatedTools?.()
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
/** 全量更新所有的 mcpServers */
|
|
142
|
+
async updateMcpServers(mcpServers?: Record<string, McpServerConfig>) {
|
|
142
143
|
await this.closeAll()
|
|
143
|
-
this.mcpServers = mcpServers
|
|
144
|
+
this.mcpServers = mcpServers || this.mcpServers
|
|
144
145
|
await this.initClientsAndTools()
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
const client = await this._createOneClient(mcpServer)
|
|
153
|
-
this.mcpClients.push(client)
|
|
154
|
-
this.mcpTools.push((await client?.tools?.()) as Record<string, any>)
|
|
155
|
-
return true
|
|
148
|
+
/** 插入一个新的mcpServer,如果已经存在则返回false */
|
|
149
|
+
async insertMcpServer(serverName: string, mcpServer: McpServerConfig) {
|
|
150
|
+
// 检查是否已存在相同名称的服务器
|
|
151
|
+
if (this.mcpServers[serverName]) {
|
|
152
|
+
return false
|
|
156
153
|
}
|
|
157
|
-
|
|
154
|
+
|
|
155
|
+
this.mcpServers[serverName] = mcpServer
|
|
156
|
+
const client = await this._createOneClient(mcpServer)
|
|
157
|
+
this.mcpClients.push(client)
|
|
158
|
+
this.mcpTools.push((await client?.tools?.()) as Record<string, any>)
|
|
159
|
+
this.onUpdatedTools?.()
|
|
160
|
+
|
|
161
|
+
return true
|
|
158
162
|
}
|
|
159
|
-
/**
|
|
160
|
-
async removeMcpServer(
|
|
161
|
-
|
|
163
|
+
/** 通过服务器名称删除mcpServer: mcpServers mcpClients mcpTools ignoreToolnames */
|
|
164
|
+
async removeMcpServer(serverName: string) {
|
|
165
|
+
if (!this.mcpServers[serverName]) {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
162
168
|
|
|
163
|
-
//
|
|
164
|
-
this.mcpServers
|
|
169
|
+
// 找到对应的索引
|
|
170
|
+
const serverNames = Object.keys(this.mcpServers)
|
|
171
|
+
const index = serverNames.indexOf(serverName)
|
|
172
|
+
|
|
173
|
+
delete this.mcpServers[serverName]
|
|
165
174
|
|
|
166
|
-
// 移除
|
|
167
175
|
const delClient = this.mcpClients[index]
|
|
168
176
|
this.mcpClients.splice(index, 1)
|
|
169
177
|
try {
|
|
170
178
|
await this._closeOneClient(delClient)
|
|
171
179
|
} catch (error) {}
|
|
172
180
|
|
|
173
|
-
// 移除 tools
|
|
174
181
|
const delTool = this.mcpTools[index]
|
|
175
182
|
this.mcpTools.splice(index, 1)
|
|
176
183
|
|
|
177
|
-
// 移除 ignoreToolnames
|
|
178
184
|
if (delTool) {
|
|
179
185
|
Object.keys(delTool).forEach((toolName) => {
|
|
180
186
|
this.ignoreToolnames = this.ignoreToolnames.filter((name) => name !== toolName)
|
|
@@ -203,8 +209,6 @@ export class AgentModelProvider {
|
|
|
203
209
|
|
|
204
210
|
await this.initClientsAndTools()
|
|
205
211
|
|
|
206
|
-
this.onUpdatedTools?.()
|
|
207
|
-
|
|
208
212
|
const chatOptions = {
|
|
209
213
|
// @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
|
|
210
214
|
model: this.llm(model),
|
package/agent/type.ts
CHANGED
|
@@ -25,6 +25,6 @@ export interface IAgentModelProviderOption {
|
|
|
25
25
|
llm?: ProviderV2
|
|
26
26
|
/** 代理模型提供器的大语言配置对象, 不能与 llm 同时传入 */
|
|
27
27
|
llmConfig?: IAgentModelProviderLlmConfig
|
|
28
|
-
/** Mcp Server
|
|
29
|
-
mcpServers?: McpServerConfig
|
|
28
|
+
/** Mcp Server的配置对象的集合,键为服务器名称,值为配置对象 */
|
|
29
|
+
mcpServers?: Record<string, McpServerConfig>
|
|
30
30
|
}
|
|
@@ -2,9 +2,9 @@ import { dynamicTool, jsonSchema, Tool, ToolCallOptions, ToolSet } from 'ai'
|
|
|
2
2
|
import { WebMcpClient } from '../../WebMcpClient'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* 快速从官方 mcp 或 WebMcpClient 这2种client中读取 tools 数组,并转换成 ai-sdk 的tool的对象格式。
|
|
6
6
|
* @params client 一个已连接好的 WebMcpClient
|
|
7
|
-
* @returns
|
|
7
|
+
* @returns ai-sdk的dynamicTool对象。
|
|
8
8
|
*/
|
|
9
9
|
export const getAISDKTools = async (client: WebMcpClient): Promise<ToolSet> => {
|
|
10
10
|
const tools: Record<string, Tool> = {}
|
package/dist/WebMcpClient.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
|
3
3
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
4
4
|
import { z, ZodObject, ZodLiteral, ZodType } from 'zod';
|
|
5
5
|
import { ElicitRequestSchema, ListRootsRequestSchema, CreateMessageRequestSchema, LoggingMessageNotificationSchema, ToolListChangedNotificationSchema, ResourceUpdatedNotificationSchema, PromptListChangedNotificationSchema, ResourceListChangedNotificationSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
-
import { MessageChannelClientTransport
|
|
6
|
+
import { MessageChannelClientTransport } from '@opentiny/next';
|
|
7
7
|
import type { Result, Request, Notification, Implementation, ServerCapabilities, LoggingLevel, CompleteRequest, CallToolRequest, ListToolsRequest, GetPromptRequest, SubscribeRequest, UnsubscribeRequest, ListPromptsRequest, ReadResourceRequest, ListResourcesRequest, ListResourceTemplatesRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
9
9
|
import type { ClientOptions } from '@modelcontextprotocol/sdk/client/index.js';
|
|
@@ -17,12 +17,9 @@ export interface ClientConnectOptions {
|
|
|
17
17
|
url: string;
|
|
18
18
|
token?: string;
|
|
19
19
|
sessionId?: string;
|
|
20
|
-
authProvider?: AuthClientProvider;
|
|
21
20
|
type?: 'channel' | 'sse' | 'stream' | 'socket';
|
|
22
21
|
agent?: boolean;
|
|
23
22
|
onError?: (error: Error) => void;
|
|
24
|
-
onUnauthorized?: (connect: () => Promise<void>) => Promise<void>;
|
|
25
|
-
onReconnect?: () => Promise<void>;
|
|
26
23
|
}
|
|
27
24
|
type SendRequestT = Request;
|
|
28
25
|
type SendNotificationT = Notification;
|
package/dist/WebMcpClient.js
CHANGED
|
@@ -12,7 +12,7 @@ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
|
12
12
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
13
13
|
import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
|
|
14
14
|
import { ElicitRequestSchema, CallToolResultSchema, ListRootsRequestSchema, CreateMessageRequestSchema, LoggingMessageNotificationSchema, ToolListChangedNotificationSchema, ResourceUpdatedNotificationSchema, PromptListChangedNotificationSchema, ResourceListChangedNotificationSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
-
import { MessageChannelClientTransport, sseOptions, streamOptions,
|
|
15
|
+
import { MessageChannelClientTransport, sseOptions, streamOptions, createSseProxy, createStreamProxy, createSocketProxy } from '@opentiny/next';
|
|
16
16
|
/**
|
|
17
17
|
* An MCP client on top of a pluggable transport.
|
|
18
18
|
* The client will automatically begin the initialization flow with the server when connect() is called.
|
|
@@ -51,10 +51,9 @@ export class WebMcpClient {
|
|
|
51
51
|
yield this.client.connect(this.transport);
|
|
52
52
|
return { transport: this.transport, sessionId: this.transport.sessionId };
|
|
53
53
|
}
|
|
54
|
-
const { url, token, sessionId,
|
|
54
|
+
const { url, token, sessionId, type, agent, onError } = options;
|
|
55
55
|
if (agent === true) {
|
|
56
|
-
const proxyOptions = { client: this.client, url, token, sessionId
|
|
57
|
-
let reconnect = false;
|
|
56
|
+
const proxyOptions = { client: this.client, url, token, sessionId };
|
|
58
57
|
let response;
|
|
59
58
|
const connectProxy = () => __awaiter(this, void 0, void 0, function* () {
|
|
60
59
|
const { transport, sessionId } = type === 'sse'
|
|
@@ -64,17 +63,6 @@ export class WebMcpClient {
|
|
|
64
63
|
: yield createStreamProxy(proxyOptions);
|
|
65
64
|
transport.onerror = (error) => __awaiter(this, void 0, void 0, function* () {
|
|
66
65
|
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
67
|
-
if (error.message === 'Unauthorized' && !reconnect) {
|
|
68
|
-
if (typeof onUnauthorized === 'function') {
|
|
69
|
-
yield onUnauthorized(connectProxy);
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
reconnect = true;
|
|
73
|
-
yield connectProxy();
|
|
74
|
-
reconnect = false;
|
|
75
|
-
yield (onReconnect === null || onReconnect === void 0 ? void 0 : onReconnect());
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
66
|
});
|
|
79
67
|
response = { transport, sessionId };
|
|
80
68
|
});
|
|
@@ -88,15 +76,9 @@ export class WebMcpClient {
|
|
|
88
76
|
yield this.client.connect(transport);
|
|
89
77
|
}
|
|
90
78
|
if (type === 'sse') {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
const opts = sseOptions(token, sessionId);
|
|
97
|
-
transport = new SSEClientTransport(endpoint, opts);
|
|
98
|
-
yield this.client.connect(transport);
|
|
99
|
-
}
|
|
79
|
+
const opts = sseOptions(token, sessionId);
|
|
80
|
+
transport = new SSEClientTransport(endpoint, opts);
|
|
81
|
+
yield this.client.connect(transport);
|
|
100
82
|
}
|
|
101
83
|
if (type === 'socket') {
|
|
102
84
|
transport = new WebSocketClientTransport(new URL(`${url}?sessionId=${sessionId}&token=${token}`));
|
|
@@ -104,15 +86,9 @@ export class WebMcpClient {
|
|
|
104
86
|
yield this.client.connect(transport);
|
|
105
87
|
}
|
|
106
88
|
if (typeof transport === 'undefined') {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
const opts = streamOptions(token, sessionId);
|
|
113
|
-
transport = new StreamableHTTPClientTransport(endpoint, opts);
|
|
114
|
-
yield this.client.connect(transport);
|
|
115
|
-
}
|
|
89
|
+
const opts = streamOptions(token, sessionId);
|
|
90
|
+
transport = new StreamableHTTPClientTransport(endpoint, opts);
|
|
91
|
+
yield this.client.connect(transport);
|
|
116
92
|
}
|
|
117
93
|
this.transport = transport;
|
|
118
94
|
return { transport: this.transport, sessionId: this.transport.sessionId };
|
|
@@ -8,43 +8,46 @@ export declare const AIProviderFactories: {
|
|
|
8
8
|
openai: typeof createOpenAI;
|
|
9
9
|
deepseek: typeof createDeepSeek;
|
|
10
10
|
};
|
|
11
|
-
/** 一个通用的ai-sdk的
|
|
11
|
+
/** 一个通用的ai-sdk的Agent封装
|
|
12
12
|
* @summary 内部自动管理了 llm, mcpServer, ai-sdk的clients 和 tools
|
|
13
13
|
* @returns 暴露了 chat, chatStream方法
|
|
14
14
|
*/
|
|
15
15
|
export declare class AgentModelProvider {
|
|
16
16
|
llm: ProviderV2 | OpenAIProvider;
|
|
17
|
-
/** mcpServers
|
|
17
|
+
/** 当前mcpServers对象集合。键为服务器名称,值为 McpServerConfig 或任意的 MCPTransport
|
|
18
18
|
* 参考: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#initializing-an-mcp-client */
|
|
19
|
-
mcpServers: McpServerConfig
|
|
20
|
-
/**
|
|
19
|
+
mcpServers: Record<string, McpServerConfig>;
|
|
20
|
+
/** 当前ai-sdk的 mcpClient 数组 */
|
|
21
21
|
mcpClients: any[];
|
|
22
|
-
/**
|
|
22
|
+
/** 当前 mcpClients 所对应的tools */
|
|
23
23
|
mcpTools: Array<Record<string, any>>;
|
|
24
|
-
/**
|
|
24
|
+
/** 需要实时过滤掉的tools name*/
|
|
25
25
|
ignoreToolnames: string[];
|
|
26
|
-
/**
|
|
26
|
+
/** Agent 自动更新所有的tools 后的事件 */
|
|
27
27
|
onUpdatedTools: (() => void) | undefined;
|
|
28
|
-
/**
|
|
28
|
+
/** Agent 内部报错时,抛出的错误事件 */
|
|
29
29
|
onError: ((msg: string, err?: any) => void) | undefined;
|
|
30
|
-
/** 缓存 ai-sdk response 中的
|
|
30
|
+
/** 缓存 ai-sdk response 中的 多轮会话的上下文 */
|
|
31
31
|
messages: any[];
|
|
32
32
|
constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption);
|
|
33
|
-
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回
|
|
33
|
+
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
|
|
34
34
|
private _createOneClient;
|
|
35
|
-
/** 关闭一个
|
|
35
|
+
/** 关闭一个 mcpClient */
|
|
36
36
|
private _closeOneClient;
|
|
37
|
-
/**
|
|
37
|
+
/** 创建所有 mcpClients */
|
|
38
38
|
private _createMpcClients;
|
|
39
|
-
/**
|
|
39
|
+
/** 查询所有 mcpClients 的 tools, 失败则保存为null */
|
|
40
40
|
private _createMpcTools;
|
|
41
41
|
/** 关闭所有的 clients */
|
|
42
42
|
closeAll(): Promise<void>;
|
|
43
|
+
/** 创建所有的 mcpClients,并更新它们的tools */
|
|
43
44
|
initClientsAndTools(): Promise<void>;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
|
|
45
|
+
/** 全量更新所有的 mcpServers */
|
|
46
|
+
updateMcpServers(mcpServers?: Record<string, McpServerConfig>): Promise<void>;
|
|
47
|
+
/** 插入一个新的mcpServer,如果已经存在则返回false */
|
|
48
|
+
insertMcpServer(serverName: string, mcpServer: McpServerConfig): Promise<boolean>;
|
|
49
|
+
/** 通过服务器名称删除mcpServer: mcpServers mcpClients mcpTools ignoreToolnames */
|
|
50
|
+
removeMcpServer(serverName: string): Promise<void>;
|
|
48
51
|
/** 创建临时允许调用的tools集合 */
|
|
49
52
|
private _tempMergeTools;
|
|
50
53
|
private _chat;
|
|
@@ -27,26 +27,24 @@ export const AIProviderFactories = {
|
|
|
27
27
|
['openai']: createOpenAI,
|
|
28
28
|
['deepseek']: createDeepSeek
|
|
29
29
|
};
|
|
30
|
-
/** 一个通用的ai-sdk的
|
|
30
|
+
/** 一个通用的ai-sdk的Agent封装
|
|
31
31
|
* @summary 内部自动管理了 llm, mcpServer, ai-sdk的clients 和 tools
|
|
32
32
|
* @returns 暴露了 chat, chatStream方法
|
|
33
33
|
*/
|
|
34
34
|
export class AgentModelProvider {
|
|
35
35
|
constructor({ llmConfig, mcpServers, llm }) {
|
|
36
|
-
/** mcpServers
|
|
36
|
+
/** 当前mcpServers对象集合。键为服务器名称,值为 McpServerConfig 或任意的 MCPTransport
|
|
37
37
|
* 参考: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#initializing-an-mcp-client */
|
|
38
|
-
this.mcpServers =
|
|
39
|
-
/**
|
|
38
|
+
this.mcpServers = {};
|
|
39
|
+
/** 当前ai-sdk的 mcpClient 数组 */
|
|
40
40
|
this.mcpClients = [];
|
|
41
|
-
/**
|
|
41
|
+
/** 当前 mcpClients 所对应的tools */
|
|
42
42
|
this.mcpTools = [];
|
|
43
|
-
/**
|
|
43
|
+
/** 需要实时过滤掉的tools name*/
|
|
44
44
|
this.ignoreToolnames = [];
|
|
45
|
-
/** 缓存 ai-sdk response 中的
|
|
45
|
+
/** 缓存 ai-sdk response 中的 多轮会话的上下文 */
|
|
46
46
|
this.messages = [];
|
|
47
|
-
|
|
48
|
-
this.mcpServers = mcpServers || [];
|
|
49
|
-
// 2、保存 llm
|
|
47
|
+
this.mcpServers = mcpServers || {};
|
|
50
48
|
if (llm) {
|
|
51
49
|
this.llm = llm;
|
|
52
50
|
}
|
|
@@ -67,7 +65,7 @@ export class AgentModelProvider {
|
|
|
67
65
|
throw new Error('Either llmConfig or llm must be provided');
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
|
-
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回
|
|
68
|
+
/** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
|
|
71
69
|
_createOneClient(serverConfig) {
|
|
72
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
73
71
|
try {
|
|
@@ -93,25 +91,28 @@ export class AgentModelProvider {
|
|
|
93
91
|
}
|
|
94
92
|
});
|
|
95
93
|
}
|
|
96
|
-
/** 关闭一个
|
|
94
|
+
/** 关闭一个 mcpClient */
|
|
97
95
|
_closeOneClient(client) {
|
|
98
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
99
97
|
var _a, _b, _c, _d, _e;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
try {
|
|
99
|
+
yield ((_b = (_a = client['__transport__']) === null || _a === void 0 ? void 0 : _a.terminateSession) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
100
|
+
yield ((_d = (_c = client['__transport__']) === null || _c === void 0 ? void 0 : _c.close) === null || _d === void 0 ? void 0 : _d.call(_c));
|
|
101
|
+
yield ((_e = client === null || client === void 0 ? void 0 : client.close) === null || _e === void 0 ? void 0 : _e.call(client));
|
|
102
|
+
}
|
|
103
|
+
catch (error) { }
|
|
103
104
|
});
|
|
104
105
|
}
|
|
105
|
-
/**
|
|
106
|
+
/** 创建所有 mcpClients */
|
|
106
107
|
_createMpcClients() {
|
|
107
108
|
return __awaiter(this, void 0, void 0, function* () {
|
|
108
109
|
// 使用 Promise.all 并行处理所有 mcpServer 项
|
|
109
|
-
this.mcpClients = yield Promise.all(this.mcpServers.map((server) => __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
this.mcpClients = yield Promise.all(Object.values(this.mcpServers).map((server) => __awaiter(this, void 0, void 0, function* () {
|
|
110
111
|
return this._createOneClient(server);
|
|
111
112
|
})));
|
|
112
113
|
});
|
|
113
114
|
}
|
|
114
|
-
/**
|
|
115
|
+
/** 查询所有 mcpClients 的 tools, 失败则保存为null */
|
|
115
116
|
_createMpcTools() {
|
|
116
117
|
return __awaiter(this, void 0, void 0, function* () {
|
|
117
118
|
this.mcpTools = yield Promise.all(this.mcpClients.map((client) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -145,50 +146,57 @@ export class AgentModelProvider {
|
|
|
145
146
|
})));
|
|
146
147
|
});
|
|
147
148
|
}
|
|
149
|
+
/** 创建所有的 mcpClients,并更新它们的tools */
|
|
148
150
|
initClientsAndTools() {
|
|
149
151
|
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
var _a;
|
|
150
153
|
yield this._createMpcClients();
|
|
151
154
|
yield this._createMpcTools();
|
|
155
|
+
(_a = this.onUpdatedTools) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
152
156
|
});
|
|
153
157
|
}
|
|
158
|
+
/** 全量更新所有的 mcpServers */
|
|
154
159
|
updateMcpServers(mcpServers) {
|
|
155
160
|
return __awaiter(this, void 0, void 0, function* () {
|
|
156
161
|
yield this.closeAll();
|
|
157
|
-
this.mcpServers = mcpServers;
|
|
162
|
+
this.mcpServers = mcpServers || this.mcpServers;
|
|
158
163
|
yield this.initClientsAndTools();
|
|
159
164
|
});
|
|
160
165
|
}
|
|
161
|
-
|
|
166
|
+
/** 插入一个新的mcpServer,如果已经存在则返回false */
|
|
167
|
+
insertMcpServer(serverName, mcpServer) {
|
|
162
168
|
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
-
var _a;
|
|
164
|
-
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
const client = yield this._createOneClient(mcpServer);
|
|
168
|
-
this.mcpClients.push(client);
|
|
169
|
-
this.mcpTools.push((yield ((_a = client === null || client === void 0 ? void 0 : client.tools) === null || _a === void 0 ? void 0 : _a.call(client))));
|
|
170
|
-
return true;
|
|
169
|
+
var _a, _b;
|
|
170
|
+
// 检查是否已存在相同名称的服务器
|
|
171
|
+
if (this.mcpServers[serverName]) {
|
|
172
|
+
return false;
|
|
171
173
|
}
|
|
172
|
-
|
|
174
|
+
this.mcpServers[serverName] = mcpServer;
|
|
175
|
+
const client = yield this._createOneClient(mcpServer);
|
|
176
|
+
this.mcpClients.push(client);
|
|
177
|
+
this.mcpTools.push((yield ((_a = client === null || client === void 0 ? void 0 : client.tools) === null || _a === void 0 ? void 0 : _a.call(client))));
|
|
178
|
+
(_b = this.onUpdatedTools) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
179
|
+
return true;
|
|
173
180
|
});
|
|
174
181
|
}
|
|
175
|
-
/**
|
|
176
|
-
removeMcpServer(
|
|
182
|
+
/** 通过服务器名称删除mcpServer: mcpServers mcpClients mcpTools ignoreToolnames */
|
|
183
|
+
removeMcpServer(serverName) {
|
|
177
184
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
//
|
|
185
|
+
if (!this.mcpServers[serverName]) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
// 找到对应的索引
|
|
189
|
+
const serverNames = Object.keys(this.mcpServers);
|
|
190
|
+
const index = serverNames.indexOf(serverName);
|
|
191
|
+
delete this.mcpServers[serverName];
|
|
182
192
|
const delClient = this.mcpClients[index];
|
|
183
193
|
this.mcpClients.splice(index, 1);
|
|
184
194
|
try {
|
|
185
195
|
yield this._closeOneClient(delClient);
|
|
186
196
|
}
|
|
187
197
|
catch (error) { }
|
|
188
|
-
// 移除 tools
|
|
189
198
|
const delTool = this.mcpTools[index];
|
|
190
199
|
this.mcpTools.splice(index, 1);
|
|
191
|
-
// 移除 ignoreToolnames
|
|
192
200
|
if (delTool) {
|
|
193
201
|
Object.keys(delTool).forEach((toolName) => {
|
|
194
202
|
this.ignoreToolnames = this.ignoreToolnames.filter((name) => name !== toolName);
|
|
@@ -207,13 +215,12 @@ export class AgentModelProvider {
|
|
|
207
215
|
}
|
|
208
216
|
_chat(chatMethod, _a) {
|
|
209
217
|
return __awaiter(this, void 0, void 0, function* () {
|
|
210
|
-
var _b
|
|
218
|
+
var _b;
|
|
211
219
|
var { model, maxSteps = 5 } = _a, options = __rest(_a, ["model", "maxSteps"]);
|
|
212
220
|
if (!this.llm) {
|
|
213
221
|
throw new Error('LLM is not initialized');
|
|
214
222
|
}
|
|
215
223
|
yield this.initClientsAndTools();
|
|
216
|
-
(_b = this.onUpdatedTools) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
217
224
|
const chatOptions = Object.assign(Object.assign({
|
|
218
225
|
// @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
|
|
219
226
|
model: this.llm(model), stopWhen: stepCountIs(maxSteps) }, options), { tools: this._tempMergeTools(options.tools) });
|
|
@@ -222,7 +229,7 @@ export class AgentModelProvider {
|
|
|
222
229
|
chatOptions.messages = [...this.messages];
|
|
223
230
|
}
|
|
224
231
|
const result = chatMethod(chatOptions);
|
|
225
|
-
(
|
|
232
|
+
(_b = result === null || result === void 0 ? void 0 : result.response) === null || _b === void 0 ? void 0 : _b.then((res) => {
|
|
226
233
|
this.messages.push(...res.messages);
|
|
227
234
|
});
|
|
228
235
|
return result;
|
package/dist/agent/type.d.ts
CHANGED
|
@@ -27,6 +27,6 @@ export interface IAgentModelProviderOption {
|
|
|
27
27
|
llm?: ProviderV2;
|
|
28
28
|
/** 代理模型提供器的大语言配置对象, 不能与 llm 同时传入 */
|
|
29
29
|
llmConfig?: IAgentModelProviderLlmConfig;
|
|
30
|
-
/** Mcp Server
|
|
31
|
-
mcpServers?: McpServerConfig
|
|
30
|
+
/** Mcp Server的配置对象的集合,键为服务器名称,值为配置对象 */
|
|
31
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
32
32
|
}
|