xiaor-cli 0.1.0

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/.npmignore ADDED
@@ -0,0 +1,24 @@
1
+ # 忽略隐藏文件和文件夹
2
+ .*
3
+ !.npmignore
4
+ !.gitignore
5
+
6
+ # 忽略 Git 相关文件
7
+ .git/
8
+ .gitignore
9
+
10
+ # 忽略开发相关文件
11
+ *.log
12
+ node_modules/
13
+
14
+ # 忽略测试文件(如果有的话)
15
+ test/
16
+ tests/
17
+
18
+ # 忽略构建文件(如果有的话)
19
+ dist/
20
+ build/
21
+
22
+ # 忽略其他可能的临时文件
23
+ .DS_Store
24
+ Thumbs.db
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # XiaoR CLI
2
+
3
+ 小R AI助手命令行工具 - 独立于主程序运行,提供桌面版的完整功能体验
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install -g xiaor-cli
9
+ ```
10
+
11
+ 或者直接运行:
12
+
13
+ ```bash
14
+ npx xiaor-cli chat
15
+ ```
16
+
17
+ ## 功能
18
+
19
+ - 与AI模型直接交互
20
+ - 支持多种AI模型(DeepSeek, 豆包, 腾讯元宝, Qwen3, 蚂蚁Ling2.0, Gemini-2.5, 小米MiMo-V2, GLM)
21
+ - 管理对话历史
22
+ - 导出聊天记录
23
+ - 查看系统信息
24
+
25
+ ## 用法
26
+
27
+ ### 启动交互式聊天
28
+
29
+ ```bash
30
+ xiaor-cli chat
31
+ ```
32
+
33
+ 或者
34
+
35
+ ```bash
36
+ npx xiaor-cli chat
37
+ ```
38
+
39
+ ### 切换AI模型
40
+
41
+ ```bash
42
+ xiaor-cli model xiaomi
43
+ ```
44
+
45
+ ### 列出所有支持的模型
46
+
47
+ ```bash
48
+ xiaor-cli list-models
49
+ ```
50
+
51
+ ### 查看对话历史
52
+
53
+ ```bash
54
+ xiaor-cli history
55
+ ```
56
+
57
+ ### 导出对话历史
58
+
59
+ ```bash
60
+ xiaor-cli export md --output ./exports/
61
+ ```
62
+
63
+ ## 支持的命令
64
+
65
+ - `chat` - 启动交互式聊天模式
66
+ - `model [name]` - 切换AI模型 (deepseek, doubao, yuanbao, qwen3, ling, gemini, xiaomi, glm)
67
+ - `list-models` - 列出所有支持的AI模型
68
+ - `history` - 显示对话历史
69
+ - `clear-history` - 清空对话历史
70
+ - `export [format]` - 导出对话历史 (json, txt, md)
71
+ - `version` - 显示版本号
72
+ - `help` - 显示帮助信息
73
+
74
+ ## 选项
75
+
76
+ - `--model [name]` - 指定AI模型
77
+ - `--format [format]` - 指定导出格式 (json, txt, md)
78
+ - `--output [path]` - 指定导出路径,默认为当前目录
79
+
80
+ ## 在线使用
81
+
82
+ 不需要安装,可以直接使用:
83
+
84
+ ```bash
85
+ npx xiaor-cli chat
86
+ ```
87
+
88
+ ## 特性
89
+
90
+ - 独立于主程序运行
91
+ - 提供桌面版的完整功能体验
92
+ - 支持多种AI模型
93
+ - 对话历史管理
94
+ - 数据导出功能
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "xiaor-cli",
3
+ "version": "0.1.0",
4
+ "description": "XiaoR AI助手命令行工具 - 独立的AI交互命令行界面,支持多种AI模型",
5
+ "main": "xiaor-cli.js",
6
+ "bin": {
7
+ "xiaor-cli": "./xiaor-cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node xiaor-cli.js",
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "ai",
15
+ "cli",
16
+ "assistant",
17
+ "xiaor",
18
+ "electron",
19
+ "chat",
20
+ "models"
21
+ ],
22
+ "author": "Ruanm",
23
+ "license": "MIT",
24
+ "engines": {
25
+ "node": ">=14.0.0"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/RuanMingze/XiaoR-Ai.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/RuanMingze/XiaoR-Ai/issues"
33
+ },
34
+ "homepage": "https://github.com/RuanMingze/XiaoR-Ai#readme"
35
+ }
package/xiaor-cli.js ADDED
@@ -0,0 +1,445 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * XiaoR CLI - 小R AI助手命令行工具
5
+ *
6
+ * 独立于主程序运行,提供桌面版的完整功能体验
7
+ * 功能:
8
+ * - 与AI模型直接交互
9
+ * - 支持多种AI模型
10
+ * - 管理对话历史
11
+ * - 导出聊天记录
12
+ * - 查看系统信息
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const readline = require('readline');
18
+ const { stdin: input, stdout: output } = require('process');
19
+ const https = require('https');
20
+
21
+ // CLI版本
22
+ const VERSION = '1.0.0';
23
+
24
+ // 支持的AI模型API端点
25
+ const MODEL_ENDPOINTS = {
26
+ 'deepseek': 'https://yunzhiapi.cn/API/depsek3.2.php', // DeepseekV3.2
27
+ 'doubao': 'https://yunzhiapi.cn/API/doubao.php', // 豆包
28
+ 'yuanbao': 'https://yunzhiapi.cn/API/yuanbao.php', // 腾讯元宝
29
+ 'qwen3': 'https://yunzhiapi.cn/API/qwen3.php', // Qwen3
30
+ 'ling': 'https://yunzhiapi.cn/API/ling-1t.php', // 蚂蚁Ling2.0
31
+ 'gemini': 'https://yunzhiapi.cn/API/gemini2.5/index.php', // Gemini-2.5
32
+ 'xiaomi': 'https://yunzhiapi.cn/API/xiaomi/index.php', // 小米MiMo-V2
33
+ 'glm': 'https://api.52vmy.cn/api/chat/glm' // GLM
34
+ };
35
+
36
+ // 当前选中的模型
37
+ let currentModel = 'deepseek';
38
+
39
+ // 对话历史
40
+ let conversationHistory = [];
41
+
42
+ // 显示帮助信息
43
+ function showHelp() {
44
+ console.log(`
45
+ 小R AI助手命令行工具 (XiaoR CLI)
46
+
47
+ 用法:
48
+ xiaor-cli [command]
49
+
50
+ 命令:
51
+ chat 启动交互式聊天模式
52
+ model [name] 切换AI模型 (deepseek, doubao, yuanbao, qwen3, ling, gemini, xiaomi, glm)
53
+ list-models 列出所有支持的AI模型
54
+ history 显示对话历史
55
+ clear-history 清空对话历史
56
+ export [format] 导出对话历史 (json, txt, md)
57
+ version 显示版本号
58
+ help 显示此帮助信息
59
+
60
+ 选项:
61
+ --model [name] 指定AI模型
62
+ --format [format] 指定导出格式 (json, txt, md)
63
+ --output [path] 指定导出路径,默认为当前目录
64
+
65
+ 示例:
66
+ xiaor-cli chat
67
+ xiaor-cli model xiaomi
68
+ xiaor-cli chat --model glm
69
+ xiaor-cli export md --output ./exports/
70
+ xiaor-cli history
71
+ `);
72
+ }
73
+
74
+ // 显示版本号
75
+ function showVersion() {
76
+ console.log(`XiaoR CLI v${VERSION}`);
77
+ }
78
+
79
+ // 列出所有支持的模型
80
+ function listModels() {
81
+ console.log('支持的AI模型:');
82
+ for (const [key, value] of Object.entries(MODEL_ENDPOINTS)) {
83
+ console.log(`- ${key}: ${value}`);
84
+ }
85
+ }
86
+
87
+ // 切换AI模型
88
+ function setModel(modelName) {
89
+ if (MODEL_ENDPOINTS[modelName]) {
90
+ currentModel = modelName;
91
+ console.log(`已切换到模型: ${modelName}`);
92
+ } else {
93
+ console.error(`错误: 不支持的模型 "${modelName}"`);
94
+ console.log('支持的模型:', Object.keys(MODEL_ENDPOINTS).join(', '));
95
+ }
96
+ }
97
+
98
+ // 显示对话历史
99
+ function showHistory() {
100
+ if (conversationHistory.length === 0) {
101
+ console.log('暂无对话历史');
102
+ return;
103
+ }
104
+
105
+ console.log('对话历史:');
106
+ conversationHistory.forEach((entry, index) => {
107
+ console.log(`${index + 1}. [${entry.timestamp}] ${entry.role}: ${entry.content.substring(0, 50)}${entry.content.length > 50 ? '...' : ''}`);
108
+ });
109
+ }
110
+
111
+ // 清空对话历史
112
+ function clearHistory() {
113
+ conversationHistory = [];
114
+ console.log('对话历史已清空');
115
+ }
116
+
117
+ // 导出对话历史
118
+ function exportHistory(format, outputPath) {
119
+ if (conversationHistory.length === 0) {
120
+ console.log('暂无对话历史可导出');
121
+ return;
122
+ }
123
+
124
+ const exportPath = outputPath || './';
125
+
126
+ // 确保输出目录存在
127
+ if (!fs.existsSync(exportPath)) {
128
+ fs.mkdirSync(exportPath, { recursive: true });
129
+ }
130
+
131
+ let exportData = '';
132
+ let fileName = '';
133
+
134
+ switch (format.toLowerCase()) {
135
+ case 'json':
136
+ exportData = JSON.stringify(conversationHistory, null, 2);
137
+ fileName = `xiaor-conversation-${Date.now()}.json`;
138
+ break;
139
+
140
+ case 'txt':
141
+ exportData = conversationHistory.map(entry => {
142
+ return `[${entry.timestamp}] ${entry.role}: ${entry.content}`;
143
+ }).join('\n');
144
+ fileName = `xiaor-conversation-${Date.now()}.txt`;
145
+ break;
146
+
147
+ case 'md':
148
+ exportData = '# XiaoR AI助手对话记录\n\n';
149
+ exportData += conversationHistory.map(entry => {
150
+ return `### [${entry.timestamp}] ${entry.role}
151
+
152
+ ${entry.content}
153
+
154
+ ---
155
+
156
+ `;
157
+ }).join('');
158
+ fileName = `xiaor-conversation-${Date.now()}.md`;
159
+ break;
160
+
161
+ default:
162
+ console.error(`不支持的导出格式: ${format}`);
163
+ return;
164
+ }
165
+
166
+ const filePath = path.join(exportPath, fileName);
167
+ fs.writeFileSync(filePath, exportData);
168
+
169
+ console.log(`对话历史已导出到: ${filePath}`);
170
+ }
171
+
172
+ // 发送请求到AI模型
173
+ function sendToAI(question, systemPrompt = '') {
174
+ return new Promise((resolve, reject) => {
175
+ const endpoint = MODEL_ENDPOINTS[currentModel];
176
+ if (!endpoint) {
177
+ reject(new Error(`不支持的模型: ${currentModel}`));
178
+ return;
179
+ }
180
+
181
+ // 替换系统提示词中的变量
182
+ const processedSystemPrompt = systemPrompt.replace(/\$MODEL_NAME/g, currentModel);
183
+
184
+ // GLM模型使用不同的API格式
185
+ if (currentModel === 'glm') {
186
+ const glmUrl = `${endpoint}?msg=${encodeURIComponent(question + '。提示词是:' + processedSystemPrompt)}&type=text`;
187
+
188
+ https.get(glmUrl, (res) => {
189
+ let data = '';
190
+
191
+ res.on('data', (chunk) => {
192
+ data += chunk;
193
+ });
194
+
195
+ res.on('end', () => {
196
+ try {
197
+ // 尝试解析JSON响应
198
+ const response = JSON.parse(data);
199
+ if (response.content) {
200
+ resolve(response.content);
201
+ } else if (response.result) {
202
+ resolve(response.result);
203
+ } else {
204
+ resolve(data);
205
+ }
206
+ } catch (e) {
207
+ // 如果不是JSON格式,直接返回原始数据
208
+ resolve(data);
209
+ }
210
+ });
211
+ }).on('error', (err) => {
212
+ reject(err);
213
+ });
214
+ } else {
215
+ // 构建请求URL
216
+ const url = new URL(endpoint);
217
+ url.searchParams.append('question', question);
218
+ url.searchParams.append('system', processedSystemPrompt);
219
+
220
+ https.get(url.toString(), (res) => {
221
+ let data = '';
222
+
223
+ res.on('data', (chunk) => {
224
+ data += chunk;
225
+ });
226
+
227
+ res.on('end', () => {
228
+ try {
229
+ // 尝试解析JSON响应
230
+ const response = JSON.parse(data);
231
+ if (response.content) {
232
+ resolve(response.content);
233
+ } else if (response.result) {
234
+ resolve(response.result);
235
+ } else {
236
+ resolve(data);
237
+ }
238
+ } catch (e) {
239
+ // 如果不是JSON格式,直接返回原始数据
240
+ resolve(data);
241
+ }
242
+ });
243
+ }).on('error', (err) => {
244
+ reject(err);
245
+ });
246
+ }
247
+ });
248
+ }
249
+
250
+ // 启动交互式聊天模式
251
+ async function startChat() {
252
+ console.log(`欢迎使用小R AI助手CLI! 当前模型: ${currentModel}`);
253
+ console.log('输入 "exit" 或 "quit" 退出,输入 "help" 获取帮助');
254
+
255
+ const rl = readline.createInterface({
256
+ input,
257
+ output,
258
+ prompt: '> '
259
+ });
260
+
261
+ // 显示初始提示
262
+ rl.prompt();
263
+
264
+ rl.on('line', async (input) => {
265
+ const command = input.trim();
266
+
267
+ if (command.toLowerCase() === 'exit' || command.toLowerCase() === 'quit') {
268
+ console.log('再见!');
269
+ rl.close();
270
+ return;
271
+ }
272
+
273
+ if (command.toLowerCase() === 'help') {
274
+ console.log('命令: exit/quit - 退出, history - 查看历史, clear - 清空历史, model [name] - 切换模型');
275
+ rl.prompt();
276
+ return;
277
+ }
278
+
279
+ if (command.toLowerCase() === 'history') {
280
+ showHistory();
281
+ rl.prompt();
282
+ return;
283
+ }
284
+
285
+ if (command.toLowerCase() === 'clear') {
286
+ clearHistory();
287
+ console.log('历史已清空');
288
+ rl.prompt();
289
+ return;
290
+ }
291
+
292
+ if (command.toLowerCase().startsWith('model ')) {
293
+ const modelName = command.split(' ')[1];
294
+ setModel(modelName);
295
+ rl.prompt();
296
+ return;
297
+ }
298
+
299
+ if (command === '') {
300
+ rl.prompt();
301
+ return;
302
+ }
303
+
304
+ // 添加用户输入到历史记录
305
+ conversationHistory.push({
306
+ role: 'user',
307
+ content: command,
308
+ timestamp: new Date().toISOString()
309
+ });
310
+
311
+ try {
312
+ console.log('AI: 正在思考...');
313
+
314
+ // 构建系统提示词
315
+ const systemPrompt = `你是Ruanm开发的小R-Ai助手,但是底层模型是$MODEL_NAME,专注于帮用户解决各种难题、聊天。现在正值中国农历新年,你可以向用户送上新年祝福,分享春节文化知识,或参与与春节相关的话题讨论。`;
316
+
317
+ // 发送请求到AI
318
+ const aiResponse = await sendToAI(command, systemPrompt);
319
+
320
+ console.log(`AI: ${aiResponse}`);
321
+
322
+ // 添加AI响应到历史记录
323
+ conversationHistory.push({
324
+ role: 'assistant',
325
+ content: aiResponse,
326
+ timestamp: new Date().toISOString()
327
+ });
328
+ } catch (error) {
329
+ console.error(`错误: ${error.message}`);
330
+ }
331
+
332
+ // 显示下一个提示
333
+ rl.prompt();
334
+ }).on('close', () => {
335
+ console.log('再见!');
336
+ process.exit(0);
337
+ });
338
+ }
339
+
340
+ // 解析命令行参数
341
+ function parseArgs(args) {
342
+ const parsed = {
343
+ command: null,
344
+ options: {}
345
+ };
346
+
347
+ for (let i = 0; i < args.length; i++) {
348
+ const arg = args[i];
349
+
350
+ if (arg.startsWith('--')) {
351
+ const optionName = arg.substring(2);
352
+ if (args[i + 1] && !args[i + 1].startsWith('--')) {
353
+ parsed.options[optionName] = args[i + 1];
354
+ i++; // 跳过下一个参数(因为它已被用作当前选项的值)
355
+ } else {
356
+ parsed.options[optionName] = true;
357
+ }
358
+ } else if (!parsed.command) {
359
+ parsed.command = arg;
360
+ }
361
+ }
362
+
363
+ return parsed;
364
+ }
365
+
366
+ // 主函数
367
+ async function main() {
368
+ const args = process.argv.slice(2);
369
+ const parsed = parseArgs(args);
370
+
371
+ // 检查是否有--help参数
372
+ if (parsed.options.help || parsed.command === 'help' || parsed.command === '--help' || parsed.command === '-h') {
373
+ showHelp();
374
+ return;
375
+ }
376
+
377
+ // 如果没有提供命令,默认执行chat命令
378
+ if (!parsed.command) {
379
+ parsed.command = 'chat';
380
+ }
381
+
382
+ switch (parsed.command) {
383
+ case 'chat':
384
+ if (parsed.options.model) {
385
+ setModel(parsed.options.model);
386
+ }
387
+ await startChat();
388
+ break;
389
+
390
+ case 'model':
391
+ if (args[1]) {
392
+ setModel(args[1]);
393
+ } else {
394
+ console.log(`当前模型: ${currentModel}`);
395
+ }
396
+ break;
397
+
398
+ case 'list-models':
399
+ listModels();
400
+ break;
401
+
402
+ case 'history':
403
+ showHistory();
404
+ break;
405
+
406
+ case 'clear-history':
407
+ clearHistory();
408
+ break;
409
+
410
+ case 'export':
411
+ const format = parsed.options.format || 'json';
412
+ const outputPath = parsed.options.output || './';
413
+ exportHistory(format, outputPath);
414
+ break;
415
+
416
+ case 'version':
417
+ case '--version':
418
+ case '-v':
419
+ showVersion();
420
+ break;
421
+
422
+ case 'help':
423
+ case '--help':
424
+ case '-h':
425
+ default:
426
+ showHelp();
427
+ break;
428
+ }
429
+ }
430
+
431
+ // 如果直接运行此文件,则执行主函数
432
+ if (require.main === module) {
433
+ main().catch(console.error);
434
+ }
435
+
436
+ module.exports = {
437
+ showHelp,
438
+ showVersion,
439
+ startChat,
440
+ setModel,
441
+ listModels,
442
+ showHistory,
443
+ clearHistory,
444
+ exportHistory
445
+ };