@nickyzj2023/ai 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,11 +1,9 @@
1
- import { a as defineTool, i as defineModel, n as get_weather_default, o as runAgent, r as get_time_default } from "./src-Dm0rwYe2.mjs";
2
- import { extractErrorMessage, isObject, omit } from "@nickyzj2023/utils";
1
+ import { a as get_time_default, c as runAgent, i as get_weather_default, o as defineModel, r as loadMCPTools } from "./src-DEDOOez9.mjs";
2
+ import { compactStr, extractErrorMessage } from "@nickyzj2023/utils";
3
3
  import readline from "node:readline";
4
4
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { dirname, join } from "node:path";
7
- import { Client } from "@modelcontextprotocol/sdk/client";
8
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
9
7
  //#region src/utils/config.ts
10
8
  /**
11
9
  * 获取全局配置文件路径(Windows/macOS/Linux通用)
@@ -138,7 +136,7 @@ var TUI = class {
138
136
  /**
139
137
  * 为文本添加ANSI颜色;非TTY输出(重定向/管道)时返回原文本,避免日志出现转义码。
140
138
  * @param text 原始文本
141
- * @param ansiCode ANSI颜色代码,如 "90"(亮黑,大多数终端显示为灰色)
139
+ * @param ansiCode ANSI颜色代码,如"90"(亮黑,大多数终端显示为灰色)
142
140
  */
143
141
  colorize(text, ansiCode) {
144
142
  if (!process.stdout.isTTY) return text;
@@ -157,12 +155,17 @@ var TUI = class {
157
155
  /** 打印工具调用 */
158
156
  printToolCall(name, args) {
159
157
  this.preparePrint("tool_call");
160
- process.stdout.write(`[工具调用:${name}] ${args}`);
158
+ process.stdout.write(`[工具调用:${name}] ${args}\n`);
161
159
  }
162
160
  /** 打印工具结果 */
163
- printToolResult(name, result) {
161
+ printToolResult(name, result, options) {
162
+ const { ellipsis = true } = options ?? {};
163
+ const _result = ellipsis ? compactStr(result, {
164
+ maxLength: 200,
165
+ truncateMiddle: true
166
+ }) : result;
164
167
  this.preparePrint("tool_result");
165
- process.stdout.write(this.colorize(`[工具结果:${name}] ${result}`, "90"));
168
+ process.stdout.write(this.colorize(`[工具结果:${name}] ${_result}\n`, "90"));
166
169
  }
167
170
  formatter = new Intl.NumberFormat("en-US", {
168
171
  notation: "compact",
@@ -178,61 +181,6 @@ var TUI = class {
178
181
  }
179
182
  };
180
183
  //#endregion
181
- //#region src/tools/mcp.ts
182
- /** 全局单例MCP加载器 */
183
- let router = null;
184
- var MCPRouter = class {
185
- entries = /* @__PURE__ */ new Map();
186
- /** 注册一个新的MCP客户端 */
187
- async addClient(name, url, options) {
188
- if (this.entries.has(name)) return;
189
- const transport = new StreamableHTTPClientTransport(new URL(url), { requestInit: { headers: options?.headers } });
190
- const client = new Client({
191
- name,
192
- version: "1.0.0"
193
- });
194
- await client.connect(transport);
195
- const { tools } = await client.listTools();
196
- const normalizedTools = tools.filter((tool) => !options?.ignoredToolNames?.includes(tool.name)).map((tool) => {
197
- const _properties = { ...tool.inputSchema.properties ?? {} };
198
- tool.inputSchema.required?.forEach((key) => {
199
- if (isObject(_properties[key])) _properties[key] = {
200
- ..._properties[key],
201
- required: true
202
- };
203
- });
204
- return defineTool(tool.name, tool.description ?? "", _properties, (args) => client.callTool({
205
- name: tool.name,
206
- arguments: args
207
- }));
208
- });
209
- this.entries.set(name, {
210
- client,
211
- tools: normalizedTools
212
- });
213
- return client;
214
- }
215
- /** 返回OpenAI API兼容的tools数组 */
216
- async getTools() {
217
- return [...this.entries.values()].flatMap((e) => e.tools);
218
- }
219
- };
220
- /**
221
- * 把传入的MCPServer列表转换成OpenAI API兼容的tools数组
222
- */
223
- const loadMCPTools = async (mcpServers) => {
224
- router ||= new MCPRouter();
225
- await Promise.allSettled(Object.entries(mcpServers).map(async ([name, server]) => {
226
- try {
227
- await router?.addClient(name, server.url, omit(server, ["type", "url"]));
228
- console.log(`已加载MCP工具:${name}`);
229
- } catch (e) {
230
- console.error(`MCP服务器${name}连接失败,跳过:${extractErrorMessage(e)}`);
231
- }
232
- }));
233
- return router.getTools();
234
- };
235
- //#endregion
236
184
  //#region src/cli.ts
237
185
  /** 启动交互对话:配置来自全局配置文件,环境变量可临时覆盖 */
238
186
  const startChat = async () => {
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client";
1
2
  //#region src/types.d.ts
2
3
  type Model = {
3
4
  baseUrl: string;
@@ -148,6 +149,58 @@ declare const _default: ToolDefinition;
148
149
  //#region src/tools/get-weather.d.ts
149
150
  declare const _default$1: ToolDefinition;
150
151
  //#endregion
152
+ //#region src/tools/mcp.d.ts
153
+ type McpServer = {
154
+ type: "streamable_http" | "sse";
155
+ url: string;
156
+ headers?: Record<string, any>;
157
+ ignoredToolNames?: string[];
158
+ };
159
+ declare class MCPRouter {
160
+ private entries;
161
+ /** 注册一个新的MCP客户端 */
162
+ addClient(name: string, url: string, options?: Omit<McpServer, "type" | "url">): Promise<Client<{
163
+ method: string;
164
+ params?: {
165
+ [x: string]: unknown;
166
+ _meta?: {
167
+ [x: string]: unknown;
168
+ progressToken?: string | number | undefined;
169
+ "io.modelcontextprotocol/related-task"?: {
170
+ taskId: string;
171
+ } | undefined;
172
+ } | undefined;
173
+ } | undefined;
174
+ }, {
175
+ method: string;
176
+ params?: {
177
+ [x: string]: unknown;
178
+ _meta?: {
179
+ [x: string]: unknown;
180
+ progressToken?: string | number | undefined;
181
+ "io.modelcontextprotocol/related-task"?: {
182
+ taskId: string;
183
+ } | undefined;
184
+ } | undefined;
185
+ } | undefined;
186
+ }, {
187
+ [x: string]: unknown;
188
+ _meta?: {
189
+ [x: string]: unknown;
190
+ progressToken?: string | number | undefined;
191
+ "io.modelcontextprotocol/related-task"?: {
192
+ taskId: string;
193
+ } | undefined;
194
+ } | undefined;
195
+ }> | undefined>;
196
+ /** 返回OpenAI API兼容的tools数组 */
197
+ getTools(): Promise<ToolDefinition[]>;
198
+ }
199
+ /**
200
+ * 把传入的MCPServer列表转换成OpenAI API兼容的tools数组
201
+ */
202
+ declare const loadMCPTools: (mcpServers: Record<string, McpServer>) => Promise<ToolDefinition[]>;
203
+ //#endregion
151
204
  //#region src/utils/compact/types.d.ts
152
205
  declare namespace Compact {
153
206
  type Options = {
@@ -260,4 +313,4 @@ declare const defineModel: (config: Model) => Model;
260
313
  */
261
314
  declare const defineTool: (name: ToolDefinition["function"]["name"], description: ToolDefinition["function"]["description"], properties: ToolDefinition["function"]["parameters"]["properties"], execute: ToolDefinition["execute"]) => ToolDefinition;
262
315
  //#endregion
263
- export { type AgentEvent, type AudioContent, type ChatCompletionsChunk, type ContentPart, type FinishReason, type ImageContent, type LLMEvent, type Message, type Modality, type Model, type TextContent, type ToolCall, type ToolDefinition, type Usage, type VideoContent, compact, defineModel, defineTool, _default as getTime, _default$1 as getWeather, runAgent };
316
+ export { type AgentEvent, type AudioContent, type ChatCompletionsChunk, type ContentPart, type FinishReason, type ImageContent, type LLMEvent, MCPRouter, McpServer, type Message, type Modality, type Model, type TextContent, type ToolCall, type ToolDefinition, type Usage, type VideoContent, compact, defineModel, defineTool, _default as getTime, _default$1 as getWeather, loadMCPTools, runAgent };
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as defineTool, i as defineModel, n as get_weather_default, o as runAgent, r as get_time_default, t as compact } from "./src-Dm0rwYe2.mjs";
2
- export { compact, defineModel, defineTool, get_time_default as getTime, get_weather_default as getWeather, runAgent };
1
+ import { a as get_time_default, c as runAgent, i as get_weather_default, n as MCPRouter, o as defineModel, r as loadMCPTools, s as defineTool, t as compact } from "./src-DEDOOez9.mjs";
2
+ export { MCPRouter, compact, defineModel, defineTool, get_time_default as getTime, get_weather_default as getWeather, loadMCPTools, runAgent };
@@ -1,4 +1,6 @@
1
- import { createXMLText, fetcher, logger, parseSSE, pick, to } from "@nickyzj2023/utils";
1
+ import { createXMLText, extractErrorMessage, fetcher, isObject, logger, omit, parseSSE, pick, to } from "@nickyzj2023/utils";
2
+ import { Client } from "@modelcontextprotocol/sdk/client";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
2
4
  //#region src/llm.ts
3
5
  /**
4
6
  * 分离ToolDefinition中的valid/invalid字段,前者可以传给模型,后者用于本地运算
@@ -229,6 +231,61 @@ var get_weather_default = defineTool("get_weather", "查询指定城市的天气
229
231
  return fetcher("https://wttr.in", { params: { format: "j1" } }).get(`/${city}`);
230
232
  });
231
233
  //#endregion
234
+ //#region src/tools/mcp.ts
235
+ /** 全局单例MCP加载器 */
236
+ let router = null;
237
+ var MCPRouter = class {
238
+ entries = /* @__PURE__ */ new Map();
239
+ /** 注册一个新的MCP客户端 */
240
+ async addClient(name, url, options) {
241
+ if (this.entries.has(name)) return;
242
+ const transport = new StreamableHTTPClientTransport(new URL(url), { requestInit: { headers: options?.headers } });
243
+ const client = new Client({
244
+ name,
245
+ version: "1.0.0"
246
+ });
247
+ await client.connect(transport);
248
+ const { tools } = await client.listTools();
249
+ const normalizedTools = tools.filter((tool) => !options?.ignoredToolNames?.includes(tool.name)).map((tool) => {
250
+ const _properties = { ...tool.inputSchema.properties ?? {} };
251
+ tool.inputSchema.required?.forEach((key) => {
252
+ if (isObject(_properties[key])) _properties[key] = {
253
+ ..._properties[key],
254
+ required: true
255
+ };
256
+ });
257
+ return defineTool(tool.name, tool.description ?? "", _properties, (args) => client.callTool({
258
+ name: tool.name,
259
+ arguments: args
260
+ }));
261
+ });
262
+ this.entries.set(name, {
263
+ client,
264
+ tools: normalizedTools
265
+ });
266
+ return client;
267
+ }
268
+ /** 返回OpenAI API兼容的tools数组 */
269
+ async getTools() {
270
+ return [...this.entries.values()].flatMap((e) => e.tools);
271
+ }
272
+ };
273
+ /**
274
+ * 把传入的MCPServer列表转换成OpenAI API兼容的tools数组
275
+ */
276
+ const loadMCPTools = async (mcpServers) => {
277
+ router ||= new MCPRouter();
278
+ await Promise.allSettled(Object.entries(mcpServers).map(async ([name, server]) => {
279
+ try {
280
+ await router?.addClient(name, server.url, omit(server, ["type", "url"]));
281
+ logger(`已激活MCP客户端:${name}`);
282
+ } catch (e) {
283
+ logger(`MCP服务器${name}连接失败,跳过:${extractErrorMessage(e)}`);
284
+ }
285
+ }));
286
+ return router.getTools();
287
+ };
288
+ //#endregion
232
289
  //#region src/utils/compact/helper.ts
233
290
  /**
234
291
  * 校验assistant(tool_calls)消息
@@ -428,4 +485,4 @@ const compact = Object.assign(async (messages, model, options) => {
428
485
  discardMessagesUntil
429
486
  });
430
487
  //#endregion
431
- export { defineTool as a, defineModel as i, get_weather_default as n, runAgent as o, get_time_default as r, compact as t };
488
+ export { get_time_default as a, runAgent as c, get_weather_default as i, MCPRouter as n, defineModel as o, loadMCPTools as r, defineTool as s, compact as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nickyzj2023/ai",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "我的“pi”,参考了pi-from-scratch",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",