@opentiny/next-sdk 0.1.6 → 0.1.8

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.
@@ -1,4 +1,4 @@
1
- import { streamText, stepCountIs, generateText } from 'ai'
1
+ import { streamText, stepCountIs, generateText, StreamTextResult } from 'ai'
2
2
  import { experimental_createMCPClient as createMCPClient, experimental_MCPClientConfig as MCPClientConfig } from 'ai'
3
3
  import type { ToolSet } from 'ai'
4
4
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
@@ -31,14 +31,14 @@ export class AgentModelProvider {
31
31
  /** 需要实时过滤掉的tools name*/
32
32
  ignoreToolnames: string[] = []
33
33
 
34
- /** 在 chat 之前,自动更新 所有的tools */
35
- autoUpdateTools = true
36
-
37
34
  /** chat 时,自动更新 所有的tools 后的事件 */
38
35
  onUpdatedTools: (() => void) | undefined
39
36
  /** 内部报错时,抛出错误事件 */
40
37
  onError: ((msg: string, err?: any) => void) | undefined
41
38
 
39
+ /** 缓存 ai-sdk response 中的 多轮会话 */
40
+ messages: any[] = []
41
+
42
42
  constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption) {
43
43
  // 1、保存 mcpServer
44
44
  this.mcpServers = mcpServers || []
@@ -75,9 +75,9 @@ export class AgentModelProvider {
75
75
  }
76
76
 
77
77
  return await createMCPClient({ transport: transport as MCPClientConfig['transport'] })
78
- } catch (error) {
78
+ } catch (error: unknown) {
79
79
  if (this.onError) {
80
- this.onError(`Failed to create MCP client`, error)
80
+ this.onError((error as Error)?.message || `Failed to create MCP client`, error)
81
81
  }
82
82
  console.error(`Failed to create MCP client`, serverConfig, error)
83
83
  return null
@@ -98,9 +98,9 @@ export class AgentModelProvider {
98
98
  this.mcpClients.map(async (client) => {
99
99
  try {
100
100
  return client ? await client?.tools?.() : null
101
- } catch (error) {
101
+ } catch (error: unknown) {
102
102
  if (this.onError) {
103
- this.onError(`Failed to query tools`, error)
103
+ this.onError((error as Error)?.message || `Failed to query tools`, error)
104
104
  }
105
105
  console.error(`Failed to query tools`, error)
106
106
  return null
@@ -113,8 +113,13 @@ export class AgentModelProvider {
113
113
  await Promise.all(
114
114
  this.mcpClients.map(async (client) => {
115
115
  try {
116
- client.close()
117
- } catch (error) {}
116
+ await client?.close()
117
+ } catch (error: unknown) {
118
+ if (this.onError) {
119
+ this.onError((error as Error)?.message || `Failed to close client`, error)
120
+ }
121
+ console.error(`Failed to close client`, error)
122
+ }
118
123
  })
119
124
  )
120
125
  }
@@ -169,7 +174,7 @@ export class AgentModelProvider {
169
174
  }
170
175
 
171
176
  /** 创建临时允许调用的tools集合 */
172
- tempMergeTools(extraTool = {}) {
177
+ private _tempMergeTools(extraTool = {}) {
173
178
  const toolsResult = this.mcpTools.reduce((acc, curr) => ({ ...acc, ...curr }), {})
174
179
  Object.assign(toolsResult, extraTool)
175
180
 
@@ -179,33 +184,46 @@ export class AgentModelProvider {
179
184
  return toolsResult
180
185
  }
181
186
 
182
- async _chat(
187
+ private async _chat(
183
188
  chatMethod: ChatMethodFn,
184
- { model, maxSteps = 5, ...options }: Parameters<typeof generateText>[0] & { maxSteps?: number }
189
+ { model, maxSteps = 5, ...options }: Parameters<typeof generateText>[0] & { maxSteps?: number; message?: string }
185
190
  ): Promise<any> {
186
191
  if (!this.llm) {
187
192
  throw new Error('LLM is not initialized')
188
193
  }
189
194
 
190
- if (this.autoUpdateTools) {
191
- await this._createMpcTools()
192
- this.onUpdatedTools?.()
193
- }
195
+ await this.initClientsAndTools()
194
196
 
195
- return chatMethod({
197
+ this.onUpdatedTools?.()
198
+
199
+ const chatOptions = {
196
200
  // @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
197
201
  model: this.llm(model),
198
202
  stopWhen: stepCountIs(maxSteps),
199
203
  ...options,
200
- tools: this.tempMergeTools(options.tools) as ToolSet
204
+ tools: this._tempMergeTools(options.tools) as ToolSet
205
+ }
206
+
207
+ if (options.message && !options.messages) {
208
+ this.messages.push({ role: 'user', content: options.message })
209
+ chatOptions.messages = [...this.messages]
210
+ }
211
+
212
+ const result = chatMethod(chatOptions)
213
+
214
+ // 缓存 ai-sdk的多轮对话的消息
215
+ ;(result as StreamTextResult<ToolSet, unknown>)?.response?.then((res: any) => {
216
+ this.messages.push(...res.messages)
201
217
  })
218
+
219
+ return result
202
220
  }
203
221
 
204
- async chat(options: Parameters<typeof generateText>[0] & { maxSteps?: number }): Promise<any> {
222
+ async chat(options: Parameters<typeof generateText>[0] & { maxSteps?: number; message?: string }): Promise<any> {
205
223
  return this._chat(generateText, options)
206
224
  }
207
225
 
208
- async chatStream(options: Parameters<typeof streamText>[0] & { maxSteps?: number }): Promise<any> {
226
+ async chatStream(options: Parameters<typeof streamText>[0] & { maxSteps?: number; message?: string }): Promise<any> {
209
227
  return this._chat(streamText, options as any)
210
228
  }
211
229
  }
@@ -8,7 +8,6 @@ export declare const AIProviderFactories: {
8
8
  openai: typeof createOpenAI;
9
9
  deepseek: typeof createDeepSeek;
10
10
  };
11
- type ChatMethodFn = typeof streamText | typeof generateText;
12
11
  /** 一个通用的ai-sdk的agent封装
13
12
  * @summary 内部自动管理了 llm, mcpServer, ai-sdk的clients 和 tools
14
13
  * @returns 暴露了 chat, chatStream方法
@@ -24,12 +23,12 @@ export declare class AgentModelProvider {
24
23
  mcpTools: Array<Record<string, any>>;
25
24
  /** 需要实时过滤掉的tools name*/
26
25
  ignoreToolnames: string[];
27
- /** 在 chat 之前,自动更新 所有的tools */
28
- autoUpdateTools: boolean;
29
26
  /** chat 时,自动更新 所有的tools 后的事件 */
30
27
  onUpdatedTools: (() => void) | undefined;
31
28
  /** 内部报错时,抛出错误事件 */
32
29
  onError: ((msg: string, err?: any) => void) | undefined;
30
+ /** 缓存 ai-sdk response 中的 多轮会话 */
31
+ messages: any[];
33
32
  constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption);
34
33
  /** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 Null */
35
34
  private _createOneClient;
@@ -45,15 +44,14 @@ export declare class AgentModelProvider {
45
44
  /** 通过引用,删除一个 mcpServers mcpClients mcpTools ignoreToolnames */
46
45
  removeMcpServer(mcpServer: McpServerConfig): void;
47
46
  /** 创建临时允许调用的tools集合 */
48
- tempMergeTools(extraTool?: {}): Record<string, any>;
49
- _chat(chatMethod: ChatMethodFn, { model, maxSteps, ...options }: Parameters<typeof generateText>[0] & {
50
- maxSteps?: number;
51
- }): Promise<any>;
47
+ private _tempMergeTools;
48
+ private _chat;
52
49
  chat(options: Parameters<typeof generateText>[0] & {
53
50
  maxSteps?: number;
51
+ message?: string;
54
52
  }): Promise<any>;
55
53
  chatStream(options: Parameters<typeof streamText>[0] & {
56
54
  maxSteps?: number;
55
+ message?: string;
57
56
  }): Promise<any>;
58
57
  }
59
- export {};
@@ -42,8 +42,8 @@ export class AgentModelProvider {
42
42
  this.mcpTools = [];
43
43
  /** 需要实时过滤掉的tools name*/
44
44
  this.ignoreToolnames = [];
45
- /** chat 之前,自动更新 所有的tools */
46
- this.autoUpdateTools = true;
45
+ /** 缓存 ai-sdk response 中的 多轮会话 */
46
+ this.messages = [];
47
47
  // 1、保存 mcpServer
48
48
  this.mcpServers = mcpServers || [];
49
49
  // 2、保存 llm
@@ -83,7 +83,7 @@ export class AgentModelProvider {
83
83
  }
84
84
  catch (error) {
85
85
  if (this.onError) {
86
- this.onError(`Failed to create MCP client`, error);
86
+ this.onError((error === null || error === void 0 ? void 0 : error.message) || `Failed to create MCP client`, error);
87
87
  }
88
88
  console.error(`Failed to create MCP client`, serverConfig, error);
89
89
  return null;
@@ -109,7 +109,7 @@ export class AgentModelProvider {
109
109
  }
110
110
  catch (error) {
111
111
  if (this.onError) {
112
- this.onError(`Failed to query tools`, error);
112
+ this.onError((error === null || error === void 0 ? void 0 : error.message) || `Failed to query tools`, error);
113
113
  }
114
114
  console.error(`Failed to query tools`, error);
115
115
  return null;
@@ -122,9 +122,14 @@ export class AgentModelProvider {
122
122
  return __awaiter(this, void 0, void 0, function* () {
123
123
  yield Promise.all(this.mcpClients.map((client) => __awaiter(this, void 0, void 0, function* () {
124
124
  try {
125
- client.close();
125
+ yield (client === null || client === void 0 ? void 0 : client.close());
126
+ }
127
+ catch (error) {
128
+ if (this.onError) {
129
+ this.onError((error === null || error === void 0 ? void 0 : error.message) || `Failed to close client`, error);
130
+ }
131
+ console.error(`Failed to close client`, error);
126
132
  }
127
- catch (error) { }
128
133
  })));
129
134
  });
130
135
  }
@@ -178,7 +183,7 @@ export class AgentModelProvider {
178
183
  }
179
184
  }
180
185
  /** 创建临时允许调用的tools集合 */
181
- tempMergeTools(extraTool = {}) {
186
+ _tempMergeTools(extraTool = {}) {
182
187
  const toolsResult = this.mcpTools.reduce((acc, curr) => (Object.assign(Object.assign({}, acc), curr)), {});
183
188
  Object.assign(toolsResult, extraTool);
184
189
  this.ignoreToolnames.forEach((name) => {
@@ -188,18 +193,25 @@ export class AgentModelProvider {
188
193
  }
189
194
  _chat(chatMethod, _a) {
190
195
  return __awaiter(this, void 0, void 0, function* () {
191
- var _b;
196
+ var _b, _c;
192
197
  var { model, maxSteps = 5 } = _a, options = __rest(_a, ["model", "maxSteps"]);
193
198
  if (!this.llm) {
194
199
  throw new Error('LLM is not initialized');
195
200
  }
196
- if (this.autoUpdateTools) {
197
- yield this._createMpcTools();
198
- (_b = this.onUpdatedTools) === null || _b === void 0 ? void 0 : _b.call(this);
199
- }
200
- return chatMethod(Object.assign(Object.assign({
201
+ yield this.initClientsAndTools();
202
+ (_b = this.onUpdatedTools) === null || _b === void 0 ? void 0 : _b.call(this);
203
+ const chatOptions = Object.assign(Object.assign({
201
204
  // @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
202
- model: this.llm(model), stopWhen: stepCountIs(maxSteps) }, options), { tools: this.tempMergeTools(options.tools) }));
205
+ model: this.llm(model), stopWhen: stepCountIs(maxSteps) }, options), { tools: this._tempMergeTools(options.tools) });
206
+ if (options.message && !options.messages) {
207
+ this.messages.push({ role: 'user', content: options.message });
208
+ chatOptions.messages = [...this.messages];
209
+ }
210
+ const result = chatMethod(chatOptions);
211
+ (_c = result === null || result === void 0 ? void 0 : result.response) === null || _c === void 0 ? void 0 : _c.then((res) => {
212
+ this.messages.push(...res.messages);
213
+ });
214
+ return result;
203
215
  });
204
216
  }
205
217
  chat(options) {
@@ -24885,6 +24885,8 @@ class QrCode {
24885
24885
  img.src = await this.toDataURL();
24886
24886
  }
24887
24887
  }
24888
+ const DEFAULT_REMOTE_URL = "https://agent.opentiny.design/tiny-robot";
24889
+ const DEFAULT_QR_CODE_URL = "https://ai.opentiny.design/next-remoter";
24888
24890
  const getDefaultMenuItems = (options) => {
24889
24891
  return [
24890
24892
  {
@@ -24933,8 +24935,8 @@ const getDefaultMenuItems = (options) => {
24933
24935
  {
24934
24936
  action: "remote-url",
24935
24937
  show: true,
24936
- text: `${options.qrCodeUrl}`,
24937
- tip: options.qrCodeUrl,
24938
+ text: `${options.remoteUrl}`,
24939
+ tip: options.remoteUrl,
24938
24940
  showCopyIcon: true,
24939
24941
  icon: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
24940
24942
  <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
@@ -24950,8 +24952,9 @@ class FloatingBlock {
24950
24952
  throw new Error("sessionId is required");
24951
24953
  }
24952
24954
  this.options = {
24953
- qrCodeUrl: options.qrCodeUrl || "https://ai.opentiny.design/next-remoter",
24954
- ...options
24955
+ ...options,
24956
+ qrCodeUrl: options.qrCodeUrl || DEFAULT_QR_CODE_URL,
24957
+ remoteUrl: options.remoteUrl || DEFAULT_REMOTE_URL
24955
24958
  };
24956
24959
  this.menuItems = this.mergeMenuItems(options.menuItems);
24957
24960
  this.init();
@@ -24995,7 +24998,7 @@ class FloatingBlock {
24995
24998
  this.floatingBlock.className = "tiny-remoter-floating-block";
24996
24999
  this.floatingBlock.innerHTML = `
24997
25000
  <div class="tiny-remoter-floating-block__icon">
24998
- <img style="display: block; width: 56px;" src="https://ai.opentiny.design/next-remoter/svgs/logo-next-no-bg-left.svg" alt="icon" />
25001
+ <img style="display: block; width: 56px;" src="${DEFAULT_QR_CODE_URL}/svgs/logo-next-no-bg-left.svg" alt="icon" />
24999
25002
  </div>
25000
25003
  `;
25001
25004
  document.body.appendChild(this.floatingBlock);
@@ -25095,7 +25098,7 @@ class FloatingBlock {
25095
25098
  this.copyToClipboard(this.options.sessionId.slice(-6));
25096
25099
  }
25097
25100
  copyRemoteURL() {
25098
- this.copyToClipboard((this.options.qrCodeUrl || "") + this.sessionPrefix + this.options.sessionId);
25101
+ this.copyToClipboard((this.options.remoteUrl || DEFAULT_REMOTE_URL) + this.sessionPrefix + this.options.sessionId);
25099
25102
  }
25100
25103
  // 实现复制到剪贴板功能
25101
25104
  async copyToClipboard(text2) {
@@ -42810,7 +42813,7 @@ class AgentModelProvider {
42810
42813
  this.mcpClients = [];
42811
42814
  this.mcpTools = [];
42812
42815
  this.ignoreToolnames = [];
42813
- this.autoUpdateTools = true;
42816
+ this.messages = [];
42814
42817
  this.mcpServers = mcpServers || [];
42815
42818
  if (llm) {
42816
42819
  this.llm = llm;
@@ -42841,7 +42844,7 @@ class AgentModelProvider {
42841
42844
  return await createMCPClient({ transport });
42842
42845
  } catch (error2) {
42843
42846
  if (this.onError) {
42844
- this.onError(`Failed to create MCP client`, error2);
42847
+ this.onError((error2 == null ? void 0 : error2.message) || `Failed to create MCP client`, error2);
42845
42848
  }
42846
42849
  console.error(`Failed to create MCP client`, serverConfig, error2);
42847
42850
  return null;
@@ -42864,7 +42867,7 @@ class AgentModelProvider {
42864
42867
  return client ? await ((_a16 = client == null ? void 0 : client.tools) == null ? void 0 : _a16.call(client)) : null;
42865
42868
  } catch (error2) {
42866
42869
  if (this.onError) {
42867
- this.onError(`Failed to query tools`, error2);
42870
+ this.onError((error2 == null ? void 0 : error2.message) || `Failed to query tools`, error2);
42868
42871
  }
42869
42872
  console.error(`Failed to query tools`, error2);
42870
42873
  return null;
@@ -42877,8 +42880,12 @@ class AgentModelProvider {
42877
42880
  await Promise.all(
42878
42881
  this.mcpClients.map(async (client) => {
42879
42882
  try {
42880
- client.close();
42883
+ await (client == null ? void 0 : client.close());
42881
42884
  } catch (error2) {
42885
+ if (this.onError) {
42886
+ this.onError((error2 == null ? void 0 : error2.message) || `Failed to close client`, error2);
42887
+ }
42888
+ console.error(`Failed to close client`, error2);
42882
42889
  }
42883
42890
  })
42884
42891
  );
@@ -42923,7 +42930,7 @@ class AgentModelProvider {
42923
42930
  }
42924
42931
  }
42925
42932
  /** 创建临时允许调用的tools集合 */
42926
- tempMergeTools(extraTool = {}) {
42933
+ _tempMergeTools(extraTool = {}) {
42927
42934
  const toolsResult = this.mcpTools.reduce((acc, curr) => ({ ...acc, ...curr }), {});
42928
42935
  Object.assign(toolsResult, extraTool);
42929
42936
  this.ignoreToolnames.forEach((name16) => {
@@ -42932,21 +42939,28 @@ class AgentModelProvider {
42932
42939
  return toolsResult;
42933
42940
  }
42934
42941
  async _chat(chatMethod, { model, maxSteps = 5, ...options }) {
42935
- var _a16;
42942
+ var _a16, _b8;
42936
42943
  if (!this.llm) {
42937
42944
  throw new Error("LLM is not initialized");
42938
42945
  }
42939
- if (this.autoUpdateTools) {
42940
- await this._createMpcTools();
42941
- (_a16 = this.onUpdatedTools) == null ? void 0 : _a16.call(this);
42942
- }
42943
- return chatMethod({
42946
+ await this.initClientsAndTools();
42947
+ (_a16 = this.onUpdatedTools) == null ? void 0 : _a16.call(this);
42948
+ const chatOptions = {
42944
42949
  // @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
42945
42950
  model: this.llm(model),
42946
42951
  stopWhen: stepCountIs(maxSteps),
42947
42952
  ...options,
42948
- tools: this.tempMergeTools(options.tools)
42953
+ tools: this._tempMergeTools(options.tools)
42954
+ };
42955
+ if (options.message && !options.messages) {
42956
+ this.messages.push({ role: "user", content: options.message });
42957
+ chatOptions.messages = [...this.messages];
42958
+ }
42959
+ const result = chatMethod(chatOptions);
42960
+ (_b8 = result == null ? void 0 : result.response) == null ? void 0 : _b8.then((res) => {
42961
+ this.messages.push(...res.messages);
42949
42962
  });
42963
+ return result;
42950
42964
  }
42951
42965
  async chat(options) {
42952
42966
  return this._chat(generateText, options);