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
- - ✨ Refactor messy code files
9
- - 🧠 Check Git status and improve workflows
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
+ }
@@ -1,7 +1,14 @@
1
1
  import { jest } from '@jest/globals';
2
- // Jest setup to mock fetch for Node.js 18+
3
- if (typeof global.fetch === 'undefined') {
4
- global.fetch = jest.fn(() => Promise.resolve({
5
- json: () => Promise.resolve({ response: 'Mocked Commit Message' }),
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 all functions longer than 20 lines by extracting logical parts into smaller helper functions.
10
- - Each resulting function should aim for clarity and ideally be under 20 lines, unless splitting would harm readability or functionality.
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}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scai",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "scai": "./dist/index.js"