ask-my-llm 1.1.4 → 1.1.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/LICENSE +25 -0
- package/README.md +10 -2
- package/bin/ask-ai +37 -81
- package/package.json +12 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <https://unlicense.org>
|
|
25
|
+
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Oversimplified AI usage npm module.
|
|
4
4
|
|
|
5
|
+
**NEW:** Now ask-my-llm is fully zero dependency!
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -21,7 +23,7 @@ Prompts for:
|
|
|
21
23
|
|
|
22
24
|
Config saved to `~/.askairc`.
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## TL;DR
|
|
25
27
|
|
|
26
28
|
```js
|
|
27
29
|
const { ask, askAsync, getModel } = require("ask-my-llm");
|
|
@@ -33,7 +35,7 @@ console.log(response);
|
|
|
33
35
|
// async
|
|
34
36
|
askAsync("Hello").then(console.log);
|
|
35
37
|
|
|
36
|
-
//
|
|
38
|
+
// other
|
|
37
39
|
console.log(getModel()) // Returns currently used model e.g. `google/gemma-3-4b-it`
|
|
38
40
|
```
|
|
39
41
|
|
|
@@ -52,3 +54,9 @@ Sends a prompt to the configured AI and returns a Promise.
|
|
|
52
54
|
|
|
53
55
|
- `prompt` - The message to send
|
|
54
56
|
- Returns: Promise that resolves to AI response as string
|
|
57
|
+
|
|
58
|
+
### getModel(): string
|
|
59
|
+
|
|
60
|
+
Gets current model used.
|
|
61
|
+
|
|
62
|
+
- Returns: raw model string.
|
package/bin/ask-ai
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const readline = require('readline');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const { ask } = require('../index.js');
|
|
@@ -19,12 +19,27 @@ function saveConfig(config) {
|
|
|
19
19
|
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function question(query, defaultValue) {
|
|
23
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
24
|
+
return new Promise(resolve => {
|
|
25
|
+
const text = defaultValue != null ? `${query} (${defaultValue}): ` : `${query}: `;
|
|
26
|
+
rl.question(text, answer => {
|
|
27
|
+
rl.close();
|
|
28
|
+
resolve(answer || defaultValue || '');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function listQuestion(message, choices) {
|
|
34
|
+
console.log(`${message}:`);
|
|
35
|
+
choices.forEach((c, i) => console.log(` ${i + 1}) ${c}`));
|
|
36
|
+
const answer = await question('Enter number');
|
|
37
|
+
const idx = parseInt(answer, 10) - 1;
|
|
38
|
+
return choices[idx] || choices[0];
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
async function testConfig(config) {
|
|
23
|
-
const
|
|
24
|
-
type: 'input',
|
|
25
|
-
name: 'prompt',
|
|
26
|
-
message: 'Enter prompt:'
|
|
27
|
-
}]);
|
|
42
|
+
const prompt = await question('Enter prompt');
|
|
28
43
|
|
|
29
44
|
try {
|
|
30
45
|
console.log('Response:', ask(prompt));
|
|
@@ -35,7 +50,7 @@ async function testConfig(config) {
|
|
|
35
50
|
|
|
36
51
|
async function mainMenu() {
|
|
37
52
|
let config = loadConfig();
|
|
38
|
-
|
|
53
|
+
|
|
39
54
|
if (!config || !config.configs || Object.keys(config.configs).length === 0) {
|
|
40
55
|
console.log('No configs found. Creating first one...');
|
|
41
56
|
await addConfig({ current: null, configs: {} });
|
|
@@ -43,13 +58,7 @@ async function mainMenu() {
|
|
|
43
58
|
}
|
|
44
59
|
|
|
45
60
|
const choices = ['Add new config', 'Select config', 'Edit config', 'Remove config', 'Test config'];
|
|
46
|
-
|
|
47
|
-
const { action } = await inquirer.prompt([{
|
|
48
|
-
type: 'list',
|
|
49
|
-
name: 'action',
|
|
50
|
-
message: `Current: ${config.current}`,
|
|
51
|
-
choices
|
|
52
|
-
}]);
|
|
61
|
+
const action = await listQuestion(`Current: ${config.current}`, choices);
|
|
53
62
|
|
|
54
63
|
if (action === 'Add new config') {
|
|
55
64
|
await addConfig(config);
|
|
@@ -65,39 +74,18 @@ async function mainMenu() {
|
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
async function addConfig(config) {
|
|
68
|
-
const
|
|
69
|
-
type: 'input',
|
|
70
|
-
name: 'name',
|
|
71
|
-
message: 'Config name:'
|
|
72
|
-
}]);
|
|
77
|
+
const name = await question('Config name');
|
|
73
78
|
|
|
74
79
|
if (config.configs[name]) {
|
|
75
80
|
console.log('Config already exists. Edit it instead.');
|
|
76
81
|
return;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
default: 'https://api.openai.com/v1'
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
type: 'input',
|
|
88
|
-
name: 'apiKey',
|
|
89
|
-
message: 'API Key (leave empty for none):',
|
|
90
|
-
default: ''
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
type: 'input',
|
|
94
|
-
name: 'model',
|
|
95
|
-
message: 'Model:',
|
|
96
|
-
default: 'gpt-3.5-turbo'
|
|
97
|
-
}
|
|
98
|
-
]);
|
|
99
|
-
|
|
100
|
-
config.configs[name] = answers;
|
|
84
|
+
const baseApi = await question('Base API URL', 'https://api.openai.com/v1');
|
|
85
|
+
const apiKey = await question('API Key (leave empty for none)', '');
|
|
86
|
+
const model = await question('Model', 'gpt-3.5-turbo');
|
|
87
|
+
|
|
88
|
+
config.configs[name] = { baseApi, apiKey, model };
|
|
101
89
|
config.current = name;
|
|
102
90
|
saveConfig(config);
|
|
103
91
|
console.log(`Config '${name}' saved.`);
|
|
@@ -105,12 +93,7 @@ async function addConfig(config) {
|
|
|
105
93
|
|
|
106
94
|
async function selectConfig(config) {
|
|
107
95
|
const names = Object.keys(config.configs);
|
|
108
|
-
const
|
|
109
|
-
type: 'list',
|
|
110
|
-
name: 'name',
|
|
111
|
-
message: 'Select config:',
|
|
112
|
-
choices: names
|
|
113
|
-
}]);
|
|
96
|
+
const name = await listQuestion('Select config', names);
|
|
114
97
|
|
|
115
98
|
config.current = name;
|
|
116
99
|
saveConfig(config);
|
|
@@ -119,36 +102,14 @@ async function selectConfig(config) {
|
|
|
119
102
|
|
|
120
103
|
async function editConfig(config) {
|
|
121
104
|
const names = Object.keys(config.configs);
|
|
122
|
-
const
|
|
123
|
-
type: 'list',
|
|
124
|
-
name: 'name',
|
|
125
|
-
message: 'Edit config:',
|
|
126
|
-
choices: names
|
|
127
|
-
}]);
|
|
105
|
+
const name = await listQuestion('Edit config', names);
|
|
128
106
|
|
|
129
107
|
const existing = config.configs[name];
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
default: existing.baseApi
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
type: 'input',
|
|
139
|
-
name: 'apiKey',
|
|
140
|
-
message: 'API Key (leave empty for none):',
|
|
141
|
-
default: existing.apiKey || ''
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
type: 'input',
|
|
145
|
-
name: 'model',
|
|
146
|
-
message: 'Model:',
|
|
147
|
-
default: existing.model
|
|
148
|
-
}
|
|
149
|
-
]);
|
|
150
|
-
|
|
151
|
-
config.configs[name] = answers;
|
|
108
|
+
const baseApi = await question('Base API URL', existing.baseApi);
|
|
109
|
+
const apiKey = await question('API Key (leave empty for none)', existing.apiKey || '');
|
|
110
|
+
const model = await question('Model', existing.model);
|
|
111
|
+
|
|
112
|
+
config.configs[name] = { baseApi, apiKey, model };
|
|
152
113
|
saveConfig(config);
|
|
153
114
|
console.log(`Config '${name}' updated.`);
|
|
154
115
|
}
|
|
@@ -160,12 +121,7 @@ async function removeConfig(config) {
|
|
|
160
121
|
return;
|
|
161
122
|
}
|
|
162
123
|
|
|
163
|
-
const
|
|
164
|
-
type: 'list',
|
|
165
|
-
name: 'name',
|
|
166
|
-
message: 'Remove config:',
|
|
167
|
-
choices: names
|
|
168
|
-
}]);
|
|
124
|
+
const name = await listQuestion('Remove config', names);
|
|
169
125
|
|
|
170
126
|
delete config.configs[name];
|
|
171
127
|
if (config.current === name) {
|
package/package.json
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ask-my-llm",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "Oversimplified AI usage npm module",
|
|
3
|
+
"version": "1.1.6",
|
|
4
|
+
"description": "Oversimplified, zero-dependency AI usage npm module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"ask-my-llm": "
|
|
7
|
+
"ask-my-llm": "bin/ask-ai"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
12
|
+
"keywords": [
|
|
13
|
+
"ai",
|
|
14
|
+
"openai",
|
|
15
|
+
"chatgpt",
|
|
16
|
+
"llm",
|
|
17
|
+
"zero-dependency"
|
|
18
|
+
],
|
|
19
|
+
"license": "unlicense",
|
|
20
|
+
"dependencies": {}
|
|
17
21
|
}
|