shellsia 1.0.1
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 +156 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +96 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +12 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +40 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/llm.d.ts +9 -0
- package/dist/llm.d.ts.map +1 -0
- package/dist/llm.js +101 -0
- package/dist/llm.js.map +1 -0
- package/dist/prompt.d.ts +4 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +49 -0
- package/dist/prompt.js.map +1 -0
- package/dist/renderer.d.ts +8 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +73 -0
- package/dist/renderer.js.map +1 -0
- package/dist/runner.d.ts +2 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +90 -0
- package/dist/runner.js.map +1 -0
- package/package.json +52 -0
- package/src/config.ts +109 -0
- package/src/context.ts +51 -0
- package/src/index.ts +135 -0
- package/src/llm.ts +133 -0
- package/src/prompt.ts +48 -0
- package/src/renderer.ts +77 -0
- package/src/runner.ts +97 -0
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 Shellsia, 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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":";;AAEA,8CAyCC;AAED,0CAEC;AA7CD,SAAgB,iBAAiB,CAAC,OAAsB;IACtD,MAAM,MAAM,GAAG;QACb,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,SAAS;KACjB,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC;IAE5B,OAAO;;;sBAGa,MAAM,KAAK,OAAO,CAAC,EAAE;WAChC,OAAO,CAAC,KAAK;uBACD,OAAO,CAAC,GAAG;oBACd,OAAO,CAAC,OAAO;UACzB,OAAO,CAAC,QAAQ;kBACR,OAAO,CAAC,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;EAyB5B,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,KAAa;IAC3C,OAAO,qCAAqC,KAAK,GAAG,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LLMResponse } from './llm';
|
|
2
|
+
export declare function renderResponse(response: LLMResponse): void;
|
|
3
|
+
export declare function renderRunning(command: string): void;
|
|
4
|
+
export declare function renderSuccess(): void;
|
|
5
|
+
export declare function renderError(error: string): void;
|
|
6
|
+
export declare function renderCopied(): void;
|
|
7
|
+
export declare function renderCancelled(): void;
|
|
8
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAQpC,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CA4C1D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,aAAa,IAAI,IAAI,CAGpC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAG/C;AAED,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
|
package/dist/renderer.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
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.renderResponse = renderResponse;
|
|
7
|
+
exports.renderRunning = renderRunning;
|
|
8
|
+
exports.renderSuccess = renderSuccess;
|
|
9
|
+
exports.renderError = renderError;
|
|
10
|
+
exports.renderCopied = renderCopied;
|
|
11
|
+
exports.renderCancelled = renderCancelled;
|
|
12
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
13
|
+
function pad(str, width) {
|
|
14
|
+
const visible = str.replace(/\u001b\[[0-9;]*m/g, '');
|
|
15
|
+
const padding = Math.max(0, width - visible.length);
|
|
16
|
+
return str + ' '.repeat(padding);
|
|
17
|
+
}
|
|
18
|
+
function renderResponse(response) {
|
|
19
|
+
const { command, explanation, dangerous, alternatives } = response;
|
|
20
|
+
if (!command) {
|
|
21
|
+
console.log(chalk_1.default.yellow('\nā Could not generate a command.'));
|
|
22
|
+
console.log(chalk_1.default.gray(` ${explanation}\n`));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const boxWidth = Math.max(command.length + 4, 44);
|
|
26
|
+
const innerWidth = boxWidth - 4;
|
|
27
|
+
// Command box
|
|
28
|
+
console.log('');
|
|
29
|
+
console.log(chalk_1.default.cyan(` āā Command ${'ā'.repeat(Math.max(0, boxWidth - 13))}ā®`));
|
|
30
|
+
console.log(chalk_1.default.cyan(' ā ') + chalk_1.default.bold.white(pad(command, innerWidth)) + chalk_1.default.cyan('ā'));
|
|
31
|
+
console.log(chalk_1.default.cyan(` ā°${'ā'.repeat(boxWidth - 2)}āÆ`));
|
|
32
|
+
// Explanation
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log(chalk_1.default.gray(' Explains ') + chalk_1.default.white(explanation));
|
|
35
|
+
// Dangerous warning
|
|
36
|
+
if (dangerous) {
|
|
37
|
+
console.log('');
|
|
38
|
+
console.log(chalk_1.default.red.bold(' [!] Warning: this command modifies files'));
|
|
39
|
+
}
|
|
40
|
+
// Sudo warning
|
|
41
|
+
if (command.toLowerCase().includes('sudo')) {
|
|
42
|
+
console.log('');
|
|
43
|
+
console.log(chalk_1.default.yellow.bold(' [ā”] This command uses sudo ā elevated privileges required'));
|
|
44
|
+
}
|
|
45
|
+
// Alternatives
|
|
46
|
+
if (alternatives.length > 0) {
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log(chalk_1.default.gray(' Alternatives:'));
|
|
49
|
+
for (const alt of alternatives) {
|
|
50
|
+
console.log(chalk_1.default.gray(' ⢠') + chalk_1.default.white(alt));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
console.log('');
|
|
54
|
+
}
|
|
55
|
+
function renderRunning(command) {
|
|
56
|
+
console.log(chalk_1.default.cyan.bold('\n ā¶ Running: ') + chalk_1.default.white(command));
|
|
57
|
+
console.log(chalk_1.default.gray(' ' + 'ā'.repeat(50)));
|
|
58
|
+
}
|
|
59
|
+
function renderSuccess() {
|
|
60
|
+
console.log(chalk_1.default.gray(' ' + 'ā'.repeat(50)));
|
|
61
|
+
console.log(chalk_1.default.green.bold(' ā Command finished successfully\n'));
|
|
62
|
+
}
|
|
63
|
+
function renderError(error) {
|
|
64
|
+
console.log(chalk_1.default.gray(' ' + 'ā'.repeat(50)));
|
|
65
|
+
console.log(chalk_1.default.red.bold(' ā Command failed: ') + chalk_1.default.red(error) + '\n');
|
|
66
|
+
}
|
|
67
|
+
function renderCopied() {
|
|
68
|
+
console.log(chalk_1.default.green.bold(' š Copied to clipboard!\n'));
|
|
69
|
+
}
|
|
70
|
+
function renderCancelled() {
|
|
71
|
+
console.log(chalk_1.default.gray(' Cancelled.\n'));
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAgDA,wBAAsB,UAAU,CAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
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.runCommand = runCommand;
|
|
7
|
+
const execa_1 = __importDefault(require("execa"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
|
+
const config_1 = require("./config");
|
|
11
|
+
const renderer_1 = require("./renderer");
|
|
12
|
+
async function confirmDangerousCommand(command) {
|
|
13
|
+
console.log(chalk_1.default.red.bold('\n ā ļø DANGER: This command may modify or delete files!'));
|
|
14
|
+
console.log(chalk_1.default.red(` Command: ${command}\n`));
|
|
15
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
16
|
+
{
|
|
17
|
+
type: 'confirm',
|
|
18
|
+
name: 'confirm',
|
|
19
|
+
message: chalk_1.default.red.bold('Are you absolutely sure you want to run this?'),
|
|
20
|
+
default: false,
|
|
21
|
+
},
|
|
22
|
+
]);
|
|
23
|
+
return confirm;
|
|
24
|
+
}
|
|
25
|
+
async function confirmRmRf(command) {
|
|
26
|
+
console.log(chalk_1.default.bgRed.white.bold('\n šØ CRITICAL: This command uses rm -rf!'));
|
|
27
|
+
console.log(chalk_1.default.red(` Command: ${command}\n`));
|
|
28
|
+
const { firstConfirm } = await inquirer_1.default.prompt([
|
|
29
|
+
{
|
|
30
|
+
type: 'confirm',
|
|
31
|
+
name: 'firstConfirm',
|
|
32
|
+
message: chalk_1.default.red.bold('This will PERMANENTLY delete files. Continue?'),
|
|
33
|
+
default: false,
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
36
|
+
if (!firstConfirm)
|
|
37
|
+
return false;
|
|
38
|
+
const { secondConfirm } = await inquirer_1.default.prompt([
|
|
39
|
+
{
|
|
40
|
+
type: 'input',
|
|
41
|
+
name: 'secondConfirm',
|
|
42
|
+
message: chalk_1.default.red.bold('Type "yes" to confirm deletion:'),
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
return secondConfirm.toLowerCase() === 'yes';
|
|
46
|
+
}
|
|
47
|
+
async function runCommand(command, dangerous) {
|
|
48
|
+
const config = (0, config_1.getConfig)();
|
|
49
|
+
// Safety checks for dangerous commands
|
|
50
|
+
if (dangerous && config.confirmBeforeRun) {
|
|
51
|
+
// Extra check for rm -rf
|
|
52
|
+
if (command.includes('rm -rf') || command.includes('rm --recursive --force')) {
|
|
53
|
+
const confirmed = await confirmRmRf(command);
|
|
54
|
+
if (!confirmed) {
|
|
55
|
+
console.log(chalk_1.default.gray(' Aborted.\n'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const confirmed = await confirmDangerousCommand(command);
|
|
61
|
+
if (!confirmed) {
|
|
62
|
+
console.log(chalk_1.default.gray(' Aborted.\n'));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Sudo warning
|
|
68
|
+
if (command.includes('sudo')) {
|
|
69
|
+
console.log(chalk_1.default.yellow('\n ā” Running with elevated privileges (sudo)...'));
|
|
70
|
+
}
|
|
71
|
+
(0, renderer_1.renderRunning)(command);
|
|
72
|
+
try {
|
|
73
|
+
const subprocess = (0, execa_1.default)(command, {
|
|
74
|
+
shell: true,
|
|
75
|
+
stdio: 'inherit',
|
|
76
|
+
cwd: process.cwd(),
|
|
77
|
+
});
|
|
78
|
+
await subprocess;
|
|
79
|
+
(0, renderer_1.renderSuccess)();
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const error = err;
|
|
83
|
+
const message = error.exitCode
|
|
84
|
+
? `Exit code ${error.exitCode}`
|
|
85
|
+
: error.message || 'Unknown error';
|
|
86
|
+
(0, renderer_1.renderError)(message);
|
|
87
|
+
process.exitCode = 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "shellsia",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A CLI tool that converts plain English into shell commands using AI",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sia": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "ts-node src/index.ts",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"cli",
|
|
23
|
+
"shell",
|
|
24
|
+
"ai",
|
|
25
|
+
"llm",
|
|
26
|
+
"groq",
|
|
27
|
+
"openai",
|
|
28
|
+
"command-line"
|
|
29
|
+
],
|
|
30
|
+
"author": "Sukhwinder-i0",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"chalk": "^4.1.2",
|
|
34
|
+
"clipboardy": "^2.3.0",
|
|
35
|
+
"commander": "^12.1.0",
|
|
36
|
+
"conf": "^10.2.0",
|
|
37
|
+
"execa": "^5.1.1",
|
|
38
|
+
"groq-sdk": "^0.8.0",
|
|
39
|
+
"inquirer": "^8.2.6",
|
|
40
|
+
"openai": "^4.73.0",
|
|
41
|
+
"ora": "^5.4.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/inquirer": "^8.2.10",
|
|
45
|
+
"@types/node": "^20.11.0",
|
|
46
|
+
"ts-node": "^10.9.2",
|
|
47
|
+
"typescript": "^5.3.3"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=18.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Conf from 'conf';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
export interface ShellsiaConfig {
|
|
6
|
+
groqApiKey: string;
|
|
7
|
+
openaiApiKey: string;
|
|
8
|
+
defaultProvider: 'groq' | 'openai';
|
|
9
|
+
shell: string;
|
|
10
|
+
confirmBeforeRun: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const defaults: ShellsiaConfig = {
|
|
14
|
+
groqApiKey: '',
|
|
15
|
+
openaiApiKey: '',
|
|
16
|
+
defaultProvider: 'groq',
|
|
17
|
+
shell: 'auto',
|
|
18
|
+
confirmBeforeRun: true,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const config = new Conf<ShellsiaConfig>({
|
|
22
|
+
projectName: 'shellsia',
|
|
23
|
+
cwd: `${process.env.HOME || process.env.USERPROFILE}/.shellsia`,
|
|
24
|
+
defaults,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export function getConfig(): ShellsiaConfig {
|
|
28
|
+
return {
|
|
29
|
+
groqApiKey: config.get('groqApiKey'),
|
|
30
|
+
openaiApiKey: config.get('openaiApiKey'),
|
|
31
|
+
defaultProvider: config.get('defaultProvider'),
|
|
32
|
+
shell: config.get('shell'),
|
|
33
|
+
confirmBeforeRun: config.get('confirmBeforeRun'),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function setConfig(key: keyof ShellsiaConfig, value: string | boolean): void {
|
|
38
|
+
config.set(key, value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function runSetup(): Promise<void> {
|
|
42
|
+
console.log(chalk.bold.cyan('\nš§ Shellsia Setup\n'));
|
|
43
|
+
console.log(chalk.gray('Configure your API keys and preferences.\n'));
|
|
44
|
+
|
|
45
|
+
interface SetupAnswers {
|
|
46
|
+
defaultProvider: 'groq' | 'openai';
|
|
47
|
+
groqApiKey?: string;
|
|
48
|
+
openaiApiKey?: string;
|
|
49
|
+
shell: string;
|
|
50
|
+
confirmBeforeRun: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const answers: SetupAnswers = await (inquirer.prompt as any)([
|
|
54
|
+
{
|
|
55
|
+
type: 'list',
|
|
56
|
+
name: 'defaultProvider',
|
|
57
|
+
message: 'Select your default LLM provider:',
|
|
58
|
+
choices: [
|
|
59
|
+
{ name: 'Groq (free, fast ā recommended)', value: 'groq' },
|
|
60
|
+
{ name: 'OpenAI (gpt-4o-mini)', value: 'openai' },
|
|
61
|
+
],
|
|
62
|
+
default: config.get('defaultProvider'),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: 'input',
|
|
66
|
+
name: 'groqApiKey',
|
|
67
|
+
message: 'Groq API key (get one free at https://console.groq.com):',
|
|
68
|
+
default: config.get('groqApiKey') || undefined,
|
|
69
|
+
when: (ans: { defaultProvider: string }) => ans.defaultProvider === 'groq',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'input',
|
|
73
|
+
name: 'openaiApiKey',
|
|
74
|
+
message: 'OpenAI API key:',
|
|
75
|
+
default: config.get('openaiApiKey') || undefined,
|
|
76
|
+
when: (ans: { defaultProvider: string }) => ans.defaultProvider === 'openai',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
type: 'list',
|
|
80
|
+
name: 'shell',
|
|
81
|
+
message: 'Shell preference:',
|
|
82
|
+
choices: [
|
|
83
|
+
{ name: 'Auto-detect (recommended)', value: 'auto' },
|
|
84
|
+
{ name: 'bash', value: 'bash' },
|
|
85
|
+
{ name: 'zsh', value: 'zsh' },
|
|
86
|
+
{ name: 'fish', value: 'fish' },
|
|
87
|
+
{ name: 'PowerShell', value: 'powershell' },
|
|
88
|
+
],
|
|
89
|
+
default: config.get('shell'),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: 'confirm',
|
|
93
|
+
name: 'confirmBeforeRun',
|
|
94
|
+
message: 'Always confirm before running commands?',
|
|
95
|
+
default: config.get('confirmBeforeRun'),
|
|
96
|
+
},
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
if (answers.groqApiKey !== undefined) config.set('groqApiKey', answers.groqApiKey);
|
|
100
|
+
if (answers.openaiApiKey !== undefined) config.set('openaiApiKey', answers.openaiApiKey);
|
|
101
|
+
config.set('defaultProvider', answers.defaultProvider);
|
|
102
|
+
config.set('shell', answers.shell);
|
|
103
|
+
config.set('confirmBeforeRun', answers.confirmBeforeRun);
|
|
104
|
+
|
|
105
|
+
console.log(chalk.green('\nā
Setup complete!'));
|
|
106
|
+
console.log(chalk.gray(`Config saved to: ${config.path}\n`));
|
|
107
|
+
console.log(chalk.cyan('Try it out:'));
|
|
108
|
+
console.log(chalk.white(' sia find large files or sia "make file me.txt"\n'));
|
|
109
|
+
}
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { getConfig } from './config';
|
|
4
|
+
|
|
5
|
+
export interface SystemContext {
|
|
6
|
+
os: string;
|
|
7
|
+
shell: string;
|
|
8
|
+
cwd: string;
|
|
9
|
+
homeDir: string;
|
|
10
|
+
username: string;
|
|
11
|
+
hostname: string;
|
|
12
|
+
arch: string;
|
|
13
|
+
nodeVersion: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function detectShell(): string {
|
|
17
|
+
const config = getConfig();
|
|
18
|
+
|
|
19
|
+
if (config.shell && config.shell !== 'auto') {
|
|
20
|
+
return config.shell;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const shellEnv = process.env.SHELL || '';
|
|
24
|
+
if (shellEnv) {
|
|
25
|
+
const shellName = path.basename(shellEnv);
|
|
26
|
+
return shellName;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (process.env.PSModulePath) {
|
|
30
|
+
return 'powershell';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (process.env.COMSPEC) {
|
|
34
|
+
return 'cmd';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return 'bash';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getSystemContext(): SystemContext {
|
|
41
|
+
return {
|
|
42
|
+
os: process.platform,
|
|
43
|
+
shell: detectShell(),
|
|
44
|
+
cwd: process.cwd(),
|
|
45
|
+
homeDir: os.homedir(),
|
|
46
|
+
username: os.userInfo().username,
|
|
47
|
+
hostname: os.hostname(),
|
|
48
|
+
arch: process.arch,
|
|
49
|
+
nodeVersion: process.version,
|
|
50
|
+
};
|
|
51
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
|
+
import clipboardy from 'clipboardy';
|
|
8
|
+
import { runSetup, getConfig } from './config';
|
|
9
|
+
import { getSystemContext } from './context';
|
|
10
|
+
import { queryLLM } from './llm';
|
|
11
|
+
import { renderResponse, renderCopied, renderCancelled } from './renderer';
|
|
12
|
+
import { runCommand } from './runner';
|
|
13
|
+
|
|
14
|
+
const program = new Command();
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.name('sia')
|
|
18
|
+
.description('Shellsia ā Convert plain English to shell commands using AI (Created by Sukhwinder-i0 - https://github.com/Sukhwinder-i0)')
|
|
19
|
+
.version('1.0.0')
|
|
20
|
+
.argument('[query...]', 'Natural language description of the command you need')
|
|
21
|
+
.option('--setup', 'Run interactive setup to configure API keys')
|
|
22
|
+
.option('--config', 'Show current configuration')
|
|
23
|
+
.action(async (queryParts: string[], options: { setup?: boolean; config?: boolean }) => {
|
|
24
|
+
try {
|
|
25
|
+
// Handle --setup
|
|
26
|
+
if (options.setup) {
|
|
27
|
+
await runSetup();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Handle --config
|
|
32
|
+
if (options.config) {
|
|
33
|
+
const config = getConfig();
|
|
34
|
+
console.log(chalk.bold.cyan('\nš Current Configuration:\n'));
|
|
35
|
+
console.log(chalk.gray(' Provider: ') + chalk.white(config.defaultProvider));
|
|
36
|
+
console.log(
|
|
37
|
+
chalk.gray(' Groq Key: ') +
|
|
38
|
+
chalk.white(config.groqApiKey ? 'ā¢ā¢ā¢ā¢' + config.groqApiKey.slice(-4) : chalk.yellow('not set'))
|
|
39
|
+
);
|
|
40
|
+
console.log(
|
|
41
|
+
chalk.gray(' OpenAI Key: ') +
|
|
42
|
+
chalk.white(config.openaiApiKey ? 'ā¢ā¢ā¢ā¢' + config.openaiApiKey.slice(-4) : chalk.yellow('not set'))
|
|
43
|
+
);
|
|
44
|
+
console.log(chalk.gray(' Shell: ') + chalk.white(config.shell));
|
|
45
|
+
console.log(chalk.gray(' Confirm: ') + chalk.white(config.confirmBeforeRun ? 'yes' : 'no'));
|
|
46
|
+
console.log('');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Need a query
|
|
51
|
+
const query = queryParts.join(' ').trim();
|
|
52
|
+
if (!query) {
|
|
53
|
+
console.log(chalk.bold.cyan('\n Shellsia') + chalk.gray(' ā Convert English to shell commands (Created by Sukhwinder-i0 - https://github.com/Sukhwinder-i0)\n'));
|
|
54
|
+
console.log(chalk.white(' Usage (quotes optional):'));
|
|
55
|
+
console.log(chalk.gray(' sia find all files larger than 100MB'));
|
|
56
|
+
console.log(chalk.gray(' sia "kill the process running on port 3000"'));
|
|
57
|
+
console.log(chalk.gray(' sia compress this folder into a zip'));
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log(chalk.white(' Setup:'));
|
|
60
|
+
console.log(chalk.gray(' sia --setup Configure API keys'));
|
|
61
|
+
console.log(chalk.gray(' sia --config Show current config'));
|
|
62
|
+
console.log('');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check for API keys
|
|
67
|
+
const config = getConfig();
|
|
68
|
+
if (!config.groqApiKey && !config.openaiApiKey) {
|
|
69
|
+
console.log(chalk.red('\n ā No API key configured.'));
|
|
70
|
+
console.log(chalk.gray(' Run ') + chalk.cyan('sia --setup') + chalk.gray(' to configure your API keys.\n'));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Query the LLM
|
|
75
|
+
const context = getSystemContext();
|
|
76
|
+
const spinner = ora({
|
|
77
|
+
text: chalk.gray('Thinking...'),
|
|
78
|
+
spinner: 'dots',
|
|
79
|
+
color: 'cyan',
|
|
80
|
+
}).start();
|
|
81
|
+
|
|
82
|
+
let response;
|
|
83
|
+
try {
|
|
84
|
+
response = await queryLLM(query, context);
|
|
85
|
+
spinner.stop();
|
|
86
|
+
} catch (err: unknown) {
|
|
87
|
+
spinner.stop();
|
|
88
|
+
const error = err as Error;
|
|
89
|
+
console.log(chalk.red(`\n ā Error: ${error.message}\n`));
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Render the response
|
|
94
|
+
renderResponse(response);
|
|
95
|
+
|
|
96
|
+
// If no command was generated, exit
|
|
97
|
+
if (!response.command) {
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Prompt for action
|
|
102
|
+
const { action } = await inquirer.prompt([
|
|
103
|
+
{
|
|
104
|
+
type: 'list',
|
|
105
|
+
name: 'action',
|
|
106
|
+
message: 'Run it?',
|
|
107
|
+
choices: [
|
|
108
|
+
{ name: `${chalk.green('[y]')} run`, value: 'run' },
|
|
109
|
+
{ name: `${chalk.red('[n]')} cancel`, value: 'cancel' },
|
|
110
|
+
{ name: `${chalk.blue('[c]')} copy`, value: 'copy' },
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
switch (action) {
|
|
116
|
+
case 'run':
|
|
117
|
+
await runCommand(response.command, response.dangerous);
|
|
118
|
+
break;
|
|
119
|
+
case 'copy':
|
|
120
|
+
await clipboardy.write(response.command);
|
|
121
|
+
renderCopied();
|
|
122
|
+
break;
|
|
123
|
+
case 'cancel':
|
|
124
|
+
default:
|
|
125
|
+
renderCancelled();
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
} catch (err: unknown) {
|
|
129
|
+
const error = err as Error;
|
|
130
|
+
console.error(chalk.red(`\n Fatal error: ${error.message}\n`));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
program.parse(process.argv);
|