scai 0.1.10 → 0.1.12

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
@@ -1,16 +1,29 @@
1
1
  # ⚙️ scai — Smart Commit AI ✨
2
2
 
3
- > AI-powered CLI tools for smart commit messages, automated refactoring, and developer insight — all powered by local models.
3
+ > AI-powered CLI tools for smart commit messages, auto generated comments, and readme files — all powered by local models.
4
4
 
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
+ - 🧠 Get a summary of any code file directly to the terminal
10
10
  - 🔒 100% local — no API keys, no cloud, no telemetry
11
11
 
12
12
  ---
13
13
 
14
+ ## 🚀 Features
15
+
16
+ - ⚡️ Powered by open local Ollama models like `mistral` and new `commentModule`
17
+ - 🛠️ CLI built with Node.js + TypeScript
18
+ - 🔒 No external services, full privacy by design
19
+ - ✅ Now supports global options for model and language settings
20
+
21
+ ### 📦 Recent Additions
22
+
23
+ * **Summary Command**: Print a summary of the given file to the terminal (e.g., `scai summ <file>`)
24
+
25
+ ---
26
+
14
27
  ## ❤️ Philosophy: Why Local AI?
15
28
 
16
29
  We believe your code — and your workflow — should stay **yours**. scai runs entirely on your machine using open-source models and tools.
@@ -22,19 +35,8 @@ No internet connection. No vendor lock-in. Just local, private, AI-enhanced deve
22
35
  ✅ Backed by open-source models
23
36
  ✅ Designed for CLI-first devs and scriptable workflows
24
37
 
25
- ---
26
-
27
38
  **scai** follows the Unix philosophy — small, composable tools with powerful output.
28
39
 
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
40
  ---
39
41
 
40
42
  ## 📦 Installation
@@ -76,7 +78,7 @@ This will:
76
78
  git add .
77
79
 
78
80
  # Let scai suggest a commit message
79
- scai suggest
81
+ scai sugg
80
82
  ```
81
83
 
82
84
  > Example output:
@@ -87,42 +89,29 @@ feat(api): add error handling to user service
87
89
  To automatically commit with the suggested message:
88
90
 
89
91
  ```bash
90
- scai suggest --commit
91
- ```
92
-
93
- ---
94
-
95
- ### 🛠 Refactor a JavaScript file
96
-
97
- ```bash
98
- scai refac path/to/file.js
99
- ```
100
-
101
- A cleaned-up version will be written to:
102
-
103
- ```
104
- path/to/refactored/file.refactored.js
92
+ scai sugg --commit
105
93
  ```
106
94
 
107
95
  ---
108
96
 
109
- ### 🧩 Generate Tests
97
+ ### 🛠 Comment a code file
110
98
 
111
99
  ```bash
112
- scai generate-tests <file>
100
+ scai comment <file>
113
101
  ```
114
102
 
115
- Automatically generates Jest test files for specified JavaScript/TypeScript modules.
103
+ Write comments for the given file. Optional flags:
104
+ - `-a, --apply` - Apply the refactored version to the original file
116
105
 
117
106
  ---
118
107
 
119
- ### 🔍 Check Git status
108
+ ### 🔍 Code summary
120
109
 
121
110
  ```bash
122
- scai git
111
+ scai summ <file>
123
112
  ```
124
113
 
125
- Useful overview of current branch, commits, and uncommitted changes.
114
+ Create a quick summary of the file your working on to gain fast insights.
126
115
 
127
116
  ---
128
117
 
@@ -142,4 +131,4 @@ However:
142
131
 
143
132
  For full terms, see the [LICENSE](./LICENSE) file.
144
133
 
145
- ---
134
+ ---
@@ -0,0 +1,106 @@
1
+ import { execSync } from 'child_process';
2
+ import readline from 'readline';
3
+ async function askUserToChoose(suggestions) {
4
+ return new Promise((resolve) => {
5
+ console.log('\n💡 AI-suggested commit messages:\n'); // Display all suggestions to the user
6
+ suggestions.forEach((msg, i) => {
7
+ console.log(`${i + 1}) ${msg}`);
8
+ });
9
+ console.log(`${suggestions.length + 1}) 🔁 Regenerate suggestions`); // Allow the user to regenerate suggestions if they want
10
+ console.log(`${suggestions.length + 2}) ✍️ Write your own commit message`); // Allow the user to write their own commit message
11
+ const rl = readline.createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout,
14
+ });
15
+ rl.question(`\n👉 Choose a commit message [1-${suggestions.length + 2}]: `, // Ask the user to choose from the suggestions or write their own
16
+ (answer) => {
17
+ rl.close();
18
+ const choice = parseInt(answer, 10); // Parse the user's input as a number
19
+ if (isNaN(choice) || choice < 1 || choice > suggestions.length + 2) { // Check that the user has entered a valid number
20
+ console.log('⚠️ Invalid selection. Using the first suggestion by default.'); // Default to the first suggestion if the input is invalid
21
+ resolve(0); // Resolve the promise with the 0-based index (0 to 3)
22
+ }
23
+ else if (choice === suggestions.length + 2) { // If the user has chosen "Write your own commit message"
24
+ resolve('custom'); // Return 'custom' to indicate that the user wants to write their own commit message
25
+ }
26
+ else {
27
+ resolve(choice - 1); // Return the 0-based index (0 to 3) of the selected suggestion
28
+ }
29
+ });
30
+ });
31
+ }
32
+ async function generateSuggestions(prompt) {
33
+ const res = await fetch("http://localhost:11434/api/generate", {
34
+ method: "POST",
35
+ headers: { "Content-Type": "application/json" },
36
+ body: JSON.stringify({
37
+ model: "llama3",
38
+ prompt,
39
+ stream: false,
40
+ }),
41
+ });
42
+ const { response } = await res.json(); // Parse the response from the API as JSON
43
+ if (!response || typeof response !== 'string') { // Check that the response is valid
44
+ throw new Error('Invalid LLM response'); // Throw an error if the response is invalid
45
+ }
46
+ const lines = response.trim().split('\n').filter(line => /^\d+\.\s+/.test(line)); // Split the response into individual lines and filter out any lines that don't start with a number followed by a period
47
+ const messages = lines.map(line => // Map each line to its commit message suggestion
48
+ line.replace(/^\d+\.\s+/, '').replace(/^"(.*)"$/, '$1').trim());
49
+ if (messages.length === 0) { // Check that there are any commit message suggestions
50
+ throw new Error('No valid commit messages found in LLM response.'); // Throw an error if there are no valid commit message suggestions
51
+ }
52
+ return messages; // Return the array of commit message suggestions
53
+ }
54
+ function promptCustomMessage() {
55
+ return new Promise((resolve) => {
56
+ const rl = readline.createInterface({
57
+ input: process.stdin,
58
+ output: process.stdout,
59
+ });
60
+ rl.question('\n📝 Enter your custom commit message:\n> ', (input) => {
61
+ rl.close();
62
+ resolve(input.trim()); // Resolve the promise with the trimmed input string
63
+ });
64
+ });
65
+ }
66
+ export async function suggestCommitMessage(options) {
67
+ try {
68
+ let diff = execSync("git diff", { encoding: "utf-8" }).trim(); // Get the current Git diff
69
+ if (!diff) { // Check that there are any changes to stage
70
+ diff = execSync("git diff --cached", { encoding: "utf-8" }).trim(); // If there are no staged changes, check for unstaged changes
71
+ }
72
+ if (!diff) { // If there are still no changes, display a message and return early
73
+ console.log('⚠️ No staged changes to suggest a message for.');
74
+ return;
75
+ }
76
+ const prompt = `Suggest 3 concise, conventional Git commit message options for this diff. Return ONLY the commit messages, numbered 1 to 3, like so:
77
+ 1. ...
78
+ 2. ...
79
+ 3. ...
80
+
81
+ Here is the diff:
82
+ ${diff}`; // Create a prompt string for the user to enter their own commit message suggestions
83
+ let message = null;
84
+ while (message === null) { // Loop until the user has entered a valid commit message or chosen to write their own
85
+ const suggestions = await generateSuggestions(prompt); // Generate commit message suggestions based on the diff output from Git
86
+ const choice = await askUserToChoose(suggestions); // Ask the user to choose from the suggestions or write their own
87
+ if (choice === 'custom') { // If the user has chosen "Write your own commit message"
88
+ message = await promptCustomMessage(); // Prompt the user for their custom commit message
89
+ break; // Break out of the loop and use the custom commit message
90
+ }
91
+ message = suggestions[choice]; // Use the selected suggestion as the commit message
92
+ }
93
+ console.log(`\n✅ Selected commit message:\n${message}\n`); // Display the selected commit message to the user
94
+ if (options.commit) { // If the user has specified that they want to commit the changes
95
+ const commitDiff = execSync("git diff", { encoding: "utf-8" }).trim(); // Get the current Git diff again, in case anything has changed since the last call to `generateSuggestions`
96
+ if (commitDiff) { // Check that there are any staged changes
97
+ execSync("git add .", { encoding: "utf-8" }); // Stage all changes before committing
98
+ }
99
+ execSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' }); // Commit the changes with the selected commit message
100
+ console.log('✅ Committed with selected message.'); // Display a success message to the user
101
+ }
102
+ }
103
+ catch (err) { // If there is an error in the code
104
+ console.error('❌ Error in commit message suggestion:', err); // Log the error to the console
105
+ }
106
+ }
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Here;
3
+ 's a Jest test file for the `checkEnv` function: `` `typescript
4
+ import { checkEnv } from "../src/utils";
5
+
6
+ describe("checkEnv", () => {
7
+ it("should warn when missing required env vars", () => {
8
+ const processEnv = Object.assign({}, process.env);
9
+ delete processEnv.DB_HOST;
10
+ delete processEnv.API_KEY;
11
+ const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation();
12
+ checkEnv();
13
+ expect(consoleWarnSpy).toHaveBeenCalledWith("❌ Missing env vars: DB_HOST, API_KEY");
14
+ consoleWarnSpy.mockRestore();
15
+ });
16
+
17
+ it("should log a message when all required env vars are set", () => {
18
+ const processEnv = Object.assign({}, process.env);
19
+ checkEnv();
20
+ expect(console.log).toHaveBeenCalledWith("✅ All env vars are set");
21
+ });
22
+ });
23
+ ` ``;
24
+ In;
25
+ this;
26
+ test;
27
+ file, we;
28
+ first;
29
+ var the = ;
30
+ `checkEnv`;
31
+ function from() { }
32
+ the;
33
+ contains;
34
+ it.We;
35
+ then;
36
+ define;
37
+ two;
38
+ test;
39
+ cases: one;
40
+ for (when; required; environment)
41
+ variables;
42
+ are;
43
+ missing;
44
+ and;
45
+ another;
46
+ for (when; all; required)
47
+ environment;
48
+ variables;
49
+ are;
50
+ set.
51
+ ;
52
+ In;
53
+ the;
54
+ first;
55
+ test;
56
+ we;
57
+ use `jest.spyOn()`;
58
+ to;
59
+ mock;
60
+ the `console.warn()`;
61
+ method;
62
+ and;
63
+ replace;
64
+ it;
65
+ with (a)
66
+ spy;
67
+ function () { }
68
+ We;
69
+ then;
70
+ delete the `DB_HOST`;
71
+ and `API_KEY`;
72
+ environment;
73
+ variables;
74
+ and;
75
+ call;
76
+ the `checkEnv()`;
77
+ function () { }
78
+ Finally, we;
79
+ check;
80
+ that;
81
+ the `console.warn()`;
82
+ method;
83
+ was;
84
+ called;
85
+ with (the)
86
+ expected;
87
+ message.
88
+ ;
89
+ In;
90
+ the;
91
+ second;
92
+ test;
93
+ we;
94
+ simply;
95
+ call;
96
+ the `checkEnv()`;
97
+ function without() { }
98
+ deleting;
99
+ any;
100
+ environment;
101
+ variables;
102
+ and;
103
+ check;
104
+ that;
105
+ the `console.log()`;
106
+ method;
107
+ was;
108
+ called;
109
+ with (the)
110
+ expected;
111
+ message.
112
+ ;
113
+ Note;
114
+ that;
115
+ we;
116
+ use;
117
+ the `mockImplementation()`;
118
+ method;
119
+ to;
120
+ mock;
121
+ the `console.warn()`;
122
+ method;
123
+ and;
124
+ the `mockRestore()`;
125
+ method;
126
+ to;
127
+ restore;
128
+ it;
129
+ after;
130
+ the;
131
+ test;
132
+ is;
133
+ done.This;
134
+ is;
135
+ necessary;
136
+ because;
137
+ Jest;
138
+ does;
139
+ not;
140
+ allow;
141
+ us;
142
+ to;
143
+ modify;
144
+ the;
145
+ original `console.warn()`;
146
+ method.;
@@ -0,0 +1,12 @@
1
+ // File: src/commands/SummaryCmd.ts
2
+ import fs from 'fs/promises';
3
+ import { summaryModule } from '../pipeline/modules/summaryModule.js';
4
+ export async function summarizeFile(filepath) {
5
+ try {
6
+ const code = await fs.readFile(filepath, 'utf-8');
7
+ await summaryModule.run({ code });
8
+ }
9
+ catch (err) {
10
+ console.error(`❌ Could not read or summarize ${filepath}:`, err.message);
11
+ }
12
+ }
@@ -0,0 +1,16 @@
1
+ export class ModelConfig {
2
+ static setModel(model) {
3
+ this.model = model;
4
+ }
5
+ static getModel() {
6
+ return this.model;
7
+ }
8
+ static setLanguage(lang) {
9
+ this.language = lang;
10
+ }
11
+ static getLanguage() {
12
+ return this.language;
13
+ }
14
+ }
15
+ ModelConfig.model = 'codellama:7b';
16
+ ModelConfig.language = 'ts';
package/dist/index.js CHANGED
@@ -1,16 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { createRequire } from 'module';
4
+ const require = createRequire(import.meta.url);
5
+ const { version } = require('../package.json');
3
6
  import { checkEnv } from "./commands/EnvCmd.js";
4
7
  import { checkGit } from "./commands/GitCmd.js";
5
8
  import { suggestCommitMessage } from "./commands/CommitSuggesterCmd.js";
6
9
  import { handleRefactor } from "./commands/RefactorCmd.js";
7
10
  import { updateReadmeIfNeeded } from "./commands/ReadmeCmd.js";
8
11
  import { generateTests } from "./commands/TestGenCmd.js";
9
- // Import the model check and initialization logic
10
12
  import { bootstrap } from './modelSetup.js';
13
+ import { ModelConfig } from './config/ModelConfig.js';
14
+ import { summarizeFile } from "./commands/SummaryCmd.js";
11
15
  // Create the CLI instance
12
16
  const cmd = new Command('scai')
13
- .version('0.1.0');
17
+ .version(version)
18
+ .option('--model <model>', 'Set the model to use (e.g., codellama:34b)')
19
+ .option('--lang <lang>', 'Set the target language (ts, java, rust)');
14
20
  // Define CLI commands
15
21
  cmd
16
22
  .command('init')
@@ -20,21 +26,13 @@ cmd
20
26
  console.log('✅ Model initialization completed!');
21
27
  });
22
28
  cmd
23
- .command('env')
24
- .description('Check environment variables')
25
- .action(checkEnv);
26
- cmd
27
- .command('git')
28
- .description('Check Git status')
29
- .action(checkGit);
30
- cmd
31
- .command('suggest')
29
+ .command('sugg')
32
30
  .description('Suggest a commit message from staged changes')
33
31
  .option('-c, --commit', 'Automatically commit with suggested message')
34
32
  .action(suggestCommitMessage);
35
33
  cmd
36
- .command('refac <file>')
37
- .description('Suggest a refactor for the given JS/TS file')
34
+ .command('comm <file>')
35
+ .description('Write comments for the given file')
38
36
  .option('-a, --apply', 'Apply the refactored version to the original file')
39
37
  .action((file, options) => handleRefactor(file, options));
40
38
  cmd
@@ -42,8 +40,26 @@ cmd
42
40
  .description('Update README.md if relevant changes were made')
43
41
  .action(updateReadmeIfNeeded);
44
42
  cmd
45
- .command('generate-tests <file>')
43
+ .command('summ <file>')
44
+ .description('Print a summary of the given file to the terminal')
45
+ .action((file) => summarizeFile(file));
46
+ cmd
47
+ .command('git')
48
+ .description('Check Git status')
49
+ .action(checkGit);
50
+ cmd
51
+ .command('env')
52
+ .description('Check environment variables')
53
+ .action(checkEnv);
54
+ cmd
55
+ .command('gen-tests <file>')
46
56
  .description('Generate a Jest test file for the specified JS/TS module')
47
57
  .action((file) => generateTests(file));
48
- // Parse CLI arguments
58
+ // Now that commands are defined, parse args
49
59
  cmd.parse(process.argv);
60
+ // ✅ Apply global options after parsing
61
+ const opts = cmd.opts();
62
+ if (opts.model)
63
+ ModelConfig.setModel(opts.model);
64
+ if (opts.lang)
65
+ ModelConfig.setLanguage(opts.lang);
@@ -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
+ );
@@ -1,9 +1,12 @@
1
+ import { ModelConfig } from '../../config/ModelConfig.js';
1
2
  export const addCommentsModule = {
2
3
  name: 'addComments',
3
4
  description: 'Adds meaningful // comments to each block of code',
4
5
  async run(input) {
6
+ const model = ModelConfig.getModel();
7
+ const lang = ModelConfig.getLanguage();
5
8
  const prompt = `
6
- You are a senior JavaScript engineer.
9
+ You are a senior ${lang.toUpperCase()} engineer.
7
10
 
8
11
  Add clear and helpful single-line // comments to complex parts of the code.
9
12
  - Do NOT remove or change in ANY way any parts of the code!
@@ -17,8 +20,8 @@ ${input.code}
17
20
  method: 'POST',
18
21
  headers: { 'Content-Type': 'application/json' },
19
22
  body: JSON.stringify({
20
- model: 'mistral',
21
- prompt: prompt,
23
+ model,
24
+ prompt,
22
25
  stream: false,
23
26
  }),
24
27
  });
@@ -1,11 +1,14 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
+ import { ModelConfig } from '../../config/ModelConfig.js';
3
4
  export const generateTestsModule = {
4
5
  name: 'generateTests',
5
6
  description: 'Generate a Jest test file for the class/module',
6
7
  async run({ code, filepath }) {
8
+ const model = ModelConfig.getModel();
9
+ const lang = ModelConfig.getLanguage();
7
10
  const prompt = `
8
- You're a senior TypeScript developer. Given the following class or module, generate a Jest test file.
11
+ You are a senior ${lang.toUpperCase()} engineer. Given the following class or module, generate a Jest test file.
9
12
 
10
13
  Guidelines:
11
14
  - Use the 'jest' test framework
@@ -21,7 +24,7 @@ ${code}
21
24
  method: 'POST',
22
25
  headers: { 'Content-Type': 'application/json' },
23
26
  body: JSON.stringify({
24
- model: 'mistral',
27
+ model,
25
28
  prompt,
26
29
  stream: false
27
30
  })
@@ -1,24 +1,45 @@
1
+ import { ModelConfig } from '../../config/ModelConfig.js';
1
2
  export const refactorModule = {
2
3
  name: 'refactor',
3
4
  description: 'Break code into small, clean functions',
4
- async run({ code }) {
5
+ async run(input) {
6
+ const model = ModelConfig.getModel();
7
+ const lang = ModelConfig.getLanguage();
5
8
  const prompt = `
6
- You are a senior JavaScript/TypeScript engineer.
9
+ You are a senior ${lang.toUpperCase()} engineer.
7
10
 
8
11
  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.
12
+ - Refactor only long and complex functions
13
+ - Keep original names and semantics.
14
+ - Do NOT insert comments
11
15
 
12
16
  --- CODE START ---
13
- ${code}
17
+ ${input.code}
14
18
  --- CODE END ---
15
19
  `.trim();
16
- const res = await fetch('http://localhost:11434/api/generate', {
17
- method: 'POST',
18
- headers: { 'Content-Type': 'application/json' },
19
- body: JSON.stringify({ model: 'mistral', prompt: prompt, stream: false })
20
- });
21
- const data = await res.json();
22
- return { code: data.response?.trim() ?? '' };
20
+ try {
21
+ const res = await fetch('http://localhost:11434/api/generate', {
22
+ method: 'POST',
23
+ headers: { 'Content-Type': 'application/json' },
24
+ body: JSON.stringify({
25
+ model,
26
+ prompt,
27
+ stream: false
28
+ })
29
+ });
30
+ if (!res.ok) {
31
+ const errBody = await res.text();
32
+ throw new Error(`❌ Refactor failed: ${res.status} ${res.statusText} - ${errBody}`);
33
+ }
34
+ const data = await res.json();
35
+ if (!data.response) {
36
+ throw new Error('❌ No response field returned from model.');
37
+ }
38
+ return { code: data.response.trim() };
39
+ }
40
+ catch (err) {
41
+ console.error('🔥 Error in refactorModule:', err);
42
+ throw new Error('❌ Error in refactor module: ' + err.message);
43
+ }
23
44
  }
24
45
  };
@@ -1,20 +1,22 @@
1
+ import { ModelConfig } from '../../config/ModelConfig.js';
1
2
  export const summaryModule = {
2
3
  name: 'summary',
3
- description: 'Append // Summary of changes at the end',
4
+ description: 'Prints a summary of changes to the terminal',
4
5
  async run({ code }) {
6
+ const model = ModelConfig.getModel();
7
+ const lang = ModelConfig.getLanguage();
5
8
  const prompt = `
6
- You are a senior developer assistant.
9
+ You are a senior ${lang.toUpperCase()} engineer.
7
10
 
8
- Take the following code and return it exactly as-is,
9
- but add a summary at the very end in this format:
11
+ Analyze the code below and return a concise summary of its functionality or structure.
12
+ Only return the summary in this format:
10
13
 
11
- // Summary of refactor:
12
- // - Did X
13
- // - Did Y
14
+ // Summary of code:
15
+ // - [Bullet 1]
16
+ // - [Bullet 2]
14
17
  // - etc.
15
18
 
16
- DO NOT modify or omit any existing code.
17
- Just append the summary.
19
+ Return the original code after the summary.
18
20
 
19
21
  --- CODE START ---
20
22
  ${code}
@@ -23,9 +25,18 @@ ${code}
23
25
  const res = await fetch('http://localhost:11434/api/generate', {
24
26
  method: 'POST',
25
27
  headers: { 'Content-Type': 'application/json' },
26
- body: JSON.stringify({ model: 'llama3', prompt: prompt, stream: false })
28
+ body: JSON.stringify({ model, prompt, stream: false })
27
29
  });
28
30
  const data = await res.json();
29
- return { code: data.response?.trim() ?? '' };
31
+ const summary = data.response?.trim();
32
+ if (summary) {
33
+ console.log('\n📝 Code Summary:\n');
34
+ console.log(summary);
35
+ }
36
+ else {
37
+ console.warn('⚠️ No summary generated.');
38
+ }
39
+ // Return unchanged input so it’s pipe-safe, if reused in pipelines
40
+ return { code };
30
41
  }
31
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scai",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "scai": "./dist/index.js"