viho 0.0.6 → 0.0.8

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,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="./logo.png" alt="viho logo" width="200"/>
2
+ <img src="https://static-small.vincentqiao.com/viho/logo.png" alt="viho logo" width="200"/>
3
3
  </p>
4
4
 
5
5
  <h1 align="center">viho</h1>
@@ -74,14 +74,39 @@ You'll be prompted to enter:
74
74
  viho model add
75
75
  ```
76
76
 
77
+ After adding a model, it will be available for use with `viho ask` and `viho chat` commands.
78
+
77
79
  #### `viho model list`
78
80
 
79
- List all configured models:
81
+ List all configured models with detailed information.
80
82
 
81
83
  ```bash
82
84
  viho model list
83
85
  ```
84
86
 
87
+ This command displays:
88
+
89
+ - Model name with a `(default)` tag for the default model
90
+ - Model ID
91
+ - Base URL
92
+ - Thinking mode setting
93
+
94
+ **Example output:**
95
+
96
+ ```
97
+ Configured models:
98
+
99
+ • deepseek (default)
100
+ Model ID: ep-20250822181529-2gg27
101
+ Base URL: https://ark.cn-beijing.volces.com/api/v3
102
+ Thinking: auto
103
+
104
+ • kimi
105
+ Model ID: kimi-k2-thinking
106
+ Base URL: https://api.moonshot.cn/v1
107
+ Thinking: enabled
108
+ ```
109
+
85
110
  #### `viho model remove`
86
111
 
87
112
  Remove a model configuration:
@@ -90,14 +115,18 @@ Remove a model configuration:
90
115
  viho model remove
91
116
  ```
92
117
 
118
+ You'll be prompted to enter the model name to remove. If the removed model was set as default, you'll need to set a new default model.
119
+
93
120
  #### `viho model default`
94
121
 
95
- Set a default model for chat sessions:
122
+ Set a default model for chat and ask sessions:
96
123
 
97
124
  ```bash
98
125
  viho model default
99
126
  ```
100
127
 
128
+ The default model will be used when you run `viho ask` or `viho chat` without specifying a model name.
129
+
101
130
  ### Ask
102
131
 
103
132
  #### `viho ask [modelName]`
@@ -156,13 +185,15 @@ Configuration is stored in `~/viho.json`. You can manage all settings through th
156
185
 
157
186
  ```json
158
187
  {
159
- "mymodel": {
160
- "modelName": "mymodel",
161
- "apiKey": "your-api-key",
162
- "baseURL": "https://api.openai.com/v1",
163
- "modelID": "gpt-4",
164
- "modelThinking": "auto"
165
- },
188
+ "models": [
189
+ {
190
+ "modelName": "mymodel",
191
+ "apiKey": "your-api-key",
192
+ "baseURL": "https://api.openai.com/v1",
193
+ "modelID": "gpt-4",
194
+ "modelThinking": "auto"
195
+ }
196
+ ],
166
197
  "default": "mymodel"
167
198
  }
168
199
  ```
package/bin/viho-ask.js CHANGED
@@ -6,7 +6,7 @@ const LLM = require('qiao-llm');
6
6
 
7
7
  // util
8
8
  const { ask } = require('../src/llm.js');
9
- const { getModels } = require('../src/model.js');
9
+ const { getModelByName } = require('../src/model.js');
10
10
  const { getDB, printLogo } = require('../src/util.js');
11
11
  const db = getDB();
12
12
 
@@ -15,25 +15,11 @@ cli.cmd
15
15
  .command('ask [modelName]')
16
16
  .description('Ask a question to an AI model')
17
17
  .action(async (modelName) => {
18
- if (!modelName) {
19
- const defaultModel = await db.config('default');
20
- if (!defaultModel) {
21
- console.log(cli.colors.red('No default model set. Use: viho model default'));
22
- return;
23
- }
18
+ // model
19
+ const model = await getModelByName(db, modelName);
20
+ if (!model) return;
24
21
 
25
- modelName = defaultModel;
26
- }
27
-
28
- // check
29
- const models = await getModels(db);
30
- const model = models.find((m) => m.modelName === modelName);
31
- if (!model) {
32
- console.log(cli.colors.red(`Model not found: ${modelName}`));
33
- return;
34
- }
35
-
36
- // init
22
+ // llm
37
23
  const llm = LLM({
38
24
  apiKey: model.apiKey,
39
25
  baseURL: model.baseURL,
package/bin/viho-chat.js CHANGED
@@ -6,7 +6,7 @@ const LLM = require('qiao-llm');
6
6
 
7
7
  // util
8
8
  const { ask } = require('../src/llm.js');
9
- const { getModels } = require('../src/model.js');
9
+ const { getModelByName } = require('../src/model.js');
10
10
  const { getDB, printLogo } = require('../src/util.js');
11
11
  const db = getDB();
12
12
 
@@ -15,23 +15,9 @@ cli.cmd
15
15
  .command('chat [modelName]')
16
16
  .description('Start a continuous chat session with an AI model')
17
17
  .action(async (modelName) => {
18
- if (!modelName) {
19
- const defaultModel = await db.config('default');
20
- if (!defaultModel) {
21
- console.log(cli.colors.red('No default model set. Use: viho model default'));
22
- return;
23
- }
24
-
25
- modelName = defaultModel;
26
- }
27
-
28
- // check
29
- const models = await getModels(db);
30
- const model = models.find((m) => m.modelName === modelName);
31
- if (!model) {
32
- console.log(cli.colors.red(`Model not found: ${modelName}`));
33
- return;
34
- }
18
+ // model
19
+ const model = await getModelByName(db, modelName);
20
+ if (!model) return;
35
21
 
36
22
  // init
37
23
  const llm = LLM({
@@ -41,7 +27,7 @@ cli.cmd
41
27
 
42
28
  // logo
43
29
  printLogo();
44
- console.log(cli.colors.cyan(`Welcome to viho chat! Using model: ${modelName}`));
30
+ console.log(cli.colors.cyan(`Welcome to viho chat! Using model: ${model.modelName}`));
45
31
  console.log(cli.colors.gray('Press Ctrl+C to exit\n'));
46
32
 
47
33
  // chat
package/bin/viho-model.js CHANGED
@@ -58,7 +58,7 @@ async function modelAdd() {
58
58
  type: 'list',
59
59
  name: 'modelThinking',
60
60
  message: 'Thinking mode:',
61
- choices: ['enabled', 'disabled', 'auto'],
61
+ choices: ['enabled', 'disabled'],
62
62
  },
63
63
  ];
64
64
  const answers = await cli.ask(questions);
@@ -76,12 +76,8 @@ async function modelAdd() {
76
76
  // set
77
77
  models.push(answers);
78
78
  await setModels(db, models);
79
- console.log(cli.colors.green('Model added'));
79
+ console.log(cli.colors.green('Model added successfully!'));
80
80
  console.log();
81
-
82
- // list
83
- const allModels = await getModels(db);
84
- console.log(allModels);
85
81
  } catch (e) {
86
82
  console.log(cli.colors.red('Error: Failed to add model'));
87
83
  console.log();
@@ -99,9 +95,31 @@ async function modelList() {
99
95
 
100
96
  // list
101
97
  const models = await getModels(db);
98
+ const defaultModel = await db.config('default');
99
+
102
100
  console.log(cli.colors.cyan('Configured models:'));
103
101
  console.log();
104
- console.log(models);
102
+
103
+ if (!models || models.length === 0) {
104
+ console.log(cli.colors.gray('No models configured. Use: viho model add'));
105
+ console.log();
106
+ return;
107
+ }
108
+
109
+ models.forEach((model) => {
110
+ const isDefault = model.modelName === defaultModel;
111
+ const defaultTag = isDefault ? cli.colors.green(' (default)') : '';
112
+ console.log(cli.colors.white(` • ${model.modelName}${defaultTag}`));
113
+ console.log(cli.colors.gray(` Model ID: ${model.modelID}`));
114
+ console.log(cli.colors.gray(` Base URL: ${model.baseURL}`));
115
+ console.log(cli.colors.gray(` Thinking: ${model.modelThinking}`));
116
+ console.log();
117
+ });
118
+
119
+ if (!defaultModel) {
120
+ console.log(cli.colors.yellow('No default model set. Use: viho model default'));
121
+ console.log();
122
+ }
105
123
  } catch (e) {
106
124
  console.log(cli.colors.red('Error: Failed to list models'));
107
125
  console.log();
@@ -149,12 +167,8 @@ async function modelRemove() {
149
167
  console.log();
150
168
  }
151
169
 
152
- console.log(cli.colors.green('Model removed'));
170
+ console.log(cli.colors.green('Model removed successfully!'));
153
171
  console.log();
154
-
155
- // list
156
- const allModels = await getModels(db);
157
- console.log(allModels);
158
172
  } catch (e) {
159
173
  console.log(cli.colors.red('Error: Failed to remove model'));
160
174
  console.log();
@@ -195,13 +209,16 @@ async function modelDefault() {
195
209
  if (!keys.includes(answers.modelName)) {
196
210
  console.log(cli.colors.red('Model not found. Available models:'));
197
211
  console.log();
198
- console.log(models);
212
+ models.forEach((model) => {
213
+ console.log(cli.colors.gray(` • ${model.modelName}`));
214
+ });
215
+ console.log();
199
216
  return;
200
217
  }
201
218
 
202
219
  // set
203
220
  await db.config('default', answers.modelName);
204
- console.log(cli.colors.green(`Default model: ${answers.modelName}`));
221
+ console.log(cli.colors.green(`Default model set to: ${answers.modelName}`));
205
222
  console.log();
206
223
  } catch (e) {
207
224
  console.log(cli.colors.red('Error: Failed to set default model'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viho",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "A lightweight CLI tool for managing and interacting with AI models",
5
5
  "keywords": [
6
6
  "ai",
@@ -31,9 +31,9 @@
31
31
  },
32
32
  "files": [
33
33
  "bin",
34
+ "src",
34
35
  "LICENSE",
35
- "README.md",
36
- "logo.png"
36
+ "README.md"
37
37
  ],
38
38
  "engines": {
39
39
  "node": ">=18.0.0"
@@ -43,5 +43,5 @@
43
43
  "qiao-config": "^5.0.1",
44
44
  "qiao-llm": "^0.2.5"
45
45
  },
46
- "gitHead": "2a10a0acfc92501a023e93f7f268e6f8ad57f9fc"
46
+ "gitHead": "6e3c00750d92bc6da1e84096ca4afe2f7f51624e"
47
47
  }
package/src/llm.js ADDED
@@ -0,0 +1,69 @@
1
+ // qiao
2
+ const cli = require('qiao-cli');
3
+
4
+ /**
5
+ * ask
6
+ * @param {*} llm
7
+ * @param {*} model
8
+ */
9
+ exports.ask = async (llm, model) => {
10
+ // ask
11
+ const questions = [
12
+ {
13
+ type: 'editor',
14
+ name: 'content',
15
+ message: 'Your question:',
16
+ },
17
+ ];
18
+ const answers = await cli.ask(questions);
19
+
20
+ // answers
21
+ console.log();
22
+ console.log(cli.colors.gray('Question:'));
23
+ console.log(cli.colors.gray(answers.content));
24
+ console.log();
25
+
26
+ // chat
27
+ const chatOptions = {
28
+ model: model.modelID,
29
+ messages: [
30
+ { role: 'system', content: 'You are a helpful AI assistant' },
31
+ { role: 'user', content: answers.content },
32
+ ],
33
+ thinking: {
34
+ type: model.modelThinking,
35
+ },
36
+ };
37
+
38
+ // callback options
39
+ const callbackOptions = {
40
+ firstThinkingCallback: () => {
41
+ console.log();
42
+ console.log(cli.colors.gray('[Thinking...]'));
43
+ console.log();
44
+ },
45
+ thinkingCallback: (msg) => {
46
+ process.stdout.write(cli.colors.gray(msg));
47
+ },
48
+ firstContentCallback: () => {
49
+ console.log();
50
+ console.log(cli.colors.cyan('[Response]'));
51
+ console.log();
52
+ },
53
+ contentCallback: (msg) => {
54
+ process.stdout.write(msg);
55
+ },
56
+ endCallback: () => {
57
+ console.log();
58
+ console.log();
59
+ },
60
+ errorCallback: (error) => {
61
+ console.log();
62
+ console.log(cli.colors.red('Error:'));
63
+ console.log(error);
64
+ },
65
+ };
66
+
67
+ // go
68
+ await llm.chatWithStreaming(chatOptions, callbackOptions);
69
+ };
package/src/model.js ADDED
@@ -0,0 +1,51 @@
1
+ // qiao
2
+ const cli = require('qiao-cli');
3
+
4
+ // models
5
+ const modelsKey = 'models';
6
+
7
+ /**
8
+ * getModels
9
+ * @param {*} db
10
+ * @returns
11
+ */
12
+ exports.getModels = async (db) => {
13
+ return (await db.config(modelsKey)) || [];
14
+ };
15
+
16
+ /**
17
+ * setModels
18
+ * @param {*} db
19
+ * @returns
20
+ */
21
+ exports.setModels = async (db, models) => {
22
+ await db.config(modelsKey, models);
23
+ };
24
+
25
+ /**
26
+ * getModelByName
27
+ * @param {*} db
28
+ * @returns
29
+ */
30
+ exports.getModelByName = async (db, modelName) => {
31
+ if (!modelName) {
32
+ const defaultModel = await db.config('default');
33
+ if (!defaultModel) {
34
+ console.log(cli.colors.red('No default model set. Use: viho model default'));
35
+ return;
36
+ }
37
+
38
+ modelName = defaultModel;
39
+ }
40
+
41
+ // check
42
+ const models = await exports.getModels(db);
43
+ const model = models.find((m) => m.modelName === modelName);
44
+ if (!model) {
45
+ console.log(cli.colors.red(`Model not found: ${modelName}`));
46
+ return;
47
+ }
48
+
49
+ // r
50
+ return model;
51
+ };
package/src/util.js ADDED
@@ -0,0 +1,36 @@
1
+ // os
2
+ const os = require('os');
3
+
4
+ // path
5
+ const path = require('path');
6
+
7
+ // qiao
8
+ const cli = require('qiao-cli');
9
+
10
+ // db
11
+ const DB = require('qiao-config');
12
+
13
+ /**
14
+ * getDB
15
+ * @returns
16
+ */
17
+ exports.getDB = () => {
18
+ const dbPath = path.resolve(os.homedir(), './viho.json');
19
+ return DB(dbPath);
20
+ };
21
+
22
+ /**
23
+ * printLogo
24
+ */
25
+ exports.printLogo = () => {
26
+ console.log(
27
+ cli.colors.green(`
28
+ ██╗ ██╗██╗██╗ ██╗ ██████╗
29
+ ██║ ██║██║██║ ██║██╔═══██╗
30
+ ██║ ██║██║███████║██║ ██║
31
+ ╚██╗ ██╔╝██║██╔══██║██║ ██║
32
+ ╚████╔╝ ██║██║ ██║╚██████╔╝
33
+ ╚═══╝ ╚═╝╚═╝ ╚═╝ ╚═════╝
34
+ `),
35
+ );
36
+ };
package/logo.png DELETED
Binary file