scai 0.1.10 ā 0.1.11
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
CHANGED
|
@@ -5,12 +5,24 @@
|
|
|
5
5
|
**scai** (Smart Commit AI) is a lightweight, privacy-focused CLI tool that uses local AI models (via [Ollama](https://ollama.com)) to help developers work faster and cleaner:
|
|
6
6
|
|
|
7
7
|
- š¤ Suggest high-quality Git commit messages
|
|
8
|
-
- āØ
|
|
9
|
-
- š§
|
|
8
|
+
- ⨠Comments your code automatically
|
|
9
|
+
- š§ Generate README updates based on your diff
|
|
10
10
|
- š 100% local ā no API keys, no cloud, no telemetry
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
**scai** follows the Unix philosophy ā small, composable tools with powerful output.
|
|
15
|
+
|
|
16
|
+
## š Features
|
|
17
|
+
|
|
18
|
+
- š¬ Generate commit messages from staged Git changes
|
|
19
|
+
- ⨠Add comments to your code
|
|
20
|
+
- ā”ļø Powered by open local Ollama models like `mistral`
|
|
21
|
+
- š ļø CLI built with Node.js + TypeScript
|
|
22
|
+
- š No external services, full privacy by design
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
14
26
|
## ā¤ļø Philosophy: Why Local AI?
|
|
15
27
|
|
|
16
28
|
We believe your code ā and your workflow ā should stay **yours**. scai runs entirely on your machine using open-source models and tools.
|
|
@@ -24,19 +36,6 @@ No internet connection. No vendor lock-in. Just local, private, AI-enhanced deve
|
|
|
24
36
|
|
|
25
37
|
---
|
|
26
38
|
|
|
27
|
-
**scai** follows the Unix philosophy ā small, composable tools with powerful output.
|
|
28
|
-
|
|
29
|
-
## š Features
|
|
30
|
-
|
|
31
|
-
- š¬ Generate commit messages from staged Git changes
|
|
32
|
-
- ⨠Refactor a single JavaScript file for improved readability
|
|
33
|
-
- š Check Git status with one command
|
|
34
|
-
- ā”ļø Powered by open local Ollama models like `mistral`
|
|
35
|
-
- š ļø CLI built with Node.js + TypeScript
|
|
36
|
-
- š No external services, full privacy by design
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
39
|
## š¦ Installation
|
|
41
40
|
|
|
42
41
|
1. **Install [Ollama](https://ollama.com)**
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Import required modules
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import readline from 'readline';
|
|
4
|
+
// Function to ask the user to choose a commit message suggestion
|
|
5
|
+
async function askUserToChoose(suggestions) {
|
|
6
|
+
// Create an interface for reading and writing to the console
|
|
7
|
+
const rl = readline.createInterface({
|
|
8
|
+
input: process.stdin,
|
|
9
|
+
output: process.stdout,
|
|
10
|
+
});
|
|
11
|
+
// Show AI-suggested commit messages to the user and ask for their choice
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
console.log('\nš” AI-suggested commit messages:\n');
|
|
14
|
+
suggestions.forEach((msg, i) => {
|
|
15
|
+
console.log(`${i + 1}) ${msg}`);
|
|
16
|
+
});
|
|
17
|
+
console.log(`${suggestions.length + 1}) š Regenerate suggestions`);
|
|
18
|
+
console.log(`${suggestions.length + 2}) āļø Write your own commit message`);
|
|
19
|
+
rl.question(`\nš Choose a commit message [1-${suggestions.length + 2}]: `, (answer) => {
|
|
20
|
+
// Close the readline interface and resolve the promise with user choice
|
|
21
|
+
rl.close();
|
|
22
|
+
const choice = parseInt(answer, 10);
|
|
23
|
+
if (isNaN(choice) || choice < 1 || choice > suggestions.length + 2) {
|
|
24
|
+
console.log('ā ļø Invalid selection. Using the first suggestion by default.');
|
|
25
|
+
resolve(0);
|
|
26
|
+
}
|
|
27
|
+
else if (choice === suggestions.length + 2) {
|
|
28
|
+
resolve('custom');
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
resolve(choice - 1); // Return 0-based index (0 to 3)
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// Async function to generate commit message suggestions using an API call
|
|
37
|
+
async function generateSuggestions(prompt) {
|
|
38
|
+
// Fetch the suggestions from an API and return them as an array of strings
|
|
39
|
+
const res = await fetch("http://localhost:11434/api/generate", {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: { "Content-Type": "application/json" },
|
|
42
|
+
body: JSON.stringify({
|
|
43
|
+
model: "llama3",
|
|
44
|
+
prompt,
|
|
45
|
+
stream: false,
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
const { response } = await res.json();
|
|
49
|
+
// Check for validity of the LLM response and return an array of commit messages
|
|
50
|
+
if (!response || typeof response !== 'string') {
|
|
51
|
+
throw new Error('Invalid LLM response');
|
|
52
|
+
}
|
|
53
|
+
const lines = response.trim().split('\n').filter(line => /^\d+\.\s+/.test(line));
|
|
54
|
+
return lines.map(line => line.replace(/^\d+\.\s+/, '').replace(/^"(.*)"$/, '$1').trim());
|
|
55
|
+
}
|
|
56
|
+
// Function to prompt the user for a custom commit message
|
|
57
|
+
async function promptCustomMessage() {
|
|
58
|
+
// Read the user's input for their custom commit message
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
const rl = readline.createInterface({
|
|
61
|
+
input: process.stdin,
|
|
62
|
+
output: process.stdout,
|
|
63
|
+
});
|
|
64
|
+
rl.question('\nš Enter your custom commit message:\n> ', (input) => {
|
|
65
|
+
rl.close();
|
|
66
|
+
resolve(input.trim());
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// Export the main function to suggest a commit message based on user input and generated suggestions
|
|
71
|
+
export async function suggestCommitMessage(options) {
|
|
72
|
+
try {
|
|
73
|
+
let diff = execSync("git diff", { encoding: "utf-8" }).trim();
|
|
74
|
+
if (!diff) {
|
|
75
|
+
diff = execSync("git diff --cached", { encoding: "utf-8" }).trim();
|
|
76
|
+
}
|
|
77
|
+
if (!diff) {
|
|
78
|
+
console.log('ā ļø No staged changes to suggest a message for.');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const prompt = `Suggest 3 concise, conventional Git commit message options for this diff. Return ONLY the commit messages, numbered 1 to 3, like so:
|
|
82
|
+
1. ...
|
|
83
|
+
2. ...
|
|
84
|
+
3. ...
|
|
85
|
+
|
|
86
|
+
Here is the diff:
|
|
87
|
+
${diff}`;
|
|
88
|
+
let message = null;
|
|
89
|
+
while (message === null) {
|
|
90
|
+
const suggestions = await generateSuggestions(prompt);
|
|
91
|
+
const choice = await askUserToChoose(suggestions);
|
|
92
|
+
if (choice === suggestions.length) {
|
|
93
|
+
// User chose "Regenerate"
|
|
94
|
+
console.log('\nš Regenerating suggestions...\n');
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (choice === 'custom') {
|
|
98
|
+
message = await promptCustomMessage();
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
message = suggestions[choice];
|
|
102
|
+
}
|
|
103
|
+
console.log(`\nā
Selected commit message:\n${message}\n`);
|
|
104
|
+
if (options.commit) {
|
|
105
|
+
const commitDiff = execSync("git diff", { encoding: "utf-8" }).trim();
|
|
106
|
+
if (commitDiff) {
|
|
107
|
+
execSync("git add .", { encoding: "utf-8" });
|
|
108
|
+
}
|
|
109
|
+
execSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
|
|
110
|
+
console.log('ā
Committed with selected message.');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
console.error('ā Error in commit message suggestion:', err.message);
|
|
115
|
+
}
|
|
116
|
+
}
|
package/dist/jest.setup.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { jest } from '@jest/globals';
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
// jest.setup.ts
|
|
3
|
+
// Mock the global fetch function in Jest for Node.js 18+
|
|
4
|
+
global.fetch = jest.fn(() => Promise.resolve({
|
|
5
|
+
json: () => Promise.resolve({ response: 'Mocked Commit Message' }),
|
|
6
|
+
ok: true,
|
|
7
|
+
status: 200,
|
|
8
|
+
statusText: 'OK',
|
|
9
|
+
headers: new Headers(),
|
|
10
|
+
redirected: false,
|
|
11
|
+
type: 'default',
|
|
12
|
+
url: 'https://mocked-url.com',
|
|
13
|
+
}) // Type assertion for `Response` object
|
|
14
|
+
);
|
|
@@ -6,8 +6,9 @@ export const refactorModule = {
|
|
|
6
6
|
You are a senior JavaScript/TypeScript engineer.
|
|
7
7
|
|
|
8
8
|
Refactor the following code:
|
|
9
|
-
- Refactor
|
|
10
|
-
-
|
|
9
|
+
- Refactor only long and complex functions
|
|
10
|
+
- Keep original names and semantics.
|
|
11
|
+
- Do NOT insert comments
|
|
11
12
|
|
|
12
13
|
--- CODE START ---
|
|
13
14
|
${code}
|