@nickyzj2023/ai 1.4.4 → 1.6.0

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/index.d.mts CHANGED
@@ -1,206 +1,21 @@
1
- import { Client } from "@modelcontextprotocol/sdk/client";
2
- //#region src/types.d.ts
3
- type Model = {
4
- baseUrl: string;
5
- /** 如果不传,会尝试使用GET {baseUrl}/models获取到的第一个模型 */
6
- model?: string;
7
- /** 使用本地llama.cpp等服务时可以不填 */
8
- apiKey?: string;
9
- /**
10
- * 模型支持的消息输入类型
11
- * @default ["text"]
12
- * @remarks 会在每轮对话前校验消息类型,存在不支持的输入时报错
13
- */
14
- modalities?: Modality[];
15
- /**
16
- * 模型的最大上下文
17
- * @default 131072
18
- * @remarks 会在每轮对话结束后检查上下文阈值,自动压缩消息
19
- */
20
- context?: number;
21
- /**
22
- * 自定义请求体,会在每轮请求时带上
23
- * @example chat_template_kwargs: { enable_thinking: false }
24
- */
25
- [key: string]: unknown;
26
- };
27
- /** 文/图/音/视频,暂未实现文件输入 */
28
- type Modality = "text" | "image" | "audio" | "video";
29
- type Message = {
30
- role: "system" | "user" | "assistant" | "tool";
31
- reasoning?: string | null;
32
- content: string | ContentPart[];
33
- tool_calls?: ToolCall[];
34
- tool_call_id?: string;
35
- [key: string]: unknown;
36
- };
37
- type ContentPart = TextContent | ImageContent | AudioContent | VideoContent;
38
- type TextContent = {
39
- type: "text";
40
- text: string;
41
- };
42
- type ImageContent = {
43
- type: "image_url";
44
- image_url: {
45
- url: string;
46
- };
47
- };
48
- type AudioContent = {
49
- type: "input_audio";
50
- input_audio: {
51
- /** 使用公网可访问的音频链接 */
52
- url?: string;
53
- /** 使用base64 */
54
- data?: string;
55
- format: string;
56
- };
57
- };
58
- type VideoContent = {
59
- type: "video_url";
60
- video_url: {
61
- url: string;
62
- };
63
- };
64
- type ToolDefinition = {
65
- type: "function";
66
- function: {
67
- name: string;
68
- description: string;
69
- parameters: {
70
- type: "object";
71
- properties: Record<string, {
72
- type: string;
73
- description?: string;
74
- /** defineTool()提供的语法糖,等价于在parameters.required.push(当前property key) */
75
- required?: boolean;
76
- }>;
77
- required?: string[];
78
- };
79
- };
80
- /** 工具的实际执行函数 */
81
- execute: (...args: any) => any;
82
- };
83
- type ToolCall = {
84
- id: string;
85
- type: "function";
86
- function: {
87
- name: string;
88
- arguments: string;
89
- };
90
- };
91
- /** stream()对外输出的事件 */
92
- type LLMEvent = {
93
- type: "reasoning_delta";
94
- delta: string;
95
- } | {
96
- type: "content_delta";
97
- delta: string;
98
- } | {
99
- type: "tool_call";
100
- id: string;
101
- name: string;
102
- args: any;
103
- } | {
104
- type: "done";
105
- finishReason: FinishReason;
106
- usage?: Usage;
107
- } | {
108
- type: "error";
109
- message: string;
110
- };
111
- /** stream()内部要处理的事件流 */
112
- type ChatCompletionsChunk = {
113
- id: string;
114
- object: "chat.completion.chunk";
115
- created: number;
116
- model: string;
117
- choices: {
118
- index: number;
119
- delta: Pick<Message, "reasoning" | "content"> & {
120
- tool_calls?: ({
121
- index: number;
122
- } & Partial<ToolCall>)[];
123
- };
124
- finish_reason: FinishReason;
125
- }[];
126
- usage?: Usage;
127
- } | "[DONE]";
128
- /** 模型可能返回的finish_reason值:停止/工具调用/上下文超限 */
129
- type FinishReason = "stop" | "tool_calls" | "length" | null;
130
- type Usage = {
131
- prompt_tokens: number;
132
- completion_tokens: number;
133
- total_tokens: number;
134
- [key: string]: any;
135
- };
136
- type AgentEvent = LLMEvent | {
137
- type: "tool_result";
138
- id: string;
139
- name: string;
140
- result: string;
141
- };
142
- //#endregion
1
+ import { a as FinishReason, c as Message, d as TextContent, f as ToolCall, h as VideoContent, i as ContentPart, l as Modality, m as Usage, n as AudioContent, o as ImageContent, p as ToolDefinition, r as ChatCompletionsChunk, s as LLMEvent, t as AgentEvent, u as Model } from "./types--dXFoUow.mjs";
143
2
  //#region src/agent.d.ts
144
3
  declare function runAgent(model: Model, messages: Message[], tools: ToolDefinition[]): AsyncGenerator<AgentEvent>;
145
4
  //#endregion
5
+ //#region src/llm.d.ts
6
+ /**
7
+ * 流式请求模型,转发
8
+ */
9
+ declare function stream(model: Model, messages: Message[], tools?: ToolDefinition[], options?: Omit<RequestInit, "body"> & {
10
+ body?: Record<string, unknown>;
11
+ }): AsyncGenerator<LLMEvent>;
12
+ //#endregion
146
13
  //#region src/tools/get-time.d.ts
147
14
  declare const _default: ToolDefinition;
148
15
  //#endregion
149
16
  //#region src/tools/get-weather.d.ts
150
17
  declare const _default$1: ToolDefinition;
151
18
  //#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
204
19
  //#region src/utils/compact/types.d.ts
205
20
  declare namespace Compact {
206
21
  type Options = {
@@ -249,12 +64,21 @@ declare namespace Compact {
249
64
  */
250
65
  summarizeOptions?: Partial<Compact.SummarizeOptions>;
251
66
  };
252
- type ReplacerOfToolResultContent = (content: Message["content"], options?: Record<string, any>) => Promise<string> | string;
253
- type ReplacerOfMediaContent = (content: Message["content"], options?: Record<string, any>) => Promise<string> | string;
67
+ type ReplacerOfToolResultContent = (content: Message["content"], options?: {
68
+ model?: Model;
69
+ [key: string]: any;
70
+ }) => Promise<string> | string;
71
+ type ReplacerOfMediaContent = (content: Message["content"], options?: {
72
+ model?: Model;
73
+ modality?: Modality;
74
+ [key: string]: any;
75
+ }) => Promise<string> | string;
254
76
  type SummarizeOptions = {
255
77
  /** 指导大模型如何总结消息 */
256
78
  systemPrompt: string;
257
79
  model: Model;
80
+ /** 触发总结前的钩子 */
81
+ beforeSummarize?: (summarizable: Message[]) => void | Promise<void>;
258
82
  };
259
83
  type Result = {
260
84
  /** 是否压缩了工具调用结果 */
@@ -312,5 +136,13 @@ declare const defineModel: (config: Model) => Model;
312
136
  * @param execute 实际执行工具的函数
313
137
  */
314
138
  declare const defineTool: (name: ToolDefinition["function"]["name"], description: ToolDefinition["function"]["description"], properties: ToolDefinition["function"]["parameters"]["properties"], execute: ToolDefinition["execute"]) => ToolDefinition;
139
+ declare const estimateTextTokens: (text: string) => number;
140
+ /**
141
+ * 根据上下文里的中/英文/多模态消息,估算出可能消耗的token
142
+ * - 单词 ≈ 1.5token
143
+ * - 标点/空白等非词字符每4个 ≈ 1token
144
+ * - 图片/音频/视频/文件 ≈ 4096token(不好估算,取个较大的值)
145
+ */
146
+ declare const estimateTokens: (messages?: Message[]) => number;
315
147
  //#endregion
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 };
148
+ 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, estimateTextTokens, estimateTokens, _default as getTime, _default$1 as getWeather, runAgent, stream };
package/dist/index.mjs CHANGED
@@ -1,2 +1,3 @@
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-CuZ-6Jye.mjs";
2
- export { MCPRouter, compact, defineModel, defineTool, get_time_default as getTime, get_weather_default as getWeather, loadMCPTools, runAgent };
1
+ import { a as stream, i as runAgent, n as get_weather_default, r as get_time_default, t as compact } from "./src-CKKPKPMG.mjs";
2
+ import { i as estimateTokens, n as defineTool, r as estimateTextTokens, t as defineModel } from "./helper-juLVGxlQ.mjs";
3
+ export { compact, defineModel, defineTool, estimateTextTokens, estimateTokens, get_time_default as getTime, get_weather_default as getWeather, runAgent, stream };
@@ -0,0 +1,58 @@
1
+ import { n as defineTool } from "./helper-juLVGxlQ.mjs";
2
+ import { extractErrorMessage, isObject, logger, omit } from "@nickyzj2023/utils";
3
+ //#region src/tools/mcp.ts
4
+ /** 全局单例MCP加载器 */
5
+ let router = null;
6
+ var MCPRouter = class {
7
+ entries = /* @__PURE__ */ new Map();
8
+ /** 注册一个新的MCP客户端 */
9
+ async addClient(name, url, options) {
10
+ if (this.entries.has(name)) return;
11
+ const [{ Client }, { StreamableHTTPClientTransport }] = await Promise.all([import("@modelcontextprotocol/sdk/client"), import("@modelcontextprotocol/sdk/client/streamableHttp.js")]);
12
+ const transport = new StreamableHTTPClientTransport(new URL(url), { requestInit: { headers: options?.headers } });
13
+ const client = new Client({
14
+ name,
15
+ version: "1.0.0"
16
+ });
17
+ await client.connect(transport);
18
+ const { tools } = await client.listTools();
19
+ const normalizedTools = tools.filter((tool) => !options?.ignoredToolNames?.includes(tool.name)).map((tool) => {
20
+ const _properties = { ...tool.inputSchema.properties ?? {} };
21
+ tool.inputSchema.required?.forEach((key) => {
22
+ if (isObject(_properties[key])) _properties[key] = {
23
+ ..._properties[key],
24
+ required: true
25
+ };
26
+ });
27
+ return defineTool(tool.name, tool.description ?? "", _properties, (args) => client.callTool({
28
+ name: tool.name,
29
+ arguments: args
30
+ }));
31
+ });
32
+ this.entries.set(name, {
33
+ client,
34
+ tools: normalizedTools
35
+ });
36
+ return client;
37
+ }
38
+ /** 返回OpenAI API兼容的tools数组 */
39
+ async getTools() {
40
+ return [...this.entries.values()].flatMap((e) => e.tools);
41
+ }
42
+ };
43
+ /**
44
+ * 把传入的MCPServer列表转换成OpenAI API兼容的tools数组
45
+ */
46
+ const loadMCPTools = async (mcpServers = {}) => {
47
+ router ||= new MCPRouter();
48
+ await Promise.allSettled(Object.entries(mcpServers).map(async ([name, server]) => {
49
+ try {
50
+ await router?.addClient(name, server.url, omit(server, ["type", "url"]));
51
+ } catch (e) {
52
+ logger(`MCP服务器${name}加载失败:${extractErrorMessage(e)}`);
53
+ }
54
+ }));
55
+ return router.getTools();
56
+ };
57
+ //#endregion
58
+ export { loadMCPTools as n, MCPRouter as t };