@atharvaspatil5/aish 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 ADDED
@@ -0,0 +1,70 @@
1
+ # AI.sh
2
+
3
+ AI.sh is a CLI tool that converts natural language into safe shell commands.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ ai "list files"
9
+ ai "delete node_modules"
10
+ ai "find files larger than 100MB"
11
+ ```
12
+
13
+ ## Options
14
+
15
+ ```bash
16
+ -y, --yes skip confirmation prompt
17
+ ```
18
+
19
+ ## How it works
20
+
21
+ 1. Takes user input from CLI
22
+ 2. Sends it to Groq (LLM)
23
+ 3. Converts it into a shell command
24
+ 4. Validates the command for safety
25
+ 5. Asks for confirmation (optional)
26
+ 6. Executes the command
27
+
28
+ ## Example
29
+
30
+ ```bash
31
+ ai "list all files"
32
+ # → ls
33
+
34
+ ai "delete everything"
35
+ # → rm -i *
36
+ ```
37
+
38
+ ## Safety
39
+
40
+ * Blocks critical system-level commands
41
+ * Warns on risky operations (like file deletion)
42
+ * Requires confirmation before execution
43
+
44
+ ## Setup
45
+
46
+ ```bash
47
+ npm install
48
+ npm link
49
+ ```
50
+
51
+ Create a `.env` file:
52
+
53
+ ```env
54
+ GROQ_API_KEY=your_api_key
55
+ ```
56
+
57
+ ## Structure
58
+
59
+ ```
60
+ bin/ CLI entry
61
+ src/ core logic
62
+ llm.js
63
+ validator.js
64
+ executor.js
65
+ index.js
66
+ ```
67
+
68
+ ## Notes
69
+
70
+ This is a local CLI tool. Use carefully when executing destructive commands.
package/bin/ai.js ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from "commander";
4
+ import chalk from "chalk";
5
+ import { getCommand } from "../src/llm.js";
6
+ import { askConfirmation, runCommand } from "../src/executor.js";
7
+
8
+ const program = new Command();
9
+
10
+ program
11
+ .name("ai")
12
+ .description("AI-powered shell assistant")
13
+ .argument("<query>", "What you want to do")
14
+ .option("-y, --yes", "Skip confirmation prompt")
15
+ .action(async (query, options) => {
16
+ const result = await getCommand(query);
17
+
18
+ let coloredCommand;
19
+ if (result.risk_level === "danger") {
20
+ coloredCommand = chalk.red(result.command);
21
+ } else if (result.risk_level === "warning") {
22
+ coloredCommand = chalk.yellow(result.command);
23
+ } else {
24
+ coloredCommand = chalk.green(result.command);
25
+ }
26
+
27
+ console.log(coloredCommand);
28
+
29
+ let confirm = true;
30
+
31
+ if (!options.yes || result.risk_level === "danger") {
32
+ confirm = await askConfirmation("Run this? (y/n) ");
33
+ }
34
+
35
+ if (!confirm) {
36
+ console.log(chalk.blue("Command execution cancelled."));
37
+ return;
38
+ }
39
+
40
+ try {
41
+ const output = await runCommand(result.command);
42
+ console.log(output);
43
+ } catch (error) {
44
+ console.error(chalk.red("Error: "));
45
+ console.error(chalk.red(error.message));
46
+ }
47
+ });
48
+
49
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@atharvaspatil5/aish",
3
+ "version": "1.0.1",
4
+ "description": "AI-powered CLI that converts natural language to shell commands",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "keywords": [],
10
+ "author": "athPATIL247",
11
+ "license": "ISC",
12
+ "bin": {
13
+ "ai": "./bin/ai.js"
14
+ },
15
+ "type": "module",
16
+ "dependencies": {
17
+ "chalk": "^5.6.2",
18
+ "commander": "^14.0.3",
19
+ "dotenv": "^17.4.0",
20
+ "groq-sdk": "^1.1.2"
21
+ }
22
+ }
@@ -0,0 +1,28 @@
1
+ import { exec } from "child_process";
2
+ import readline from "readline";
3
+
4
+ export function askConfirmation(question) {
5
+ const rl = readline.createInterface({
6
+ input: process.stdin,
7
+ output: process.stdout,
8
+ });
9
+
10
+ return new Promise((resolve) => {
11
+ rl.question(question, (answer) => {
12
+ rl.close();
13
+ resolve(answer.toLowerCase() === "y");
14
+ });
15
+ });
16
+ }
17
+
18
+ export function runCommand(command) {
19
+ return new Promise((resolve, reject) => {
20
+ exec(command, (error, stdout, stderr) => {
21
+ if (error) {
22
+ reject(stderr || error.message);
23
+ } else {
24
+ resolve(stdout);
25
+ }
26
+ });
27
+ });
28
+ }
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ // Entry point is bin/ai.js
package/src/llm.js ADDED
@@ -0,0 +1,63 @@
1
+ import Groq from "groq-sdk";
2
+ import { readFileSync } from 'fs';
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join } from 'path';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+
9
+ const envPath = join(__dirname, '..', '.env');
10
+ const envContent = readFileSync(envPath, 'utf8');
11
+ const envLines = envContent.split('\n');
12
+ for (const line of envLines) {
13
+ const [key, ...valueParts] = line.split('=');
14
+ if (key && valueParts.length) {
15
+ process.env[key.trim()] = valueParts.join('=').trim();
16
+ }
17
+ }
18
+
19
+ const groq = new Groq({
20
+ apiKey: process.env.GROQ_API_KEY,
21
+ });
22
+
23
+ export async function getCommand(query){
24
+ const response = await groq.chat.completions.create({
25
+ model: "llama-3.1-8b-instant",
26
+ messages: [
27
+ {
28
+ role: "system",
29
+ content: `You are a Linux shell expert. Convert user instructions into a single shell command and assess its risk level.
30
+
31
+ Output ONLY a JSON object with exactly these fields:
32
+ - command: the shell command (string)
33
+ - risk_level: "safe", "warning", or "danger" (string)
34
+
35
+ Do not output any other text, explanations, code blocks, or notes. Just the raw JSON.`,
36
+ },
37
+ {
38
+ role: "user",
39
+ content: query,
40
+ },
41
+ ],
42
+ });
43
+
44
+ const content = response.choices[0].message.content.trim();
45
+ // Remove markdown code blocks if present
46
+ let jsonString = content;
47
+ if (jsonString.startsWith('```json')) {
48
+ jsonString = jsonString.replace(/^```json\s*/, '').replace(/\s*```$/, '');
49
+ } else if (jsonString.startsWith('```')) {
50
+ jsonString = jsonString.replace(/^```\s*/, '').replace(/\s*```$/, '');
51
+ }
52
+ try {
53
+ const result = JSON.parse(jsonString);
54
+ return result;
55
+ } catch (e) {
56
+ // Fallback: assume safe if parsing fails
57
+ return {
58
+ command: content,
59
+ risk_level: "safe",
60
+ reason: "Unable to assess risk"
61
+ };
62
+ }
63
+ }