@nickyzj2023/ai 1.3.2 → 1.4.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 CHANGED
@@ -1,6 +1,10 @@
1
1
  # ai
2
2
 
3
- 男生自用MyPi Coding Agent
3
+ 男生自用Coding Agent,参考了[nanopi教学](https://pi-from-scratch.vercel.app/)
4
+
5
+ 不断学习+开发中,当前项目仍属于比nano还简陋的“bare-pi”,but one day...
6
+
7
+ ![demo](demo.gif)
4
8
 
5
9
  ## 安装
6
10
 
package/dist/cli.mjs CHANGED
@@ -1,9 +1,10 @@
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";
1
+ import { a as get_time_default, c as runAgent, i as get_weather_default, o as defineModel, r as loadMCPTools } from "./src-izgP3Lfk.mjs";
2
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 { MarkdownRenderer } from "@wterm/markdown";
7
8
  //#region src/utils/config.ts
8
9
  /**
9
10
  * 获取全局配置文件路径(Windows/macOS/Linux通用)
@@ -82,6 +83,8 @@ async function runSetup() {
82
83
  var TUI = class {
83
84
  rl = null;
84
85
  onPrompt = null;
86
+ /** content专用的markdown渲染器 */
87
+ md = null;
85
88
  /** 是否允许输入 */
86
89
  isBusy = false;
87
90
  /** 上次打印内容所属的状态(reasoning/content/tool)
@@ -123,12 +126,17 @@ var TUI = class {
123
126
  });
124
127
  }
125
128
  /**
126
- * 所有print方法调用前的统一入口(相当于“父类逻辑”):
127
- * 状态切换时打印换行,并记录当前状态。
129
+ * 所有print方法调用前:
130
+ * 状态切换时打印换行,并记录当前状态
128
131
  * @returns 是否发生了状态切换
129
132
  */
130
133
  preparePrint(type) {
131
134
  if (this.prevPrintType === type) return false;
135
+ if (type === "content_delta" && this.md === null) this.md = new MarkdownRenderer();
136
+ if (this.prevPrintType === "content_delta") {
137
+ const remaining = this.md?.flush();
138
+ if (remaining) process.stdout.write(remaining);
139
+ }
132
140
  process.stdout.write("\n");
133
141
  this.prevPrintType = type;
134
142
  return true;
@@ -150,7 +158,8 @@ var TUI = class {
150
158
  /** 流式打印AI回复内容 */
151
159
  printContent(delta) {
152
160
  this.preparePrint("content_delta");
153
- process.stdout.write(delta);
161
+ const rendered = this.md?.push(delta);
162
+ if (rendered) process.stdout.write(rendered);
154
163
  }
155
164
  /** 打印工具调用 */
156
165
  printToolCall(name, args) {
@@ -179,6 +188,12 @@ var TUI = class {
179
188
  this.preparePrint("done");
180
189
  process.stdout.write(this.colorize(`[本轮结束:${finishReason}] ${usage ? `输入${this.format(usage.prompt_tokens)}token,输出${this.format(usage.completion_tokens)}token,总共${this.format(usage.total_tokens)}token` : ""}${finishReason === "stop" ? "\n\n" : "\n"}`, "90"));
181
190
  }
191
+ /**
192
+ * 打印一行黄色状态提示(如“等待MCP工具加载完成…”)
193
+ */
194
+ printStatus(message) {
195
+ process.stdout.write(this.colorize(message, "93"));
196
+ }
182
197
  };
183
198
  //#endregion
184
199
  //#region src/cli.ts
@@ -190,18 +205,24 @@ const startChat = async () => {
190
205
  process.exit(1);
191
206
  }
192
207
  const model = defineModel(config);
208
+ let mcpReady = false;
209
+ const mcpLoading = loadMCPTools(config.mcpServers).then((tools) => {
210
+ mcpReady = true;
211
+ return tools;
212
+ });
193
213
  const messages = [];
194
- const mcpTools = await loadMCPTools(config.mcpServers);
195
- const tools = [
196
- get_weather_default,
197
- get_time_default,
198
- ...mcpTools
199
- ];
214
+ let tools = null;
200
215
  const tui = new TUI(async (input) => {
201
216
  messages.push({
202
217
  role: "user",
203
218
  content: input
204
219
  });
220
+ if (!mcpReady) tui.printStatus("等待MCP工具加载完成…");
221
+ tools ??= [
222
+ get_weather_default,
223
+ get_time_default,
224
+ ...await mcpLoading
225
+ ];
205
226
  for await (const e of runAgent(model, messages, tools)) switch (e.type) {
206
227
  case "reasoning_delta":
207
228
  tui.printReasoning(e.delta);
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
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";
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-izgP3Lfk.mjs";
2
2
  export { MCPRouter, compact, defineModel, defineTool, get_time_default as getTime, get_weather_default as getWeather, loadMCPTools, runAgent };
@@ -278,9 +278,8 @@ const loadMCPTools = async (mcpServers) => {
278
278
  await Promise.allSettled(Object.entries(mcpServers).map(async ([name, server]) => {
279
279
  try {
280
280
  await router?.addClient(name, server.url, omit(server, ["type", "url"]));
281
- logger(`已激活MCP客户端:${name}`);
282
281
  } catch (e) {
283
- logger(`MCP服务器${name}连接失败,跳过:${extractErrorMessage(e)}`);
282
+ logger(`MCP服务器${name}加载失败:${extractErrorMessage(e)}`);
284
283
  }
285
284
  }));
286
285
  return router.getTools();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nickyzj2023/ai",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "description": "我的“pi”,参考了pi-from-scratch",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -33,7 +33,8 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@modelcontextprotocol/sdk": "^1.30.0",
36
- "@nickyzj2023/utils": "link:../utils"
36
+ "@nickyzj2023/utils": "link:../utils",
37
+ "@wterm/markdown": "^0.5.0"
37
38
  },
38
39
  "scripts": {
39
40
  "build": "tsdown",