xiaozhou-chat 1.0.28 → 1.0.30

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/bin/cli.js CHANGED
@@ -173,7 +173,7 @@ const commands = [
173
173
  "/system", "/scan", "/当前项目结构", "/load", "/save",
174
174
  "/mcp", "/profile", "/切换模型", "/paste", "/clear",
175
175
  "/history", "/init", "/初始化配置", "/commit", "/token",
176
- "/compress"
176
+ "/compress", "/tools"
177
177
  ];
178
178
 
179
179
  function completer(line) {
@@ -293,6 +293,12 @@ let inputMode = "chat";
293
293
  let pasteBuffer = [];
294
294
 
295
295
  rl.on("line", async (line) => {
296
+ // 防止并发输入 (解决光标跳动问题)
297
+ if (isProcessing && inputMode !== "paste") {
298
+ console.log("⚠️ AI 正在思考中,请稍候...");
299
+ return;
300
+ }
301
+
296
302
  // 粘贴模式处理
297
303
  if (inputMode === "paste") {
298
304
  if (line.trim() === "---") {
@@ -437,13 +443,16 @@ rl.on("line", async (line) => {
437
443
  const toCompress = messages.slice(0, -2);
438
444
  const recent = messages.slice(-2);
439
445
 
446
+ // 优化: 将 JSON 转换为更紧凑的文本格式以节省 Token
447
+ const conversationText = toCompress.map(m => `[${m.role.toUpperCase()}]: ${m.content}`).join("\n\n");
448
+
440
449
  const summaryPrompt = `
441
450
  请总结以下对话的主要内容,提取关键信息、代码片段和决策。
442
451
  摘要应简洁明了,以便作为后续对话的上下文。
443
452
  保留所有重要的技术细节。
444
453
 
445
454
  对话内容:
446
- ${JSON.stringify(toCompress)}
455
+ ${conversationText}
447
456
  `;
448
457
  try {
449
458
  const summary = await generateCompletion(activeConfig, [{role: "user", content: summaryPrompt}]);
@@ -513,6 +522,28 @@ ${diff.slice(0, 8000)}
513
522
  }
514
523
  return rl.prompt();
515
524
  }
525
+
526
+ if (input.startsWith("/system")) {
527
+ const prompt = input.slice(7).trim();
528
+ if (!prompt) {
529
+ console.log("当前系统提示词:", activeConfig.systemPrompt || "(未设置)");
530
+ console.log("用法: /system <prompt>");
531
+ return rl.prompt();
532
+ }
533
+ updateConfig("systemPrompt", prompt);
534
+ if (config.currentProfile) {
535
+ setProfileValue(config.currentProfile, "systemPrompt", prompt);
536
+ }
537
+ config = loadConfig();
538
+ activeConfig = getActiveConfig(config);
539
+ console.log("✅ 系统提示词已更新");
540
+ return rl.prompt();
541
+ }
542
+
543
+ if (input === "/init" || input === "/初始化配置") {
544
+ initProjectConfigFile();
545
+ return rl.prompt();
546
+ }
516
547
 
517
548
  if (input.startsWith("/profile") || input.startsWith("/切换模型")) {
518
549
  // ... (Similar logic to before, simplified)
@@ -540,6 +571,29 @@ ${diff.slice(0, 8000)}
540
571
  return rl.prompt();
541
572
  }
542
573
 
574
+ if (input === "/tools") {
575
+ console.log("\n🛠️ 可用工具列表:");
576
+ console.log("\n[Built-in]");
577
+ builtInTools.forEach(t => {
578
+ console.log(` - ${t.function.name}: ${t.function.description.slice(0, 40)}...`);
579
+ });
580
+
581
+ if (mcpClients.size > 0) {
582
+ console.log("\n[MCP Servers]");
583
+ for (const [name, client] of mcpClients) {
584
+ console.log(` Sources: ${name}`);
585
+ if (client.tools && client.tools.length > 0) {
586
+ client.tools.forEach(t => {
587
+ console.log(` - ${t.name}: ${t.description ? t.description.slice(0, 40) + "..." : "(No description)"}`);
588
+ });
589
+ } else {
590
+ console.log(" (No tools available)");
591
+ }
592
+ }
593
+ }
594
+ return rl.prompt();
595
+ }
596
+
543
597
  // Default: Chat
544
598
  isProcessing = true;
545
599
  try {
package/lib/history.js CHANGED
@@ -61,8 +61,10 @@ export function exportHistory(messages) {
61
61
  }).join("\n");
62
62
 
63
63
  const dir = canWriteProjectDir() ? projectRoot : os.homedir();
64
- const file = path.join(dir, "newapi-chat-history.md");
64
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
65
+ const file = path.join(dir, `newapi-chat-history-${timestamp}.md`);
65
66
 
66
67
  fs.writeFileSync(file, md, "utf-8");
68
+ console.log(`✅ 历史记录已导出至: ${file}`);
67
69
  return file;
68
70
  }
package/lib/tools.js CHANGED
@@ -8,7 +8,7 @@ export function scanDir(dir, ignoreList = [], prefix = "", depth = 0) {
8
8
  if (depth > 10) return ""; // Recursion limit
9
9
 
10
10
  // 默认忽略列表
11
- const defaultIgnore = ["node_modules", ".git", "dist", "coverage", ".DS_Store", ".env", ".next", "build"];
11
+ const defaultIgnore = ["node_modules", ".git", "dist", "coverage", ".DS_Store", ".env", ".next", "build", "*.log", "*.lock"];
12
12
  const ignore = [...defaultIgnore, ...ignoreList];
13
13
 
14
14
  let output = "";
@@ -23,7 +23,16 @@ export function scanDir(dir, ignoreList = [], prefix = "", depth = 0) {
23
23
  });
24
24
 
25
25
  for (const file of files) {
26
- if (ignore.includes(file.name)) continue;
26
+ // Check ignore (support simple globs)
27
+ const shouldIgnore = ignore.some(pattern => {
28
+ if (pattern === file.name) return true;
29
+ if (pattern.startsWith("*") && file.name.endsWith(pattern.slice(1))) return true;
30
+ if (pattern.endsWith("*") && file.name.startsWith(pattern.slice(0, -1))) return true;
31
+ return false;
32
+ });
33
+
34
+ if (shouldIgnore) continue;
35
+
27
36
  if (file.isDirectory()) {
28
37
  output += `${prefix}- ${file.name}/\n`;
29
38
  output += scanDir(path.join(dir, file.name), ignoreList, `${prefix} `, depth + 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xiaozhou-chat",
3
- "version": "1.0.28",
3
+ "version": "1.0.30",
4
4
  "description": "CLI chatbot based on NewAPI",
5
5
  "bin": {
6
6
  "xiaozhou-chat": "bin/cli.js"