yuangs 1.3.10 → 1.3.13

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 (3) hide show
  1. package/cli.js +78 -16
  2. package/index.js +50 -4
  3. package/package.json +1 -1
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
@@ -64,18 +83,36 @@ async function askOnce(question, model) {
64
83
  async function handleAICommand() {
65
84
  const commandArgs = args.slice(1);
66
85
 
67
- // 支持 --model 和 -m 两种写法
68
- const longIndex = commandArgs.indexOf('--model');
69
- const shortIndex = commandArgs.indexOf('-m');
70
- const modelIndex = longIndex !== -1 ? longIndex : shortIndex;
71
-
72
86
  let model = null; // Default model will be handled in index.js
73
87
  let questionParts = commandArgs;
74
88
 
75
- if (modelIndex !== -1 && commandArgs.length > modelIndex + 1) {
76
- model = commandArgs[modelIndex + 1];
77
- // Filter out --model/-m and its value
78
- questionParts = commandArgs.filter((_, index) => index !== modelIndex && index !== modelIndex + 1);
89
+ // Check for shorthand model flags first
90
+ const proIndex = commandArgs.indexOf('-p');
91
+ const flashIndex = commandArgs.indexOf('-f');
92
+ const liteIndex = commandArgs.indexOf('-l');
93
+
94
+ if (proIndex !== -1) {
95
+ model = 'gemini-pro';
96
+ questionParts = commandArgs.filter((_, index) => index !== proIndex);
97
+ } else if (flashIndex !== -1) {
98
+ model = 'gemini-flash-latest';
99
+ questionParts = commandArgs.filter((_, index) => index !== flashIndex);
100
+ } else if (liteIndex !== -1) {
101
+ model = 'gemini-flash-lite-latest';
102
+ questionParts = commandArgs.filter((_, index) => index !== liteIndex);
103
+ }
104
+
105
+ // If shorthand flags are not used, check for --model or -m
106
+ if (!model) {
107
+ const longIndex = questionParts.indexOf('--model');
108
+ const shortIndex = questionParts.indexOf('-m');
109
+ const modelIndex = longIndex !== -1 ? longIndex : shortIndex;
110
+
111
+ if (modelIndex !== -1 && questionParts.length > modelIndex + 1) {
112
+ model = questionParts[modelIndex + 1];
113
+ // Filter out --model/-m and its value
114
+ questionParts = questionParts.filter((_, index) => index !== modelIndex && index !== modelIndex + 1);
115
+ }
79
116
  }
80
117
 
81
118
  const question = questionParts.join(' ').trim();
@@ -84,6 +121,9 @@ async function handleAICommand() {
84
121
  if (!question) {
85
122
  console.log(chalk.bold.cyan('\n🤖 进入 AI 交互模式 (输入 exit 退出)\n'));
86
123
  console.log(chalk.gray('直接输入你的问题,每回车一次提一个问题。\n'));
124
+ console.log(chalk.gray('支持的命令:'));
125
+ console.log(chalk.gray(' /clear - 清空对话历史'));
126
+ console.log(chalk.gray(' /history - 查看对话历史\n'));
87
127
 
88
128
  const readline = require('readline');
89
129
  const rl = readline.createInterface({
@@ -103,10 +143,32 @@ async function handleAICommand() {
103
143
  process.exit(0);
104
144
  }
105
145
 
146
+ // Handle special commands
147
+ if (trimmed === '/clear') {
148
+ yuangs.clearConversationHistory();
149
+ console.log(chalk.yellow('✓ 对话历史已清空\n'));
150
+ return askLoop();
151
+ }
152
+
153
+ if (trimmed === '/history') {
154
+ const history = yuangs.getConversationHistory();
155
+ if (history.length === 0) {
156
+ console.log(chalk.gray('暂无对话历史\n'));
157
+ } else {
158
+ console.log(chalk.bold('📋 对话历史:\n'));
159
+ history.forEach((msg, index) => {
160
+ const prefix = msg.role === 'user' ? chalk.green('你: ') : chalk.blue('AI: ');
161
+ console.log(prefix + msg.content);
162
+ });
163
+ console.log('');
164
+ }
165
+ return askLoop();
166
+ }
167
+
106
168
  if (!trimmed) {
107
169
  return askLoop(); // 空输入则重新询问
108
170
  }
109
-
171
+
110
172
  // 等待回答完成后,再开启下一轮询问
111
173
  await askOnce(trimmed, model);
112
174
  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.10",
3
+ "version": "1.3.13",
4
4
  "description": "苑广山的个人应用集合 CLI(彩色版)",
5
5
  "main": "index.js",
6
6
  "bin": {