ask-cli-ai 1.0.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Minaya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # Ask CLI
2
+
3
+ A fast and lightweight AI-powered CLI tool to help you with commands, coding, apps and more.
4
+
5
+ - 🤖 Get help about commands, coding, apps, etc.
6
+ - 📝 Short and precise answers, just the info you need, straight to the point.
7
+ - 🚀 Blazing fast speed, almost instant responses.
8
+ - 🛡️ Safe by design, it cannot run commands or access your files without your explicit authorization.
9
+
10
+ > Forget about switching between applications to know how to use a command or fix an error. Just ask your terminal how to do it.
11
+
12
+ ![Ask CLI demo showing quick terminal responses](https://github.com/david-minaya/ask/raw/main/images/ask.gif)
13
+
14
+ ## Content
15
+
16
+ - [Why use Ask CLI?](#why-use-ask-cli)
17
+ - [For whom is Ask CLI?](#for-whom-is-ask-cli)
18
+ - [Installation](#installation)
19
+ - [Usage](#usage)
20
+ - [Select model](#select-model)
21
+ - [Supported models](#supported-models)
22
+ - [Reference](#reference)
23
+
24
+ ## Why use Ask CLI?
25
+
26
+ Why use Ask CLI and not an AI agent like Claude or Gemini?
27
+
28
+ - Ask CLI was created to do one thing and do it well: help you with commands, coding, apps and more from your terminal.
29
+ - The AI models it uses are optimized to generate short, precise and fast answers.
30
+ - No risk of prompt injection, Ask CLI cannot run commands or access your files by default.
31
+ - No risk of running dangerous commands on your computer, you have to explicitly authorize it using the `--command` option. See [Running commands](#running-commands) for more details.
32
+
33
+ ## For whom is Ask CLI?
34
+
35
+ - Students who want to learn how to use commands and the terminal.
36
+ - Developers who want to be more productive and avoid context switching.
37
+ - Sysadmins who need quick help with commands and troubleshooting.
38
+ - DevOps engineers who want to automate tasks and get help with commands.
39
+ - Anyone working in production environments where security is critical.
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ npm install -g ask-cli-ai
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ > To use Ask CLI, you first need to set up the API key. See the [Select model](#select-model) section to learn how.
50
+
51
+ ### Ask questions
52
+
53
+ ```bash
54
+ # Basic usage
55
+ ask <your question>
56
+
57
+ # Examples
58
+ ask how to find files by name in linux
59
+ ask what is a promise in javascript
60
+ ask how to create a new branch in git
61
+
62
+ # Using quotes
63
+ ask 'What does this command do: git config user.name "Ask CLI"?'
64
+ ```
65
+
66
+ ### Aliases
67
+
68
+ You can use `how` and `what` as aliases for the `ask` command:
69
+
70
+ ```bash
71
+ # Using 'how' alias
72
+ how to install docker on ubuntu
73
+
74
+ # Using 'what' alias
75
+ what is the difference between git merge and rebase
76
+ ```
77
+
78
+ ### Running commands
79
+
80
+ By default, Ask CLI cannot run commands on your computer. However, you can use the `-c` or `--command` option to execute a command and include its output in your question. This allows Ask CLI to analyze errors, logs, or any command output and provide context-aware answers.
81
+
82
+ ```bash
83
+ # Analyze an error
84
+ ask why is this failing -c "npm run build"
85
+
86
+ # Get help with command output
87
+ ask explain this output -c "docker ps -a"
88
+
89
+ # Debug issues
90
+ ask what is wrong here -c "git status"
91
+ ```
92
+
93
+ ## Select model
94
+
95
+ You can select a model using the `ask /models` command. This will list all the available models and let you select the model you want to use.
96
+
97
+ ![Model selection screen](https://github.com/david-minaya/ask/blob/main/images/select-model.png)
98
+
99
+ > If it's the first time you select a model, you will be prompted to set the API key for the model's provider.
100
+
101
+ ## Supported models
102
+
103
+ **Gemini**
104
+
105
+ - Gemini 3 Flash Preview
106
+ - Gemini 3 Pro Preview
107
+ - Gemini 2.5 Flash
108
+ - Gemini 2.5 Flash Lite
109
+ - Gemini 2.5 Pro
110
+
111
+ **OpenAI**
112
+
113
+ - GPT-5 Mini
114
+ - GPT-5 Nano
115
+ - GPT-5
116
+ - GPT-5.2
117
+ - GPT-5.2 Pro
118
+ - GPT-4.1
119
+
120
+ **Anthropic**
121
+
122
+ - Claude Haiku 4.5
123
+ - Claude Sonnet 4.5
124
+ - Claude Opus 4.5
125
+
126
+ ## Reference
127
+
128
+ ```
129
+ AI CLI to help you with commands, coding, apps and more.
130
+
131
+ Usage: ask <prompt..>
132
+
133
+ Commands:
134
+ ask <prompt..> Ask something. Alias: what, how [default]
135
+ ask /models Select a model
136
+ ask /providers Setup providers
137
+ ask /history List the chat history
138
+ ask /clear Clear the chat history
139
+
140
+ Positionals:
141
+ prompt [string]
142
+
143
+ Options:
144
+ --version Show version number [boolean]
145
+ --help Show help [boolean]
146
+ -c, --command Command to execute [string]
147
+
148
+ Examples:
149
+ ask how to run a docker container
150
+ how to setup my git account
151
+ what is the chmod command
152
+ ask what is using port 80 -c "netstat -ano"
153
+ ```
package/dist/app.js ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ import yargs from 'yargs';
3
+ import { hideBin } from 'yargs/helpers';
4
+ import { ask } from "./commands/ask.js";
5
+ import { selectModel } from "./commands/selectModel.js";
6
+ import { listHistory } from "./commands/listHistory.js";
7
+ import { clearHistory } from "./commands/clearHistory.js";
8
+ import { providers } from "./commands/providers.js";
9
+ import { logo } from "./utils/logo.js";
10
+ void yargs(hideBin(process.argv))
11
+ .scriptName('ask')
12
+ .usage(`${logo}\nAI CLI to help you with commands, coding, apps and more.\n\nUsage: $0 <prompt..>`)
13
+ .version('0.1.0')
14
+ .locale('en')
15
+ .example('$0 how to run a docker container', '')
16
+ .example('how to setup my git account', '')
17
+ .example('what is the chmod command', '')
18
+ .example('$0 what is using port 80 -c "netstat -ano"', '')
19
+ .help()
20
+ .command({
21
+ command: '$0 <prompt..>',
22
+ describe: 'Ask something. Alias: what, how',
23
+ builder: yargs => yargs
24
+ .positional('prompt', { type: 'string', array: true, demandOption: true })
25
+ .option('command', {
26
+ alias: ['c'],
27
+ type: 'string',
28
+ description: 'Command to execute',
29
+ requiresArg: true
30
+ }),
31
+ handler: (args) => ask(args.prompt.join(' '), args.command)
32
+ })
33
+ .command({
34
+ command: '/models',
35
+ describe: 'Select a model',
36
+ handler: () => selectModel()
37
+ })
38
+ .command({
39
+ command: '/providers',
40
+ describe: 'Setup providers',
41
+ handler: () => providers()
42
+ })
43
+ .command({
44
+ command: '/history',
45
+ describe: 'List the chat history',
46
+ handler: () => listHistory()
47
+ })
48
+ .command({
49
+ command: '/clear',
50
+ describe: 'Clear the chat history',
51
+ handler: () => clearHistory()
52
+ })
53
+ .parse();
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDeEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLG1CQUFvQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFdkMsS0FBSyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUM5QixVQUFVLENBQUMsS0FBSyxDQUFDO0tBQ2pCLEtBQUssQ0FBQyxHQUFHLElBQUksb0ZBQW9GLENBQUM7S0FDbEcsT0FBTyxDQUFDLE9BQU8sQ0FBQztLQUNoQixNQUFNLENBQUMsSUFBSSxDQUFDO0tBQ1osT0FBTyxDQUFDLGtDQUFrQyxFQUFFLEVBQUUsQ0FBQztLQUMvQyxPQUFPLENBQUMsNkJBQTZCLEVBQUUsRUFBRSxDQUFDO0tBQzFDLE9BQU8sQ0FBQywyQkFBMkIsRUFBRSxFQUFFLENBQUM7S0FDeEMsT0FBTyxDQUFDLDRDQUE0QyxFQUFFLEVBQUUsQ0FBQztLQUV6RCxJQUFJLEVBQUU7S0FDTixPQUFPLENBQUM7SUFDUCxPQUFPLEVBQUUsZUFBZTtJQUN4QixRQUFRLEVBQUUsaUNBQWlDO0lBQzNDLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUs7U0FDcEIsVUFBVSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUM7U0FDekUsTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUNqQixLQUFLLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDWixJQUFJLEVBQUUsUUFBUTtRQUNkLFdBQVcsRUFBRSxvQkFBb0I7UUFDakMsV0FBVyxFQUFFLElBQUk7S0FDbEIsQ0FBQztJQUNKLE9BQU8sRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUM7Q0FDNUQsQ0FBQztLQUNELE9BQU8sQ0FBQztJQUNQLE9BQU8sRUFBRSxTQUFTO0lBQ2xCLFFBQVEsRUFBRSxnQkFBZ0I7SUFDMUIsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLFdBQVcsRUFBRTtDQUM3QixDQUFDO0tBQ0QsT0FBTyxDQUFDO0lBQ1AsT0FBTyxFQUFFLFlBQVk7SUFDckIsUUFBUSxFQUFFLGlCQUFpQjtJQUMzQixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsU0FBUyxFQUFFO0NBQzNCLENBQUM7S0FDRCxPQUFPLENBQUM7SUFDUCxPQUFPLEVBQUUsVUFBVTtJQUNuQixRQUFRLEVBQUUsdUJBQXVCO0lBQ2pDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxXQUFXLEVBQUU7Q0FDN0IsQ0FBQztLQUNELE9BQU8sQ0FBQztJQUNQLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLFFBQVEsRUFBRSx3QkFBd0I7SUFDbEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLFlBQVksRUFBRTtDQUM5QixDQUFDO0tBQ0QsS0FBSyxFQUFFLENBQUMifQ==
@@ -0,0 +1,125 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import util from 'node:util';
3
+ import path from 'node:path';
4
+ import fs from 'node:fs/promises';
5
+ import { exec as execCb } from 'node:child_process';
6
+ import findProcess from 'find-process';
7
+ import { useEffect, useState } from 'react';
8
+ import { Box, render, Static, Text, useApp } from 'ink';
9
+ import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
10
+ import { configStore } from "../stores/config.js";
11
+ import { historyStore } from "../stores/history.js";
12
+ import { Welcome } from "../components/welcome.js";
13
+ import { Loading } from "../components/loading.js";
14
+ import { root } from "../utils/root.js";
15
+ import { ChatAnthropic } from '@langchain/anthropic';
16
+ import { ChatOpenAI } from '@langchain/openai';
17
+ import { instructions } from "../templates/instructions.js";
18
+ import { providers } from "../providers.js";
19
+ const exec = util.promisify(execCb);
20
+ const config = await configStore.get();
21
+ const history = await historyStore.get();
22
+ export function ask(prompt, command) {
23
+ render(_jsx(Ask, { prompt: prompt, command: command }));
24
+ }
25
+ function Ask(props) {
26
+ const { prompt, command } = props;
27
+ const { exit } = useApp();
28
+ const [view, setView] = useState('ask');
29
+ const [sending, setSending] = useState(false);
30
+ const [response, setResponse] = useState('');
31
+ const [exitCode, setExitCode] = useState();
32
+ const [isFirstRun, setIsFirstRun] = useState(false);
33
+ useEffect(() => {
34
+ void (async () => {
35
+ if (!config.model)
36
+ return setView('welcome');
37
+ await send(config.model.provider, config.model.model, config.model.apiKey);
38
+ })();
39
+ }, []);
40
+ useEffect(() => {
41
+ if (exitCode !== undefined) {
42
+ setTimeout(() => exit(), 0);
43
+ }
44
+ }, [exitCode]);
45
+ useEffect(() => {
46
+ (async () => {
47
+ const dirPath = path.join(root, '/data/chats');
48
+ const fileNames = await fs.readdir(dirPath);
49
+ const files = await Promise.all(fileNames.map(async (name) => {
50
+ const filePath = path.join(dirPath, name);
51
+ const stats = await fs.stat(filePath);
52
+ return { path: filePath, time: stats.ctimeMs };
53
+ }));
54
+ const sortedFiles = files
55
+ .sort((a, b) => b.time - a.time)
56
+ .slice(10);
57
+ await Promise.all(sortedFiles.map(file => fs.unlink(file.path)));
58
+ })().catch(() => { });
59
+ }, []);
60
+ async function handleSend(modelId, apiKey) {
61
+ setIsFirstRun(true);
62
+ setView('ask');
63
+ const config = await configStore.get();
64
+ await send(config.model.provider, modelId, apiKey);
65
+ }
66
+ async function send(providerId, modelId, apiKey) {
67
+ try {
68
+ setSending(true);
69
+ const prompt = await getPrompt();
70
+ const model = getModel(providerId, modelId, apiKey);
71
+ const response = await model.invoke([
72
+ { role: 'system', content: instructions },
73
+ ...history.map(item => ({ ...item })),
74
+ { role: 'human', content: prompt }
75
+ ]);
76
+ await historyStore.add([
77
+ { role: 'human', content: prompt },
78
+ { role: 'ai', content: response.text }
79
+ ]);
80
+ setResponse(response.text.replaceAll('\\x1b', '\x1b').replaceAll('\\n', '\n').concat('\x1b[0m'));
81
+ setSending(false);
82
+ setExitCode(0);
83
+ }
84
+ catch (err) {
85
+ console.error('Error running model:', err.message);
86
+ setExitCode(1);
87
+ }
88
+ }
89
+ async function getPrompt() {
90
+ let result = prompt;
91
+ if (command) {
92
+ const commandOutput = await runCommand(command);
93
+ result += `\n\nCommand: ${command}\n\nCommand output:\n\n${commandOutput}`;
94
+ }
95
+ return result;
96
+ }
97
+ function getModel(providerId, modelId, apiKey) {
98
+ const provider = providers.find(provider => provider.id === providerId);
99
+ const model = provider?.models.find(model => model.name === modelId);
100
+ switch (providerId) {
101
+ case 'openai': return new ChatOpenAI({ model: modelId, apiKey, ...model?.config });
102
+ case 'gemini': return new ChatGoogleGenerativeAI({ model: modelId, apiKey, ...model?.config });
103
+ case 'anthropic': return new ChatAnthropic({ model: modelId, apiKey, ...model?.config });
104
+ default: throw new Error('Model not found');
105
+ }
106
+ }
107
+ async function runCommand(command) {
108
+ try {
109
+ const [processInfo] = await findProcess.default('pid', process.ppid);
110
+ const result = await exec(command, { shell: processInfo.name });
111
+ return result.stdout;
112
+ }
113
+ catch (err) {
114
+ const { stdout, stderr } = err;
115
+ return `Error executing command: \n\n${stdout}\n\n${stderr}`;
116
+ }
117
+ }
118
+ return (_jsxs(Box, { children: [view === 'welcome' &&
119
+ _jsx(Welcome, { onSend: handleSend }), view === 'ask' &&
120
+ _jsxs(Box, { children: [isFirstRun &&
121
+ _jsx(Static, { items: [''], children: item => _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: [_jsx(Text, { color: 'cyan', bold: true, children: "Prompt:" }), " ", prompt] }) }, item) }), sending &&
122
+ _jsx(Loading, {}), !sending && response &&
123
+ _jsx(Static, { items: [''], children: item => _jsx(Text, { children: response }, item) })] })] }));
124
+ }
125
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2Fzay50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQztBQUM3QixPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFDN0IsT0FBTyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDbEMsT0FBTyxFQUFFLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLFdBQVcsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFDNUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDeEQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sMEJBQTJCLENBQUM7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDBCQUEyQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN4QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDckQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFNUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENB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
@@ -0,0 +1,6 @@
1
+ import { historyStore } from "../stores/history.js";
2
+ export async function clearHistory() {
3
+ await historyStore.clear();
4
+ console.log('Conversation history cleared.');
5
+ }
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xlYXJIaXN0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2NsZWFySGlzdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFcEQsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZO0lBQ2hDLE1BQU0sWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztBQUMvQyxDQUFDIn0=
@@ -0,0 +1,17 @@
1
+ import { historyStore } from "../stores/history.js";
2
+ export async function listHistory() {
3
+ const history = await historyStore.get();
4
+ if (history.length === 0) {
5
+ console.log('No conversation history found.');
6
+ return;
7
+ }
8
+ history.forEach((item, index) => {
9
+ if (item.role === 'human') {
10
+ if (index !== 0)
11
+ console.log('');
12
+ console.log('-----');
13
+ }
14
+ console.log(`${item.role === 'human' ? 'User' : 'Model'}:`, item.content.replaceAll('\\x1b', '\x1b').replaceAll('\\n', '\n'), '\x1b[0m');
15
+ });
16
+ }
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdEhpc3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvbGlzdEhpc3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXBELE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVztJQUUvQixNQUFNLE9BQU8sR0FBRyxNQUFNLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUV6QyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQzlDLE9BQU87SUFDVCxDQUFDO0lBRUQsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRTtRQUM5QixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFLENBQUM7WUFDMUIsSUFBSSxLQUFLLEtBQUssQ0FBQztnQkFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFRLEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUM1SSxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, render } from 'ink';
3
+ import { useState } from 'react';
4
+ import { Providers } from "../components/providers.js";
5
+ import { Provider } from "../components/provider.js";
6
+ export function providers() {
7
+ render(_jsx(Providers2, {}));
8
+ }
9
+ function Providers2() {
10
+ const [view, setView] = useState('providers');
11
+ const [selectedProvider, setSelectedProvider] = useState();
12
+ function onSelectProvider(provider) {
13
+ setSelectedProvider(provider);
14
+ setView('provider');
15
+ }
16
+ return (_jsxs(Box, { children: [view === 'providers' &&
17
+ _jsx(Providers, { onSelect: onSelectProvider }), view === 'provider' && selectedProvider &&
18
+ _jsx(Provider, { provider: selectedProvider, onClose: () => setView('providers') })] }));
19
+ }
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL3Byb3ZpZGVycy50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFDakMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDRCQUE2QixDQUFDO0FBRXhELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBNEIsQ0FBQztBQUV0RCxNQUFNLFVBQVUsU0FBUztJQUN2QixNQUFNLENBQUMsS0FBQyxVQUFVLEtBQUUsQ0FBQyxDQUFDO0FBQ3hCLENBQUM7QUFFRCxTQUFTLFVBQVU7SUFFakIsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsR0FBRyxRQUFRLENBQW9DLFdBQVcsQ0FBQyxDQUFDO0lBQ2pGLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxtQkFBbUIsQ0FBQyxHQUFHLFFBQVEsRUFBZ0IsQ0FBQztJQUV6RSxTQUFTLGdCQUFnQixDQUFDLFFBQXNCO1FBQzlDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlCLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN0QixDQUFDO0lBRUQsT0FBTyxDQUNMLE1BQUMsR0FBRyxlQUNELElBQUksS0FBSyxXQUFXO2dCQUNuQixLQUFDLFNBQVMsSUFBQyxRQUFRLEVBQUUsZ0JBQWdCLEdBQUcsRUFFekMsSUFBSSxLQUFLLFVBQVUsSUFBSSxnQkFBZ0I7Z0JBQ3RDLEtBQUMsUUFBUSxJQUNQLFFBQVEsRUFBRSxnQkFBZ0IsRUFDMUIsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxJQUV0QyxDQUNQLENBQUM7QUFDSixDQUFDIn0=
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { Box, render, Text, useApp, useInput } from 'ink';
4
+ import { SelectModel } from "../components/selectModel.js";
5
+ export function selectModel() {
6
+ render(_jsx(Select, {}));
7
+ }
8
+ function Select() {
9
+ const { exit } = useApp();
10
+ const [view, setView] = useState('select-model');
11
+ const [model, setModel] = useState();
12
+ useInput((_, key) => {
13
+ if (key.escape) {
14
+ setView('none');
15
+ }
16
+ });
17
+ useEffect(() => {
18
+ if (view === 'none' || view === 'selected-model') {
19
+ exit();
20
+ }
21
+ }, [view]);
22
+ function handleSelect(model) {
23
+ setModel(model);
24
+ setView('selected-model');
25
+ }
26
+ return (_jsxs(Box, { flexDirection: 'column', children: [view === 'select-model' &&
27
+ _jsx(SelectModel, { onSelect: handleSelect }), view === 'selected-model' &&
28
+ _jsxs(Text, { children: ["Selected model: ", _jsx(Text, { bold: true, color: 'cyanBright', children: model.title })] })] }));
29
+ }
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0TW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc2VsZWN0TW9kZWwudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUM1QyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sOEJBQStCLENBQUM7QUFHNUQsTUFBTSxVQUFVLFdBQVc7SUFDekIsTUFBTSxDQUFDLEtBQUMsTUFBTSxLQUFFLENBQUMsQ0FBQztBQUNwQixDQUFDO0FBRUQsU0FBUyxNQUFNO0lBRWIsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO0lBRTFCLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLEdBQUcsUUFBUSxDQUE2QyxjQUFjLENBQUMsQ0FBQztJQUM3RixNQUFNLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxHQUFHLFFBQVEsRUFBUyxDQUFDO0lBRTVDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRTtRQUNsQixJQUFJLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxTQUFTLENBQUMsR0FBRyxFQUFFO1FBQ2IsSUFBSSxJQUFJLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ2pELElBQUksRUFBRSxDQUFDO1FBQ1QsQ0FBQztJQUNILENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFFWCxTQUFTLFlBQVksQ0FBQyxLQUFZO1FBQ2hDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoQixPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQsT0FBTyxDQUNMLE1BQUMsR0FBRyxJQUFDLGFBQWEsRUFBQyxRQUFRLGFBQ3hCLElBQUksS0FBSyxjQUFjO2dCQUN0QixLQUFDLFdBQVcsSUFBQyxRQUFRLEVBQUUsWUFBWSxHQUFHLEVBRXZDLElBQUksS0FBSyxnQkFBZ0I7Z0JBQ3hCLE1BQUMsSUFBSSxtQ0FBaUIsS0FBQyxJQUFJLElBQUMsSUFBSSxRQUFDLEtBQUssRUFBQyxZQUFZLFlBQUUsS0FBTSxDQUFDLEtBQUssR0FBUSxJQUFPLElBRTlFLENBQ1AsQ0FBQztBQUNKLENBQUMifQ==
@@ -0,0 +1,10 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import TextInput from 'ink-text-input';
3
+ import { Box, Text } from 'ink';
4
+ import { useState } from 'react';
5
+ export function ApiKey(props) {
6
+ const { provider, onChange } = props;
7
+ const [apiKey, setApiKey] = useState('');
8
+ return (_jsxs(Box, { flexDirection: 'column', children: [_jsxs(Text, { bold: true, children: [provider?.name, " Api Key:"] }), _jsx(Box, { flexDirection: 'column', marginTop: 1, borderStyle: 'single', borderLeftColor: 'cyan', borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, paddingLeft: 1, children: _jsx(TextInput, { value: apiKey, onChange: setApiKey, onSubmit: () => onChange(apiKey), placeholder: "Enter api key, paste (Ctrl+V)" }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: 'grey', dimColor: true, children: 'Esc (Exit) | Enter (Save)' }) })] }));
9
+ }
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpS2V5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbXBvbmVudHMvYXBpS2V5LnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxTQUFTLE1BQU0sZ0JBQWdCLENBQUM7QUFDdkMsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFFaEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQU9qQyxNQUFNLFVBQVUsTUFBTSxDQUFDLEtBQVk7SUFFakMsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFFckMsTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsR0FBRyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFekMsT0FBTyxDQUNMLE1BQUMsR0FBRyxJQUFDLGFBQWEsRUFBQyxRQUFRLGFBQ3pCLE1BQUMsSUFBSSxJQUFDLElBQUksbUJBQUUsUUFBUSxFQUFFLElBQUksaUJBQWlCLEVBQzNDLEtBQUMsR0FBRyxJQUNGLGFBQWEsRUFBQyxRQUFRLEVBQ3RCLFNBQVMsRUFBRSxDQUFDLEVBQ1osV0FBVyxFQUFDLFFBQVEsRUFDcEIsZUFBZSxFQUFDLE1BQU0sRUFDdEIsVUFBVSxFQUFFLElBQUksRUFDaEIsV0FBVyxFQUFFLEtBQUssRUFDbEIsU0FBUyxFQUFFLEtBQUssRUFDaEIsWUFBWSxFQUFFLEtBQUssRUFDbkIsV0FBVyxFQUFFLENBQUMsWUFDZCxLQUFDLFNBQVMsSUFDUixLQUFLLEVBQUUsTUFBTSxFQUNiLFFBQVEsRUFBRSxTQUFTLEVBQ25CLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQ2hDLFdBQVcsRUFBQywrQkFBK0IsR0FDM0MsR0FDRSxFQUNOLEtBQUMsR0FBRyxJQUFDLFNBQVMsRUFBRSxDQUFDLFlBQ2YsS0FBQyxJQUFJLElBQUMsS0FBSyxFQUFDLE1BQU0sRUFBQyxRQUFRLGtCQUFFLDJCQUEyQixHQUFRLEdBQzVELElBQ0YsQ0FDUCxDQUFDO0FBQ0osQ0FBQyJ9
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import Spinner from 'ink-spinner';
4
+ import spinners from 'cli-spinners';
5
+ import { useMemo } from 'react';
6
+ const colors = ['gray', 'red', 'green', 'yellow', 'blue', 'cyan', 'magenta', 'white'];
7
+ const types = Object.keys(spinners);
8
+ export function Loading() {
9
+ const color = useMemo(() => colors[Math.floor(Math.random() * (colors.length - 1))], []);
10
+ const type = useMemo(() => types[Math.floor(Math.random() * (types.length - 1))], []);
11
+ return (_jsx(Text, { bold: true, color: color, children: _jsx(Spinner, { type: type }) }));
12
+ }
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL2xvYWRpbmcudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQzNCLE9BQU8sT0FBTyxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLFFBQXlCLE1BQU0sY0FBYyxDQUFDO0FBQ3JELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFFaEMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDdEYsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQWtCLENBQUM7QUFFckQsTUFBTSxVQUFVLE9BQU87SUFFckIsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUV0RixPQUFPLENBQ0wsS0FBQyxJQUFJLElBQUMsSUFBSSxRQUFDLEtBQUssRUFBRSxLQUFLLFlBQ3JCLEtBQUMsT0FBTyxJQUFDLElBQUksRUFBRSxJQUFJLEdBQUcsR0FDakIsQ0FDUixDQUFDO0FBQ0osQ0FBQyJ9
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { measureElement, useInput, Box, Text } from 'ink';
3
+ import { useState, useRef, useMemo, useEffect } from 'react';
4
+ import { providers as providerList } from "../providers.js";
5
+ import { configStore } from "../stores/config.js";
6
+ import TextInput from 'ink-text-input';
7
+ const config = await configStore.get();
8
+ export function Provider(props) {
9
+ const { provider, onClose } = props;
10
+ const [enableEdit, setEnableEdit] = useState(false);
11
+ const [apiKey, setApiKey] = useState(config.providers[provider.id]?.apiKey ?? '');
12
+ const [apiKeyInput, setApiKeyInput] = useState(apiKey);
13
+ const [contentHeight, setContentHeight] = useState();
14
+ const contentRef = useRef(null);
15
+ const height = useMemo(() => process.stdout.rows - 2, []);
16
+ useEffect(() => {
17
+ const contentSize = measureElement(contentRef.current);
18
+ const contentHeight = height - contentSize.height;
19
+ setContentHeight(providerList.length > contentHeight ? contentHeight : undefined);
20
+ }, [height]);
21
+ useInput((input, key) => {
22
+ if (key.escape)
23
+ onClose();
24
+ if (input === 'e')
25
+ setEnableEdit(true);
26
+ });
27
+ async function handleSave() {
28
+ await configStore.setProviderApiKey(provider.id, apiKeyInput);
29
+ setApiKey(apiKeyInput);
30
+ setEnableEdit(false);
31
+ }
32
+ return (_jsx(Box, { flexDirection: 'column', children: _jsxs(Box, { flexDirection: 'column', ref: contentRef, children: [_jsx(Text, { bold: true, children: provider.name }), _jsx(Box, { height: contentHeight, marginTop: 1, children: _jsxs(Text, { children: [_jsx(Text, { color: 'gray', bold: true, children: "Api key:" }), " ", apiKey || 'none'] }) }), enableEdit &&
33
+ _jsxs(Box, { marginTop: 1, borderStyle: 'single', borderLeftColor: 'cyan', borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, paddingLeft: 1, children: [_jsx(Text, { color: 'gray', children: "Key: " }), _jsx(TextInput, { value: apiKeyInput, onChange: setApiKeyInput, onSubmit: handleSave, placeholder: "Enter api key, paste (Ctrl + V)" })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: 'gray', children: 'Esc (Back) E (Edit api key)' }) })] }) }));
34
+ }
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcG9uZW50cy9wcm92aWRlci50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQWMsTUFBTSxLQUFLLENBQUM7QUFDdEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUM3RCxPQUFPLEVBQUUsU0FBUyxJQUFJLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTVELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLFNBQVMsTUFBTSxnQkFBZ0IsQ0FBQztBQUV2QyxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQU92QyxNQUFNLFVBQVUsUUFBUSxDQUFDLEtBQVk7SUFFbkMsTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFFcEMsTUFBTSxDQUFDLFVBQVUsRUFBRSxhQUFhLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEQsTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLE1BQU0sQ0FBQyxXQUFXLEVBQUUsY0FBYyxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sQ0FBQyxhQUFhLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxRQUFRLEVBQVUsQ0FBQztJQUU3RCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQWEsSUFBSSxDQUFDLENBQUM7SUFFNUMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUUxRCxTQUFTLENBQUMsR0FBRyxFQUFFO1FBQ2IsTUFBTSxXQUFXLEdBQUcsY0FBYyxDQUFDLFVBQVUsQ0FBQyxPQUFRLENBQUMsQ0FBQztRQUN4RCxNQUFNLGFBQWEsR0FBRyxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQztRQUNsRCxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNwRixDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBRWIsUUFBUSxDQUFDLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ3RCLElBQUksR0FBRyxDQUFDLE1BQU07WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUMxQixJQUFJLEtBQUssS0FBSyxHQUFHO1lBQUUsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBRUgsS0FBSyxVQUFVLFVBQVU7UUFDdkIsTUFBTSxXQUFXLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM5RCxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkIsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxPQUFPLENBQ0wsS0FBQyxHQUFHLElBQUMsYUFBYSxFQUFDLFFBQVEsWUFDekIsTUFBQyxHQUFHLElBQUMsYUFBYSxFQUFDLFFBQVEsRUFBQyxHQUFHLEVBQUUsVUFBVSxhQUN6QyxLQUFDLElBQUksSUFBQyxJQUFJLGtCQUFFLFFBQVEsQ0FBQyxJQUFJLEdBQVEsRUFDakMsS0FBQyxHQUFHLElBQ0YsTUFBTSxFQUFFLGFBQWEsRUFDckIsU0FBUyxFQUFFLENBQUMsWUFDWixNQUFDLElBQUksZUFBQyxLQUFDLElBQUksSUFBQyxLQUFLLEVBQUMsTUFBTSxFQUFDLElBQUksK0JBQWdCLE9BQUUsTUFBTSxJQUFJLE1BQU0sSUFBUSxHQUNuRSxFQUNMLFVBQVU7b0JBQ1QsTUFBQyxHQUFHLElBQ0YsU0FBUyxFQUFFLENBQUMsRUFDWixXQUFXLEVBQUMsUUFBUSxFQUNwQixlQUFlLEVBQUMsTUFBTSxFQUN0QixVQUFVLEVBQUUsSUFBSSxFQUNoQixXQUFXLEVBQUUsS0FBSyxFQUNsQixTQUFTLEVBQUUsS0FBSyxFQUNoQixZQUFZLEVBQUUsS0FBSyxFQUNuQixXQUFXLEVBQUUsQ0FBQyxhQUNkLEtBQUMsSUFBSSxJQUFDLEtBQUssRUFBQyxNQUFNLHNCQUFhLEVBQy9CLEtBQUMsU0FBUyxJQUNSLEtBQUssRUFBRSxXQUFXLEVBQ2xCLFFBQVEsRUFBRSxjQUFjLEVBQ3hCLFFBQVEsRUFBRSxVQUFVLEVBQ3BCLFdBQVcsRUFBQyxpQ0FBaUMsR0FDN0MsSUFDRSxFQUVSLEtBQUMsR0FBRyxJQUFDLFNBQVMsRUFBRSxDQUFDLFlBQ2YsS0FBQyxJQUFJLElBQUMsS0FBSyxFQUFDLE1BQU0sWUFBRSw4QkFBOEIsR0FBUSxHQUN0RCxJQUNGLEdBQ0YsQ0FDUCxDQUFDO0FBQ0osQ0FBQyJ9
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { measureElement, useInput, Box, Text } from 'ink';
3
+ import { ScrollList } from 'ink-scroll-list';
4
+ import { useState, useRef, useMemo, useEffect } from 'react';
5
+ import { providers as providerList } from "../providers.js";
6
+ export function Providers(props) {
7
+ const { onSelect } = props;
8
+ const [visible, setVisible] = useState(true);
9
+ const [currentIndex, setCurrentIndex] = useState(0);
10
+ const [scrollListHeight, setScrollListHeight] = useState();
11
+ const [event, setEvent] = useState();
12
+ const contentRef = useRef(null);
13
+ const height = useMemo(() => process.stdout.rows - 2, []);
14
+ useEffect(() => {
15
+ const contentSize = measureElement(contentRef.current);
16
+ const scrollListHeight = height - contentSize.height;
17
+ setScrollListHeight(providerList.length > scrollListHeight ? scrollListHeight : undefined);
18
+ }, [height]);
19
+ useEffect(() => {
20
+ if (event === 'exit') {
21
+ process.exit();
22
+ }
23
+ }, [event]);
24
+ useInput((_, key) => {
25
+ if (key.escape) {
26
+ setVisible(false);
27
+ setEvent('exit');
28
+ }
29
+ if (key.upArrow) {
30
+ setCurrentIndex((index) => index - 1 >= 0 ? index - 1 : providerList.length - 1);
31
+ }
32
+ if (key.downArrow) {
33
+ setCurrentIndex((index) => index + 1 < providerList.length ? index + 1 : 0);
34
+ }
35
+ if (key.return) {
36
+ onSelect(providerList[currentIndex]);
37
+ }
38
+ });
39
+ if (!visible)
40
+ return null;
41
+ return (_jsx(Box, { flexDirection: 'column', children: _jsxs(Box, { flexDirection: 'column', ref: contentRef, children: [_jsx(Text, { bold: true, children: "Providers" }), _jsx(Box, { height: scrollListHeight, borderStyle: 'single', borderColor: 'cyan', borderTop: false, borderRight: false, borderBottom: false, paddingLeft: 1, marginTop: 1, children: _jsx(ScrollList, { selectedIndex: currentIndex, children: providerList.map((provider, index) => (_jsx(Text, { color: index === currentIndex ? 'cyanBright' : undefined, inverse: index === currentIndex, children: provider.name }, provider.name))) }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: 'gray', children: 'Esc (Exit), Enter (Select)' }) })] }) }));
42
+ }
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbXBvbmVudHMvcHJvdmlkZXJzLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBYyxNQUFNLEtBQUssQ0FBQztBQUN0RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUM3RCxPQUFPLEVBQUUsU0FBUyxJQUFJLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBTzVELE1BQU0sVUFBVSxTQUFTLENBQUMsS0FBWTtJQUVwQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsS0FBSyxDQUFDO0lBRTNCLE1BQU0sQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsZUFBZSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxtQkFBbUIsQ0FBQyxHQUFHLFFBQVEsRUFBVSxDQUFDO0lBQ25FLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLEdBQUcsUUFBUSxFQUFVLENBQUM7SUFFN0MsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFhLElBQUksQ0FBQyxDQUFDO0lBRTVDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFMUQsU0FBUyxDQUFDLEdBQUcsRUFBRTtRQUNiLE1BQU0sV0FBVyxHQUFHLGNBQWMsQ0FBQyxVQUFVLENBQUMsT0FBUSxDQUFDLENBQUM7UUFDeEQsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQztRQUNyRCxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDN0YsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUViLFNBQVMsQ0FBQyxHQUFHLEVBQUU7UUFDYixJQUFJLEtBQUssS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUNyQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDakIsQ0FBQztJQUNILENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFFWixRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFFbEIsSUFBSSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZixVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbEIsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25CLENBQUM7UUFFRCxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoQixlQUFlLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ25GLENBQUM7UUFFRCxJQUFJLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNsQixlQUFlLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUUsQ0FBQztRQUVELElBQUksR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2YsUUFBUSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxPQUFPO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFFMUIsT0FBTyxDQUNMLEtBQUMsR0FBRyxJQUFDLGFBQWEsRUFBQyxRQUFRLFlBQ3pCLE1BQUMsR0FBRyxJQUFDLGFBQWEsRUFBQyxRQUFRLEVBQUMsR0FBRyxFQUFFLFVBQVUsYUFDekMsS0FBQyxJQUFJLElBQUMsSUFBSSxnQ0FBaUIsRUFDM0IsS0FBQyxHQUFHLElBQ0YsTUFBTSxFQUFFLGdCQUFnQixFQUN4QixXQUFXLEVBQUMsUUFBUSxFQUNwQixXQUFXLEVBQUMsTUFBTSxFQUNsQixTQUFTLEVBQUUsS0FBSyxFQUNoQixXQUFXLEVBQUUsS0FBSyxFQUNsQixZQUFZLEVBQUUsS0FBSyxFQUNuQixXQUFXLEVBQUUsQ0FBQyxFQUNkLFNBQVMsRUFBRSxDQUFDLFlBQ1osS0FBQyxVQUFVLElBQUMsYUFBYSxFQUFFLFlBQVksWUFDcEMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQ3JDLEtBQUMsSUFBSSxJQUVILEtBQUssRUFBRSxLQUFLLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFDeEQsT0FBTyxFQUFFLEtBQUssS0FBSyxZQUFZLFlBQzlCLFFBQVEsQ0FBQyxJQUFJLElBSFQsUUFBUSxDQUFDLElBQUksQ0FJYixDQUNSLENBQUMsR0FDUyxHQUNULEVBQ04sS0FBQyxHQUFHLElBQUMsU0FBUyxFQUFFLENBQUMsWUFDZixLQUFDLElBQUksSUFBQyxLQUFLLEVBQUMsTUFBTSxZQUFFLDRCQUE0QixHQUFRLEdBQ3BELElBQ0YsR0FDRixDQUNQLENBQUM7QUFDSixDQUFDIn0=
@@ -0,0 +1,106 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { measureElement, useInput, Box, Text } from 'ink';
3
+ import { useState, useRef, useMemo, useEffect } from 'react';
4
+ import { ScrollView } from 'ink-scroll-view';
5
+ import { Fragment } from 'react/jsx-runtime';
6
+ import { providers } from "../providers.js";
7
+ import { configStore } from "../stores/config.js";
8
+ import { ApiKey } from "./apiKey.js";
9
+ const config = await configStore.get();
10
+ export function SelectModel(props) {
11
+ const { onSelect } = props;
12
+ const [view, setView] = useState('select-model');
13
+ const [currentPosition, setCurrentPosition] = useState(0);
14
+ const [scrollViewHeight, setScrollViewHeight] = useState(0);
15
+ const [model, setModel] = useState();
16
+ const [provider, setProvider] = useState();
17
+ const [startPosition, setStartPosition] = useState(0);
18
+ const [endPosition, setEndPosition] = useState(0);
19
+ const scrollRef = useRef(null);
20
+ const contentRef = useRef(null);
21
+ const items = useMemo(() => {
22
+ const items = [];
23
+ const selectedModel = providers.flatMap(provider => provider.models).find(m => m.name === config.model?.model);
24
+ if (selectedModel) {
25
+ items.push({ type: 'provider', key: 'selected-model-title', provider: 'Selected model' });
26
+ items.push({ type: 'model', key: 'selected-model', model: selectedModel });
27
+ items.push({ type: 'new-line', key: 'selected-model-newline' });
28
+ }
29
+ for (const provider of providers) {
30
+ items.push({ type: 'provider', key: provider.name, provider: provider.name });
31
+ for (const model of provider.models) {
32
+ items.push({ type: 'model', key: model.name, model: model });
33
+ }
34
+ items.push({ type: 'new-line', key: `${provider.name}-newline` });
35
+ }
36
+ return items;
37
+ }, []);
38
+ useEffect(() => {
39
+ const height = process.stdout.rows - 2;
40
+ const contentSize = measureElement(contentRef.current);
41
+ const scrollViewHeight = height - contentSize.height;
42
+ setScrollViewHeight(scrollViewHeight);
43
+ setEndPosition(scrollViewHeight - 1);
44
+ }, []);
45
+ useEffect(() => {
46
+ setCurrentPosition(items.findIndex(item => item.type === 'model'));
47
+ }, [items]);
48
+ useInput((_, key) => {
49
+ if (key.upArrow) {
50
+ const previousModelItemIndex = items.findLastIndex((item, index) => item.type === 'model' && index < currentPosition);
51
+ const position = previousModelItemIndex === -1 ? currentPosition : previousModelItemIndex;
52
+ setCurrentPosition(position);
53
+ if (position < startPosition) {
54
+ scrollRef.current?.scrollBy(position - startPosition);
55
+ setStartPosition(position);
56
+ setEndPosition(position + (scrollViewHeight - 1));
57
+ return;
58
+ }
59
+ if (items.findIndex(item => item.type === 'model') === position) {
60
+ scrollRef.current?.scrollToTop();
61
+ setStartPosition(0);
62
+ setEndPosition(scrollViewHeight - 1);
63
+ }
64
+ }
65
+ if (key.downArrow) {
66
+ const nextModelItemIndex = items.findIndex((item, index) => item.type === 'model' && index > currentPosition);
67
+ const position = nextModelItemIndex === -1 ? currentPosition : nextModelItemIndex;
68
+ setCurrentPosition(position);
69
+ if (position > endPosition && position < items.length - 1) {
70
+ scrollRef.current?.scrollBy(position - endPosition);
71
+ setStartPosition(position - (scrollViewHeight - 1));
72
+ setEndPosition(position);
73
+ }
74
+ }
75
+ if (key.return) {
76
+ void handleSelectModel(items[currentPosition].model);
77
+ }
78
+ });
79
+ async function handleSelectModel(model) {
80
+ const provider = providers.find(provider => provider.models.some(item => item.name === model.name));
81
+ const config = await configStore.get();
82
+ const apikey = config.providers[provider.id].apiKey;
83
+ setProvider(provider);
84
+ setModel(model);
85
+ if (!apikey) {
86
+ setView('set-api-key');
87
+ return;
88
+ }
89
+ void save(provider, model, apikey);
90
+ }
91
+ function handleApiKeyChange(apiKey) {
92
+ void save(provider, model, apiKey);
93
+ }
94
+ async function save(provider, model, apikey) {
95
+ await configStore.setProviderApiKey(provider.id, apikey);
96
+ await configStore.setModel(provider.id, model.name, apikey);
97
+ onSelect(model, apikey);
98
+ }
99
+ return (_jsxs(Box, { children: [view === 'select-model' &&
100
+ _jsxs(Box, { ref: contentRef, flexDirection: 'column', children: [_jsx(Text, { bold: true, children: "Select a model" }), _jsx(Box, { flexDirection: 'column', height: scrollViewHeight < items.length ? scrollViewHeight : undefined, borderStyle: 'single', borderLeftColor: 'cyan', borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, marginTop: 1, paddingLeft: 1, children: _jsx(ScrollView, { ref: scrollRef, children: items.map((item, index) => _jsxs(Fragment, { children: [item.type === 'provider' &&
101
+ _jsx(Text, { bold: true, color: 'blue', children: item.provider }, item.provider), item.type === 'model' &&
102
+ _jsx(Text, { color: index === currentPosition ? 'cyanBright' : undefined, inverse: index === currentPosition, children: item.model.title }, item.model.name), item.type === 'new-line' &&
103
+ _jsx(Text, { children: " " })] }, item.key)) }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: 'gray', children: 'Esc (Exit), Enter (Select)' }) })] }), view === 'set-api-key' &&
104
+ _jsx(ApiKey, { provider: provider, onChange: handleApiKeyChange })] }));
105
+ }
106
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0TW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tcG9uZW50cy9zZWxlY3RNb2RlbC50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQWMsTUFBTSxLQUFLLENBQUM7QUFDdEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBTyxNQUFNLE9BQU8sQ0FBQztBQUNsRSxPQUFPLEVBQWlCLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM3QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFNUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWxELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxhQUFjLENBQUM7QUFPdEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7QUFNdkMsTUFBTSxVQUFVLFdBQVcsQ0FBQyxLQUFZO0lBRXRDLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFFM0IsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsR0FBRyxRQUFRLENBQWlDLGNBQWMsQ0FBQyxDQUFDO0lBQ2pGLE1BQU0sQ0FBQyxlQUFlLEVBQUUsa0JBQWtCLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUQsTUFBTSxDQUFDLGdCQUFnQixFQUFFLG1CQUFtQixDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVELE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLEdBQUcsUUFBUSxFQUFTLENBQUM7SUFDNUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxXQUFXLENB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
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Static, Text, useInput } from 'ink';
4
+ import { SelectModel } from "./selectModel.js";
5
+ import { logo } from "../utils/logo.js";
6
+ export function Welcome(props) {
7
+ const { onSend } = props;
8
+ const [closed, setClosed] = useState(false);
9
+ useInput((_, key) => {
10
+ if (key.escape) {
11
+ process.exit(0);
12
+ }
13
+ });
14
+ function handleSend(model, apiKey) {
15
+ setClosed(true);
16
+ onSend(model.name, apiKey);
17
+ }
18
+ if (closed) {
19
+ return null;
20
+ }
21
+ return (_jsxs(Box, { flexDirection: 'column', children: [_jsx(Static, { items: [''], children: item => _jsxs(Box, { flexDirection: 'column', marginBottom: 1, children: [_jsx(Text, { children: logo }), _jsxs(Box, { flexDirection: 'column', marginTop: 1, children: [_jsx(Text, { children: "Welcome to ASK CLI, your handy assistant to help you from the terminal!" }), _jsxs(Box, { flexDirection: 'column', marginTop: 1, paddingLeft: 1, children: [_jsx(Text, { children: "\uD83E\uDD16 Get help about commands, coding, apps, etc." }), _jsx(Text, { children: "\uD83D\uDCDD Short and precise answers, just the info you need, straight to the point." }), _jsx(Text, { children: "\uD83D\uDE80 Blazing fast speed, almost instant responses." }), _jsx(Text, { children: "\uD83D\uDEE1\uFE0F Safe by design, it cannot run commands or access your files without your explicit authorization." })] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "To get started, select a model." }) })] }, item) }), _jsx(SelectModel, { onSelect: handleSend })] }));
22
+ }
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2VsY29tZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL3dlbGNvbWUudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDbEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGtCQUFtQixDQUFDO0FBRWhELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU14QyxNQUFNLFVBQVUsT0FBTyxDQUFDLEtBQVk7SUFFbEMsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQztJQUV6QixNQUFNLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUU1QyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDbEIsSUFBSSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUVILFNBQVMsVUFBVSxDQUFDLEtBQVksRUFBRSxNQUFjO1FBQzlDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoQixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRUQsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE9BQU8sQ0FDTCxNQUFDLEdBQUcsSUFBQyxhQUFhLEVBQUMsUUFBUSxhQUN6QixLQUFDLE1BQU0sSUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsWUFDaEIsSUFBSSxDQUFDLEVBQUUsQ0FDTixNQUFDLEdBQUcsSUFBQyxhQUFhLEVBQUMsUUFBUSxFQUFZLFlBQVksRUFBRSxDQUFDLGFBQ3BELEtBQUMsSUFBSSxjQUFFLElBQUksR0FBUSxFQUNuQixNQUFDLEdBQUcsSUFBQyxhQUFhLEVBQUMsUUFBUSxFQUFDLFNBQVMsRUFBRSxDQUFDLGFBQ3RDLEtBQUMsSUFBSSwwRkFBK0UsRUFDcEYsTUFBQyxHQUFHLElBQUMsYUFBYSxFQUFDLFFBQVEsRUFBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLGFBQ3RELEtBQUMsSUFBSSw0RUFBdUQsRUFDNUQsS0FBQyxJQUFJLDBHQUFxRixFQUMxRixLQUFDLElBQUksOEVBQXlELEVBQzlELEtBQUMsSUFBSSx1SUFBNkcsSUFDOUcsSUFDRixFQUNOLEtBQUMsR0FBRyxJQUFDLFNBQVMsRUFBRSxDQUFDLFlBQ2YsS0FBQyxJQUFJLGtEQUF1QyxHQUN4QyxLQWJ5QixJQUFJLENBYy9CLEdBRUQsRUFDVCxLQUFDLFdBQVcsSUFBQyxRQUFRLEVBQUUsVUFBVSxHQUFHLElBQ2hDLENBQ1AsQ0FBQztBQUNKLENBQUMifQ==
@@ -0,0 +1,35 @@
1
+ export const providers = [
2
+ {
3
+ id: 'gemini',
4
+ name: 'Gemini',
5
+ models: [
6
+ { title: 'Gemini 3 Flash Preview', name: 'gemini-3-flash-preview', config: { thinkingConfig: { thinkingLevel: 'LOW' } } },
7
+ { title: 'Gemini 3 Pro Preview', name: 'gemini-3-pro-preview', config: { thinkingConfig: { thinkingLevel: 'LOW' } } },
8
+ { title: 'Gemini 2.5 Flash', name: 'gemini-2.5-flash', config: { thinkingBudget: 500 } },
9
+ { title: 'Gemini 2.5 Flash Lite', name: 'gemini-2.5-flash-lite', config: { thinkingBudget: 512 } },
10
+ { title: 'Gemini 2.5 Pro', name: 'gemini-2.5-pro', config: { thinkingBudget: 500 } }
11
+ ]
12
+ },
13
+ {
14
+ id: 'openai',
15
+ name: 'OpenAI',
16
+ models: [
17
+ { title: 'GPT-5 Mini', name: 'gpt-5-mini', config: { effort: 'low' } },
18
+ { title: 'GPT-5 Nano', name: 'gpt-5-nano', config: { effort: 'low' } },
19
+ { title: 'GPT-5', name: 'gpt-5', config: { effort: 'low' } },
20
+ { title: 'GPT-5.2', name: 'gpt-5.2', config: { effort: 'low' } },
21
+ { title: 'GPT-5.2 Pro', name: 'gpt-5.2-pro', config: { effort: 'low' } },
22
+ { title: 'GPT-4.1', name: 'gpt-4.1' },
23
+ ]
24
+ },
25
+ {
26
+ id: 'anthropic',
27
+ name: 'Anthropic',
28
+ models: [
29
+ { title: 'Claude Haiku 4.5', name: 'claude-haiku-4-5' },
30
+ { title: 'Claude Sonnet 4.5', name: 'claude-sonnet-4-5' },
31
+ { title: 'Claude Opus 4.5', name: 'claude-opus-4-5' }
32
+ ]
33
+ }
34
+ ];
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb3ZpZGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLENBQUMsTUFBTSxTQUFTLEdBQWU7SUFDbkM7UUFDRSxFQUFFLEVBQUUsUUFBUTtRQUNaLElBQUksRUFBRSxRQUFRO1FBQ2QsTUFBTSxFQUFFO1lBQ04sRUFBRSxLQUFLLEVBQUUsd0JBQXdCLEVBQUUsSUFBSSxFQUFFLHdCQUF3QixFQUFFLE1BQU0sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ3pILEVBQUUsS0FBSyxFQUFFLHNCQUFzQixFQUFFLElBQUksRUFBRSxzQkFBc0IsRUFBRSxNQUFNLEVBQUUsRUFBRSxjQUFjLEVBQUUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNySCxFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxFQUFFLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxFQUFFO1lBQ3hGLEVBQUUsS0FBSyxFQUFFLHVCQUF1QixFQUFFLElBQUksRUFBRSx1QkFBdUIsRUFBRSxNQUFNLEVBQUUsRUFBRSxjQUFjLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDbEcsRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxFQUFFLGNBQWMsRUFBRSxHQUFHLEVBQUUsRUFBRTtTQUNyRjtLQUNGO0lBQ0Q7UUFDRSxFQUFFLEVBQUUsUUFBUTtRQUNaLElBQUksRUFBRSxRQUFRO1FBQ2QsTUFBTSxFQUFFO1lBQ04sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3RFLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUN0RSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDNUQsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ2hFLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUN4RSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtTQUN0QztLQUNGO0lBQ0Q7UUFDRSxFQUFFLEVBQUUsV0FBVztRQUNmLElBQUksRUFBRSxXQUFXO1FBQ2pCLE1BQU0sRUFBRTtZQUNOLEVBQUUsS0FBSyxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUN2RCxFQUFFLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUU7WUFDekQsRUFBRSxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1NBQ3REO0tBQ0Y7Q0FDRixDQUFDIn0=
@@ -0,0 +1,46 @@
1
+ import { store } from "./store.js";
2
+ const path = './data/config.json';
3
+ let config;
4
+ async function get() {
5
+ if (config)
6
+ return config;
7
+ config = await store.get(path, {
8
+ model: undefined,
9
+ providers: {
10
+ gemini: {
11
+ apiKey: undefined
12
+ },
13
+ anthropic: {
14
+ apiKey: undefined
15
+ },
16
+ openai: {
17
+ apiKey: undefined
18
+ }
19
+ }
20
+ });
21
+ return config;
22
+ }
23
+ async function setModel(provider, model, apiKey) {
24
+ const config = await get();
25
+ config.model = {
26
+ provider: provider,
27
+ model: model,
28
+ apiKey: apiKey
29
+ };
30
+ await save(config);
31
+ }
32
+ async function setProviderApiKey(providerId, apiKey) {
33
+ const config = await get();
34
+ config.providers[providerId].apiKey = apiKey;
35
+ await save(config);
36
+ }
37
+ async function save(config) {
38
+ await store.save(path, config);
39
+ }
40
+ export const configStore = {
41
+ get,
42
+ setModel,
43
+ setProviderApiKey,
44
+ save
45
+ };
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3Jlcy9jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVuQyxNQUFNLElBQUksR0FBRyxvQkFBb0IsQ0FBQztBQUVsQyxJQUFJLE1BQWMsQ0FBQztBQUVuQixLQUFLLFVBQVUsR0FBRztJQUVoQixJQUFJLE1BQU07UUFBRSxPQUFPLE1BQU0sQ0FBQztJQUUxQixNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFTLElBQUksRUFBRTtRQUNyQyxLQUFLLEVBQUUsU0FBUztRQUNoQixTQUFTLEVBQUU7WUFDVCxNQUFNLEVBQUU7Z0JBQ04sTUFBTSxFQUFFLFNBQVM7YUFDbEI7WUFDRCxTQUFTLEVBQUU7Z0JBQ1QsTUFBTSxFQUFFLFNBQVM7YUFDbEI7WUFDRCxNQUFNLEVBQUU7Z0JBQ04sTUFBTSxFQUFFLFNBQVM7YUFDbEI7U0FDRjtLQUNGLENBQUMsQ0FBQztJQUVILE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxLQUFLLFVBQVUsUUFBUSxDQUFDLFFBQWdCLEVBQUUsS0FBYSxFQUFFLE1BQWM7SUFFckUsTUFBTSxNQUFNLEdBQUcsTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUUzQixNQUFNLENBQUMsS0FBSyxHQUFHO1FBQ2IsUUFBUSxFQUFFLFFBQVE7UUFDbEIsS0FBSyxFQUFFLEtBQUs7UUFDWixNQUFNLEVBQUUsTUFBTTtLQUNmLENBQUM7SUFFRixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNyQixDQUFDO0FBRUQsS0FBSyxVQUFVLGlCQUFpQixDQUFDLFVBQWtCLEVBQUUsTUFBYztJQUNqRSxNQUFNLE1BQU0sR0FBRyxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQzNCLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUM3QyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNyQixDQUFDO0FBRUQsS0FBSyxVQUFVLElBQUksQ0FBQyxNQUFjO0lBQ2hDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVELE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRztJQUN6QixHQUFHO0lBQ0gsUUFBUTtJQUNSLGlCQUFpQjtJQUNqQixJQUFJO0NBQ0wsQ0FBQyJ9
@@ -0,0 +1,29 @@
1
+ import { store } from "./store.js";
2
+ const path = `./data/chats/history.${process.ppid}.json`;
3
+ let history;
4
+ async function get() {
5
+ if (history)
6
+ return history;
7
+ history = await store.get(path, []);
8
+ return history;
9
+ }
10
+ async function add(message) {
11
+ const messages = Array.isArray(message) ? message : [message];
12
+ const history = await get();
13
+ history.push(...messages);
14
+ await save(history);
15
+ }
16
+ async function clear() {
17
+ history = [];
18
+ await save(history);
19
+ }
20
+ async function save(history) {
21
+ await store.save(path, history);
22
+ }
23
+ export const historyStore = {
24
+ get,
25
+ add,
26
+ clear,
27
+ save
28
+ };
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGlzdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZXMvaGlzdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRW5DLE1BQU0sSUFBSSxHQUFHLHdCQUF3QixPQUFPLENBQUMsSUFBSSxPQUFPLENBQUM7QUFFekQsSUFBSSxPQUFrQixDQUFDO0FBRXZCLEtBQUssVUFBVSxHQUFHO0lBQ2hCLElBQUksT0FBTztRQUFFLE9BQU8sT0FBTyxDQUFDO0lBQzVCLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQVksSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxLQUFLLFVBQVUsR0FBRyxDQUFDLE9BQTRCO0lBQzdDLE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5RCxNQUFNLE9BQU8sR0FBRyxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQzVCLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQztJQUMxQixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUN0QixDQUFDO0FBRUQsS0FBSyxVQUFVLEtBQUs7SUFDbEIsT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUNiLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ3RCLENBQUM7QUFFRCxLQUFLLFVBQVUsSUFBSSxDQUFDLE9BQWtCO0lBQ3BDLE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDbEMsQ0FBQztBQUVELE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRztJQUMxQixHQUFHO0lBQ0gsR0FBRztJQUNILEtBQUs7SUFDTCxJQUFJO0NBQ0wsQ0FBQyJ9
@@ -0,0 +1,26 @@
1
+ import { dirname, join } from 'path';
2
+ import { existsSync } from 'fs';
3
+ import { readFile, mkdir, writeFile } from 'fs/promises';
4
+ import { root } from "../utils/root.js";
5
+ async function get(path, defaultData) {
6
+ try {
7
+ const filePath = join(root, path);
8
+ const content = await readFile(filePath, 'utf-8');
9
+ return JSON.parse(content);
10
+ }
11
+ catch {
12
+ return defaultData;
13
+ }
14
+ }
15
+ async function save(path, data) {
16
+ const filePath = join(root, path);
17
+ if (!existsSync(dirname(filePath))) {
18
+ await mkdir(dirname(filePath), { recursive: true });
19
+ }
20
+ await writeFile(filePath, JSON.stringify(data));
21
+ }
22
+ export const store = {
23
+ get,
24
+ save
25
+ };
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmVzL3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDaEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUV4QyxLQUFLLFVBQVUsR0FBRyxDQUFJLElBQVksRUFBRSxXQUFjO0lBQ2hELElBQUksQ0FBQztRQUNILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxRQUFRLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2xELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQU0sQ0FBQztJQUNsQyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsSUFBSSxDQUFDLElBQVksRUFBRSxJQUFhO0lBQzdDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ25DLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFDRCxNQUFNLFNBQVMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQUc7SUFDbkIsR0FBRztJQUNILElBQUk7Q0FDTCxDQUFDIn0=
@@ -0,0 +1,55 @@
1
+ export const instructions = `
2
+ You are a CLI (command line tool).
3
+ - Your name is Ask Cli
4
+ - Your main job is to answer the user question in the best way possible. Your responses must be clear, exact and precise.
5
+ - You must help the user with info about commands, programs, OS, coding, development, etc.
6
+ - If the user doesn't specify the OS, assume they are using ${process.platform}.
7
+ - Don't add more information than necessary.
8
+ - Your answers must be short but complete.
9
+ - You must format your responses for a terminal or a console.
10
+ - Highlight the response using console colors like \\x1b[94m (blue), \x1b[32m (green), etc.
11
+ - Use colors to highlight code snippets, important information, commands, warnings, errors, etc.
12
+ - Use white for normal text.
13
+ - Use \\x1b[0m to reset the color after using colors.
14
+ - Always highlight the code in the response using different colors like \\x1b[94m (blue), \x1b[32m (green). Highlight it as a modern dark theme of VS Code.
15
+ - You must respond in plain text, not markdown.
16
+ - Do not use markdown syntax.
17
+ - Your answers must be compact.
18
+ - Limit your answer to 500 tokens. This is not mandatory, but try to stick to it. If you really need more tokens, you can exceed this limit.
19
+ - Try to save as many lines as possible. If two or three lines can be one, just use one.
20
+ - You cannot execute commands on the user's system. If the user wants to run a command and analyze its output, guide them to use the -c option (e.g., ask "explain this" -c "command").
21
+
22
+ Current OS: ${process.platform}
23
+
24
+ Current path: ${process.cwd()}
25
+
26
+ Current date: ${new Date().toString()}
27
+
28
+ Ask Cli help:
29
+
30
+ AI CLI to help you with commands, coding, apps and more.
31
+
32
+ Usage: ask <prompt..>
33
+
34
+ Commands:
35
+ ask <prompt..> Ask something. Alias: what, how [default]
36
+ ask /models Select a model
37
+ ask /providers Setup providers
38
+ ask /history List the chat history
39
+ ask /clear Clear the chat history
40
+
41
+ Positionals:
42
+ prompt [string]
43
+
44
+ Options:
45
+ --version Show version number [boolean]
46
+ --help Show help [boolean]
47
+ -c, --command Command to execute [string]
48
+
49
+ Examples:
50
+ ask how to run a docker container
51
+ how to setup my git account
52
+ what is the chmod command
53
+ ask what is using port 80 -c "netstat -ano"
54
+ `;
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdHJ1Y3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RlbXBsYXRlcy9pbnN0cnVjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHOzs7OztnRUFLb0MsT0FBTyxDQUFDLFFBQVE7Ozs7Ozs7Ozs7Ozs7Ozs7Y0FnQmxFLE9BQU8sQ0FBQyxRQUFROztnQkFFZCxPQUFPLENBQUMsR0FBRyxFQUFFOztnQkFFYixJQUFJLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQTRCcEMsQ0FBQyJ9
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R5cGVzL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9tZXNzYWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvbW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -0,0 +1,12 @@
1
+ export const logo = `
2
+
3
+ │ ░██ ░██ ░██ ░██
4
+ │ ░██ ░██ ░██
5
+ │ ░██████ ░███████ ░██ ░██ ░███████ ░██ ░██ ░██
6
+ │ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
7
+ │ ░███████ ░███████ ░███████ ░██ ░██ ░██ ░██
8
+ │ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██
9
+ │ ░█████░██ ░███████ ░██ ░██ ░███████ ░██ ░██ ░██
10
+
11
+ `;
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9sb2dvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sQ0FBQyxNQUFNLElBQUksR0FBRzs7Ozs7Ozs7OztDQVVuQixDQUFDIn0=
@@ -0,0 +1,3 @@
1
+ import path from 'path';
2
+ export const root = path.join(import.meta.dirname, '..');
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9vdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9yb290LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUV4QixNQUFNLENBQUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyJ9
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "ask-cli-ai",
3
+ "description": "AI CLI to help you with commands, coding, apps, and more from your terminal.",
4
+ "version": "1.0.0",
5
+ "license": "ISC",
6
+ "author": "David Minaya",
7
+ "type": "module",
8
+ "main": "./dist/app.js",
9
+ "bin": {
10
+ "ask": "dist/app.js",
11
+ "how": "dist/app.js",
12
+ "what": "dist/app.js",
13
+ "que": "dist/app.js",
14
+ "como": "dist/app.js",
15
+ "cual": "dist/app.js"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsc --incremental && node --enable-source-maps .",
20
+ "lint": "eslint .",
21
+ "typelint": "npm run lint && tsc --noEmit"
22
+ },
23
+ "dependencies": {
24
+ "@langchain/anthropic": "^1.3.7",
25
+ "@langchain/core": "^1.1.12",
26
+ "@langchain/google-genai": "^2.1.7",
27
+ "@langchain/openai": "^1.2.1",
28
+ "dotenv": "^17.2.3",
29
+ "find-process": "^2.0.0",
30
+ "ink": "^6.6.0",
31
+ "ink-scroll-list": "^0.4.1",
32
+ "ink-scroll-view": "^0.3.5",
33
+ "ink-select-input": "^6.2.0",
34
+ "ink-spinner": "^5.0.0",
35
+ "ink-text-input": "^6.0.0",
36
+ "langchain": "^1.2.7",
37
+ "react": "^19.2.3",
38
+ "yargs": "^18.0.0"
39
+ },
40
+ "devDependencies": {
41
+ "@eslint/js": "^9.39.2",
42
+ "@stylistic/eslint-plugin": "^5.6.1",
43
+ "@tsconfig/node22": "^22.0.5",
44
+ "@types/node": "^25.0.3",
45
+ "@types/react": "^19.2.7",
46
+ "@types/yargs": "^17.0.35",
47
+ "eslint": "^9.39.2",
48
+ "eslint-plugin-react": "^7.37.5",
49
+ "globals": "^17.0.0",
50
+ "ts-node": "^10.9.2",
51
+ "typescript": "^5.9.3",
52
+ "typescript-eslint": "^8.51.0"
53
+ }
54
+ }