viho 0.0.3 → 0.0.5

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 +1,235 @@
1
- ## viho
1
+ <p align="center">
2
+ <img src="./logo.png" alt="viho logo" width="200"/>
3
+ </p>
4
+
5
+ <h1 align="center">viho</h1>
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>
13
+
14
+ ## Features
15
+
16
+ - Multiple AI model management
17
+ - Interactive Q&A with streaming responses
18
+ - Continuous chat sessions for multi-turn conversations
19
+ - Support for thinking mode (enabled/disabled/auto)
20
+ - Configurable API endpoints (OpenAI, Anthropic, custom providers)
21
+ - Default model configuration
22
+ - Simple and intuitive CLI interface
23
+ - Persistent configuration storage
24
+
25
+ ## Installation
26
+
27
+ Install globally via npm:
28
+
29
+ ```bash
30
+ npm install -g viho
31
+ ```
32
+
33
+ ## Requirements
34
+
35
+ - Node.js >= 18.0.0
36
+
37
+ ## Quick Start
38
+
39
+ 1. Add your first AI model:
40
+
41
+ ```bash
42
+ viho model add
43
+ ```
44
+
45
+ 2. Set it as default:
46
+
47
+ ```bash
48
+ viho model default
49
+ ```
50
+
51
+ 3. Start asking questions:
52
+
53
+ ```bash
54
+ viho ask
55
+ ```
56
+
57
+ ## Commands
58
+
59
+ ### Model Management
60
+
61
+ #### `viho model add`
62
+
63
+ Add a new AI model configuration interactively.
64
+
65
+ You'll be prompted to enter:
66
+
67
+ - Model name (a custom identifier)
68
+ - API key
69
+ - Base URL (e.g., https://api.openai.com/v1)
70
+ - Model ID (e.g., gpt-4, claude-3-5-sonnet-20241022)
71
+ - Thinking mode (enabled/disabled/auto)
72
+
73
+ ```bash
74
+ viho model add
75
+ ```
76
+
77
+ #### `viho model list`
78
+
79
+ List all configured models:
80
+
81
+ ```bash
82
+ viho model list
83
+ ```
84
+
85
+ #### `viho model remove`
86
+
87
+ Remove a model configuration:
88
+
89
+ ```bash
90
+ viho model remove
91
+ ```
92
+
93
+ #### `viho model default`
94
+
95
+ Set a default model for chat sessions:
96
+
97
+ ```bash
98
+ viho model default
99
+ ```
100
+
101
+ ### Ask
102
+
103
+ #### `viho ask [modelName]`
104
+
105
+ Ask a question to an AI model.
106
+
107
+ If no model name is provided, uses the default model:
108
+
109
+ ```bash
110
+ viho ask
111
+ ```
112
+
113
+ Or specify a model explicitly:
114
+
115
+ ```bash
116
+ viho ask mymodel
117
+ ```
118
+
119
+ The interface includes:
120
+
121
+ - Editor-based question input
122
+ - Streaming responses
123
+ - Visual thinking process (when enabled)
124
+ - Colored output for better readability
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
+
151
+ ## Configuration
152
+
153
+ Configuration is stored in `~/viho.json`. You can manage all settings through the CLI commands.
154
+
155
+ ### Example Configuration Structure
156
+
157
+ ```json
158
+ {
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
+ },
166
+ "default": "mymodel"
167
+ }
168
+ ```
169
+
170
+ ## Supported Providers
171
+
172
+ viho works with any OpenAI-compatible API, including:
173
+
174
+ - OpenAI (GPT-4, GPT-3.5, etc.)
175
+ - Anthropic Claude (via compatible endpoints)
176
+ - Custom LLM providers with OpenAI-compatible APIs
177
+
178
+ ## Examples
179
+
180
+ ### Adding an OpenAI Model
181
+
182
+ ```bash
183
+ viho model add
184
+ # Enter model name: gpt4
185
+ # Enter API key: sk-...
186
+ # Enter base URL: https://api.openai.com/v1
187
+ # Enter model ID: gpt-4
188
+ # Thinking mode: disabled
189
+ ```
190
+
191
+ ### Adding a Claude Model
192
+
193
+ ```bash
194
+ viho model add
195
+ # Enter model name: claude
196
+ # Enter API key: your-anthropic-key
197
+ # Enter base URL: https://api.anthropic.com
198
+ # Enter model ID: claude-3-5-sonnet-20241022
199
+ # Thinking mode: auto
200
+ ```
201
+
202
+ ### Setting Up for First Use
203
+
204
+ ```bash
205
+ # Add a model
206
+ viho model add
207
+
208
+ # Set it as default
209
+ viho model default
210
+
211
+ # Start asking questions
212
+ viho ask
213
+ ```
214
+
215
+ ## Dependencies
216
+
217
+ - [qiao-cli](https://www.npmjs.com/package/qiao-cli) - CLI utilities
218
+ - [qiao-config](https://www.npmjs.com/package/qiao-config) - Configuration management
219
+ - [qiao-llm](https://www.npmjs.com/package/qiao-llm) - LLM integration
220
+
221
+ ## License
222
+
223
+ MIT
224
+
225
+ ## Author
226
+
227
+ uikoo9 <uikoo9@qq.com>
228
+
229
+ ## Issues
230
+
231
+ Report issues at: https://github.com/uikoo9/viho/issues
232
+
233
+ ## Homepage
234
+
235
+ https://github.com/uikoo9/viho
package/bin/util.js ADDED
@@ -0,0 +1,103 @@
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
+ };
37
+
38
+ /**
39
+ * ask
40
+ * @param {*} llm
41
+ * @param {*} model
42
+ */
43
+ exports.ask = async (llm, model) => {
44
+ // ask
45
+ const questions = [
46
+ {
47
+ type: 'editor',
48
+ name: 'content',
49
+ message: 'Your question:',
50
+ },
51
+ ];
52
+ const answers = await cli.ask(questions);
53
+
54
+ // answers
55
+ console.log();
56
+ console.log(cli.colors.gray('Question:'));
57
+ console.log(cli.colors.gray(answers.content));
58
+ console.log();
59
+
60
+ // chat
61
+ const chatOptions = {
62
+ model: model.modelID,
63
+ messages: [
64
+ { role: 'system', content: 'You are a helpful AI assistant' },
65
+ { role: 'user', content: answers.content },
66
+ ],
67
+ thinking: {
68
+ type: model.modelThinking,
69
+ },
70
+ };
71
+
72
+ // callback options
73
+ const callbackOptions = {
74
+ firstThinkingCallback: () => {
75
+ console.log();
76
+ console.log(cli.colors.gray('[Thinking...]'));
77
+ console.log();
78
+ },
79
+ thinkingCallback: (msg) => {
80
+ process.stdout.write(cli.colors.gray(msg));
81
+ },
82
+ firstContentCallback: () => {
83
+ console.log();
84
+ console.log(cli.colors.cyan('[Response]'));
85
+ console.log();
86
+ },
87
+ contentCallback: (msg) => {
88
+ process.stdout.write(msg);
89
+ },
90
+ endCallback: () => {
91
+ console.log();
92
+ console.log();
93
+ },
94
+ errorCallback: (error) => {
95
+ console.log();
96
+ console.log(cli.colors.red('Error:'));
97
+ console.log(error);
98
+ },
99
+ };
100
+
101
+ // go
102
+ await llm.chatWithStreaming(chatOptions, callbackOptions);
103
+ };
@@ -0,0 +1,43 @@
1
+ // qiao
2
+ const cli = require('qiao-cli');
3
+
4
+ // llm
5
+ const LLM = require('qiao-llm');
6
+
7
+ // util
8
+ const { getDB, ask, printLogo } = require('./util.js');
9
+ const db = getDB();
10
+
11
+ // cmd
12
+ cli.cmd
13
+ .command('ask [modelName]')
14
+ .description('Ask a question to an AI model')
15
+ .action(async (modelName) => {
16
+ if (!modelName) {
17
+ const defaultModel = await db.config('default');
18
+ if (!defaultModel) {
19
+ console.log(cli.colors.red('No default model set. Use: viho model default'));
20
+ return;
21
+ }
22
+
23
+ modelName = defaultModel;
24
+ }
25
+
26
+ // check
27
+ const model = await db.config(modelName);
28
+ if (!model) {
29
+ console.log(cli.colors.red(`Model not found: ${modelName}`));
30
+ return;
31
+ }
32
+
33
+ // init
34
+ const llm = LLM({
35
+ apiKey: model.apiKey,
36
+ baseURL: model.baseURL,
37
+ });
38
+
39
+ // logo
40
+ printLogo();
41
+
42
+ await ask(llm, model);
43
+ });
@@ -0,0 +1,49 @@
1
+ // qiao
2
+ const cli = require('qiao-cli');
3
+
4
+ // llm
5
+ const LLM = require('qiao-llm');
6
+
7
+ // util
8
+ const { getDB, ask, printLogo } = require('./util.js');
9
+ const db = getDB();
10
+
11
+ // cmd
12
+ cli.cmd
13
+ .command('chat [modelName]')
14
+ .description('Start a continuous chat session with an AI model')
15
+ .action(async (modelName) => {
16
+ if (!modelName) {
17
+ const defaultModel = await db.config('default');
18
+ if (!defaultModel) {
19
+ console.log(cli.colors.red('No default model set. Use: viho model default'));
20
+ return;
21
+ }
22
+
23
+ modelName = defaultModel;
24
+ }
25
+
26
+ // check
27
+ const model = await db.config(modelName);
28
+ if (!model) {
29
+ console.log(cli.colors.red(`Model not found: ${modelName}`));
30
+ return;
31
+ }
32
+
33
+ // init
34
+ const llm = LLM({
35
+ apiKey: model.apiKey,
36
+ baseURL: model.baseURL,
37
+ });
38
+
39
+ // logo
40
+ printLogo();
41
+ console.log(cli.colors.cyan(`Welcome to viho chat! Using model: ${modelName}`));
42
+ console.log(cli.colors.gray('Press Ctrl+C to exit\n'));
43
+
44
+ // chat
45
+ let keepChatting = true;
46
+ while (keepChatting) {
47
+ await ask(llm, model);
48
+ }
49
+ });
@@ -0,0 +1,188 @@
1
+ // qiao
2
+ const cli = require('qiao-cli');
3
+
4
+ // util
5
+ const { getDB, printLogo } = require('./util.js');
6
+ const db = getDB();
7
+
8
+ // actions
9
+ const actions = ['add', 'list', 'remove', 'default'];
10
+
11
+ // model
12
+ cli.cmd
13
+ .command('model <action>')
14
+ .description('Manage AI models')
15
+ .action((action) => {
16
+ if (!actions.includes(action)) {
17
+ console.log(cli.colors.red('Invalid action. Use: add, list, remove, default'));
18
+ return;
19
+ }
20
+
21
+ // actions
22
+ if (action === 'add') modelAdd();
23
+ if (action === 'list') modelList();
24
+ if (action === 'remove') modelRemove();
25
+ if (action === 'default') modelDefault();
26
+ });
27
+
28
+ /**
29
+ * modelAdd
30
+ * @returns
31
+ */
32
+ async function modelAdd() {
33
+ try {
34
+ // q a
35
+ const questions = [
36
+ {
37
+ type: 'input',
38
+ name: 'modelName',
39
+ message: 'Enter model name:',
40
+ },
41
+ {
42
+ type: 'input',
43
+ name: 'apiKey',
44
+ message: 'Enter API key:',
45
+ },
46
+ {
47
+ type: 'input',
48
+ name: 'baseURL',
49
+ message: 'Enter base URL:',
50
+ },
51
+ {
52
+ type: 'input',
53
+ name: 'modelID',
54
+ message: 'Enter model ID:',
55
+ },
56
+ {
57
+ type: 'list',
58
+ name: 'modelThinking',
59
+ message: 'Thinking mode:',
60
+ choices: ['enabled', 'disabled', 'auto'],
61
+ },
62
+ ];
63
+ const answers = await cli.ask(questions);
64
+ console.log();
65
+
66
+ // check
67
+ const dbKey = answers.modelName;
68
+ const dbValue = await db.config(dbKey);
69
+ if (dbValue) {
70
+ console.log(cli.colors.red('Model name already exists'));
71
+ return;
72
+ }
73
+
74
+ // set
75
+ await db.config(dbKey, answers);
76
+ console.log(cli.colors.green('Model added'));
77
+ console.log();
78
+
79
+ // list
80
+ const all = await db.all();
81
+ console.log(all);
82
+ } catch (e) {
83
+ console.log(cli.colors.red('Error: Failed to add model'));
84
+ console.log();
85
+ console.log(e);
86
+ }
87
+ }
88
+
89
+ /**
90
+ * modelList
91
+ */
92
+ async function modelList() {
93
+ try {
94
+ // logo
95
+ printLogo();
96
+
97
+ // list
98
+ const all = await db.all();
99
+ console.log(cli.colors.cyan('Configured models:'));
100
+ console.log();
101
+ console.log(all);
102
+ } catch (e) {
103
+ console.log(cli.colors.red('Error: Failed to list models'));
104
+ console.log();
105
+
106
+ console.log(e);
107
+ }
108
+ }
109
+
110
+ /**
111
+ * modelRemove
112
+ */
113
+ async function modelRemove() {
114
+ try {
115
+ // q a
116
+ const questions = [
117
+ {
118
+ type: 'input',
119
+ name: 'modelName',
120
+ message: 'Enter model name to remove:',
121
+ },
122
+ ];
123
+ const answers = await cli.ask(questions);
124
+ console.log();
125
+
126
+ // del
127
+ const dbKey = answers.modelName;
128
+ await db.config(dbKey, null);
129
+ console.log(cli.colors.green('Model removed'));
130
+ console.log();
131
+
132
+ // list
133
+ const all = await db.all();
134
+ console.log(all);
135
+ } catch (e) {
136
+ console.log(cli.colors.red('Error: Failed to remove model'));
137
+ console.log();
138
+
139
+ console.log(e);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * modelDefault
145
+ * @returns
146
+ */
147
+ async function modelDefault() {
148
+ try {
149
+ // q a
150
+ const questions = [
151
+ {
152
+ type: 'input',
153
+ name: 'modelName',
154
+ message: 'Enter default model name:',
155
+ },
156
+ ];
157
+ const answers = await cli.ask(questions);
158
+ console.log();
159
+
160
+ // get keys
161
+ const all = await db.all();
162
+ const keys = Object.keys(all);
163
+
164
+ // check keys
165
+ if (!keys || !keys.length) {
166
+ console.log(cli.colors.red('No models found. Add one first: viho model add'));
167
+ console.log();
168
+ return;
169
+ }
170
+
171
+ // check model
172
+ if (!keys.includes(answers.modelName)) {
173
+ console.log(cli.colors.red('Model not found. Available models:'));
174
+ console.log();
175
+ console.log(all);
176
+ return;
177
+ }
178
+
179
+ // set
180
+ await db.config('default', answers.modelName);
181
+ console.log(cli.colors.green(`Default model: ${answers.modelName}`));
182
+ console.log();
183
+ } catch (e) {
184
+ console.log(cli.colors.red('Error: Failed to set default model'));
185
+ console.log();
186
+ console.log(e);
187
+ }
188
+ }
package/bin/viho.js CHANGED
@@ -4,6 +4,9 @@
4
4
  const cli = require('qiao-cli');
5
5
 
6
6
  // cmds
7
+ require('./viho-model.js');
8
+ require('./viho-ask.js');
9
+ require('./viho-chat.js');
7
10
  require('./viho-version.js');
8
11
 
9
12
  // parse
package/logo.png ADDED
Binary file
package/package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "name": "viho",
3
- "version": "0.0.3",
4
- "description": "",
5
- "keywords": [],
3
+ "version": "0.0.5",
4
+ "description": "A lightweight CLI tool for managing and interacting with AI models",
5
+ "keywords": [
6
+ "ai",
7
+ "llm",
8
+ "qa",
9
+ "ask",
10
+ "chat",
11
+ "cli",
12
+ "chatgpt",
13
+ "anthropic",
14
+ "openai",
15
+ "ai-assistant",
16
+ "command-line",
17
+ "terminal"
18
+ ],
6
19
  "author": "uikoo9 <uikoo9@qq.com>",
7
20
  "license": "MIT",
8
21
  "homepage": "https://github.com/uikoo9/viho#readme",
@@ -19,13 +32,16 @@
19
32
  "files": [
20
33
  "bin",
21
34
  "LICENSE",
22
- "README.md"
35
+ "README.md",
36
+ "logo.png"
23
37
  ],
24
38
  "engines": {
25
- "node": ">=14.0.0"
39
+ "node": ">=18.0.0"
26
40
  },
27
41
  "dependencies": {
28
- "qiao-cli": "^5.0.0"
42
+ "qiao-cli": "^5.0.0",
43
+ "qiao-config": "^5.0.1",
44
+ "qiao-llm": "^0.2.5"
29
45
  },
30
- "gitHead": "689ac084e471c52e399cc4dd83278cf51a380b15"
46
+ "gitHead": "4536783e6823add1a9556e0fb2f569e8d1f5bac0"
31
47
  }