command-gpt 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/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # ShellAI (`s`)
2
+
3
+ > Convert plain English into shell commands — powered by AI.
4
+
5
+ ```
6
+ $ s "find all files larger than 100MB"
7
+
8
+ ╭─ Command ──────────────────────────────╮
9
+ │ find . -size +100M │
10
+ ╰────────────────────────────────────────╯
11
+
12
+ Explains Finds all files larger than 100MB in the current directory
13
+
14
+ Alternatives:
15
+ • find . -size +100M -type f
16
+ • du -ah . | sort -rh | head -20
17
+
18
+ Run it? › [y] run [n] cancel [c] copy
19
+ ```
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ # Clone and install globally
25
+ cd shellAi
26
+ npm install
27
+ npm run build
28
+ npm link
29
+
30
+ # After install, run setup
31
+ s --setup
32
+ ```
33
+
34
+ Or install from npm (once published):
35
+
36
+ ```bash
37
+ npm install -g shellai
38
+ s --setup
39
+ ```
40
+
41
+ ## Setup
42
+
43
+ Run the interactive setup to configure your API key:
44
+
45
+ ```bash
46
+ s --setup
47
+ ```
48
+
49
+ You'll be prompted to:
50
+ 1. Choose your LLM provider (Groq or OpenAI)
51
+ 2. Enter your API key
52
+ 3. Set shell preferences
53
+
54
+ ### Getting a Free Groq API Key
55
+
56
+ 1. Go to [console.groq.com](https://console.groq.com)
57
+ 2. Sign up for a free account
58
+ 3. Navigate to **API Keys** in the sidebar
59
+ 4. Click **Create API Key**
60
+ 5. Copy the key and paste it during `s --setup`
61
+
62
+ Groq provides free access to Llama 3.3 70B — it's fast and works great for command generation.
63
+
64
+ ### Switching to OpenAI
65
+
66
+ If you prefer to use OpenAI:
67
+
68
+ ```bash
69
+ s --setup
70
+ # Select "OpenAI (gpt-4o-mini)" as your provider
71
+ # Enter your OpenAI API key
72
+ ```
73
+
74
+ ## Usage Examples
75
+
76
+ ```bash
77
+ # Find large files
78
+ s "find all files larger than 100MB"
79
+
80
+ # Kill a process by port
81
+ s "kill the process running on port 3000"
82
+
83
+ # Compress a folder
84
+ s "compress this folder into a zip"
85
+
86
+ # Disk usage
87
+ s "show disk usage sorted by size"
88
+
89
+ # Git operations
90
+ s "undo the last commit but keep the changes"
91
+ ```
92
+
93
+ ## How It Works
94
+
95
+ 1. You type a command description in plain English
96
+ 2. ShellAI detects your OS, shell, and working directory
97
+ 3. It sends your request to an LLM (Groq or OpenAI) with full context
98
+ 4. The LLM returns a precise shell command with an explanation
99
+ 5. You choose to **run**, **cancel**, or **copy** the command
100
+
101
+ ## Safety Features
102
+
103
+ - **Dangerous command warnings**: Commands that delete or modify files are flagged with a red warning
104
+ - **Double confirmation for `rm -rf`**: Extra safety for destructive deletions
105
+ - **Sudo detection**: Yellow warning when commands require elevated privileges
106
+ - **No auto-sudo**: Commands never include `sudo` unless you explicitly ask
107
+
108
+ ## Configuration
109
+
110
+ Config is stored at `~/.shellai/config.json`:
111
+
112
+ ```json
113
+ {
114
+ "groqApiKey": "gsk_...",
115
+ "openaiApiKey": "",
116
+ "defaultProvider": "groq",
117
+ "shell": "auto",
118
+ "confirmBeforeRun": true
119
+ }
120
+ ```
121
+
122
+ View your current config:
123
+
124
+ ```bash
125
+ s --config
126
+ ```
127
+
128
+ ## Commands
129
+
130
+ | Command | Description |
131
+ |---------|-------------|
132
+ | `s "your request"` | Convert English to a shell command |
133
+ | `s --setup` | Configure API keys and preferences |
134
+ | `s --config` | Show current configuration |
135
+ | `s --help` | Show help information |
136
+ | `s --version` | Show version number |
137
+
138
+ ## Tech Stack
139
+
140
+ - **TypeScript** + **Node.js 18+**
141
+ - **Groq API** (primary, free) — Llama 3.3 70B
142
+ - **OpenAI API** (fallback) — GPT-4o-mini
143
+ - **Commander** — CLI argument parsing
144
+ - **Inquirer** — Interactive prompts
145
+ - **Chalk** — Colored terminal output
146
+ - **Ora** — Loading spinners
147
+ - **Execa** — Safe command execution
148
+ - **Clipboardy** — Clipboard support
149
+
150
+ ## License
151
+
152
+ MIT
@@ -0,0 +1,11 @@
1
+ export interface ShellAiConfig {
2
+ groqApiKey: string;
3
+ openaiApiKey: string;
4
+ defaultProvider: 'groq' | 'openai';
5
+ shell: string;
6
+ confirmBeforeRun: boolean;
7
+ }
8
+ export declare function getConfig(): ShellAiConfig;
9
+ export declare function setConfig(key: keyof ShellAiConfig, value: string | boolean): void;
10
+ export declare function runSetup(): Promise<void>;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,QAAQ,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAgBD,wBAAgB,SAAS,IAAI,aAAa,CAQzC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAEjF;AAED,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAoE9C"}
package/dist/config.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getConfig = getConfig;
7
+ exports.setConfig = setConfig;
8
+ exports.runSetup = runSetup;
9
+ const conf_1 = __importDefault(require("conf"));
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const defaults = {
13
+ groqApiKey: '',
14
+ openaiApiKey: '',
15
+ defaultProvider: 'groq',
16
+ shell: 'auto',
17
+ confirmBeforeRun: true,
18
+ };
19
+ const config = new conf_1.default({
20
+ projectName: 'shellai',
21
+ cwd: `${process.env.HOME || process.env.USERPROFILE}/.shellai`,
22
+ defaults,
23
+ });
24
+ function getConfig() {
25
+ return {
26
+ groqApiKey: config.get('groqApiKey'),
27
+ openaiApiKey: config.get('openaiApiKey'),
28
+ defaultProvider: config.get('defaultProvider'),
29
+ shell: config.get('shell'),
30
+ confirmBeforeRun: config.get('confirmBeforeRun'),
31
+ };
32
+ }
33
+ function setConfig(key, value) {
34
+ config.set(key, value);
35
+ }
36
+ async function runSetup() {
37
+ console.log(chalk_1.default.bold.cyan('\n🔧 ShellAI Setup\n'));
38
+ console.log(chalk_1.default.gray('Configure your API keys and preferences.\n'));
39
+ const answers = await inquirer_1.default.prompt([
40
+ {
41
+ type: 'list',
42
+ name: 'defaultProvider',
43
+ message: 'Select your default LLM provider:',
44
+ choices: [
45
+ { name: 'Groq (free, fast — recommended)', value: 'groq' },
46
+ { name: 'OpenAI (gpt-4o-mini)', value: 'openai' },
47
+ ],
48
+ default: config.get('defaultProvider'),
49
+ },
50
+ {
51
+ type: 'input',
52
+ name: 'groqApiKey',
53
+ message: 'Groq API key (get one free at https://console.groq.com):',
54
+ default: config.get('groqApiKey') || undefined,
55
+ when: (ans) => ans.defaultProvider === 'groq',
56
+ },
57
+ {
58
+ type: 'input',
59
+ name: 'openaiApiKey',
60
+ message: 'OpenAI API key:',
61
+ default: config.get('openaiApiKey') || undefined,
62
+ when: (ans) => ans.defaultProvider === 'openai',
63
+ },
64
+ {
65
+ type: 'list',
66
+ name: 'shell',
67
+ message: 'Shell preference:',
68
+ choices: [
69
+ { name: 'Auto-detect (recommended)', value: 'auto' },
70
+ { name: 'bash', value: 'bash' },
71
+ { name: 'zsh', value: 'zsh' },
72
+ { name: 'fish', value: 'fish' },
73
+ { name: 'PowerShell', value: 'powershell' },
74
+ ],
75
+ default: config.get('shell'),
76
+ },
77
+ {
78
+ type: 'confirm',
79
+ name: 'confirmBeforeRun',
80
+ message: 'Always confirm before running commands?',
81
+ default: config.get('confirmBeforeRun'),
82
+ },
83
+ ]);
84
+ if (answers.groqApiKey !== undefined)
85
+ config.set('groqApiKey', answers.groqApiKey);
86
+ if (answers.openaiApiKey !== undefined)
87
+ config.set('openaiApiKey', answers.openaiApiKey);
88
+ config.set('defaultProvider', answers.defaultProvider);
89
+ config.set('shell', answers.shell);
90
+ config.set('confirmBeforeRun', answers.confirmBeforeRun);
91
+ console.log(chalk_1.default.green('\n✅ Setup complete!'));
92
+ console.log(chalk_1.default.gray(`Config saved to: ${config.path}\n`));
93
+ console.log(chalk_1.default.cyan('Try it out:'));
94
+ console.log(chalk_1.default.white(' s "find large files"\n'));
95
+ }
96
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface SystemContext {
2
+ os: string;
3
+ shell: string;
4
+ cwd: string;
5
+ homeDir: string;
6
+ username: string;
7
+ hostname: string;
8
+ arch: string;
9
+ nodeVersion: string;
10
+ }
11
+ export declare function getSystemContext(): SystemContext;
12
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACvB;AA0BD,wBAAgB,gBAAgB,IAAI,aAAa,CAWhD"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getSystemContext = getSystemContext;
7
+ const os_1 = __importDefault(require("os"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const config_1 = require("./config");
10
+ function detectShell() {
11
+ const config = (0, config_1.getConfig)();
12
+ if (config.shell && config.shell !== 'auto') {
13
+ return config.shell;
14
+ }
15
+ const shellEnv = process.env.SHELL || '';
16
+ if (shellEnv) {
17
+ const shellName = path_1.default.basename(shellEnv);
18
+ return shellName;
19
+ }
20
+ if (process.env.PSModulePath) {
21
+ return 'powershell';
22
+ }
23
+ if (process.env.COMSPEC) {
24
+ return 'cmd';
25
+ }
26
+ return 'bash';
27
+ }
28
+ function getSystemContext() {
29
+ return {
30
+ os: process.platform,
31
+ shell: detectShell(),
32
+ cwd: process.cwd(),
33
+ homeDir: os_1.default.homedir(),
34
+ username: os_1.default.userInfo().username,
35
+ hostname: os_1.default.hostname(),
36
+ arch: process.arch,
37
+ nodeVersion: process.version,
38
+ };
39
+ }
40
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;;;;AAuCA,4CAWC;AAlDD,4CAAoB;AACpB,gDAAwB;AACxB,qCAAqC;AAarC,SAAS,WAAW;IAChB,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;IACzC,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,cAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC3B,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAgB,gBAAgB;IAC5B,OAAO;QACH,EAAE,EAAE,OAAO,CAAC,QAAQ;QACpB,KAAK,EAAE,WAAW,EAAE;QACpB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,OAAO,EAAE,YAAE,CAAC,OAAO,EAAE;QACrB,QAAQ,EAAE,YAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ;QAChC,QAAQ,EAAE,YAAE,CAAC,QAAQ,EAAE;QACvB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,OAAO;KAC/B,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const clipboardy_1 = __importDefault(require("clipboardy"));
12
+ const config_1 = require("./config");
13
+ const context_1 = require("./context");
14
+ const llm_1 = require("./llm");
15
+ const renderer_1 = require("./renderer");
16
+ const runner_1 = require("./runner");
17
+ const program = new commander_1.Command();
18
+ program
19
+ .name('s')
20
+ .description('ShellAI — Convert plain English to shell commands using AI')
21
+ .version('1.0.0')
22
+ .argument('[query...]', 'Natural language description of the command you need')
23
+ .option('--setup', 'Run interactive setup to configure API keys')
24
+ .option('--config', 'Show current configuration')
25
+ .action(async (queryParts, options) => {
26
+ try {
27
+ // Handle --setup
28
+ if (options.setup) {
29
+ await (0, config_1.runSetup)();
30
+ return;
31
+ }
32
+ // Handle --config
33
+ if (options.config) {
34
+ const config = (0, config_1.getConfig)();
35
+ console.log(chalk_1.default.bold.cyan('\n📋 Current Configuration:\n'));
36
+ console.log(chalk_1.default.gray(' Provider: ') + chalk_1.default.white(config.defaultProvider));
37
+ console.log(chalk_1.default.gray(' Groq Key: ') +
38
+ chalk_1.default.white(config.groqApiKey ? '••••' + config.groqApiKey.slice(-4) : chalk_1.default.yellow('not set')));
39
+ console.log(chalk_1.default.gray(' OpenAI Key: ') +
40
+ chalk_1.default.white(config.openaiApiKey ? '••••' + config.openaiApiKey.slice(-4) : chalk_1.default.yellow('not set')));
41
+ console.log(chalk_1.default.gray(' Shell: ') + chalk_1.default.white(config.shell));
42
+ console.log(chalk_1.default.gray(' Confirm: ') + chalk_1.default.white(config.confirmBeforeRun ? 'yes' : 'no'));
43
+ console.log('');
44
+ return;
45
+ }
46
+ // Need a query
47
+ const query = queryParts.join(' ').trim();
48
+ if (!query) {
49
+ console.log(chalk_1.default.bold.cyan('\n ShellAI') + chalk_1.default.gray(' — Convert English to shell commands\n'));
50
+ console.log(chalk_1.default.white(' Usage:'));
51
+ console.log(chalk_1.default.gray(' s "find all files larger than 100MB"'));
52
+ console.log(chalk_1.default.gray(' s "kill the process running on port 3000"'));
53
+ console.log(chalk_1.default.gray(' s "compress this folder into a zip"'));
54
+ console.log('');
55
+ console.log(chalk_1.default.white(' Setup:'));
56
+ console.log(chalk_1.default.gray(' s --setup Configure API keys'));
57
+ console.log(chalk_1.default.gray(' s --config Show current config'));
58
+ console.log('');
59
+ return;
60
+ }
61
+ // Check for API keys
62
+ const config = (0, config_1.getConfig)();
63
+ if (!config.groqApiKey && !config.openaiApiKey) {
64
+ console.log(chalk_1.default.red('\n ✗ No API key configured.'));
65
+ console.log(chalk_1.default.gray(' Run ') + chalk_1.default.cyan('s --setup') + chalk_1.default.gray(' to configure your API keys.\n'));
66
+ process.exit(1);
67
+ }
68
+ // Query the LLM
69
+ const context = (0, context_1.getSystemContext)();
70
+ const spinner = (0, ora_1.default)({
71
+ text: chalk_1.default.gray('Thinking...'),
72
+ spinner: 'dots',
73
+ color: 'cyan',
74
+ }).start();
75
+ let response;
76
+ try {
77
+ response = await (0, llm_1.queryLLM)(query, context);
78
+ spinner.stop();
79
+ }
80
+ catch (err) {
81
+ spinner.stop();
82
+ const error = err;
83
+ console.log(chalk_1.default.red(`\n ✗ Error: ${error.message}\n`));
84
+ process.exit(1);
85
+ }
86
+ // Render the response
87
+ (0, renderer_1.renderResponse)(response);
88
+ // If no command was generated, exit
89
+ if (!response.command) {
90
+ process.exit(0);
91
+ }
92
+ // Prompt for action
93
+ const { action } = await inquirer_1.default.prompt([
94
+ {
95
+ type: 'list',
96
+ name: 'action',
97
+ message: 'Run it?',
98
+ choices: [
99
+ { name: `${chalk_1.default.green('[y]')} run`, value: 'run' },
100
+ { name: `${chalk_1.default.red('[n]')} cancel`, value: 'cancel' },
101
+ { name: `${chalk_1.default.blue('[c]')} copy`, value: 'copy' },
102
+ ],
103
+ },
104
+ ]);
105
+ switch (action) {
106
+ case 'run':
107
+ await (0, runner_1.runCommand)(response.command, response.dangerous);
108
+ break;
109
+ case 'copy':
110
+ await clipboardy_1.default.write(response.command);
111
+ (0, renderer_1.renderCopied)();
112
+ break;
113
+ case 'cancel':
114
+ default:
115
+ (0, renderer_1.renderCancelled)();
116
+ break;
117
+ }
118
+ }
119
+ catch (err) {
120
+ const error = err;
121
+ console.error(chalk_1.default.red(`\n Fatal error: ${error.message}\n`));
122
+ process.exit(1);
123
+ }
124
+ });
125
+ program.parse(process.argv);
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/llm.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { SystemContext } from './context';
2
+ export interface LLMResponse {
3
+ command: string;
4
+ explanation: string;
5
+ dangerous: boolean;
6
+ alternatives: string[];
7
+ }
8
+ export declare function queryLLM(query: string, context: SystemContext): Promise<LLMResponse>;
9
+ //# sourceMappingURL=llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAqFD,wBAAsB,QAAQ,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACvB,OAAO,CAAC,WAAW,CAAC,CAiCtB"}
package/dist/llm.js ADDED
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.queryLLM = queryLLM;
7
+ const groq_sdk_1 = __importDefault(require("groq-sdk"));
8
+ const openai_1 = __importDefault(require("openai"));
9
+ const config_1 = require("./config");
10
+ const prompt_1 = require("./prompt");
11
+ function parseResponse(raw) {
12
+ // Try to extract JSON from the response, handling potential markdown code fences
13
+ let jsonStr = raw.trim();
14
+ // Remove markdown code fences if present
15
+ const jsonMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
16
+ if (jsonMatch) {
17
+ jsonStr = jsonMatch[1].trim();
18
+ }
19
+ // Try to find a JSON object in the response
20
+ const objectMatch = jsonStr.match(/\{[\s\S]*\}/);
21
+ if (objectMatch) {
22
+ jsonStr = objectMatch[0];
23
+ }
24
+ try {
25
+ const parsed = JSON.parse(jsonStr);
26
+ return {
27
+ command: parsed.command || '',
28
+ explanation: parsed.explanation || 'No explanation provided',
29
+ dangerous: Boolean(parsed.dangerous),
30
+ alternatives: Array.isArray(parsed.alternatives) ? parsed.alternatives : [],
31
+ };
32
+ }
33
+ catch {
34
+ throw new Error(`Failed to parse LLM response as JSON.\nRaw response:\n${raw}`);
35
+ }
36
+ }
37
+ async function callGroq(query, context, apiKey) {
38
+ const groq = new groq_sdk_1.default({ apiKey });
39
+ const completion = await groq.chat.completions.create({
40
+ model: 'llama-3.3-70b-versatile',
41
+ messages: [
42
+ { role: 'system', content: (0, prompt_1.buildSystemPrompt)(context) },
43
+ { role: 'user', content: (0, prompt_1.buildUserPrompt)(query) },
44
+ ],
45
+ temperature: 0.1,
46
+ max_tokens: 512,
47
+ response_format: { type: 'json_object' },
48
+ });
49
+ const content = completion.choices[0]?.message?.content;
50
+ if (!content) {
51
+ throw new Error('No response received from Groq');
52
+ }
53
+ return parseResponse(content);
54
+ }
55
+ async function callOpenAI(query, context, apiKey) {
56
+ const openai = new openai_1.default({ apiKey });
57
+ const completion = await openai.chat.completions.create({
58
+ model: 'gpt-4o-mini',
59
+ messages: [
60
+ { role: 'system', content: (0, prompt_1.buildSystemPrompt)(context) },
61
+ { role: 'user', content: (0, prompt_1.buildUserPrompt)(query) },
62
+ ],
63
+ temperature: 0.1,
64
+ max_tokens: 512,
65
+ response_format: { type: 'json_object' },
66
+ });
67
+ const content = completion.choices[0]?.message?.content;
68
+ if (!content) {
69
+ throw new Error('No response received from OpenAI');
70
+ }
71
+ return parseResponse(content);
72
+ }
73
+ async function queryLLM(query, context) {
74
+ const config = (0, config_1.getConfig)();
75
+ const provider = config.defaultProvider;
76
+ if (provider === 'groq' && config.groqApiKey) {
77
+ try {
78
+ return await callGroq(query, context, config.groqApiKey);
79
+ }
80
+ catch (err) {
81
+ // If Groq fails and we have an OpenAI key, fall back
82
+ if (config.openaiApiKey) {
83
+ console.warn('Groq failed, falling back to OpenAI...');
84
+ return await callOpenAI(query, context, config.openaiApiKey);
85
+ }
86
+ throw err;
87
+ }
88
+ }
89
+ if (provider === 'openai' && config.openaiApiKey) {
90
+ return await callOpenAI(query, context, config.openaiApiKey);
91
+ }
92
+ // Auto-detect available provider
93
+ if (config.groqApiKey) {
94
+ return await callGroq(query, context, config.groqApiKey);
95
+ }
96
+ if (config.openaiApiKey) {
97
+ return await callOpenAI(query, context, config.openaiApiKey);
98
+ }
99
+ throw new Error('No API key configured. Run "s --setup" to configure your API keys.');
100
+ }
101
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { SystemContext } from './context';
2
+ export declare function buildSystemPrompt(context: SystemContext): string;
3
+ export declare function buildUserPrompt(query: string): string;
4
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAyChE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
package/dist/prompt.js ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSystemPrompt = buildSystemPrompt;
4
+ exports.buildUserPrompt = buildUserPrompt;
5
+ function buildSystemPrompt(context) {
6
+ const osName = {
7
+ darwin: 'macOS',
8
+ linux: 'Linux',
9
+ win32: 'Windows',
10
+ }[context.os] || context.os;
11
+ return `You are ShellAI, an expert shell command assistant. Your job is to translate natural language requests into precise, working shell commands.
12
+
13
+ ENVIRONMENT:
14
+ - Operating System: ${osName} (${context.os})
15
+ - Shell: ${context.shell}
16
+ - Current Directory: ${context.cwd}
17
+ - Home Directory: ${context.homeDir}
18
+ - User: ${context.username}
19
+ - Architecture: ${context.arch}
20
+
21
+ RULES:
22
+ 1. Return ONLY a valid JSON object — no markdown, no code fences, no extra text.
23
+ 2. Never use sudo unless the user explicitly asks for it.
24
+ 3. Prefer readable, well-structured commands over clever one-liners.
25
+ 4. Use commands compatible with the detected OS and shell.
26
+ 5. If a command could be destructive (deletes files, overwrites data, modifies system config), mark "dangerous" as true.
27
+ 6. Provide 1-2 alternative commands when applicable (simpler or safer variants).
28
+ 7. The explanation should be one clear sentence describing what the command does.
29
+
30
+ RESPONSE FORMAT (strict JSON):
31
+ {
32
+ "command": "the exact shell command to run",
33
+ "explanation": "one sentence explaining what this command does",
34
+ "dangerous": false,
35
+ "alternatives": ["alternative command 1", "alternative command 2"]
36
+ }
37
+
38
+ If you cannot produce a valid command, return:
39
+ {
40
+ "command": "",
41
+ "explanation": "I'm unable to generate a command for this request because...",
42
+ "dangerous": false,
43
+ "alternatives": []
44
+ }`;
45
+ }
46
+ function buildUserPrompt(query) {
47
+ return `Convert this to a shell command: "${query}"`;
48
+ }
49
+ //# sourceMappingURL=prompt.js.map