@opentiny/next-sdk 0.0.1-alpha.1

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/README.md ADDED
@@ -0,0 +1,322 @@
1
+ # next-sdk 使用指南
2
+
3
+ ## 项目简介
4
+
5
+ `next-sdk` 是基于 `@modelcontextprotocol/sdk` 和 `@opentiny/next` 的客户端和服务端封装,提供了更友好的 API 和更丰富的功能。
6
+
7
+ ---
8
+
9
+ ## 目录结构与主要模块
10
+
11
+ - `client/`:客户端相关能力
12
+ - `createClient.ts`:创建客户端实例,提供事件注册、插件机制等核心功能
13
+ - `connectMcpServer.ts`:遥控端连接服务端的插件,支持 stream/sse 两种传输方式
14
+ - `createInMemoryTransport.ts`:内存传输实现,便于本地调试和测试
15
+ - `createMessageChannelTransport.ts`:基于 MessageChannel 的多窗口 iframe 通信的 transport 实现
16
+ - `createProxy.ts`:创建代理对象和孪生 Transport,支持 stream/sse 两种传输方式
17
+ - `index.ts`:导出所有客户端模块
18
+
19
+ - `server/`:服务端相关能力
20
+ - `createServer.ts`:创建服务端实例,提供事件监听和处理能力
21
+ - `index.ts`:导出所有服务端模块
22
+
23
+ - `mcp-host/`:多模型能力平台(MCP)相关实现
24
+ - `core/`:核心能力实现
25
+ - `deepseek/`:DeepSeek LLM 接入实现
26
+ - `index.ts`:统一导出 MCP 相关能力
27
+
28
+ - `utils/`:工具方法
29
+ - `dom.ts`:DOM 相关工具方法
30
+ - `index.ts`:导出所有工具方法
31
+
32
+ - `type.ts`:类型定义文件
33
+ - 包含客户端、服务端、传输方式等相关类型定义
34
+ - 提供完整的 TypeScript 类型支持
35
+
36
+ - `index.ts`:根入口文件
37
+ - 统一导出客户端和服务端模块
38
+ - 方便用户引入使用
39
+
40
+ ---
41
+
42
+ ## 1. 客户端能力
43
+
44
+ ### 1.1 NextClient 类
45
+
46
+ `NextClient` 封装了底层 Client 实例,提供事件注册、插件机制、连接等能力。
47
+
48
+ #### 创建 NextClient 实例
49
+
50
+ ```ts
51
+ import { createClient } from '@opentiny/next-sdk'
52
+
53
+
54
+ // 通过 createClient 创建 NextClient 实例,便于后续扩展和事件注册。
55
+ const client = createClient({name: 'next-sdk',version: '1.0.0'})
56
+ ```
57
+
58
+ ### 1.2 注册插件
59
+
60
+ ```ts
61
+ // 通过插件机制扩展 client 能力,plugin函数执行返回的是一个接收 client 实例的函数。
62
+ await client.use(plugin({options}))
63
+ ```
64
+
65
+ #### 1.2.1 createInMemoryTransport
66
+
67
+ 此插件用于本地或跨 iframe 的消息通道通信。
68
+
69
+ ```ts
70
+ import { createInMemoryTransport } from '@opentiny/next-sdk'
71
+
72
+ // 设置为 InMemory 通信,适合前端多窗口/iframe 场景。
73
+ await client.use(createInMemoryTransport())
74
+ ```
75
+
76
+ #### 1.2.2 createMessageChannelTransport
77
+
78
+ 此插件用于本地或跨 iframe 的消息通道通信。
79
+
80
+ ```ts
81
+ import { createMessageChannelTransport } from '@opentiny/next-sdk'
82
+
83
+ // 设置为 MessageChannel 通信,适合前端多窗口/iframe 场景。
84
+ await client.use(createMessageChannelTransport({ endpoint, globalObject }))
85
+ ```
86
+
87
+ #### 1.2.3 createClientProxy
88
+
89
+ 此插件用于通过 stream 或 sse 代理方式与服务端通信。
90
+
91
+ ```ts
92
+ import { createClientProxy } from '@opentiny/next-sdk'
93
+
94
+ // 根据 type 选择 stream 或 sse 方式,自动管理 session 和连接关闭。
95
+ await client.use(createClientProxy({
96
+ type: 'stream', // 或 'sse'
97
+ url: 'https://agent-server.com/mcp',
98
+ token: 'your-token',
99
+ sessionId: 'xxx'
100
+ }))
101
+ ```
102
+
103
+ #### 1.2.4 connectMcpServer
104
+
105
+ 此插件用于遥控器端或者业界通用的 `MCP HOST` 直接连接 MCP 服务端,支持 stream/sse。
106
+
107
+ ```ts
108
+ import { connectMcpServer } from 'next-sdk'
109
+
110
+ // 直接配置服务端地址和鉴权信息,快速建立连接。
111
+ await client.use(connectMcpServer({
112
+ type: 'stream', // 或 'sse'
113
+ url: 'https://agent-server.com/mcp?sessionId=xxx',
114
+ token: 'your-token',
115
+ }))
116
+ ```
117
+
118
+ ### 1.3 事件注册
119
+
120
+ ```ts
121
+ // 支持注册通知事件(如 toolListChanged、resourceUpdated 等)和请求事件(如 createMessage、listRoots 等)。
122
+
123
+ // 监听工具变化事件
124
+ client.on('toolListChanged', callback)
125
+ // 监听资源变化事件
126
+ client.on('resourceUpdated', callback)
127
+ // 监听日志发送事件
128
+ client.on('loggingMessage', callback)
129
+ // 监听listRoots
130
+ client.on('listRoots', callback)
131
+ // 监听创建消息,并返回大模型响应
132
+ client.on('createMessage', callback)
133
+ ```
134
+
135
+ #### 1.4 连接
136
+
137
+ ```ts
138
+ // 建立与服务端的连接,具体传输方式由 插件的 transport 决定。
139
+ await client.connectTransport()
140
+ ```
141
+
142
+ ---
143
+
144
+ ## 2. 服务端能力
145
+
146
+ ### 2.1 NextServer 类
147
+
148
+ `NextServer` 封装了底层 McpServer 实例,提供事件注册、插件机制、连接等能力。
149
+
150
+ #### 创建 NextServer 实例
151
+
152
+ ```ts
153
+ import { createServer } from '@opentiny/next-sdk'
154
+
155
+ // 通过 createServer 创建 NextServer 实例。
156
+ const server = createServer({name: 'next-sdk', version: '1.0.0'})
157
+ ```
158
+
159
+ ### 2.2 注册插件
160
+
161
+ ```ts
162
+ // 通过插件机制扩展 server 能力,plugin函数执行返回的是一个接收 server 实例的函数。
163
+ await server.use(plugin({options}))
164
+ ```
165
+
166
+ #### 2.2.1 createInMemoryTransport
167
+
168
+ 此插件用于本地或跨 iframe 的消息通道通信。
169
+
170
+ ```ts
171
+ import { createInMemoryTransport } from '@opentiny/next-sdk'
172
+
173
+ // 设置为 InMemory 通信,适合前端多窗口/iframe 场景。
174
+ await server.use(createInMemoryTransport())
175
+ ```
176
+
177
+ #### 2.2.2 createMessageChannelTransport
178
+
179
+ 此插件用于本地或跨 iframe 的消息通道通信。
180
+
181
+ ```ts
182
+ import { createMessageChannelTransport } from '@opentiny/next-sdk'
183
+
184
+ // 设置为 MessageChannel 通信,适合前端多窗口/iframe 场景。
185
+ await server.use(createMessageChannelTransport({ endpoint, globalObject }))
186
+ ```
187
+
188
+ #### 2.2.3 createServerProxy
189
+
190
+ 此插件用于通过 stream 或 sse 代理方式与客户端通信。
191
+
192
+ ```ts
193
+ import { createServerProxy } from '@opentiny/next-sdk'
194
+
195
+ // 根据 type 选择 stream 或 sse 方式,自动管理 session 和连接关闭。
196
+ await server.use(createServerProxy())
197
+ ```
198
+
199
+ ### 2.3 事件注册
200
+
201
+ ```ts
202
+ // 注册服务端请求事件(如 subscribe、unsubscribe、listResources 等)。
203
+
204
+ // 监听订阅资源
205
+ server.on('subscribe', callback)
206
+ // 监听取消订阅资源
207
+ server.on('unsubscribe', callback)
208
+ // 监听设置日志级别
209
+ server.on('setLogLevel', callback)
210
+ // 监听ping
211
+ server.on('ping', callback)
212
+ ```
213
+
214
+ ### 2.4 连接
215
+
216
+ ```ts
217
+ // 建立服务端监听,支持 messageChannel 等多种传输方式。
218
+ await server.connectTransport()
219
+ ```
220
+
221
+ ---
222
+
223
+ ## 3. 典型用法示例 -- (前端工程MCP 服务端、agent-server代理服务器、遥控端)
224
+
225
+ ### 3.1 前端工程(App.vue)通过 createProxy 代理 stream 方式连接agent-server代理服务器
226
+
227
+ ```ts
228
+ import { createClient, createClientProxy } from '@opentiny/next-sdk'
229
+
230
+ const nextClient = createClient({name: 'next-sdk',version: '1.0.0'})
231
+
232
+ const { sessionId, transport } = await nextClient.use(createClientProxy({
233
+ type: 'stream',
234
+ url: 'https://agent-server.com/mcp',
235
+ sessionId: 'xxx',
236
+ token: 'your-token'
237
+ }))
238
+
239
+ await client.connectTransport()
240
+ ```
241
+
242
+ ### 3.2 MCP 服务端(子路由页面)定义工具或者监听请求
243
+
244
+ ```ts
245
+ import { createServer,createServerProxy } from '@opentiny/next-sdk'
246
+
247
+ const server = createServer({name: 'next-sdk',version: '1.0.0'})
248
+
249
+ server.use(createServerProxy())
250
+
251
+ server.tool('get-weather', 'Get the weather of a city', { value: z.string() }, async ({ value }) => {
252
+ return { content: [{ type: 'text', text: `The weather of ${value} is sunny` }] }
253
+ })
254
+
255
+ server.on('subscribe', callback)
256
+
257
+ await server.connectTransport()
258
+ ```
259
+
260
+ ### 3.3 远程遥控端(可以是手机、平板、电脑等)通过 connectMcpServer 连接agent-server代理服务器
261
+
262
+ ```ts
263
+ import { createClient, connectMcpServer } from '@opentiny/next-sdk'
264
+
265
+ const client = createClient({name: 'next-sdk',version: '1.0.0'})
266
+
267
+ await client.use(connectMcpServer({
268
+ type: 'stream',
269
+ url: 'https://agent-server.com/mcp?sessionId=xxx',
270
+ token: 'your-token'
271
+ }))
272
+
273
+ await client.connectTransport()
274
+ ```
275
+
276
+ ## 4. 典型用法示例 -- (前端工程MCP 服务端、iframe 帮助文档遥控端)
277
+
278
+ ### 4.1 iframe 帮助文档遥控端通过 messageChannel 连接前端工程
279
+
280
+ ```ts
281
+ import { createClient, createMessageChannelTransport } from '@opentiny/next-sdk'
282
+
283
+ const client = createClient({name: 'next-sdk',version: '1.0.0'})
284
+
285
+ client.use(createMessageChannelTransport({
286
+ endpoint: 'endpoint',
287
+ globalObject: window.parent
288
+ }))
289
+
290
+ await client.connectTransport()
291
+ ```
292
+
293
+ ### 4.2 前端工程通过 messageChannel 连接 iframe 帮助文档遥控端,并定义工具或者监听请求
294
+
295
+ ```ts
296
+ import { createServer, createMessageChannelTransport } from '@opentiny/next-sdk'
297
+
298
+ const server = createServer({name: 'next-sdk',version: '1.0.0'})
299
+
300
+ server.use(createMessageChannelTransport({
301
+ endpoint: 'endpoint',
302
+ globalObject: window
303
+ }))
304
+
305
+ server.tool('get-weather', 'Get the weather of a city', { value: z.string() }, async ({ value }) => {
306
+ return { content: [{ type: 'text', text: `The weather of ${value} is sunny` }] }
307
+ })
308
+
309
+ server.on('subscribe', callback)
310
+
311
+ await server.connectTransport()
312
+ ```
313
+
314
+ ---
315
+
316
+ ## 5. 其他说明
317
+
318
+ - 所有通信方式均支持插件机制,便于灵活扩展。
319
+ - 支持多种事件注册,覆盖通知和请求两大类。
320
+ - 传输方式可根据实际场景选择(如 messageChannel 适合前端多窗口,stream/sse 适合前后端通信)。
321
+
322
+ ---
@@ -0,0 +1 @@
1
+ export * from './createClient';
@@ -0,0 +1,9 @@
1
+ declare enum ErrorCode {
2
+ ConnectionClosed = -32000,
3
+ RequestTimeout = -32001,
4
+ ParseError = -32700,
5
+ InvalidRequest = -32600,
6
+ MethodNotFound = -32601,
7
+ InvalidParams = -32602,
8
+ InternalError = -32603
9
+ }
@@ -0,0 +1,7 @@
1
+ export * from './client';
2
+ export * from './server';
3
+ export * from './mcp-host';
4
+ export * from './plugins/createMessageChannelTransport';
5
+ export * from './plugins/createProxy';
6
+ export * from './plugins/connectMcpServer';
7
+ export * from './plugins/createInMemoryTransport';
package/dist/index.mjs ADDED
@@ -0,0 +1,357 @@
1
+ var b = Object.defineProperty;
2
+ var x = (s, e, t) => e in s ? b(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var i = (s, e, t) => x(s, typeof e != "symbol" ? e + "" : e, t);
4
+ import { Client as v } from "@modelcontextprotocol/sdk/client/index.js";
5
+ import { LoggingMessageNotificationSchema as O, PromptListChangedNotificationSchema as P, ResourceUpdatedNotificationSchema as D, ToolListChangedNotificationSchema as q, ElicitRequestSchema as U, ListRootsRequestSchema as w, CreateMessageRequestSchema as y, PingRequestSchema as H, SetLevelRequestSchema as k, ListResourcesRequestSchema as _, UnsubscribeRequestSchema as $, SubscribeRequestSchema as j } from "@modelcontextprotocol/sdk/types.js";
6
+ import { McpServer as Y } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import F from "openai";
8
+ import { MessageChannelClientTransport as K, MessageChannelServerTransport as B, createTransportPair as J, createStreamProxy as V, createSseProxy as W, streamOptions as X, sseOptions as z } from "@opentiny/next";
9
+ import { StreamableHTTPClientTransport as R } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
10
+ import { SSEClientTransport as A } from "@modelcontextprotocol/sdk/client/sse.js";
11
+ import { InMemoryTransport as G } from "@modelcontextprotocol/sdk/inMemory.js";
12
+ const S = {
13
+ toolListChanged: q,
14
+ resourceUpdated: D,
15
+ promptListChanged: P,
16
+ loggingMessage: O
17
+ }, Q = {
18
+ createMessage: y,
19
+ listRoots: w,
20
+ elicit: U
21
+ };
22
+ class L extends v {
23
+ constructor(t, o) {
24
+ super(t, o);
25
+ i(this, "nextTransport", null);
26
+ i(this, "isMessageChannel", !1);
27
+ }
28
+ // 注册插件
29
+ use(t) {
30
+ return t(this);
31
+ }
32
+ // 注册事件,包括notification以及requestHandle
33
+ on(t, o) {
34
+ t in S ? this.setNotificationHandler(S[t], o) : this.setRequestHandler(Q[t], o);
35
+ }
36
+ async connectTransport() {
37
+ return await this.connect(this.nextTransport);
38
+ }
39
+ }
40
+ const de = (s, e) => new L(s, e), Z = {
41
+ subscribe: j,
42
+ unsubscribe: $,
43
+ listResources: _,
44
+ createMessage: y,
45
+ listRoots: w,
46
+ setLevel: k,
47
+ ping: H
48
+ };
49
+ class ee extends Y {
50
+ constructor(t, o) {
51
+ super(t, o);
52
+ i(this, "nextTransport");
53
+ i(this, "isMessageChannel", !1);
54
+ }
55
+ use(t) {
56
+ return t(this);
57
+ }
58
+ async connectTransport() {
59
+ var t, o;
60
+ return this.isMessageChannel && await ((o = (t = this.nextTransport) == null ? void 0 : t.listen) == null ? void 0 : o.call(t)), await this.connect(this.nextTransport);
61
+ }
62
+ on(t, o) {
63
+ this.server.setRequestHandler(Z[t], o);
64
+ }
65
+ }
66
+ const Se = (s, e) => new ee(s, e);
67
+ var c = /* @__PURE__ */ ((s) => (s.FUNCTION = "function", s.USER = "user", s.ASSISTANT = "assistant", s.DEVELOPER = "developer", s.SYSTEM = "system", s.TOOL = "tool", s))(c || {});
68
+ const C = 3;
69
+ class te {
70
+ // 最大迭代次数
71
+ constructor({ llmOption: e, mcpClients: t }) {
72
+ i(this, "llmOption");
73
+ i(this, "mcpClients");
74
+ i(this, "llm");
75
+ i(this, "mcpClientMap", /* @__PURE__ */ new Map());
76
+ i(this, "messages", []);
77
+ i(this, "toolClientMap", /* @__PURE__ */ new Map());
78
+ i(this, "iteration", C);
79
+ this.llmOption = e, this.mcpClients = t, this.messages.push({ role: c.SYSTEM, content: "You are a helpful assistant with access to tools." });
80
+ }
81
+ async generateMcpClient() {
82
+ for (let e = 0; e < this.mcpClients.length; e++) {
83
+ const t = this.mcpClients[e], { tools: o } = await t.listTools();
84
+ this.mcpClientMap.set(t, o), o.forEach((a) => {
85
+ this.toolClientMap.set(a.name, t);
86
+ });
87
+ }
88
+ }
89
+ init() {
90
+ this.llm = new F({
91
+ baseURL: this.llmOption.url,
92
+ apiKey: this.llmOption.apiKey,
93
+ dangerouslyAllowBrowser: !0
94
+ });
95
+ }
96
+ validateRequest(e) {
97
+ if (!e.messages || !Array.isArray(e.messages) || e.messages.length === 0)
98
+ throw new Error("请求必须包含至少一条消息");
99
+ for (const t of e.messages)
100
+ if (!t.role || !t.content)
101
+ throw new Error("每条消息必须包含角色和内容");
102
+ }
103
+ async getMcpTools() {
104
+ const e = [];
105
+ for (const [, o] of this.mcpClientMap.entries())
106
+ e.push(...o);
107
+ return e.map((o) => ({
108
+ type: "function",
109
+ function: {
110
+ name: o.name,
111
+ description: o.description,
112
+ parameters: o.inputSchema
113
+ }
114
+ }));
115
+ }
116
+ async doLLMChart() {
117
+ const e = await this.getMcpTools();
118
+ return await this.llm.chat.completions.create({
119
+ messages: this.messages,
120
+ model: this.llmOption.model,
121
+ tools: e,
122
+ stream: !0
123
+ });
124
+ }
125
+ /**
126
+ * 解析 LLM 回复,提取工具调用和最终回复内容
127
+ * @param response LLM 回复对象
128
+ * @returns [工具调用数组, 回复内容]
129
+ */
130
+ async parseToolCalls(e, t) {
131
+ var h, p, f, n;
132
+ const o = /* @__PURE__ */ new Map();
133
+ let a = "", r = "";
134
+ for await (const T of e) {
135
+ const u = T.choices[0].delta, g = u == null ? void 0 : u.tool_calls, d = u == null ? void 0 : u.content;
136
+ if (d && (a += d, t.onData({
137
+ delta: {
138
+ role: "assistant",
139
+ content: d
140
+ }
141
+ })), g && g.length > 0) {
142
+ const l = g[0];
143
+ if (l.id) {
144
+ r = l.id;
145
+ const m = {
146
+ id: l.id,
147
+ type: l.type,
148
+ function: {
149
+ name: ((h = l.function) == null ? void 0 : h.name) || "",
150
+ arguments: ((p = l.function) == null ? void 0 : p.arguments) || ""
151
+ }
152
+ };
153
+ o.set(r, m), t.onData({
154
+ delta: {
155
+ role: c.ASSISTANT,
156
+ content: `
157
+
158
+ 正在调用工具:${m.function.name}
159
+
160
+ 参数:`
161
+ }
162
+ });
163
+ }
164
+ if (o.has(r)) {
165
+ const m = o.get(r);
166
+ m && (m.function.arguments += ((f = l.function) == null ? void 0 : f.arguments) || "", t.onData({
167
+ delta: {
168
+ role: c.ASSISTANT,
169
+ content: `${(n = l.function) == null ? void 0 : n.arguments}`
170
+ }
171
+ }));
172
+ }
173
+ }
174
+ }
175
+ return t.onData({
176
+ delta: {
177
+ role: "assistant",
178
+ content: `
179
+
180
+ `
181
+ }
182
+ }), [Array.from(o.values()), a];
183
+ }
184
+ /**
185
+ * 执行工具调用
186
+ * @param toolCalls 工具调用请求列表
187
+ * @returns 工具调用结果和消息
188
+ */
189
+ async callTools(e, t) {
190
+ var o, a, r, h;
191
+ try {
192
+ const p = [], f = [];
193
+ for (const n of e) {
194
+ const T = n.function.name, u = this.toolClientMap.get(T);
195
+ if (!u)
196
+ continue;
197
+ let g = {};
198
+ try {
199
+ g = typeof n.function.arguments == "string" ? JSON.parse(n.function.arguments) : n.function.arguments;
200
+ } catch (N) {
201
+ console.error(`Failed to parse tool arguments for ${T}:`, N), g = {};
202
+ }
203
+ const d = {
204
+ id: n.id,
205
+ type: n.type,
206
+ function: {
207
+ name: ((o = n.function) == null ? void 0 : o.name) || "",
208
+ arguments: ((a = n.function) == null ? void 0 : a.arguments) || ""
209
+ }
210
+ };
211
+ t.onData({
212
+ delta: {
213
+ role: c.TOOL,
214
+ toolCall: d
215
+ }
216
+ });
217
+ const l = await u.callTool({
218
+ name: T,
219
+ arguments: g
220
+ }), m = this.getToolCallMessage(l), I = {
221
+ role: c.TOOL,
222
+ tool_call_id: n.id,
223
+ content: m
224
+ }, E = {
225
+ id: n.id,
226
+ type: n.type,
227
+ callToolContent: m,
228
+ function: {
229
+ name: ((r = n.function) == null ? void 0 : r.name) || "",
230
+ arguments: ((h = n.function) == null ? void 0 : h.arguments) || ""
231
+ }
232
+ };
233
+ t.onData({
234
+ delta: {
235
+ role: c.TOOL,
236
+ toolCall: E
237
+ }
238
+ }), f.push(I), p.push({
239
+ call: T,
240
+ result: l
241
+ });
242
+ }
243
+ return { toolResults: p, toolCallMessages: f };
244
+ } catch (p) {
245
+ return console.error("Error calling tools:", p), { toolResults: [], toolCallMessages: [{ role: c.ASSISTANT, content: "call tools failed!" }] };
246
+ }
247
+ }
248
+ /**
249
+ * 解析工具调用结果,拼接为字符串
250
+ * @param toolCallResult 工具调用结果
251
+ * @returns 拼接后的字符串
252
+ */
253
+ getToolCallMessage(e) {
254
+ var o;
255
+ let t = "";
256
+ return (o = e.content) != null && o.length && e.content.forEach((a) => {
257
+ switch (a.type) {
258
+ case "text":
259
+ t += a.text;
260
+ break;
261
+ case "image":
262
+ case "audio":
263
+ case "resource":
264
+ t += a.data;
265
+ break;
266
+ }
267
+ }), t;
268
+ }
269
+ async chatStream(e, t) {
270
+ return await this.generateMcpClient(), typeof e == "string" ? this.messages.push({ role: c.USER, content: e }) : this.messages.push(e.messages[e.messages.length - 1]), this.iteration = C, await this.processSteamToolCallsAndResponses(t).catch((o) => {
271
+ console.error("Chat failed:", o);
272
+ }), "ok";
273
+ }
274
+ /**
275
+ * 聊天迭代主流程,支持多轮工具调用和最终回复
276
+ */
277
+ async processSteamToolCallsAndResponses(e) {
278
+ try {
279
+ const t = [];
280
+ for (; this.iteration > 0; ) {
281
+ const o = await this.doLLMChart(), [a, r] = await this.parseToolCalls(o, e);
282
+ if (a.length) {
283
+ const h = {
284
+ role: c.ASSISTANT,
285
+ content: `调用工具:${a.map((n) => n.function.name).join(",")}`,
286
+ tool_calls: a.map((n) => ({
287
+ id: n.id,
288
+ type: n.type,
289
+ function: n.function
290
+ }))
291
+ };
292
+ this.messages.push(h);
293
+ const { toolResults: p, toolCallMessages: f } = await this.callTools(a, e);
294
+ t.push(...p), f.forEach((n) => this.messages.push(n)), this.iteration--;
295
+ } else
296
+ this.messages.push({ role: c.ASSISTANT, content: r }), this.iteration = 0;
297
+ }
298
+ e.onDone();
299
+ } catch (t) {
300
+ throw console.error("Chat iteration failed:", t), t;
301
+ }
302
+ }
303
+ }
304
+ class se extends te {
305
+ constructor({ llmOption: e, mcpClients: t }) {
306
+ super({ llmOption: e, mcpClients: t });
307
+ }
308
+ }
309
+ const Ce = ({ llmOption: s, mcpClients: e }) => {
310
+ let t;
311
+ return s.llm === "deepseek" && (t = new se({ llmOption: s, mcpClients: e }), t.init()), t;
312
+ }, Me = (s) => (e) => {
313
+ e.nextTransport ? e.nextTransport = new K(s.endpoint, s.globalObject) : e.nextTransport = new B(s.endpoint, s.globalObject), e.isMessageChannel = !0;
314
+ }, oe = () => typeof window < "u", ne = (s, e) => {
315
+ const t = async () => {
316
+ e instanceof R ? await (e == null ? void 0 : e.terminateSession()) : e instanceof A && await (e == null ? void 0 : e.close()), s.close();
317
+ };
318
+ oe() && (window.addEventListener("beforeunload", t), window.addEventListener("pagehide", t));
319
+ }, [ae, M] = J(), we = () => (s) => (s.nextTransport = M, M), ye = (s) => async (e) => {
320
+ let t = "", o = null;
321
+ if (s.type === "stream") {
322
+ const { sessionId: a, transport: r } = await V({
323
+ client: e,
324
+ ...s
325
+ });
326
+ t = a, o = r;
327
+ } else {
328
+ const { sessionId: a, transport: r } = await W({
329
+ client: e,
330
+ ...s
331
+ });
332
+ t = a, o = r;
333
+ }
334
+ return e.nextTransport = ae, ne(e, o), {
335
+ sessionId: t,
336
+ transport: o
337
+ };
338
+ }, Re = (s) => (e) => {
339
+ const { type: t, url: o, token: a } = s;
340
+ let r = null;
341
+ t === "stream" ? r = new R(new URL(o), X(a)) : t === "sse" && (r = new A(new URL(o), z(a))), e.nextTransport = r;
342
+ }, [re, ie] = G.createLinkedPair(), Ae = () => (s) => {
343
+ s instanceof L ? s.nextTransport = re : s.nextTransport = ie;
344
+ };
345
+ export {
346
+ L as NextClient,
347
+ ee as NextServer,
348
+ Re as connectMcpServer,
349
+ de as createClient,
350
+ ye as createClientProxy,
351
+ Ae as createInMemoryTransport,
352
+ Ce as createMCPHost,
353
+ Me as createMessageChannelTransport,
354
+ Se as createServer,
355
+ we as createServerProxy,
356
+ M as serverTransport
357
+ };
@@ -0,0 +1,7 @@
1
+ (function(n,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("@modelcontextprotocol/sdk/client/index.js"),require("@modelcontextprotocol/sdk/types.js"),require("@modelcontextprotocol/sdk/server/mcp.js"),require("openai"),require("@opentiny/next"),require("@modelcontextprotocol/sdk/client/streamableHttp.js"),require("@modelcontextprotocol/sdk/client/sse.js"),require("@modelcontextprotocol/sdk/inMemory.js")):typeof define=="function"&&define.amd?define(["exports","@modelcontextprotocol/sdk/client/index.js","@modelcontextprotocol/sdk/types.js","@modelcontextprotocol/sdk/server/mcp.js","openai","@opentiny/next","@modelcontextprotocol/sdk/client/streamableHttp.js","@modelcontextprotocol/sdk/client/sse.js","@modelcontextprotocol/sdk/inMemory.js"],l):(n=typeof globalThis<"u"?globalThis:n||self,l(n.NextSDK={},n.index_js,n.types_js,n.mcp_js,n.OpenAI,n.next,n.streamableHttp_js,n.sse_js,n.inMemory_js))})(this,function(n,l,i,E,N,T,x,A,k){"use strict";var Z=Object.defineProperty;var _=(n,l,i)=>l in n?Z(n,l,{enumerable:!0,configurable:!0,writable:!0,value:i}):n[l]=i;var u=(n,l,i)=>_(n,typeof l!="symbol"?l+"":l,i);const L={toolListChanged:i.ToolListChangedNotificationSchema,resourceUpdated:i.ResourceUpdatedNotificationSchema,promptListChanged:i.PromptListChangedNotificationSchema,loggingMessage:i.LoggingMessageNotificationSchema},q={createMessage:i.CreateMessageRequestSchema,listRoots:i.ListRootsRequestSchema,elicit:i.ElicitRequestSchema};class y extends l.Client{constructor(e,s){super(e,s);u(this,"nextTransport",null);u(this,"isMessageChannel",!1)}use(e){return e(this)}on(e,s){e in L?this.setNotificationHandler(L[e],s):this.setRequestHandler(q[e],s)}async connectTransport(){return await this.connect(this.nextTransport)}}const P=(o,t)=>new y(o,t),b={subscribe:i.SubscribeRequestSchema,unsubscribe:i.UnsubscribeRequestSchema,listResources:i.ListResourcesRequestSchema,createMessage:i.CreateMessageRequestSchema,listRoots:i.ListRootsRequestSchema,setLevel:i.SetLevelRequestSchema,ping:i.PingRequestSchema};class v extends E.McpServer{constructor(e,s){super(e,s);u(this,"nextTransport");u(this,"isMessageChannel",!1)}use(e){return e(this)}async connectTransport(){var e,s;return this.isMessageChannel&&await((s=(e=this.nextTransport)==null?void 0:e.listen)==null?void 0:s.call(e)),await this.connect(this.nextTransport)}on(e,s){this.server.setRequestHandler(b[e],s)}}const O=(o,t)=>new v(o,t);var p=(o=>(o.FUNCTION="function",o.USER="user",o.ASSISTANT="assistant",o.DEVELOPER="developer",o.SYSTEM="system",o.TOOL="tool",o))(p||{});const I=3;class D{constructor({llmOption:t,mcpClients:e}){u(this,"llmOption");u(this,"mcpClients");u(this,"llm");u(this,"mcpClientMap",new Map);u(this,"messages",[]);u(this,"toolClientMap",new Map);u(this,"iteration",I);this.llmOption=t,this.mcpClients=e,this.messages.push({role:p.SYSTEM,content:"You are a helpful assistant with access to tools."})}async generateMcpClient(){for(let t=0;t<this.mcpClients.length;t++){const e=this.mcpClients[t],{tools:s}=await e.listTools();this.mcpClientMap.set(e,s),s.forEach(r=>{this.toolClientMap.set(r.name,e)})}}init(){this.llm=new N({baseURL:this.llmOption.url,apiKey:this.llmOption.apiKey,dangerouslyAllowBrowser:!0})}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("请求必须包含至少一条消息");for(const e of t.messages)if(!e.role||!e.content)throw new Error("每条消息必须包含角色和内容")}async getMcpTools(){const t=[];for(const[,s]of this.mcpClientMap.entries())t.push(...s);return t.map(s=>({type:"function",function:{name:s.name,description:s.description,parameters:s.inputSchema}}))}async doLLMChart(){const t=await this.getMcpTools();return await this.llm.chat.completions.create({messages:this.messages,model:this.llmOption.model,tools:t,stream:!0})}async parseToolCalls(t,e){var g,h,S,a;const s=new Map;let r="",c="";for await(const M of t){const d=M.choices[0].delta,C=d==null?void 0:d.tool_calls,w=d==null?void 0:d.content;if(w&&(r+=w,e.onData({delta:{role:"assistant",content:w}})),C&&C.length>0){const m=C[0];if(m.id){c=m.id;const f={id:m.id,type:m.type,function:{name:((g=m.function)==null?void 0:g.name)||"",arguments:((h=m.function)==null?void 0:h.arguments)||""}};s.set(c,f),e.onData({delta:{role:p.ASSISTANT,content:`
2
+
3
+ 正在调用工具:${f.function.name}
4
+
5
+ 参数:`}})}if(s.has(c)){const f=s.get(c);f&&(f.function.arguments+=((S=m.function)==null?void 0:S.arguments)||"",e.onData({delta:{role:p.ASSISTANT,content:`${(a=m.function)==null?void 0:a.arguments}`}}))}}}return e.onData({delta:{role:"assistant",content:`
6
+
7
+ `}}),[Array.from(s.values()),r]}async callTools(t,e){var s,r,c,g;try{const h=[],S=[];for(const a of t){const M=a.function.name,d=this.toolClientMap.get(M);if(!d)continue;let C={};try{C=typeof a.function.arguments=="string"?JSON.parse(a.function.arguments):a.function.arguments}catch(Q){console.error(`Failed to parse tool arguments for ${M}:`,Q),C={}}const w={id:a.id,type:a.type,function:{name:((s=a.function)==null?void 0:s.name)||"",arguments:((r=a.function)==null?void 0:r.arguments)||""}};e.onData({delta:{role:p.TOOL,toolCall:w}});const m=await d.callTool({name:M,arguments:C}),f=this.getToolCallMessage(m),z={role:p.TOOL,tool_call_id:a.id,content:f},G={id:a.id,type:a.type,callToolContent:f,function:{name:((c=a.function)==null?void 0:c.name)||"",arguments:((g=a.function)==null?void 0:g.arguments)||""}};e.onData({delta:{role:p.TOOL,toolCall:G}}),S.push(z),h.push({call:M,result:m})}return{toolResults:h,toolCallMessages:S}}catch(h){return console.error("Error calling tools:",h),{toolResults:[],toolCallMessages:[{role:p.ASSISTANT,content:"call tools failed!"}]}}}getToolCallMessage(t){var s;let e="";return(s=t.content)!=null&&s.length&&t.content.forEach(r=>{switch(r.type){case"text":e+=r.text;break;case"image":case"audio":case"resource":e+=r.data;break}}),e}async chatStream(t,e){return await this.generateMcpClient(),typeof t=="string"?this.messages.push({role:p.USER,content:t}):this.messages.push(t.messages[t.messages.length-1]),this.iteration=I,await this.processSteamToolCallsAndResponses(e).catch(s=>{console.error("Chat failed:",s)}),"ok"}async processSteamToolCallsAndResponses(t){try{const e=[];for(;this.iteration>0;){const s=await this.doLLMChart(),[r,c]=await this.parseToolCalls(s,t);if(r.length){const g={role:p.ASSISTANT,content:`调用工具:${r.map(a=>a.function.name).join(",")}`,tool_calls:r.map(a=>({id:a.id,type:a.type,function:a.function}))};this.messages.push(g);const{toolResults:h,toolCallMessages:S}=await this.callTools(r,t);e.push(...h),S.forEach(a=>this.messages.push(a)),this.iteration--}else this.messages.push({role:p.ASSISTANT,content:c}),this.iteration=0}t.onDone()}catch(e){throw console.error("Chat iteration failed:",e),e}}}class H extends D{constructor({llmOption:t,mcpClients:e}){super({llmOption:t,mcpClients:e})}}const U=({llmOption:o,mcpClients:t})=>{let e;return o.llm==="deepseek"&&(e=new H({llmOption:o,mcpClients:t}),e.init()),e},j=o=>t=>{t.nextTransport?t.nextTransport=new T.MessageChannelClientTransport(o.endpoint,o.globalObject):t.nextTransport=new T.MessageChannelServerTransport(o.endpoint,o.globalObject),t.isMessageChannel=!0},$=()=>typeof window<"u",K=(o,t)=>{const e=async()=>{t instanceof x.StreamableHTTPClientTransport?await(t==null?void 0:t.terminateSession()):t instanceof A.SSEClientTransport&&await(t==null?void 0:t.close()),o.close()};$()&&(window.addEventListener("beforeunload",e),window.addEventListener("pagehide",e))},[Y,R]=T.createTransportPair(),F=()=>o=>(o.nextTransport=R,R),B=o=>async t=>{let e="",s=null;if(o.type==="stream"){const{sessionId:r,transport:c}=await T.createStreamProxy({client:t,...o});e=r,s=c}else{const{sessionId:r,transport:c}=await T.createSseProxy({client:t,...o});e=r,s=c}return t.nextTransport=Y,K(t,s),{sessionId:e,transport:s}},J=o=>t=>{const{type:e,url:s,token:r}=o;let c=null;e==="stream"?c=new x.StreamableHTTPClientTransport(new URL(s),T.streamOptions(r)):e==="sse"&&(c=new A.SSEClientTransport(new URL(s),T.sseOptions(r))),t.nextTransport=c},[V,W]=k.InMemoryTransport.createLinkedPair(),X=()=>o=>{o instanceof y?o.nextTransport=V:o.nextTransport=W};n.NextClient=y,n.NextServer=v,n.connectMcpServer=J,n.createClient=P,n.createClientProxy=B,n.createInMemoryTransport=X,n.createMCPHost=U,n.createMessageChannelTransport=j,n.createServer=O,n.createServerProxy=F,n.serverTransport=R,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,57 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
+ import { ChatCompleteResponse, ToolCall, ToolResults, Message, ChatCompleteRequest, StreamHandler } from '../../type';
4
+ export declare class MCPHost {
5
+ protected llmOption: any;
6
+ protected mcpClients: Client[];
7
+ protected llm: any;
8
+ protected mcpClientMap: Map<Client, any>;
9
+ messages: any[];
10
+ protected toolClientMap: Map<string, Client>;
11
+ protected iteration: number;
12
+ constructor({ llmOption, mcpClients }: {
13
+ llmOption: any;
14
+ mcpClients: Client[];
15
+ });
16
+ generateMcpClient(): Promise<void>;
17
+ init(): void;
18
+ protected validateRequest(request: ChatCompleteRequest): void;
19
+ getMcpTools(): Promise<{
20
+ type: string;
21
+ function: {
22
+ name: any;
23
+ description: any;
24
+ parameters: any;
25
+ };
26
+ }[]>;
27
+ doLLMChart(): Promise<any>;
28
+ /**
29
+ * 解析 LLM 回复,提取工具调用和最终回复内容
30
+ * @param response LLM 回复对象
31
+ * @returns [工具调用数组, 回复内容]
32
+ */
33
+ protected parseToolCalls(response: ChatCompleteResponse, handler: StreamHandler): Promise<[ToolCall[], string]>;
34
+ /**
35
+ * 执行工具调用
36
+ * @param toolCalls 工具调用请求列表
37
+ * @returns 工具调用结果和消息
38
+ */
39
+ protected callTools(toolCalls: ToolCall[], handler: StreamHandler): Promise<{
40
+ toolResults: ToolResults;
41
+ toolCallMessages: Message[];
42
+ }>;
43
+ /**
44
+ * 解析工具调用结果,拼接为字符串
45
+ * @param toolCallResult 工具调用结果
46
+ * @returns 拼接后的字符串
47
+ */
48
+ protected getToolCallMessage(toolCallResult: CallToolResult): string;
49
+ chatStream(message: string | {
50
+ messages: Message[];
51
+ options: any;
52
+ }, handler: StreamHandler): Promise<string>;
53
+ /**
54
+ * 聊天迭代主流程,支持多轮工具调用和最终回复
55
+ */
56
+ protected processSteamToolCallsAndResponses(handler: StreamHandler): Promise<void>;
57
+ }
@@ -0,0 +1,7 @@
1
+ import { MCPHost } from '../core';
2
+ export declare class DeepSeekMcpHost extends MCPHost {
3
+ constructor({ llmOption, mcpClients }: {
4
+ llmOption: any;
5
+ mcpClients: any;
6
+ });
7
+ }
@@ -0,0 +1,4 @@
1
+ export declare const createMCPHost: ({ llmOption, mcpClients }: {
2
+ llmOption: any;
3
+ mcpClients: any;
4
+ }) => any;
@@ -0,0 +1,3 @@
1
+ import { McpServerInfo } from '../type';
2
+ import { NextClient } from '../client/createClient';
3
+ export declare const connectMcpServer: (options: McpServerInfo) => (nextClient: NextClient) => void;
@@ -0,0 +1,3 @@
1
+ import { NextClient } from '../client/createClient';
2
+ import { NextServer } from '../server/createServer';
3
+ export declare const createInMemoryTransport: () => (nextClientOrServer: NextClient | NextServer) => void;
@@ -0,0 +1,3 @@
1
+ import { NextClient } from '../client/createClient';
2
+ import { NextServer } from '../server/createServer';
3
+ export declare const createMessageChannelTransport: (options: Record<string, any>) => (nextClientOrServer: NextClient | NextServer) => void;
@@ -0,0 +1,10 @@
1
+ import { NextClient } from '../client/createClient';
2
+ import { INextClientProxyOption } from '../type';
3
+ import { NextServer } from '../server/createServer';
4
+ declare const serverTransport: import('@opentiny/next').MessageChannelTransport;
5
+ export { serverTransport };
6
+ export declare const createServerProxy: () => (nextServer: NextServer) => import('@opentiny/next').MessageChannelTransport;
7
+ export declare const createClientProxy: (proxyOptions: INextClientProxyOption) => (nextClient: NextClient) => Promise<{
8
+ sessionId: string;
9
+ transport: any;
10
+ }>;
@@ -0,0 +1 @@
1
+ export * from './createServer';
package/dist/type.d.ts ADDED
@@ -0,0 +1,266 @@
1
+ import { ClientProxyOption } from '@opentiny/next';
2
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
4
+ export interface McpServerInfo {
5
+ /**
6
+ * 代理类型
7
+ */
8
+ type: 'stream' | 'sse';
9
+ /**
10
+ * 代理服务器的 URL
11
+ */
12
+ url: string;
13
+ /**
14
+ * 代理服务器的身份验证令牌
15
+ */
16
+ token?: string;
17
+ }
18
+ export interface INextClientProxyOption extends Omit<ClientProxyOption, 'client'> {
19
+ /**
20
+ * 代理类型
21
+ */
22
+ type?: 'stream' | 'sse';
23
+ }
24
+ export interface McpServer {
25
+ url: string;
26
+ headers?: Record<string, string>;
27
+ timeout?: number;
28
+ customTransport: never;
29
+ type: 'sse' | 'stream';
30
+ }
31
+ export interface CustomTransportMcpServer<T = any> {
32
+ config: T;
33
+ customTransport: Transport | ((config: T) => Transport);
34
+ }
35
+ export type McpServers = Record<string, McpServer | CustomTransportMcpServer>;
36
+ export interface McpServerConfig {
37
+ mcpServers: McpServers;
38
+ }
39
+ export type McpServersConfig = Record<string, McpServerConfig | any>;
40
+ export declare enum AgentStrategy {
41
+ FUNCTION_CALLING = "Function Calling",// 函数调用策略
42
+ RE_ACT = "ReAct"
43
+ }
44
+ export interface MCPClientOptions {
45
+ agentStrategy?: AgentStrategy;
46
+ llmConfig: {
47
+ url: string;
48
+ apiKey: string;
49
+ model: string;
50
+ systemPrompt: string;
51
+ summarySystemPrompt?: string;
52
+ };
53
+ mcpServersConfig: McpServersConfig;
54
+ maxIterationSteps?: number;
55
+ }
56
+ export interface AvailableTool {
57
+ type: 'function';
58
+ function: {
59
+ name: string;
60
+ description?: string;
61
+ parameters: {
62
+ type: 'object';
63
+ properties?: Record<string, unknown>;
64
+ required?: string[];
65
+ };
66
+ };
67
+ }
68
+ export interface CallToolsParams {
69
+ toolCalls: ToolCall[];
70
+ }
71
+ export interface ChatBody {
72
+ stream?: boolean;
73
+ model: string;
74
+ messages: Message[];
75
+ tools?: AvailableTool[];
76
+ }
77
+ export type ToolResults = Array<{
78
+ call: string;
79
+ result: CallToolResult;
80
+ }>;
81
+ export declare enum Role {
82
+ FUNCTION = "function",// 函数角色
83
+ USER = "user",// 用户角色
84
+ ASSISTANT = "assistant",// 助手角色
85
+ DEVELOPER = "developer",// 开发者角色
86
+ SYSTEM = "system",// 系统角色
87
+ TOOL = "tool"
88
+ }
89
+ export type ErrorResponse = {
90
+ code: number;
91
+ message: string;
92
+ metadata?: Record<string, unknown>;
93
+ };
94
+ export type FunctionCall = {
95
+ name: string;
96
+ arguments: string;
97
+ };
98
+ export type ToolCall = {
99
+ id: string;
100
+ type: 'function';
101
+ function: FunctionCall;
102
+ };
103
+ export type NonChatChoice = {
104
+ finish_reason: string | null;
105
+ text: string;
106
+ error?: ErrorResponse;
107
+ };
108
+ export type NonStreamingChoice = {
109
+ finish_reason: string | null;
110
+ native_finish_reason: string | null;
111
+ message: {
112
+ content: string | null;
113
+ role: Role;
114
+ tool_calls?: ToolCall[];
115
+ };
116
+ error?: ErrorResponse;
117
+ };
118
+ export type StreamingChoice = {
119
+ finish_reason: string | null;
120
+ native_finish_reason: string | null;
121
+ delta: {
122
+ content: string | null;
123
+ role?: Role;
124
+ tool_calls?: ToolCall[];
125
+ };
126
+ error?: ErrorResponse;
127
+ };
128
+ export type ResponseUsage = {
129
+ prompt_tokens: number;
130
+ completion_tokens: number;
131
+ total_tokens: number;
132
+ };
133
+ export type ChatCompleteResponse = {
134
+ id: string;
135
+ choices: (NonStreamingChoice | StreamingChoice | NonChatChoice)[];
136
+ created: number;
137
+ model: string;
138
+ object: 'chat.completion' | 'chat.completion.chunk';
139
+ system_fingerprint?: string;
140
+ usage?: ResponseUsage;
141
+ };
142
+ export type TextContent = {
143
+ type: 'text';
144
+ text: string;
145
+ };
146
+ export type ImageContentPart = {
147
+ type: 'image_url';
148
+ image_url: {
149
+ url: string;
150
+ detail?: string;
151
+ };
152
+ };
153
+ export type ContentPart = TextContent | ImageContentPart;
154
+ /**
155
+ * 消息角色类型
156
+ */
157
+ export type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
158
+ export type Message = {
159
+ role: MessageRole;
160
+ content: string | ContentPart[];
161
+ name?: string;
162
+ tool_call_id?: string;
163
+ };
164
+ export type FunctionDescription = {
165
+ description?: string;
166
+ name: string;
167
+ parameters: object;
168
+ };
169
+ export type Tool = {
170
+ type: 'function';
171
+ function: FunctionDescription;
172
+ };
173
+ export type ToolChoice = 'none' | 'auto' | {
174
+ type: 'function';
175
+ function: {
176
+ name: string;
177
+ };
178
+ };
179
+ export type ChatCompleteRequest = {
180
+ messages?: Message[];
181
+ prompt?: string;
182
+ model?: string;
183
+ response_format?: {
184
+ type: 'json_object';
185
+ };
186
+ stop?: string | string[];
187
+ stream?: boolean;
188
+ max_tokens?: number;
189
+ temperature?: number;
190
+ tools?: Tool[];
191
+ tool_choice?: ToolChoice;
192
+ seed?: number;
193
+ top_p?: number;
194
+ top_k?: number;
195
+ frequency_penalty?: number;
196
+ presence_penalty?: number;
197
+ repetition_penalty?: number;
198
+ logit_bias?: Record<number, number>;
199
+ top_logprobs?: number;
200
+ min_p?: number;
201
+ top_a?: number;
202
+ prediction?: {
203
+ type: 'content';
204
+ content: string;
205
+ };
206
+ transforms?: string[];
207
+ models?: string[];
208
+ route?: 'fallback';
209
+ };
210
+ export interface IChatOptions {
211
+ toolCallResponse?: boolean;
212
+ }
213
+ export interface ChatCreatePromptArgs {
214
+ suffix?: string;
215
+ prefix?: string;
216
+ humanMessageTemplate?: string;
217
+ formatInstructions?: string;
218
+ inputVariables?: string[];
219
+ }
220
+ /**
221
+ * 流式聊天完成响应增量
222
+ */
223
+ export interface ChatCompletionStreamResponseDelta {
224
+ content?: string;
225
+ role?: MessageRole;
226
+ toolCall?: ToolCall;
227
+ }
228
+ /**
229
+ * 流式聊天完成响应
230
+ */
231
+ export interface ChatCompletionStreamResponse {
232
+ delta: ChatCompletionStreamResponseDelta;
233
+ }
234
+ /**
235
+ * 错误类型
236
+ */
237
+ export declare enum ErrorType {
238
+ NETWORK_ERROR = "network_error",
239
+ AUTHENTICATION_ERROR = "authentication_error",
240
+ RATE_LIMIT_ERROR = "rate_limit_error",
241
+ SERVER_ERROR = "server_error",
242
+ MODEL_ERROR = "model_error",
243
+ TIMEOUT_ERROR = "timeout_error",
244
+ UNKNOWN_ERROR = "unknown_error"
245
+ }
246
+ /**
247
+ * AI适配器错误
248
+ */
249
+ export interface AIAdapterError {
250
+ type: ErrorType;
251
+ message: string;
252
+ statusCode?: number;
253
+ originalError?: object;
254
+ }
255
+ /**
256
+ * 流式响应处理器
257
+ */
258
+ export interface StreamHandler {
259
+ onData: (data: ChatCompletionStreamResponse) => void;
260
+ onError: (error: AIAdapterError) => void;
261
+ onMessage?: (msgObj: {
262
+ type: string;
263
+ [extra: string]: unknown;
264
+ }) => void;
265
+ onDone: () => void;
266
+ }
@@ -0,0 +1,6 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
4
+ import { MessageChannelClientTransport } from '@opentiny/next';
5
+ export declare const isWindow: () => boolean;
6
+ export declare const createCloseTransport: (client: Client, transport: StreamableHTTPClientTransport | SSEClientTransport | MessageChannelClientTransport | null) => void;
@@ -0,0 +1,7 @@
1
+ import { StreamHandler } from '../type';
2
+ /**
3
+ * 处理SSE流式响应
4
+ * @param response fetch响应对象
5
+ * @param handler 流处理器
6
+ */
7
+ export declare function handleSSEStream(response: Response, handler: StreamHandler, signal?: AbortSignal): Promise<void>;
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@opentiny/next-sdk",
3
+ "version": "0.0.1-alpha.1",
4
+ "description": "",
5
+ "module": "src/index.ts",
6
+ "types": "dist/index.d.ts",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "registry": "https://registry.npmjs.org"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "keywords": [],
16
+ "author": "",
17
+ "license": "ISC",
18
+ "dependencies": {
19
+ "@modelcontextprotocol/sdk": "^1.15.1",
20
+ "@opentiny/next": "^0.2.1",
21
+ "openai": "^5.9.0"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.8.3",
25
+ "vite": "^6.3.5",
26
+ "vite-plugin-dts": "^4.5.4"
27
+ },
28
+ "scripts": {
29
+ "build": "vite build",
30
+ "prepare-readme": "cp ../../README.md ./README.md"
31
+ },
32
+ "main": "dist/index.mjs"
33
+ }