yuangs 1.3.9 → 1.3.12

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.
Files changed (4) hide show
  1. package/README.md +9 -9
  2. package/cli.js +51 -7
  3. package/index.js +50 -4
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -43,6 +43,7 @@ yuangs ai
43
43
  ```
44
44
 
45
45
  ## 应用列表
46
+
46
47
  以下是 CLI 中可以通过相应命令直接打开的应用程序链接:
47
48
 
48
49
  古诗词 PWA: https://wealth.want.biz/shici/index.html
@@ -55,18 +56,16 @@ Pong 游戏: https://wealth.want.biz/pages/pong.html
55
56
 
56
57
  ### v1.3.6 (2025-11-29)
57
58
 
58
- * **新增** AI 命令交互模式:直接输入 `yuangs ai` 即可进入一问一答模式,无需每次输入问题,quit或exit可退出。
59
- * **新增** AI 命令模型参数 `-m` 简写:支持 `-m <模型名称>` 代替 `--model <模型名称>`。
60
- * **新增** `help` 命令显示仓库地址:方便用户直接访问项目仓库。
61
- * **优化** AI 请求错误提示:在处理 AI 请求出错时,提供更清晰的错误信息。
59
+ - **新增** AI 命令交互模式:直接输入 `yuangs ai` 即可进入一问一答模式,无需每次输入问题,quit exit 可退出。
60
+ - **新增** AI 命令模型参数 `-m` 简写:支持 `-m <模型名称>` 代替 `--model <模型名称>`。
61
+ - **新增** `help` 命令显示仓库地址:方便用户直接访问项目仓库。
62
+ - **优化** AI 请求错误提示:在处理 AI 请求出错时,提供更清晰的错误信息。
62
63
 
63
64
  ### v1.1.x (之前版本,主要更新点)
64
65
 
65
- * **新增** `ai` 命令:集成 AI 问答功能 (`yuangs ai "你的问题"`)。
66
- * **新增** `help` 命令显示当前版本号:方便用户了解工具版本。
67
- * **优化** AI 请求加载动画:在请求过程中显示加载动画和已耗时秒数,并在请求结束后显示总耗时。
68
-
69
-
66
+ - **新增** `ai` 命令:集成 AI 问答功能 (`yuangs ai "你的问题"`)。
67
+ - **新增** `help` 命令显示当前版本号:方便用户了解工具版本。
68
+ - **优化** AI 请求加载动画:在请求过程中显示加载动画和已耗时秒数,并在请求结束后显示总耗时。
70
69
 
71
70
  ## 自动发布(CI/CD)
72
71
 
@@ -78,6 +77,7 @@ Pong 游戏: https://wealth.want.biz/pages/pong.html
78
77
  - 自动运行 `npm publish --provenance` 发布到 npm。
79
78
 
80
79
  这样日常开发只需要专注写代码和推送到 `main`,发布和版本管理都由 CI 自动完成。
80
+ 本地开发前务必先:`git pull`,确保本地代码与远程仓库一致。
81
81
 
82
82
  ## 维护者
83
83
 
package/cli.js CHANGED
@@ -20,6 +20,9 @@ function printHelp() {
20
20
  console.log(` ${chalk.green('ai')} "<问题>" 向 AI 提问(不写问题进入交互模式)`);
21
21
  console.log(` ${chalk.gray('--model, -m <模型名称>')} 指定 AI 模型 (可选)`);
22
22
  console.log(` ${chalk.green('help')} 显示帮助信息\n`);
23
+ console.log(chalk.bold('AI 交互模式命令:'));
24
+ console.log(` ${chalk.gray('/clear')} 清空对话历史`);
25
+ console.log(` ${chalk.gray('/history')} 查看对话历史\n`);
23
26
  console.log(chalk.gray('AI 示例: yuangs ai "你好" --model gemini-pro-latest'));
24
27
  console.log(chalk.gray('普通示例: yuangs shici\n'));
25
28
  }
@@ -35,14 +38,23 @@ async function askOnce(question, model) {
35
38
  const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
36
39
  const interval = setInterval(() => {
37
40
  const elapsedTime = Math.floor((Date.now() - startTime) / 1000); // Calculate elapsed time in seconds
38
- process.stdout.write(chalk.cyan(`\r${spinner[i++ % spinner.length]} 正在请求 AI,请稍候... (${elapsedTime}s)`));
41
+ process.stdout.write(chalk.cyan(`\r${spinner[i++ % spinner.length]} 正在请求 AI,请稍候... (${elapsedTime}s}`));
39
42
  }, 100);
40
43
 
41
44
  try {
42
- const answer = await yuangs.getAIAnswer(question, model);
45
+ // For single requests (non-interactive mode), we may want to include history
46
+ // For now, use history for all requests, but we could make this configurable
47
+ const answer = await yuangs.getAIAnswer(question, model, true);
43
48
  clearInterval(interval);
44
- process.stdout.clearLine(0);
45
- process.stdout.cursorTo(0);
49
+
50
+ // Clear the spinner line if possible
51
+ if (process.stdout.clearLine) {
52
+ process.stdout.clearLine(0);
53
+ process.stdout.cursorTo(0);
54
+ } else {
55
+ process.stdout.write('\r'); // Fallback to just carriage return
56
+ }
57
+
46
58
  const totalElapsedTime = (Date.now() - startTime) / 1000; // Calculate total elapsed time
47
59
  if (answer && answer.explanation) {
48
60
  console.log(chalk.bold.green('🤖 AI 回答:\n'));
@@ -53,8 +65,15 @@ async function askOnce(question, model) {
53
65
  console.log(chalk.gray(`\n请求耗时: ${totalElapsedTime.toFixed(2)}s\n`)); // Display total elapsed time
54
66
  } catch (error) {
55
67
  clearInterval(interval);
56
- process.stdout.clearLine(0);
57
- process.stdout.cursorTo(0);
68
+
69
+ // Clear the spinner line if possible
70
+ if (process.stdout.clearLine) {
71
+ process.stdout.clearLine(0);
72
+ process.stdout.cursorTo(0);
73
+ } else {
74
+ process.stdout.write('\r'); // Fallback to just carriage return
75
+ }
76
+
58
77
  const totalElapsedTime = (Date.now() - startTime) / 1000; // Calculate total elapsed time on error
59
78
  console.error(chalk.red('处理 AI 请求时出错:'), error.message || error);
60
79
  console.log(chalk.gray(`\n请求耗时: ${totalElapsedTime.toFixed(2)}s\n`)); // Display total elapsed time on error
@@ -84,6 +103,9 @@ async function handleAICommand() {
84
103
  if (!question) {
85
104
  console.log(chalk.bold.cyan('\n🤖 进入 AI 交互模式 (输入 exit 退出)\n'));
86
105
  console.log(chalk.gray('直接输入你的问题,每回车一次提一个问题。\n'));
106
+ console.log(chalk.gray('支持的命令:'));
107
+ console.log(chalk.gray(' /clear - 清空对话历史'));
108
+ console.log(chalk.gray(' /history - 查看对话历史\n'));
87
109
 
88
110
  const readline = require('readline');
89
111
  const rl = readline.createInterface({
@@ -103,10 +125,32 @@ async function handleAICommand() {
103
125
  process.exit(0);
104
126
  }
105
127
 
128
+ // Handle special commands
129
+ if (trimmed === '/clear') {
130
+ yuangs.clearConversationHistory();
131
+ console.log(chalk.yellow('✓ 对话历史已清空\n'));
132
+ return askLoop();
133
+ }
134
+
135
+ if (trimmed === '/history') {
136
+ const history = yuangs.getConversationHistory();
137
+ if (history.length === 0) {
138
+ console.log(chalk.gray('暂无对话历史\n'));
139
+ } else {
140
+ console.log(chalk.bold('📋 对话历史:\n'));
141
+ history.forEach((msg, index) => {
142
+ const prefix = msg.role === 'user' ? chalk.green('你: ') : chalk.blue('AI: ');
143
+ console.log(prefix + msg.content);
144
+ });
145
+ console.log('');
146
+ }
147
+ return askLoop();
148
+ }
149
+
106
150
  if (!trimmed) {
107
151
  return askLoop(); // 空输入则重新询问
108
152
  }
109
-
153
+
110
154
  // 等待回答完成后,再开启下一轮询问
111
155
  await askOnce(trimmed, model);
112
156
  askLoop();
package/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  const { exec } = require('child_process');
2
2
  const axios = require('axios');
3
3
 
4
+ // Store conversation history
5
+ let conversationHistory = [];
6
+
4
7
  const APPS = {
5
8
  shici: 'https://wealth.want.biz/shici/index.html',
6
9
  dict: 'https://wealth.want.biz/pages/dict.html',
@@ -17,9 +20,39 @@ function openUrl(url) {
17
20
  exec(command);
18
21
  }
19
22
 
20
- async function getAIAnswer(question, model) {
23
+ // Function to add a message to the conversation history
24
+ function addToConversationHistory(role, content) {
25
+ conversationHistory.push({ role, content });
26
+
27
+ // Keep only the last 20 messages to prevent history from growing too large
28
+ if (conversationHistory.length > 20) {
29
+ conversationHistory = conversationHistory.slice(-20);
30
+ }
31
+ }
32
+
33
+ // Function to clear conversation history
34
+ function clearConversationHistory() {
35
+ conversationHistory = [];
36
+ }
37
+
38
+ // Function to get conversation history
39
+ function getConversationHistory() {
40
+ return conversationHistory;
41
+ }
42
+
43
+ async function getAIAnswer(question, model, includeHistory = true) {
21
44
  const url = 'https://aiproxy.want.biz/ai/explain';
22
- const prompt = question;
45
+
46
+ // Prepare the prompt with conversation history if enabled
47
+ let prompt = question;
48
+ if (includeHistory && conversationHistory.length > 0) {
49
+ // Create a context with the current question added to history
50
+ const contextWithHistory = [...conversationHistory, { role: 'user', content: question }];
51
+ prompt = contextWithHistory.map(msg => `${msg.role}: ${msg.content}`).join('\n\n');
52
+ } else {
53
+ // If not including history, just use the question directly
54
+ prompt = question;
55
+ }
23
56
 
24
57
  const headers = {
25
58
  'Referer': 'https://wealth.want.biz/',
@@ -35,7 +68,17 @@ async function getAIAnswer(question, model) {
35
68
 
36
69
  try {
37
70
  const response = await axios.post(url, data, { headers });
38
- return response.data;
71
+ const answer = response.data;
72
+
73
+ // Add the user's question to the conversation history
74
+ addToConversationHistory('user', question);
75
+
76
+ // Add the AI response to the conversation history
77
+ if (answer && answer.explanation) {
78
+ addToConversationHistory('assistant', answer.explanation);
79
+ }
80
+
81
+ return answer;
39
82
  } catch (error) {
40
83
  console.error('AI 请求失败:', error.response?.data?.message || error.message || '未知错误');
41
84
  return null;
@@ -51,5 +94,8 @@ module.exports = {
51
94
  console.log('--- YGS Apps ---');
52
95
  Object.entries(APPS).forEach(([key, url]) => console.log(`${key}: ${url}`));
53
96
  },
54
- getAIAnswer
97
+ getAIAnswer,
98
+ addToConversationHistory,
99
+ clearConversationHistory,
100
+ getConversationHistory
55
101
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yuangs",
3
- "version": "1.3.9",
3
+ "version": "1.3.12",
4
4
  "description": "苑广山的个人应用集合 CLI(彩色版)",
5
5
  "main": "index.js",
6
6
  "bin": {