@nickyzj2023/ai 1.6.0 → 1.6.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 +3 -0
- package/dist/cli.mjs +68 -36
- package/dist/index.mjs +1 -1
- package/dist/{src-CKKPKPMG.mjs → src-BzQy5h8z.mjs} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as runAgent, n as get_weather_default, r as get_time_default } from "./src-
|
|
1
|
+
import { i as runAgent, n as get_weather_default, r as get_time_default } from "./src-BzQy5h8z.mjs";
|
|
2
2
|
import { t as defineModel } from "./helper-juLVGxlQ.mjs";
|
|
3
3
|
import { n as loadMCPTools } from "./mcp-DcntQg-a.mjs";
|
|
4
4
|
import { compactStr, extractErrorMessage, isObject } from "@nickyzj2023/utils";
|
|
@@ -308,6 +308,8 @@ var TUI = class {
|
|
|
308
308
|
md = null;
|
|
309
309
|
/** 是否允许输入 */
|
|
310
310
|
isBusy = false;
|
|
311
|
+
/** 是否正停在提示符上等输入(决定printNotice要不要重绘提示符) */
|
|
312
|
+
isPrompting = false;
|
|
311
313
|
/** 上次打印内容所属的状态(reasoning/content/tool)
|
|
312
314
|
* 用于在新的状态开始时改变样式、打印前缀
|
|
313
315
|
*/
|
|
@@ -319,19 +321,28 @@ var TUI = class {
|
|
|
319
321
|
constructor(onPrompt) {
|
|
320
322
|
this.onPrompt = onPrompt;
|
|
321
323
|
}
|
|
322
|
-
/**
|
|
323
|
-
|
|
324
|
+
/**
|
|
325
|
+
* 启动TUI
|
|
326
|
+
* @param initialPrompt 传入时先替用户发出这一轮(ai “提示词”的快捷方式),之后照常等输入
|
|
327
|
+
*/
|
|
328
|
+
start(initialPrompt) {
|
|
324
329
|
this.rl = readline.createInterface({
|
|
325
330
|
input: process.stdin,
|
|
326
331
|
output: process.stdout
|
|
327
332
|
});
|
|
328
333
|
process.stdin.on("keypress", this.onKeypress);
|
|
329
|
-
this.prompting();
|
|
330
334
|
this.rl.on("close", () => {
|
|
331
335
|
process.stdin.off("keypress", this.onKeypress);
|
|
332
336
|
this.rl?.close();
|
|
333
337
|
this.rl = null;
|
|
334
338
|
});
|
|
339
|
+
if (initialPrompt) {
|
|
340
|
+
process.stdout.write(`> ${initialPrompt}\n`);
|
|
341
|
+
this.submit({
|
|
342
|
+
text: initialPrompt,
|
|
343
|
+
images: []
|
|
344
|
+
});
|
|
345
|
+
} else this.prompting();
|
|
335
346
|
}
|
|
336
347
|
/** 监听用户的特定按键 */
|
|
337
348
|
onKeypress = (_str, key) => {
|
|
@@ -341,7 +352,9 @@ var TUI = class {
|
|
|
341
352
|
/** 监听用户输入 */
|
|
342
353
|
prompting() {
|
|
343
354
|
if (this.isBusy) return;
|
|
355
|
+
this.isPrompting = true;
|
|
344
356
|
this.rl?.question("> ", async (answer) => {
|
|
357
|
+
this.isPrompting = false;
|
|
345
358
|
await this.clipboardTask;
|
|
346
359
|
const text = answer.trim();
|
|
347
360
|
const images = this.pendingImages;
|
|
@@ -350,15 +363,22 @@ var TUI = class {
|
|
|
350
363
|
this.prompting();
|
|
351
364
|
return;
|
|
352
365
|
}
|
|
353
|
-
this.
|
|
354
|
-
await this.onPrompt?.({
|
|
366
|
+
await this.submit({
|
|
355
367
|
text,
|
|
356
368
|
images
|
|
357
369
|
});
|
|
358
|
-
this.isBusy = false;
|
|
359
|
-
this.prompting();
|
|
360
370
|
});
|
|
361
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* 走完整的一轮:把输入交给调用方,结束后继续等用户输入
|
|
374
|
+
* @remarks 提示词来源可以是用户敲的,也可以是start()传进来的initialPrompt
|
|
375
|
+
*/
|
|
376
|
+
async submit(input) {
|
|
377
|
+
this.isBusy = true;
|
|
378
|
+
await this.onPrompt?.(input);
|
|
379
|
+
this.isBusy = false;
|
|
380
|
+
this.prompting();
|
|
381
|
+
}
|
|
362
382
|
/** 读取剪贴板图片,推入待发送列表 */
|
|
363
383
|
async attachImage() {
|
|
364
384
|
const image = await readClipboardImage();
|
|
@@ -401,6 +421,27 @@ var TUI = class {
|
|
|
401
421
|
if (!process.stdout.isTTY) return text;
|
|
402
422
|
return `\x1b[${ansiCode}m${text}\x1b[0m`;
|
|
403
423
|
}
|
|
424
|
+
/** 把一个Agent事件分发到对应的print方法上 */
|
|
425
|
+
render(event) {
|
|
426
|
+
switch (event.type) {
|
|
427
|
+
case "reasoning_delta":
|
|
428
|
+
this.printReasoning(event.delta);
|
|
429
|
+
break;
|
|
430
|
+
case "content_delta":
|
|
431
|
+
this.printContent(event.delta);
|
|
432
|
+
break;
|
|
433
|
+
case "tool_call":
|
|
434
|
+
this.printToolCall(event.name, event.args);
|
|
435
|
+
break;
|
|
436
|
+
case "tool_result":
|
|
437
|
+
this.printToolResult(event.name, event.result);
|
|
438
|
+
break;
|
|
439
|
+
case "error":
|
|
440
|
+
this.printContent(event.message);
|
|
441
|
+
break;
|
|
442
|
+
case "done": this.printFinish(event.finishReason, event.usage);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
404
445
|
/** 流式打印AI思考内容(灰色) */
|
|
405
446
|
printReasoning(delta) {
|
|
406
447
|
if (this.preparePrint("reasoning_delta")) delta = `[思考内容] ${delta.replaceAll("\n", "")}`;
|
|
@@ -432,10 +473,10 @@ var TUI = class {
|
|
|
432
473
|
this.preparePrint("done");
|
|
433
474
|
process.stdout.write(this.colorize(`[本轮结束:${finishReason}] ${usage ? `输入${humanizeNumber(usage.prompt_tokens)},输出${humanizeNumber(usage.completion_tokens)},总共${humanizeNumber(usage.total_tokens)}` : ""}${usage?.speed ? `,速度${usage.speed}/秒` : ""}${finishReason === "stop" ? "\n\n" : "\n"}`, "90"));
|
|
434
475
|
}
|
|
435
|
-
/**
|
|
476
|
+
/** 打印一行黄字提示,正停在提示符上时顺便重绘输入行 */
|
|
436
477
|
printNotice(message) {
|
|
437
478
|
process.stdout.write(`${this.colorize(message, "93")}\n`);
|
|
438
|
-
this.rl?.prompt(true);
|
|
479
|
+
if (this.isPrompting) this.rl?.prompt(true);
|
|
439
480
|
}
|
|
440
481
|
};
|
|
441
482
|
//#endregion
|
|
@@ -454,8 +495,11 @@ const buildUserContent = (text, images) => {
|
|
|
454
495
|
content.push(...images);
|
|
455
496
|
return content;
|
|
456
497
|
};
|
|
457
|
-
/**
|
|
458
|
-
|
|
498
|
+
/**
|
|
499
|
+
* 启动交互对话:配置来自全局配置文件,环境变量可临时覆盖
|
|
500
|
+
* @param prompt 带上提示词时,先自动发出这一轮,之后照常继续对话
|
|
501
|
+
*/
|
|
502
|
+
const startChat = async (prompt) => {
|
|
459
503
|
const config = loadConfig();
|
|
460
504
|
if (!config) {
|
|
461
505
|
console.error("请先运行 `ai setup` 配置一个模型");
|
|
@@ -483,38 +527,23 @@ const startChat = async () => {
|
|
|
483
527
|
get_time_default,
|
|
484
528
|
...await mcpLoading
|
|
485
529
|
];
|
|
486
|
-
for await (const e of runAgent(model, messages, tools))
|
|
487
|
-
case "reasoning_delta":
|
|
488
|
-
tui.printReasoning(e.delta);
|
|
489
|
-
break;
|
|
490
|
-
case "content_delta":
|
|
491
|
-
tui.printContent(e.delta);
|
|
492
|
-
break;
|
|
493
|
-
case "tool_call":
|
|
494
|
-
tui.printToolCall(e.name, e.args);
|
|
495
|
-
break;
|
|
496
|
-
case "tool_result":
|
|
497
|
-
tui.printToolResult(e.name, e.result);
|
|
498
|
-
break;
|
|
499
|
-
case "error":
|
|
500
|
-
tui.printContent(e.message);
|
|
501
|
-
break;
|
|
502
|
-
case "done": tui.printFinish(e.finishReason, e.usage);
|
|
503
|
-
}
|
|
530
|
+
for await (const e of runAgent(model, messages, tools)) tui.render(e);
|
|
504
531
|
});
|
|
505
|
-
tui.start();
|
|
532
|
+
tui.start(prompt);
|
|
506
533
|
};
|
|
507
534
|
/** 打印命令用法 */
|
|
508
535
|
const printHelp = () => {
|
|
509
|
-
console.log(`用法: ai [
|
|
536
|
+
console.log(`用法: ai [命令/提示词]
|
|
510
537
|
|
|
511
538
|
命令:
|
|
512
539
|
--help 显示帮助
|
|
513
540
|
setup 交互式配置模型APIKEY / BASE_URL / MODEL(保存到 ~/.@nickyzj2023/ai/config.json)
|
|
514
541
|
|
|
515
|
-
|
|
542
|
+
带上提示词时,启动对话的同时先把这段提示词发出去(如\`ai 明天适合洗车吗\`)
|
|
543
|
+
不带参数则直接进入对话`);
|
|
516
544
|
};
|
|
517
|
-
const
|
|
545
|
+
const args = process.argv.slice(2);
|
|
546
|
+
const command = args[0];
|
|
518
547
|
switch (command) {
|
|
519
548
|
case void 0:
|
|
520
549
|
startChat();
|
|
@@ -527,8 +556,11 @@ switch (command) {
|
|
|
527
556
|
printHelp();
|
|
528
557
|
break;
|
|
529
558
|
default:
|
|
530
|
-
|
|
531
|
-
|
|
559
|
+
if (command.startsWith("-")) {
|
|
560
|
+
console.error(`未知命令:${command}(可以运行ai --help查看用法)`);
|
|
561
|
+
process.exit(1);
|
|
562
|
+
}
|
|
563
|
+
startChat(args.join(" ").trim() || void 0);
|
|
532
564
|
}
|
|
533
565
|
//#endregion
|
|
534
566
|
export {};
|
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-
|
|
1
|
+
import { a as stream, i as runAgent, n as get_weather_default, r as get_time_default, t as compact } from "./src-BzQy5h8z.mjs";
|
|
2
2
|
import { i as estimateTokens, n as defineTool, r as estimateTextTokens, t as defineModel } from "./helper-juLVGxlQ.mjs";
|
|
3
3
|
export { compact, defineModel, defineTool, estimateTextTokens, estimateTokens, get_time_default as getTime, get_weather_default as getWeather, runAgent, stream };
|
|
@@ -308,7 +308,7 @@ const summarizeMessages = async (compressible, options) => {
|
|
|
308
308
|
logger("消息太少,无需总结");
|
|
309
309
|
return 0;
|
|
310
310
|
}
|
|
311
|
-
beforeSummarize?.(summarizable);
|
|
311
|
+
await beforeSummarize?.(summarizable);
|
|
312
312
|
const count = summarizable.length;
|
|
313
313
|
summarizable.push({
|
|
314
314
|
role: "system",
|