@nickyzj2023/ai 1.6.1 → 1.6.3
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 +31 -15
- package/dist/{helper-juLVGxlQ.mjs → helper-DJw58Gmz.mjs} +13 -1
- package/dist/index.d.mts +9 -1
- package/dist/index.mjs +3 -3
- package/dist/{mcp-DcntQg-a.mjs → mcp-BBjcb8es.mjs} +1 -1
- package/dist/{src-BzQy5h8z.mjs → src-Bh2ZFPb4.mjs} +54 -2
- package/dist/tools/mcp.mjs +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as runAgent, n as get_weather_default, r as get_time_default } from "./src-
|
|
2
|
-
import { t as defineModel } from "./helper-
|
|
3
|
-
import { n as loadMCPTools } from "./mcp-
|
|
4
|
-
import { compactStr, extractErrorMessage, isObject } from "@nickyzj2023/utils";
|
|
1
|
+
import { i as runAgent, n as get_weather_default, r as get_time_default } from "./src-Bh2ZFPb4.mjs";
|
|
2
|
+
import { a as listModels, t as defineModel } from "./helper-DJw58Gmz.mjs";
|
|
3
|
+
import { n as loadMCPTools } from "./mcp-BBjcb8es.mjs";
|
|
4
|
+
import { compactStr, extractErrorMessage, isObject, to } from "@nickyzj2023/utils";
|
|
5
5
|
import readline from "node:readline";
|
|
6
6
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { homedir } from "node:os";
|
|
@@ -110,12 +110,12 @@ const askMcpServer = async (current) => {
|
|
|
110
110
|
};
|
|
111
111
|
};
|
|
112
112
|
/**
|
|
113
|
-
*
|
|
113
|
+
* 把菜单输入的数字解析成对应的名称
|
|
114
114
|
* @param input 用户输入的数字串
|
|
115
|
-
* @param names
|
|
115
|
+
* @param names 当前菜单的名称列表
|
|
116
116
|
* @returns 对应名称;非整数或越界返回undefined
|
|
117
117
|
*/
|
|
118
|
-
const
|
|
118
|
+
const pickByIndex = (input, names) => {
|
|
119
119
|
const index = Number(input) - 1;
|
|
120
120
|
return Number.isInteger(index) ? names[index] : void 0;
|
|
121
121
|
};
|
|
@@ -141,7 +141,7 @@ const configMcp = async (mcpServers) => {
|
|
|
141
141
|
}
|
|
142
142
|
case "d": {
|
|
143
143
|
const target = (await ask("输入要删除的服务器编号: ")).trim();
|
|
144
|
-
const oldName =
|
|
144
|
+
const oldName = pickByIndex(target, names);
|
|
145
145
|
if (!oldName) {
|
|
146
146
|
console.log("无效编号,请输入列表中的数字");
|
|
147
147
|
break;
|
|
@@ -153,7 +153,7 @@ const configMcp = async (mcpServers) => {
|
|
|
153
153
|
break;
|
|
154
154
|
}
|
|
155
155
|
default: {
|
|
156
|
-
const oldName =
|
|
156
|
+
const oldName = pickByIndex(choice, names);
|
|
157
157
|
if (oldName) {
|
|
158
158
|
const server = mcpServers[oldName];
|
|
159
159
|
if (!server) console.log("该服务器配置缺失,将重新录入");
|
|
@@ -173,17 +173,33 @@ const configMcp = async (mcpServers) => {
|
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
175
|
/**
|
|
176
|
+
* 询问MODEL:能连上服务时先列出GET /models的模型,输入序号即可选中,同时也支持直接手输模型名
|
|
177
|
+
* @param baseUrl 刚录入的BASE_URL
|
|
178
|
+
* @param apiKey 刚录入的APIKEY
|
|
179
|
+
* @param fallback 直接回车时沿用的模型
|
|
180
|
+
*/
|
|
181
|
+
const askModel = async (baseUrl, apiKey, fallback) => {
|
|
182
|
+
const [error, models] = await to(baseUrl ? listModels(baseUrl, apiKey) : Promise.resolve([]));
|
|
183
|
+
const names = models ?? [];
|
|
184
|
+
if (error) console.log(`获取模型列表失败:${extractErrorMessage(error)}`);
|
|
185
|
+
else if (names.length === 0) console.log("服务端未返回任何模型,请手动输入模型名");
|
|
186
|
+
else {
|
|
187
|
+
console.log("可用模型(输入序号快速选择,也可直接输入模型名):");
|
|
188
|
+
names.forEach((name, i) => {
|
|
189
|
+
console.log(` ${i + 1}. ${name}`);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
const input = (await ask(`MODEL [当前为${fallback}]: `)).trim();
|
|
193
|
+
return pickByIndex(input, names) || input || fallback;
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
176
196
|
* setup入口:依次询问BASE_URL / MODEL / APIKEY,确认后写入全局配置
|
|
177
197
|
*/
|
|
178
198
|
async function runSetup() {
|
|
179
199
|
const config = loadConfig();
|
|
180
|
-
if (config) {
|
|
181
|
-
console.log(`当前配置:BASE_URL ${config.baseUrl},APIKEY ${config.apiKey},MODEL ${config.model}`);
|
|
182
|
-
console.log("直接回车可沿用当前值。\n");
|
|
183
|
-
}
|
|
184
200
|
const baseUrl = await ask(`BASE_URL [当前为${config?.baseUrl}]: `) || config?.baseUrl;
|
|
185
201
|
const apiKey = await ask(`APIKEY [当前为${config?.apiKey}]: `) || config?.apiKey;
|
|
186
|
-
const model = await
|
|
202
|
+
const model = await askModel(baseUrl, apiKey, config?.model);
|
|
187
203
|
const mcpServers = { ...config?.mcpServers };
|
|
188
204
|
if ((await ask("是否配置MCP服务器?(y/n): ")).trim().toLowerCase() === "y") await configMcp(mcpServers);
|
|
189
205
|
try {
|
|
@@ -462,7 +478,7 @@ var TUI = class {
|
|
|
462
478
|
printToolResult(name, result, options) {
|
|
463
479
|
const { ellipsis = true } = options ?? {};
|
|
464
480
|
const _result = ellipsis ? compactStr(result, {
|
|
465
|
-
maxLength:
|
|
481
|
+
maxLength: 100,
|
|
466
482
|
truncateMiddle: true
|
|
467
483
|
}) : result;
|
|
468
484
|
this.preparePrint("tool_result");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fetcher } from "@nickyzj2023/utils";
|
|
1
2
|
//#region src/utils/helper.ts
|
|
2
3
|
/**
|
|
3
4
|
* 辅助定义一个POST /chat/completions支持的model参数
|
|
@@ -44,6 +45,17 @@ const estimateTextTokens = (text) => {
|
|
|
44
45
|
return Math.ceil(words * 1.5 + others / 4);
|
|
45
46
|
};
|
|
46
47
|
/**
|
|
48
|
+
* 列出GET /models返回的模型id
|
|
49
|
+
* @param baseUrl 接口前缀,如http://127.0.0.1:11434/v1
|
|
50
|
+
* @param apiKey 本地llama.cpp等不校验鉴权的服务可以不传,不传就不带Authorization头
|
|
51
|
+
* @returns 模型的id列表
|
|
52
|
+
* @remarks 请求失败(服务没起、鉴权不过等)会抛异常,由调用方自行兜底
|
|
53
|
+
*/
|
|
54
|
+
const listModels = async (baseUrl, apiKey) => {
|
|
55
|
+
const { data } = await fetcher(baseUrl, { headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : void 0 }).get("/models");
|
|
56
|
+
return (data ?? []).map((model) => model.id).filter((id) => typeof id === "string");
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
47
59
|
* 根据上下文里的中/英文/多模态消息,估算出可能消耗的token
|
|
48
60
|
* - 单词 ≈ 1.5token
|
|
49
61
|
* - 标点/空白等非词字符每4个 ≈ 1token
|
|
@@ -62,4 +74,4 @@ const estimateTokens = (messages) => {
|
|
|
62
74
|
}, 0);
|
|
63
75
|
};
|
|
64
76
|
//#endregion
|
|
65
|
-
export { estimateTokens as i, defineTool as n, estimateTextTokens as r, defineModel as t };
|
|
77
|
+
export { listModels as a, estimateTokens as i, defineTool as n, estimateTextTokens as r, defineModel as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -137,6 +137,14 @@ declare const defineModel: (config: Model) => Model;
|
|
|
137
137
|
*/
|
|
138
138
|
declare const defineTool: (name: ToolDefinition["function"]["name"], description: ToolDefinition["function"]["description"], properties: ToolDefinition["function"]["parameters"]["properties"], execute: ToolDefinition["execute"]) => ToolDefinition;
|
|
139
139
|
declare const estimateTextTokens: (text: string) => number;
|
|
140
|
+
/**
|
|
141
|
+
* 列出GET /models返回的模型id
|
|
142
|
+
* @param baseUrl 接口前缀,如http://127.0.0.1:11434/v1
|
|
143
|
+
* @param apiKey 本地llama.cpp等不校验鉴权的服务可以不传,不传就不带Authorization头
|
|
144
|
+
* @returns 模型的id列表
|
|
145
|
+
* @remarks 请求失败(服务没起、鉴权不过等)会抛异常,由调用方自行兜底
|
|
146
|
+
*/
|
|
147
|
+
declare const listModels: (baseUrl: string, apiKey?: string) => Promise<string[]>;
|
|
140
148
|
/**
|
|
141
149
|
* 根据上下文里的中/英文/多模态消息,估算出可能消耗的token
|
|
142
150
|
* - 单词 ≈ 1.5token
|
|
@@ -145,4 +153,4 @@ declare const estimateTextTokens: (text: string) => number;
|
|
|
145
153
|
*/
|
|
146
154
|
declare const estimateTokens: (messages?: Message[]) => number;
|
|
147
155
|
//#endregion
|
|
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 };
|
|
156
|
+
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, listModels, runAgent, stream };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as stream, i as runAgent, n as get_weather_default, r as get_time_default, t as compact } from "./src-
|
|
2
|
-
import { i as estimateTokens, n as defineTool, r as estimateTextTokens, t as defineModel } from "./helper-
|
|
3
|
-
export { compact, defineModel, defineTool, estimateTextTokens, estimateTokens, get_time_default as getTime, get_weather_default as getWeather, runAgent, stream };
|
|
1
|
+
import { a as stream, i as runAgent, n as get_weather_default, r as get_time_default, t as compact } from "./src-Bh2ZFPb4.mjs";
|
|
2
|
+
import { a as listModels, i as estimateTokens, n as defineTool, r as estimateTextTokens, t as defineModel } from "./helper-DJw58Gmz.mjs";
|
|
3
|
+
export { compact, defineModel, defineTool, estimateTextTokens, estimateTokens, get_time_default as getTime, get_weather_default as getWeather, listModels, runAgent, stream };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as estimateTokens, n as defineTool, r as estimateTextTokens } from "./helper-
|
|
1
|
+
import { i as estimateTokens, n as defineTool, r as estimateTextTokens } from "./helper-DJw58Gmz.mjs";
|
|
2
2
|
import { createXMLText, extractErrorMessage, fetcher, logger, parseSSE, pick, to } from "@nickyzj2023/utils";
|
|
3
3
|
//#region src/llm.ts
|
|
4
4
|
/**
|
|
@@ -190,12 +190,64 @@ var get_time_default = defineTool("get_time", "查询指定时区的当前时间
|
|
|
190
190
|
});
|
|
191
191
|
//#endregion
|
|
192
192
|
//#region src/tools/get-weather.ts
|
|
193
|
+
/**
|
|
194
|
+
* 把wttr.in的时间转成好读的"HH:mm"
|
|
195
|
+
* @param rawTime - wttr.in hourly里的time字段,3小时粒度不带冒号,比如"0"、"300"、"1200"
|
|
196
|
+
* @returns 补零后的时间字符串,比如"00:00"、"03:00"、"12:00"
|
|
197
|
+
* @example toHHmm("930") // "09:30"
|
|
198
|
+
*/
|
|
199
|
+
const toHHmm = (rawTime) => {
|
|
200
|
+
const padded = String(rawTime ?? "").padStart(4, "0");
|
|
201
|
+
return `${padded.slice(0, 2)}:${padded.slice(2)}`;
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* 精简wttr.in返回的天气数据
|
|
205
|
+
* @param rawData - wttr.in API返回的原始JSON
|
|
206
|
+
* @returns 精简后的天气数据
|
|
207
|
+
*/
|
|
208
|
+
const pickValuableFields = (rawData) => {
|
|
209
|
+
if (!rawData) return null;
|
|
210
|
+
const area = rawData.nearest_area?.[0] || {};
|
|
211
|
+
return {
|
|
212
|
+
location: {
|
|
213
|
+
city: area.areaName?.[0]?.value || "",
|
|
214
|
+
region: area.region?.[0]?.value || "",
|
|
215
|
+
country: area.country?.[0]?.value || "",
|
|
216
|
+
latitude: area.latitude,
|
|
217
|
+
longitude: area.longitude
|
|
218
|
+
},
|
|
219
|
+
forecast: (rawData.weather || []).map((day) => ({
|
|
220
|
+
date: day.date,
|
|
221
|
+
maxTempC: day.maxtempC,
|
|
222
|
+
minTempC: day.mintempC,
|
|
223
|
+
astro: {
|
|
224
|
+
sunrise: day.astronomy?.[0]?.sunrise || "",
|
|
225
|
+
sunset: day.astronomy?.[0]?.sunset || "",
|
|
226
|
+
moonPhase: day.astronomy?.[0]?.moon_phase || ""
|
|
227
|
+
},
|
|
228
|
+
hourly: (day.hourly || []).map((h) => ({
|
|
229
|
+
time: toHHmm(h.time),
|
|
230
|
+
tempC: h.tempC,
|
|
231
|
+
feelsLikeC: h.FeelsLikeC,
|
|
232
|
+
weatherDesc: h.weatherDesc?.[0]?.value || "",
|
|
233
|
+
chanceOfRain: h.chanceofrain,
|
|
234
|
+
precipMM: h.precipMM,
|
|
235
|
+
humidity: h.humidity,
|
|
236
|
+
windSpeedKmph: h.windspeedKmph,
|
|
237
|
+
windDir: h.winddir16Point
|
|
238
|
+
}))
|
|
239
|
+
}))
|
|
240
|
+
};
|
|
241
|
+
};
|
|
193
242
|
var get_weather_default = defineTool("get_weather", "查询指定城市的天气情况", { city: {
|
|
194
243
|
type: "string",
|
|
195
244
|
description: "城市名,如shanghai、tokyo",
|
|
196
245
|
required: true
|
|
197
246
|
} }, async ({ city }) => {
|
|
198
|
-
|
|
247
|
+
const api = fetcher("https://wttr.in", { params: { format: "j1" } });
|
|
248
|
+
const [error, response] = await to(api.get(`/${city}`));
|
|
249
|
+
if (error) return error.message;
|
|
250
|
+
return pickValuableFields(response);
|
|
199
251
|
});
|
|
200
252
|
//#endregion
|
|
201
253
|
//#region src/utils/compact/helper.ts
|
package/dist/tools/mcp.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as loadMCPTools, t as MCPRouter } from "../mcp-
|
|
1
|
+
import { n as loadMCPTools, t as MCPRouter } from "../mcp-BBjcb8es.mjs";
|
|
2
2
|
export { MCPRouter, loadMCPTools };
|