viho 0.0.4 → 0.0.6
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 +47 -15
- package/bin/viho-ask.js +47 -0
- package/bin/viho-chat.js +15 -60
- package/bin/viho-model.js +43 -17
- package/bin/viho.js +1 -0
- package/logo.png +0 -0
- package/package.json +7 -4
- package/bin/util.js +0 -17
package/README.md
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./logo.png" alt="viho logo" width="200"/>
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">viho</h1>
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
<p align="center">A lightweight CLI tool for managing and interacting with AI models.</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/viho"><img src="https://img.shields.io/npm/v/viho.svg" alt="npm version"></a>
|
|
11
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
12
|
+
</p>
|
|
7
13
|
|
|
8
14
|
## Features
|
|
9
15
|
|
|
10
16
|
- Multiple AI model management
|
|
11
|
-
- Interactive
|
|
17
|
+
- Interactive Q&A with streaming responses
|
|
18
|
+
- Continuous chat sessions for multi-turn conversations
|
|
12
19
|
- Support for thinking mode (enabled/disabled/auto)
|
|
13
20
|
- Configurable API endpoints (OpenAI, Anthropic, custom providers)
|
|
14
21
|
- Default model configuration
|
|
@@ -41,10 +48,10 @@ viho model add
|
|
|
41
48
|
viho model default
|
|
42
49
|
```
|
|
43
50
|
|
|
44
|
-
3. Start
|
|
51
|
+
3. Start asking questions:
|
|
45
52
|
|
|
46
53
|
```bash
|
|
47
|
-
viho
|
|
54
|
+
viho ask
|
|
48
55
|
```
|
|
49
56
|
|
|
50
57
|
## Commands
|
|
@@ -91,31 +98,56 @@ Set a default model for chat sessions:
|
|
|
91
98
|
viho model default
|
|
92
99
|
```
|
|
93
100
|
|
|
94
|
-
###
|
|
101
|
+
### Ask
|
|
95
102
|
|
|
96
|
-
#### `viho
|
|
103
|
+
#### `viho ask [modelName]`
|
|
97
104
|
|
|
98
|
-
|
|
105
|
+
Ask a question to an AI model.
|
|
99
106
|
|
|
100
107
|
If no model name is provided, uses the default model:
|
|
101
108
|
|
|
102
109
|
```bash
|
|
103
|
-
viho
|
|
110
|
+
viho ask
|
|
104
111
|
```
|
|
105
112
|
|
|
106
113
|
Or specify a model explicitly:
|
|
107
114
|
|
|
108
115
|
```bash
|
|
109
|
-
viho
|
|
116
|
+
viho ask mymodel
|
|
110
117
|
```
|
|
111
118
|
|
|
112
|
-
The
|
|
119
|
+
The interface includes:
|
|
113
120
|
|
|
114
121
|
- Editor-based question input
|
|
115
122
|
- Streaming responses
|
|
116
123
|
- Visual thinking process (when enabled)
|
|
117
124
|
- Colored output for better readability
|
|
118
125
|
|
|
126
|
+
### Chat
|
|
127
|
+
|
|
128
|
+
#### `viho chat [modelName]`
|
|
129
|
+
|
|
130
|
+
Start a continuous chat session with an AI model for multi-turn conversations.
|
|
131
|
+
|
|
132
|
+
If no model name is provided, uses the default model:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
viho chat
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Or specify a model explicitly:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
viho chat mymodel
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The chat session runs in a loop, allowing you to ask multiple questions continuously without restarting the command. Each question uses the same model configuration but starts a fresh conversation context.
|
|
145
|
+
|
|
146
|
+
**Note:** The main difference between `viho ask` and `viho chat`:
|
|
147
|
+
|
|
148
|
+
- `viho ask` - Single question, exits after receiving the answer
|
|
149
|
+
- `viho chat` - Continuous loop, keeps asking for new questions until manually stopped (Ctrl+C)
|
|
150
|
+
|
|
119
151
|
## Configuration
|
|
120
152
|
|
|
121
153
|
Configuration is stored in `~/viho.json`. You can manage all settings through the CLI commands.
|
|
@@ -176,8 +208,8 @@ viho model add
|
|
|
176
208
|
# Set it as default
|
|
177
209
|
viho model default
|
|
178
210
|
|
|
179
|
-
# Start
|
|
180
|
-
viho
|
|
211
|
+
# Start asking questions
|
|
212
|
+
viho ask
|
|
181
213
|
```
|
|
182
214
|
|
|
183
215
|
## Dependencies
|
package/bin/viho-ask.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// qiao
|
|
2
|
+
const cli = require('qiao-cli');
|
|
3
|
+
|
|
4
|
+
// llm
|
|
5
|
+
const LLM = require('qiao-llm');
|
|
6
|
+
|
|
7
|
+
// util
|
|
8
|
+
const { ask } = require('../src/llm.js');
|
|
9
|
+
const { getModels } = require('../src/model.js');
|
|
10
|
+
const { getDB, printLogo } = require('../src/util.js');
|
|
11
|
+
const db = getDB();
|
|
12
|
+
|
|
13
|
+
// cmd
|
|
14
|
+
cli.cmd
|
|
15
|
+
.command('ask [modelName]')
|
|
16
|
+
.description('Ask a question to an AI model')
|
|
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
|
+
}
|
|
35
|
+
|
|
36
|
+
// init
|
|
37
|
+
const llm = LLM({
|
|
38
|
+
apiKey: model.apiKey,
|
|
39
|
+
baseURL: model.baseURL,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// logo
|
|
43
|
+
printLogo();
|
|
44
|
+
|
|
45
|
+
// ask
|
|
46
|
+
await ask(llm, model);
|
|
47
|
+
});
|
package/bin/viho-chat.js
CHANGED
|
@@ -4,14 +4,16 @@ const cli = require('qiao-cli');
|
|
|
4
4
|
// llm
|
|
5
5
|
const LLM = require('qiao-llm');
|
|
6
6
|
|
|
7
|
-
//
|
|
8
|
-
const {
|
|
7
|
+
// util
|
|
8
|
+
const { ask } = require('../src/llm.js');
|
|
9
|
+
const { getModels } = require('../src/model.js');
|
|
10
|
+
const { getDB, printLogo } = require('../src/util.js');
|
|
9
11
|
const db = getDB();
|
|
10
12
|
|
|
11
13
|
// cmd
|
|
12
14
|
cli.cmd
|
|
13
15
|
.command('chat [modelName]')
|
|
14
|
-
.description('
|
|
16
|
+
.description('Start a continuous chat session with an AI model')
|
|
15
17
|
.action(async (modelName) => {
|
|
16
18
|
if (!modelName) {
|
|
17
19
|
const defaultModel = await db.config('default');
|
|
@@ -24,7 +26,8 @@ cli.cmd
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
// check
|
|
27
|
-
const
|
|
29
|
+
const models = await getModels(db);
|
|
30
|
+
const model = models.find((m) => m.modelName === modelName);
|
|
28
31
|
if (!model) {
|
|
29
32
|
console.log(cli.colors.red(`Model not found: ${modelName}`));
|
|
30
33
|
return;
|
|
@@ -36,62 +39,14 @@ cli.cmd
|
|
|
36
39
|
baseURL: model.baseURL,
|
|
37
40
|
});
|
|
38
41
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
name: 'content',
|
|
44
|
-
message: 'Your question:',
|
|
45
|
-
},
|
|
46
|
-
];
|
|
47
|
-
const answers = await cli.ask(questions);
|
|
48
|
-
|
|
49
|
-
// answers
|
|
50
|
-
console.log();
|
|
51
|
-
console.log(cli.colors.gray('Question:'));
|
|
52
|
-
console.log(cli.colors.gray(answers.content));
|
|
53
|
-
console.log();
|
|
42
|
+
// logo
|
|
43
|
+
printLogo();
|
|
44
|
+
console.log(cli.colors.cyan(`Welcome to viho chat! Using model: ${modelName}`));
|
|
45
|
+
console.log(cli.colors.gray('Press Ctrl+C to exit\n'));
|
|
54
46
|
|
|
55
47
|
// chat
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
{ role: 'user', content: answers.content },
|
|
61
|
-
],
|
|
62
|
-
thinking: {
|
|
63
|
-
type: model.modelThinking,
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// callback options
|
|
68
|
-
const callbackOptions = {
|
|
69
|
-
firstThinkingCallback: () => {
|
|
70
|
-
console.log();
|
|
71
|
-
console.log(cli.colors.gray('[Thinking...]'));
|
|
72
|
-
console.log();
|
|
73
|
-
},
|
|
74
|
-
thinkingCallback: (msg) => {
|
|
75
|
-
process.stdout.write(cli.colors.gray(msg));
|
|
76
|
-
},
|
|
77
|
-
firstContentCallback: () => {
|
|
78
|
-
console.log();
|
|
79
|
-
console.log(cli.colors.cyan('[Response]'));
|
|
80
|
-
console.log();
|
|
81
|
-
},
|
|
82
|
-
contentCallback: (msg) => {
|
|
83
|
-
process.stdout.write(msg);
|
|
84
|
-
},
|
|
85
|
-
endCallback: () => {
|
|
86
|
-
console.log();
|
|
87
|
-
},
|
|
88
|
-
errorCallback: (error) => {
|
|
89
|
-
console.log();
|
|
90
|
-
console.log(cli.colors.red('Error:'));
|
|
91
|
-
console.log(error);
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// go
|
|
96
|
-
await llm.chatWithStreaming(chatOptions, callbackOptions);
|
|
48
|
+
let keepChatting = true;
|
|
49
|
+
while (keepChatting) {
|
|
50
|
+
await ask(llm, model);
|
|
51
|
+
}
|
|
97
52
|
});
|
package/bin/viho-model.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// qiao
|
|
2
2
|
const cli = require('qiao-cli');
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
const {
|
|
4
|
+
// util
|
|
5
|
+
const { getModels, setModels } = require('../src/model.js');
|
|
6
|
+
const { getDB, printLogo } = require('../src/util.js');
|
|
6
7
|
const db = getDB();
|
|
7
8
|
|
|
8
9
|
// actions
|
|
@@ -64,21 +65,23 @@ async function modelAdd() {
|
|
|
64
65
|
console.log();
|
|
65
66
|
|
|
66
67
|
// check
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
|
|
68
|
+
const modelName = answers.modelName;
|
|
69
|
+
const models = await getModels(db);
|
|
70
|
+
const isModelExists = models.some((model) => model.modelName === modelName);
|
|
71
|
+
if (isModelExists) {
|
|
70
72
|
console.log(cli.colors.red('Model name already exists'));
|
|
71
73
|
return;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
// set
|
|
75
|
-
|
|
77
|
+
models.push(answers);
|
|
78
|
+
await setModels(db, models);
|
|
76
79
|
console.log(cli.colors.green('Model added'));
|
|
77
80
|
console.log();
|
|
78
81
|
|
|
79
82
|
// list
|
|
80
|
-
const
|
|
81
|
-
console.log(
|
|
83
|
+
const allModels = await getModels(db);
|
|
84
|
+
console.log(allModels);
|
|
82
85
|
} catch (e) {
|
|
83
86
|
console.log(cli.colors.red('Error: Failed to add model'));
|
|
84
87
|
console.log();
|
|
@@ -91,11 +94,14 @@ async function modelAdd() {
|
|
|
91
94
|
*/
|
|
92
95
|
async function modelList() {
|
|
93
96
|
try {
|
|
97
|
+
// logo
|
|
98
|
+
printLogo();
|
|
99
|
+
|
|
94
100
|
// list
|
|
95
|
-
const
|
|
101
|
+
const models = await getModels(db);
|
|
96
102
|
console.log(cli.colors.cyan('Configured models:'));
|
|
97
103
|
console.log();
|
|
98
|
-
console.log(
|
|
104
|
+
console.log(models);
|
|
99
105
|
} catch (e) {
|
|
100
106
|
console.log(cli.colors.red('Error: Failed to list models'));
|
|
101
107
|
console.log();
|
|
@@ -121,14 +127,34 @@ async function modelRemove() {
|
|
|
121
127
|
console.log();
|
|
122
128
|
|
|
123
129
|
// del
|
|
124
|
-
const
|
|
125
|
-
|
|
130
|
+
const models = await getModels(db);
|
|
131
|
+
const modelNameToRemove = answers.modelName;
|
|
132
|
+
|
|
133
|
+
// check if model exists
|
|
134
|
+
const modelExists = models.some((model) => model.modelName === modelNameToRemove);
|
|
135
|
+
if (!modelExists) {
|
|
136
|
+
console.log(cli.colors.red(`Model not found: ${modelNameToRemove}`));
|
|
137
|
+
console.log();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const newModels = models.filter((model) => model.modelName !== modelNameToRemove);
|
|
142
|
+
await setModels(db, newModels);
|
|
143
|
+
|
|
144
|
+
// clear default if removed model was default
|
|
145
|
+
const defaultModel = await db.config('default');
|
|
146
|
+
if (defaultModel === modelNameToRemove) {
|
|
147
|
+
await db.config('default', null);
|
|
148
|
+
console.log(cli.colors.yellow('Removed model was set as default. Please set a new default.'));
|
|
149
|
+
console.log();
|
|
150
|
+
}
|
|
151
|
+
|
|
126
152
|
console.log(cli.colors.green('Model removed'));
|
|
127
153
|
console.log();
|
|
128
154
|
|
|
129
155
|
// list
|
|
130
|
-
const
|
|
131
|
-
console.log(
|
|
156
|
+
const allModels = await getModels(db);
|
|
157
|
+
console.log(allModels);
|
|
132
158
|
} catch (e) {
|
|
133
159
|
console.log(cli.colors.red('Error: Failed to remove model'));
|
|
134
160
|
console.log();
|
|
@@ -155,8 +181,8 @@ async function modelDefault() {
|
|
|
155
181
|
console.log();
|
|
156
182
|
|
|
157
183
|
// get keys
|
|
158
|
-
const
|
|
159
|
-
const keys =
|
|
184
|
+
const models = await getModels(db);
|
|
185
|
+
const keys = models.map((model) => model.modelName);
|
|
160
186
|
|
|
161
187
|
// check keys
|
|
162
188
|
if (!keys || !keys.length) {
|
|
@@ -169,7 +195,7 @@ async function modelDefault() {
|
|
|
169
195
|
if (!keys.includes(answers.modelName)) {
|
|
170
196
|
console.log(cli.colors.red('Model not found. Available models:'));
|
|
171
197
|
console.log();
|
|
172
|
-
console.log(
|
|
198
|
+
console.log(models);
|
|
173
199
|
return;
|
|
174
200
|
}
|
|
175
201
|
|
package/bin/viho.js
CHANGED
package/logo.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "viho",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "A lightweight CLI tool for managing and
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "A lightweight CLI tool for managing and interacting with AI models",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
7
7
|
"llm",
|
|
8
|
+
"qa",
|
|
9
|
+
"ask",
|
|
8
10
|
"chat",
|
|
9
11
|
"cli",
|
|
10
12
|
"chatgpt",
|
|
@@ -30,7 +32,8 @@
|
|
|
30
32
|
"files": [
|
|
31
33
|
"bin",
|
|
32
34
|
"LICENSE",
|
|
33
|
-
"README.md"
|
|
35
|
+
"README.md",
|
|
36
|
+
"logo.png"
|
|
34
37
|
],
|
|
35
38
|
"engines": {
|
|
36
39
|
"node": ">=18.0.0"
|
|
@@ -40,5 +43,5 @@
|
|
|
40
43
|
"qiao-config": "^5.0.1",
|
|
41
44
|
"qiao-llm": "^0.2.5"
|
|
42
45
|
},
|
|
43
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "2a10a0acfc92501a023e93f7f268e6f8ad57f9fc"
|
|
44
47
|
}
|
package/bin/util.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// os
|
|
2
|
-
const os = require('os');
|
|
3
|
-
|
|
4
|
-
// path
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
// db
|
|
8
|
-
const DB = require('qiao-config');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* getDB
|
|
12
|
-
* @returns
|
|
13
|
-
*/
|
|
14
|
-
exports.getDB = () => {
|
|
15
|
-
const dbPath = path.resolve(os.homedir(), './viho.json');
|
|
16
|
-
return DB(dbPath);
|
|
17
|
-
};
|