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 +41 -10
- package/bin/viho-ask.js +5 -19
- package/bin/viho-chat.js +5 -19
- package/bin/viho-model.js +31 -14
- package/package.json +4 -4
- package/src/llm.js +69 -0
- package/src/model.js +51 -0
- package/src/util.js +36 -0
- package/logo.png +0 -0
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="
|
|
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
|
-
"
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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 {
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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'
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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": "
|
|
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
|