@opentiny/next-sdk 0.1.12 → 0.1.14

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.
@@ -4,6 +4,7 @@ import { ProviderV2 } from '@ai-sdk/provider';
4
4
  import { OpenAIProvider } from '@ai-sdk/openai';
5
5
  import { createOpenAI } from '@ai-sdk/openai';
6
6
  import { createDeepSeek } from '@ai-sdk/deepseek';
7
+ import { WebMcpClient } from '../WebMcpClient';
7
8
  export declare const AIProviderFactories: {
8
9
  openai: typeof createOpenAI;
9
10
  deepseek: typeof createDeepSeek;
@@ -31,7 +32,7 @@ export declare class AgentModelProvider {
31
32
  onClientDisconnected?: (serverName: string, reason?: string) => void;
32
33
  /** 缓存 ai-sdk response 中的 多轮会话的上下文 */
33
34
  messages: any[];
34
- constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption);
35
+ constructor({ llmConfig, mcpServers }: IAgentModelProviderOption);
35
36
  /** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
36
37
  private _createOneClient;
37
38
  /** 关闭一个 mcpClient */
@@ -47,7 +48,7 @@ export declare class AgentModelProvider {
47
48
  /** 全量更新所有的 mcpServers */
48
49
  updateMcpServers(mcpServers?: Record<string, McpServerConfig>): Promise<void>;
49
50
  /** 插入一个新的mcpServer,如果已经存在则返回false */
50
- insertMcpServer(serverName: string, mcpServer: McpServerConfig): Promise<boolean>;
51
+ insertMcpServer(serverName: string, mcpServer: McpServerConfig): Promise<false | WebMcpClient | null>;
51
52
  /** 通过服务器名称删除mcpServer: mcpServers mcpClients mcpTools ignoreToolnames */
52
53
  removeMcpServer(serverName: string): Promise<void>;
53
54
  /** 创建临时允许调用的tools集合 */
@@ -19,11 +19,14 @@ var __rest = (this && this.__rest) || function (s, e) {
19
19
  return t;
20
20
  };
21
21
  import { streamText, stepCountIs, generateText } from 'ai';
22
- import { experimental_createMCPClient as createMCPClient } from 'ai';
23
22
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
23
+ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
24
24
  import { createOpenAI } from '@ai-sdk/openai';
25
25
  import { createDeepSeek } from '@ai-sdk/deepseek';
26
26
  import { ExtensionClientTransport } from '../transport/ExtensionClientTransport';
27
+ import { MessageChannelTransport } from '@opentiny/next';
28
+ import { WebMcpClient } from '../WebMcpClient';
29
+ import { getAISDKTools } from './utils/getAISDKTools';
27
30
  export const AIProviderFactories = {
28
31
  ['openai']: createOpenAI,
29
32
  ['deepseek']: createDeepSeek
@@ -33,7 +36,7 @@ export const AIProviderFactories = {
33
36
  * @returns 暴露了 chat, chatStream方法
34
37
  */
35
38
  export class AgentModelProvider {
36
- constructor({ llmConfig, mcpServers, llm }) {
39
+ constructor({ llmConfig, mcpServers }) {
37
40
  /** 当前mcpServers对象集合。键为服务器名称,值为 McpServerConfig 或任意的 MCPTransport
38
41
  * 参考: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling#initializing-an-mcp-client */
39
42
  this.mcpServers = {};
@@ -45,19 +48,23 @@ export class AgentModelProvider {
45
48
  this.ignoreToolnames = [];
46
49
  /** 缓存 ai-sdk response 中的 多轮会话的上下文 */
47
50
  this.messages = [];
51
+ if (!llmConfig) {
52
+ throw new Error('llmConfig is required to initialize AgentModelProvider');
53
+ }
48
54
  this.mcpServers = mcpServers || {};
49
55
  this.mcpClients = {};
50
56
  this.mcpTools = {};
51
- if (llm) {
52
- this.llm = llm;
57
+ if (llmConfig.llm) {
58
+ this.llm = llmConfig.llm;
53
59
  }
54
- else if (llmConfig) {
60
+ else if (llmConfig.providerType) {
61
+ const providerType = llmConfig.providerType;
55
62
  let providerFn;
56
- if (typeof llmConfig.providerType === 'string') {
57
- providerFn = AIProviderFactories[llmConfig.providerType];
63
+ if (typeof providerType === 'string') {
64
+ providerFn = AIProviderFactories[providerType];
58
65
  }
59
66
  else {
60
- providerFn = llmConfig.providerType;
67
+ providerFn = providerType;
61
68
  }
62
69
  this.llm = providerFn({
63
70
  apiKey: llmConfig.apiKey,
@@ -65,7 +72,7 @@ export class AgentModelProvider {
65
72
  });
66
73
  }
67
74
  else {
68
- throw new Error('Either llmConfig or llm must be provided');
75
+ throw new Error('Either llmConfig.llm or llmConfig.providerType must be provided');
69
76
  }
70
77
  }
71
78
  /** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 null */
@@ -83,7 +90,8 @@ export class AgentModelProvider {
83
90
  else {
84
91
  transport = serverConfig;
85
92
  }
86
- const client = yield createMCPClient({ transport: transport });
93
+ const client = new WebMcpClient({ name: 'mcp-web-client', version: '1.0.0' }, { capabilities: { roots: { listChanged: true }, sampling: {}, elicitation: {} } });
94
+ yield client.connect(transport);
87
95
  //@ts-ignore
88
96
  client['__transport__'] = transport;
89
97
  return client;
@@ -100,11 +108,18 @@ export class AgentModelProvider {
100
108
  /** 关闭一个 mcpClient */
101
109
  _closeOneClient(client) {
102
110
  return __awaiter(this, void 0, void 0, function* () {
103
- var _a, _b, _c, _d, _e;
111
+ var _a, _b, _c;
104
112
  try {
105
- yield ((_b = (_a = client['__transport__']) === null || _a === void 0 ? void 0 : _a.terminateSession) === null || _b === void 0 ? void 0 : _b.call(_a));
106
- yield ((_d = (_c = client['__transport__']) === null || _c === void 0 ? void 0 : _c.close) === null || _d === void 0 ? void 0 : _d.call(_c));
107
- yield ((_e = client === null || client === void 0 ? void 0 : client.close) === null || _e === void 0 ? void 0 : _e.call(client));
113
+ const transport = client['__transport__'];
114
+ // 如果是 InMemoryTransport,不关闭传输层 因为它是配对的,关闭一端会影响另一端(服务端)
115
+ if ((transport && transport instanceof InMemoryTransport) ||
116
+ (transport && transport instanceof MessageChannelTransport)) {
117
+ return;
118
+ }
119
+ // 其他类型的传输正常关闭
120
+ yield ((_a = transport === null || transport === void 0 ? void 0 : transport.terminateSession) === null || _a === void 0 ? void 0 : _a.call(transport));
121
+ yield ((_b = transport === null || transport === void 0 ? void 0 : transport.close) === null || _b === void 0 ? void 0 : _b.call(transport));
122
+ yield ((_c = client === null || client === void 0 ? void 0 : client.close) === null || _c === void 0 ? void 0 : _c.call(client));
108
123
  }
109
124
  catch (error) { }
110
125
  });
@@ -130,9 +145,8 @@ export class AgentModelProvider {
130
145
  return __awaiter(this, void 0, void 0, function* () {
131
146
  const clientEntries = Object.entries(this.mcpClients);
132
147
  const tools = yield Promise.all(clientEntries.map((_a) => __awaiter(this, [_a], void 0, function* ([serverName, client]) {
133
- var _b;
134
148
  try {
135
- const result = client ? yield ((_b = client === null || client === void 0 ? void 0 : client.tools) === null || _b === void 0 ? void 0 : _b.call(client)) : null;
149
+ const result = client ? yield getAISDKTools(client) : null;
136
150
  return { serverName, tools: result };
137
151
  }
138
152
  catch (error) {
@@ -146,7 +160,8 @@ export class AgentModelProvider {
146
160
  // 将结果存储到对象中,使用 serverName 作为键
147
161
  this.mcpTools = {};
148
162
  tools.forEach(({ serverName, tools: toolsData }) => {
149
- this.mcpTools[serverName] = toolsData;
163
+ const normalizedTools = toolsData && typeof toolsData === 'object' ? toolsData : {};
164
+ this.mcpTools[serverName] = normalizedTools;
150
165
  });
151
166
  });
152
167
  }
@@ -192,11 +207,18 @@ export class AgentModelProvider {
192
207
  return false;
193
208
  }
194
209
  const client = yield this._createOneClient(mcpServer);
210
+ if (!client) {
211
+ // 创建客户端失败时直接返回,避免后续出现空指针问题
212
+ (_a = this.onError) === null || _a === void 0 ? void 0 : _a.call(this, `Failed to create MCP client: ${serverName}`);
213
+ return null;
214
+ }
195
215
  this.mcpClients[serverName] = client;
196
- this.mcpTools[serverName] = (yield ((_a = client === null || client === void 0 ? void 0 : client.tools) === null || _a === void 0 ? void 0 : _a.call(client)));
216
+ const tools = yield getAISDKTools(client);
217
+ // 工具列表可能为 null,统一兜底为空对象,确保类型安全
218
+ this.mcpTools[serverName] = tools && typeof tools === 'object' ? tools : {};
197
219
  this.mcpServers[serverName] = mcpServer;
198
220
  (_b = this.onUpdatedTools) === null || _b === void 0 ? void 0 : _b.call(this);
199
- return true;
221
+ return client;
200
222
  });
201
223
  }
202
224
  /** 通过服务器名称删除mcpServer: mcpServers mcpClients mcpTools ignoreToolnames */
@@ -1,16 +1,27 @@
1
1
  export type { experimental_MCPClient as MCPClient } from 'ai';
2
2
  import type { ProviderV2 } from '@ai-sdk/provider';
3
3
  import type { MCPTransport } from 'ai';
4
- /** 代理模型提供器的大语言配置对象 */
5
- export interface IAgentModelProviderLlmConfig {
4
+ type ProviderFactory = 'openai' | 'deepseek' | ((options: any) => ProviderV2);
5
+ type LlmFactoryConfig = {
6
+ /** API密钥 */
6
7
  apiKey: string;
8
+ /** API基础URL */
7
9
  baseURL: string;
8
- /** 支持内置的常用模型,或者传入一个ai-sdk官方的Provider工厂函数
9
- * @example
10
- * import { createOpenAI } from '@ai-sdk/openai'
11
- */
12
- providerType: 'openai' | 'deepseek' | ((options: any) => ProviderV2);
13
- }
10
+ /** 内置或自定义 Provider 工厂函数 */
11
+ providerType: ProviderFactory;
12
+ /** 互斥:当使用 providerType 分支时不允许传入 llm */
13
+ llm?: never;
14
+ };
15
+ type LlmInstanceConfig = {
16
+ /** 自定义 Provider 实例,优先级最高 */
17
+ llm: ProviderV2;
18
+ /** 互斥:当传入 llm 实例时不需要 apiKey/baseURL/providerType */
19
+ apiKey?: never;
20
+ baseURL?: never;
21
+ providerType?: never;
22
+ };
23
+ /** 代理模型提供器的大语言配置对象, 通过 XOR 表达二选一 */
24
+ export type IAgentModelProviderLlmConfig = LlmFactoryConfig | LlmInstanceConfig;
14
25
  /** Mcp Server的配置对象 */
15
26
  export type McpServerConfig = {
16
27
  type: 'streamableHttp';
@@ -27,13 +38,8 @@ export type McpServerConfig = {
27
38
  };
28
39
  /** */
29
40
  export interface IAgentModelProviderOption {
30
- /** ai-sdk官方的Provider实例,不能与 llmConfig 同时传入
31
- * @example
32
- * import { openai } from '@ai-sdk/openai'
33
- */
34
- llm?: ProviderV2;
35
- /** 代理模型提供器的大语言配置对象, 不能与 llm 同时传入 */
36
- llmConfig?: IAgentModelProviderLlmConfig;
41
+ /** 代理模型提供器的大语言配置对象 */
42
+ llmConfig: IAgentModelProviderLlmConfig;
37
43
  /** Mcp Server的配置对象的集合,键为服务器名称,值为配置对象 */
38
44
  mcpServers?: Record<string, McpServerConfig>;
39
45
  }
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
6
6
  export { UriTemplate } from '@modelcontextprotocol/sdk/shared/uriTemplate.js';
7
7
  export { completable } from '@modelcontextprotocol/sdk/server/completable.js';
8
8
  export { getDisplayName } from '@modelcontextprotocol/sdk/shared/metadataUtils.js';
9
+ export { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
9
10
  export type * from 'zod';
10
11
  export type * from '@opentiny/next';
11
12
  export type * from '@modelcontextprotocol/sdk/types.js';