scai 0.1.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,13 @@
1
+ ```
2
+ devcheck/
3
+ ├── package.json
4
+ ├── tsconfig.json
5
+ ├── src/
6
+ │ ├── commands/
7
+ │ │ ├── checkEnv.ts
8
+ │ │ ├── checkGit.ts
9
+ │ │ └── pingEndpoints.ts
10
+ │ └── index.ts
11
+ ├── bin/
12
+ │ └── devcheck.js ← compiled entry point
13
+ ```
@@ -0,0 +1,42 @@
1
+ import { execSync } from 'child_process';
2
+ export async function suggestCommitMessage(options) {
3
+ try {
4
+ let diff = execSync("git diff", { encoding: "utf-8" }).trim();
5
+ if (!diff) {
6
+ diff = execSync("git diff --cached", { encoding: "utf-8" }).trim();
7
+ }
8
+ if (!diff) {
9
+ console.log('⚠️ No staged changes to suggest a message for.');
10
+ return;
11
+ }
12
+ const prompt = `Suggest a concise, conventional Git commit message for this diff. Return ONLY the commit message:\n\n${diff}`;
13
+ const res = await fetch("http://localhost:11434/api/generate", {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: JSON.stringify({
17
+ model: "llama3",
18
+ prompt: prompt,
19
+ stream: false
20
+ }),
21
+ });
22
+ const { response } = await res.json();
23
+ if (response.error) {
24
+ throw new Error(`LLM error: ${response.error}`);
25
+ }
26
+ const message = response?.trim();
27
+ console.log(`${message}`);
28
+ // 3) Optionally commit
29
+ if (options.commit) {
30
+ // If code not already staged
31
+ const commitDiff = execSync("git diff", { encoding: "utf-8" }).trim();
32
+ if (commitDiff) {
33
+ execSync("git add .", { encoding: "utf-8" }).trim();
34
+ }
35
+ execSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
36
+ console.log('✅ Committed with AI-suggested message.');
37
+ }
38
+ }
39
+ catch (err) {
40
+ console.error('❌ Error in msg command:', err.message);
41
+ }
42
+ }
@@ -0,0 +1,10 @@
1
+ export function checkEnv() {
2
+ const requiredVars = ["DB_HOST", "API_KEY"];
3
+ const missing = requiredVars.filter((v) => !process.env[v]);
4
+ if (missing.length) {
5
+ console.warn("❌ Missing env vars:", missing.join(", "));
6
+ }
7
+ else {
8
+ console.log("✅ All env vars are set");
9
+ }
10
+ }
@@ -0,0 +1,26 @@
1
+ import { execSync } from "child_process";
2
+ export function checkGit() {
3
+ try {
4
+ execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
5
+ const status = execSync("git status --porcelain").toString();
6
+ const isClean = status.trim().length === 0;
7
+ if (isClean) {
8
+ console.log("✅ Git working directory is clean");
9
+ }
10
+ else {
11
+ console.log("⚠️ Git working directory has uncommitted changes");
12
+ }
13
+ const branch = execSync("git rev-parse --abbrev-ref HEAD").toString().trim();
14
+ const mainHash = execSync("git rev-parse origin/main").toString().trim();
15
+ const localHash = execSync("git rev-parse HEAD").toString().trim();
16
+ if (localHash === mainHash) {
17
+ console.log("✅ Up to date with origin/main");
18
+ }
19
+ else {
20
+ console.log(`🔄 Branch ${branch} is not up to date with origin/main`);
21
+ }
22
+ }
23
+ catch {
24
+ console.error("❌ Not inside a Git repository");
25
+ }
26
+ }
@@ -0,0 +1,44 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ export async function handleRefactor(filepath) {
4
+ try {
5
+ // 1) Read original file
6
+ const code = await fs.readFile(filepath, 'utf-8');
7
+ // 2) Prompt the LLM
8
+ const prompt = `
9
+ You are a senior JavaScript engineer. Refactor the code below to improve readability,
10
+ modularity, and maintainability. Return ONLY the refactored code.
11
+
12
+ --- ORIGINAL CODE START ---
13
+ ${code}
14
+ --- ORIGINAL CODE END ---
15
+ `.trim();
16
+ const res = await fetch('http://localhost:11434/api/generate', {
17
+ method: 'POST',
18
+ headers: { 'Content-Type': 'application/json' },
19
+ body: JSON.stringify({
20
+ model: 'mistral',
21
+ prompt,
22
+ stream: false
23
+ })
24
+ });
25
+ const data = await res.json();
26
+ console.log('🔍 Raw LLM response:', data);
27
+ const refactored = data.response?.trim();
28
+ if (!refactored) {
29
+ throw new Error('No refactored code returned from the model.');
30
+ }
31
+ // 3) Write to a new file alongside the original
32
+ const { dir, name } = path.parse(filepath);
33
+ console.log('dir: ', dir);
34
+ console.log('name: ', name);
35
+ const outDir = path.join(dir, 'refactored');
36
+ await fs.mkdir(outDir, { recursive: true });
37
+ const outPath = path.join(outDir, `${name}.refactored.js`);
38
+ await fs.writeFile(outPath, refactored, 'utf-8');
39
+ console.log(`✅ Refactored code saved to: ${outPath}`);
40
+ }
41
+ catch (err) {
42
+ console.error('❌ Error in refactor command:', err.message);
43
+ }
44
+ }
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { checkEnv } from "./commands/EnvCmd.js";
4
+ import { checkGit } from "./commands/GitCmd.js";
5
+ import { suggestCommitMessage } from "./commands/CommitSuggesterCmd.js";
6
+ import { handleRefactor } from "./commands/RefactorCmd.js";
7
+ const cmd = new Command('devcheck')
8
+ .version('0.1.0');
9
+ cmd
10
+ .command('env')
11
+ .description('Check environment variables')
12
+ .action(checkEnv);
13
+ cmd
14
+ .command('git')
15
+ .description('Check Git status')
16
+ .action(checkGit);
17
+ cmd
18
+ .command('msg')
19
+ .description('Suggest a commit message from staged changes')
20
+ .option('-c, --commit', 'Automatically commit with suggested message')
21
+ .action(suggestCommitMessage);
22
+ cmd
23
+ .command('refactor <file>')
24
+ .description('Suggest a refactor for the given JS file')
25
+ .action((file) => handleRefactor(file));
26
+ cmd.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "scai",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "scai": "./dist/index.js"
7
+ },
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "start": "node dist/index.js"
11
+ },
12
+ "dependencies": {
13
+ "commander": "^11.0.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^24.0.1",
17
+ "typescript": "^5.8.3"
18
+ }
19
+ }
@@ -0,0 +1,46 @@
1
+ import { execSync } from 'child_process';
2
+
3
+ export async function suggestCommitMessage(options: { commit?: boolean }) {
4
+ try {
5
+ let diff = execSync("git diff", { encoding: "utf-8" }).trim();
6
+ if (!diff) {
7
+ diff = execSync("git diff --cached", { encoding: "utf-8" }).trim();
8
+ }
9
+ if (!diff) {
10
+ console.log('⚠️ No staged changes to suggest a message for.');
11
+ return;
12
+ }
13
+
14
+ const prompt = `Suggest a concise, conventional Git commit message for this diff. Return ONLY the commit message:\n\n${diff}`;
15
+ const res = await fetch("http://localhost:11434/api/generate", {
16
+ method: "POST",
17
+ headers: { "Content-Type": "application/json" },
18
+ body: JSON.stringify({
19
+ model: "llama3",
20
+ prompt: prompt,
21
+ stream: false
22
+ }),
23
+ });
24
+
25
+ const { response } = await res.json();
26
+ if (response.error) {
27
+ throw new Error(`LLM error: ${response.error}`);
28
+ }
29
+ const message = response?.trim();
30
+ console.log(`${message}`);
31
+
32
+ // 3) Optionally commit
33
+ if (options.commit) {
34
+ // If code not already staged
35
+ const commitDiff = execSync("git diff", { encoding: "utf-8" }).trim();
36
+ if (commitDiff) {
37
+ execSync("git add .",{ encoding: "utf-8" }).trim();
38
+ }
39
+ execSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
40
+ console.log('✅ Committed with AI-suggested message.');
41
+ }
42
+
43
+ } catch (err: any) {
44
+ console.error('❌ Error in msg command:', err.message);
45
+ }
46
+ }
@@ -0,0 +1,11 @@
1
+ export function checkEnv() {
2
+ const requiredVars = ["DB_HOST", "API_KEY"];
3
+ const missing = requiredVars.filter((v) => !process.env[v]);
4
+
5
+ if (missing.length) {
6
+ console.warn("❌ Missing env vars:", missing.join(", "));
7
+ } else {
8
+ console.log("✅ All env vars are set");
9
+ }
10
+ }
11
+
@@ -0,0 +1,28 @@
1
+ import { execSync } from "child_process";
2
+
3
+ export function checkGit() {
4
+ try {
5
+ execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
6
+ const status = execSync("git status --porcelain").toString();
7
+ const isClean = status.trim().length === 0;
8
+
9
+ if (isClean) {
10
+ console.log("✅ Git working directory is clean");
11
+ } else {
12
+ console.log("⚠️ Git working directory has uncommitted changes");
13
+ }
14
+
15
+ const branch = execSync("git rev-parse --abbrev-ref HEAD").toString().trim();
16
+ const mainHash = execSync("git rev-parse origin/main").toString().trim();
17
+ const localHash = execSync("git rev-parse HEAD").toString().trim();
18
+
19
+ if (localHash === mainHash) {
20
+ console.log("✅ Up to date with origin/main");
21
+ } else {
22
+ console.log(`🔄 Branch ${branch} is not up to date with origin/main`);
23
+ }
24
+ } catch {
25
+ console.error("❌ Not inside a Git repository");
26
+ }
27
+ }
28
+
@@ -0,0 +1,49 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+
4
+ export async function handleRefactor(filepath: string) {
5
+ try {
6
+ // 1) Read original file
7
+ const code = await fs.readFile(filepath, 'utf-8');
8
+
9
+ // 2) Prompt the LLM
10
+ const prompt = `
11
+ You are a senior JavaScript engineer. Refactor the code below to improve readability,
12
+ modularity, and maintainability. Return ONLY the refactored code.
13
+
14
+ --- ORIGINAL CODE START ---
15
+ ${code}
16
+ --- ORIGINAL CODE END ---
17
+ `.trim();
18
+
19
+ const res = await fetch('http://localhost:11434/api/generate', {
20
+ method: 'POST',
21
+ headers: { 'Content-Type': 'application/json' },
22
+ body: JSON.stringify({
23
+ model: 'mistral',
24
+ prompt,
25
+ stream: false
26
+ })
27
+ });
28
+ const data = await res.json();
29
+ console.log('🔍 Raw LLM response:', data);
30
+
31
+ const refactored = data.response?.trim();
32
+ if (!refactored) {
33
+ throw new Error('No refactored code returned from the model.');
34
+ }
35
+
36
+ // 3) Write to a new file alongside the original
37
+ const { dir, name } = path.parse(filepath);
38
+ console.log('dir: ', dir);
39
+ console.log('name: ', name);
40
+ const outDir = path.join(dir, 'refactored');
41
+ await fs.mkdir(outDir, { recursive: true });
42
+ const outPath = path.join(outDir, `${name}.refactored.js`);
43
+ await fs.writeFile(outPath, refactored, 'utf-8');
44
+
45
+ console.log(`✅ Refactored code saved to: ${outPath}`);
46
+ } catch (err: any) {
47
+ console.error('❌ Error in refactor command:', err.message);
48
+ }
49
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { checkEnv } from "./commands/EnvCmd.js";
4
+ import { checkGit } from "./commands/GitCmd.js";
5
+ import { suggestCommitMessage } from "./commands/CommitSuggesterCmd.js";
6
+ import { handleRefactor } from "./commands/RefactorCmd.js";
7
+
8
+ const cmd = new Command('devcheck')
9
+ .version('0.1.0');
10
+
11
+ cmd
12
+ .command('env')
13
+ .description('Check environment variables')
14
+ .action(checkEnv);
15
+
16
+ cmd
17
+ .command('git')
18
+ .description('Check Git status')
19
+ .action(checkGit);
20
+
21
+ cmd
22
+ .command('msg')
23
+ .description('Suggest a commit message from staged changes')
24
+ .option('-c, --commit', 'Automatically commit with suggested message')
25
+ .action(suggestCommitMessage);
26
+
27
+ cmd
28
+ .command('refactor <file>')
29
+ .description('Suggest a refactor for the given JS file')
30
+ .action((file) => handleRefactor(file));
31
+
32
+ cmd.parse(process.argv);
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "esModuleInterop": true,
9
+ "strict": true,
10
+ "resolveJsonModule": true,
11
+ "skipLibCheck": true,
12
+ "types": ["node"]
13
+ },
14
+ "include": ["src"]
15
+ }