@notyped/gitai 1.0.1 → 1.0.2
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/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import f from"chalk";import{Command as
|
|
2
|
+
import f from"chalk";import{Command as te}from"commander";import oe from"path";import S from"@anthropic-ai/sdk";import F from"groq-sdk";import _ from"openai";import m from"chalk";var s={header:e=>{console.log(m.cyan.bold(`\u{1F680} ${e}`))},success:e=>{console.log(m.green.bold(`\u2705 ${e}`))},info:e=>{console.log(m.blue.bold(`\u2139\uFE0F ${e}`))},warning:e=>{console.log(m.yellow.bold(`\u26A0\uFE0F ${e}`))},error:e=>{console.log(m.red.bold(`\u274C ${e}`))},git:e=>{console.log(m.magenta.bold(`\u{1F504} ${e}`))},ai:e=>{console.log(m.cyan.bold(`\u{1F916} ${e}`))},commit:e=>{console.log(`
|
|
3
3
|
`+m.bgBlue.white.bold(" Generated commit message: ")+`
|
|
4
|
-
`),console.log(m.white.bold(e)),console.log()}};var x=class{config;openai;groq;anthropic;constructor(o){this.config=o,this.initializeClient()}initializeClient(){switch(this.config.provider){case"openai":this.openai=new _({apiKey:this.config.apiKey});break;case"groq":this.groq=new
|
|
4
|
+
`),console.log(m.white.bold(e)),console.log()}};var x=class{config;openai;groq;anthropic;constructor(o){this.config=o,this.initializeClient()}initializeClient(){switch(this.config.provider){case"openai":this.openai=new _({apiKey:this.config.apiKey});break;case"groq":this.groq=new F({apiKey:this.config.apiKey});break;case"anthropic":this.anthropic=new S({apiKey:this.config.apiKey});break;default:s.error(`Provider ${this.config.provider} is not supported.`),process.exit(1)}}getCommitSystemPrompt(){return`
|
|
5
5
|
You are an assistant that helps generate commit messages for a Git repository.
|
|
6
6
|
Commit messages must follow the Conventional Commits standard, which uses ONLY these specific prefixes to categorize the type of change made: feat, fix, docs, chore.
|
|
7
7
|
The description must be concise and clear, explaining what was done, the reason for the change, and, if applicable, the impact of the change.
|
|
@@ -113,19 +113,19 @@ Important rules:
|
|
|
113
113
|
- Remember to follow the provided template.
|
|
114
114
|
|
|
115
115
|
If the instructions are not followed correctly, the result will not be accepted.
|
|
116
|
-
`.trim();return this.callApi(i,r)}async callApi(o,n){if(this.config.provider==="openai"&&this.openai){s.ai(`Provider: openai - Model: ${this.config.model}`);let i=["o1","o3","gpt-5"].some(l=>this.config.model.startsWith(l))?"max_completion_tokens":"max_tokens";return(await this.openai.chat.completions.create({messages:[{role:"system",content:o},{role:"user",content:n}],model:this.config.model,temperature:.5,top_p:1,frequency_penalty:0,presence_penalty:0,[i]:500})).choices[0].message.content?.trim()||""}else{if(this.config.provider==="groq"&&this.groq)return s.ai(`Provider: groq - Model: ${this.config.model}`),(await this.groq.chat.completions.create({messages:[{role:"system",content:o},{role:"user",content:n}],model:this.config.model,temperature:.5,max_tokens:500,top_p:1,frequency_penalty:0,presence_penalty:0})).choices[0].message.content?.trim()||"";if(this.config.provider==="anthropic"&&this.anthropic){s.ai(`Provider: anthropic - Model: ${this.config.model}`);let i=(await this.anthropic.messages.create({model:this.config.model,max_tokens:500,temperature:.5,system:o,messages:[{role:"user",content:n}]})).content[0];return i.type==="text"?i.text.trim():""}}return""}};import P from"fs";import
|
|
117
|
-
`).forEach(n=>{let[t,...i]=n.split("=");if(t&&i&&t.trim()){let r=i.join("=").trim();r.startsWith('"')&&r.endsWith('"')&&(r=r.slice(1,-1)),r.startsWith("'")&&r.endsWith("'")&&(r=r.slice(1,-1)),o[t.trim()]=r}}),o},
|
|
118
|
-
`);P.writeFileSync(u,o,{mode:384})},$=()=>{let e=v.node;return
|
|
119
|
-
`)}async function
|
|
116
|
+
`.trim();return this.callApi(i,r)}async callApi(o,n){if(this.config.provider==="openai"&&this.openai){s.ai(`Provider: openai - Model: ${this.config.model}`);let i=["o1","o3","gpt-5"].some(l=>this.config.model.startsWith(l))?"max_completion_tokens":"max_tokens";return(await this.openai.chat.completions.create({messages:[{role:"system",content:o},{role:"user",content:n}],model:this.config.model,temperature:.5,top_p:1,frequency_penalty:0,presence_penalty:0,[i]:500})).choices[0].message.content?.trim()||""}else{if(this.config.provider==="groq"&&this.groq)return s.ai(`Provider: groq - Model: ${this.config.model}`),(await this.groq.chat.completions.create({messages:[{role:"system",content:o},{role:"user",content:n}],model:this.config.model,temperature:.5,max_tokens:500,top_p:1,frequency_penalty:0,presence_penalty:0})).choices[0].message.content?.trim()||"";if(this.config.provider==="anthropic"&&this.anthropic){s.ai(`Provider: anthropic - Model: ${this.config.model}`);let i=(await this.anthropic.messages.create({model:this.config.model,max_tokens:500,temperature:.5,system:o,messages:[{role:"user",content:n}]})).content[0];return i.type==="text"?i.text.trim():""}}return""}};import P from"fs";import Y from"os";import K from"path";import q from"semver";var h="1.0.2",R="gitai",v={node:">=18"};var u=K.join(Y.homedir(),".gitai"),w=()=>{try{return P.existsSync(u)}catch{return!1}},C=()=>{if(!w())throw new Error(`Configuration file not found at ${u}`);let e=P.readFileSync(u,"utf-8"),o={};return e.split(`
|
|
117
|
+
`).forEach(n=>{let[t,...i]=n.split("=");if(t&&i&&t.trim()){let r=i.join("=").trim();r.startsWith('"')&&r.endsWith('"')&&(r=r.slice(1,-1)),r.startsWith("'")&&r.endsWith("'")&&(r=r.slice(1,-1)),o[t.trim()]=r}}),o},N=e=>{let o=Object.entries(e).map(([n,t])=>`${n}=${t}`).join(`
|
|
118
|
+
`);P.writeFileSync(u,o,{mode:384})},$=()=>{let e=v.node;return q.satisfies(process.version,e)};import{execa as U}from"execa";import L from"fs/promises";import W from"os";import B from"path";async function g(e,o=process.cwd(),n=!0){try{let t=await U("git",e,{cwd:o,reject:!1});return t.exitCode!==0&&n&&(s.error(`Error executing command: git ${e.join(" ")}`),s.error(`Standard output: ${t.stdout}`),s.error(`Error output: ${t.stderr}`),process.exit(1)),{stdout:t.stdout.trim(),stderr:t.stderr.trim(),exitCode:t.exitCode??1}}catch(t){if(n){let r=t instanceof Error?t.message:String(t);s.error(`Unexpected error executing git command: ${r}`),process.exit(1)}return{stdout:"",stderr:t instanceof Error?t.message:String(t),exitCode:1}}}async function O(e){let{stdout:o}=await g(["status","--porcelain"],e);return o.length>0}async function T(e){let{stdout:o}=await g(["status","-uno"],e);return o.includes("Your branch is ahead")||o.includes("Seu branch est\xE1 \xE0 frente")}async function D(e){let{stdout:o,stderr:n,exitCode:t}=await g(["pull"],e,!1);if(t!==0){if(o.includes("CONFLICT")||o.includes("CONFLITO")||n.includes("CONFLICT")||n.includes("CONFLITO"))return s.warning("Conflitos detectados durante git pull:"),s.error(o||n),!1;s.error(`Error executing git pull: ${o||n}`),process.exit(1)}return s.success("Git pull executed successfully."),!0}async function E(e,o){await g(["add","."],o);let n=W.tmpdir(),t=B.join(n,`gitai_commit_${Date.now()}.txt`);try{await L.writeFile(t,e,"utf-8"),await g(["commit","-F",t],o)}finally{try{await L.unlink(t)}catch{}}}async function k(e){await g(["add","."],e);let{stdout:o}=await g(["diff","--cached","--ignore-all-space"],e);return o}import V from"fs/promises";import z from"path";var J={"Node.js":["package.json","yarn.lock","package-lock.json","npm-shrinkwrap.json"],Python:["requirements.txt","Pipfile","pyproject.toml","setup.py","setup.cfg","manage.py"],Java:["pom.xml","build.gradle","build.gradle.kts","build.xml",".java-version"],Go:["go.mod","Gopkg.lock"],PHP:["composer.json","composer.lock","index.php"],Ruby:["Gemfile","Gemfile.lock","Rakefile","config.ru",".ruby-version"],Rust:["Cargo.toml","Cargo.lock"],Haskell:["stack.yaml","cabal.project"],Swift:["Package.swift"],Elixir:["mix.exs"],Dart:["pubspec.yaml"],Scala:["build.sbt"],Perl:["Makefile.PL","Build.PL"],R:[".Rproj"]},H={"C#":[".csproj",".sln"],Haskell:[".cabal"],Swift:[".xcodeproj",".xcworkspace"],Kotlin:[".kt",".kts"],"C/C++":[".c",".cpp",".h",".hpp"],JavaScript:[".js",".jsx"],TypeScript:[".ts",".tsx"],Python:[".py"],Java:[".java"]},X={"Node.js":"\u{1F7E2}",Python:"\u{1F40D}",Java:"\u2615",Go:"\u{1F439}",PHP:"\u{1F418}",Ruby:"\u{1F48E}",Rust:"\u{1F980}",Haskell:"\u{1F3A9}",Swift:"\u{1F34E}",Elixir:"\u{1F4A7}",Dart:"\u{1F3AF}",Scala:"\u2696\uFE0F",Perl:"\u{1F42A}",R:"\u{1F4CA}","C#":"\u{1F537}","C/C++":"\u2699\uFE0F",JavaScript:"\u{1F7E8}",TypeScript:"\u{1F537}",Unknown:"\u2753"};function Q(e){return X[e]||"\u2753"}function I(e){let o=Q(e);s.info(`${o} Linguagem detectada: ${e}
|
|
119
|
+
`)}async function G(e){try{let o=await V.readdir(e);for(let[n,t]of Object.entries(J))for(let i of t)if(!i.includes(z.sep)){if(o.includes(i))return n}for(let[n,t]of Object.entries(H))for(let i of o)if(t.some(r=>i.endsWith(r)))return n;return"Unknown"}catch{return"Unknown"}}import c from"chalk";import{execa as Z}from"execa";import ee from"inquirer";async function M(){console.clear(),console.log(c.bold.blue(`
|
|
120
120
|
\u{1F680} Welcome to GitAI v${h} Setup! \u{1F680}`)),console.log(c.dim(`Let's get you ready to code with AI assistance.
|
|
121
|
-
`));try{await
|
|
121
|
+
`));try{await Z("git",["--version"]),console.log(c.green("\u2705 Git is installed!"))}catch{console.log(c.red("\u274C Git is NOT installed or not accessible from PATH.")),console.log(c.yellow("Please install Git before proceeding.")),process.exit(1)}console.log(c.cyan(`
|
|
122
122
|
\u2699\uFE0F Global Configuration (saved to `+u+`)
|
|
123
123
|
`));let e={};if(w())try{e=C(),console.log(c.green(`\u2705 Found existing configuration at ${u}`))}catch{console.log(c.yellow("\u26A0\uFE0F Could not load existing configuration, starting fresh."))}let n=["LANGUAGE","PROVIDER","API_KEY","MODEL"].filter(l=>!e[l]);if(n.length===0)return console.log(c.green("\u2705 Configuration is complete and valid!")),console.log(c.dim(`You are all set. Running GitAI...
|
|
124
124
|
`)),e;Object.keys(e).length>0&&(console.log(c.yellow(`\u26A0\uFE0F Missing configuration for: ${n.join(", ")}`)),console.log(c.dim(`Please provide the missing details.
|
|
125
|
-
`)));let t=[{type:"list",name:"LANGUAGE",message:"What language should the AI use for commit messages?",choices:[{name:"English",value:"en"},{name:"Portuguese (Brasil)",value:"pt-br"},{name:"Spanish",value:"es"},{name:"French",value:"fr"},{name:"German",value:"de"},{name:"Italian",value:"it"},{name:"Chinese",value:"zh"},{name:"Japanese",value:"ja"},{name:"Korean",value:"ko"}],default:"en",when:()=>!e.LANGUAGE},{type:"list",name:"PROVIDER",message:"Which AI Provider do you want to use?",choices:[{name:"OpenAI",value:"openai"},{name:"Anthropic",value:"anthropic"},{name:"Groq",value:"groq"}],default:"openai",when:()=>!e.PROVIDER},{type:"password",name:"API_KEY",message:"Enter your API Key:",mask:"*",validate:l=>l.length>0?!0:"API Key is required",when:()=>!e.API_KEY},{type:"input",name:"MODEL",message:"Model ID (e.g., gpt-4o, claude-3-5-sonnet):",default:l=>{let a=l.PROVIDER||e.PROVIDER;return a==="openai"?"gpt-4o":a==="anthropic"?"claude-3-5-sonnet-20240620":a==="groq"?"llama3-70b-8192":"gpt-4o"},when:()=>!e.MODEL}],i=await
|
|
125
|
+
`)));let t=[{type:"list",name:"LANGUAGE",message:"What language should the AI use for commit messages?",choices:[{name:"English",value:"en"},{name:"Portuguese (Brasil)",value:"pt-br"},{name:"Spanish",value:"es"},{name:"French",value:"fr"},{name:"German",value:"de"},{name:"Italian",value:"it"},{name:"Chinese",value:"zh"},{name:"Japanese",value:"ja"},{name:"Korean",value:"ko"}],default:"en",when:()=>!e.LANGUAGE},{type:"list",name:"PROVIDER",message:"Which AI Provider do you want to use?",choices:[{name:"OpenAI",value:"openai"},{name:"Anthropic",value:"anthropic"},{name:"Groq",value:"groq"}],default:"openai",when:()=>!e.PROVIDER},{type:"password",name:"API_KEY",message:"Enter your API Key:",mask:"*",validate:l=>l.length>0?!0:"API Key is required",when:()=>!e.API_KEY},{type:"input",name:"MODEL",message:"Model ID (e.g., gpt-4o, claude-3-5-sonnet):",default:l=>{let a=l.PROVIDER||e.PROVIDER;return a==="openai"?"gpt-4o":a==="anthropic"?"claude-3-5-sonnet-20240620":a==="groq"?"llama3-70b-8192":"gpt-4o"},when:()=>!e.MODEL}],i=await ee.prompt(t),r={LANGUAGE:i.LANGUAGE||e.LANGUAGE,PROVIDER:i.PROVIDER||e.PROVIDER,API_KEY:i.API_KEY||e.API_KEY,MODEL:i.MODEL||e.MODEL};return N(r),console.log(c.green(`
|
|
126
126
|
\u2728 Configuration saved successfully! \u2728`)),console.log(c.dim(`You are all set. Running GitAI...
|
|
127
127
|
`)),r}$()||(console.error(f.red(`
|
|
128
128
|
\u274C GitAI requires Node.js ${v.node} or higher.`)),console.error(f.yellow(` Current version: ${process.version}
|
|
129
|
-
`)),process.exit(1));var A=new
|
|
130
|
-
`);let r=new x({provider:t.PROVIDER,model:t.MODEL,apiKey:t.API_KEY,language:t.LANGUAGE});try{process.chdir(i)}catch{s.error(`Failed to change directory to ${i}`),process.exit(1)}if(await O(i)){s.warning("Uncommitted local changes detected.");let a=await
|
|
129
|
+
`)),process.exit(1));var A=new te;A.name(R).description("AI-powered git commit assistant").version(h);A.on("--help",()=>{console.log(""),console.log(f.cyan("\u2501".repeat(50))),console.log(f.bold.blue(` GitAI v${h}`)),console.log(f.dim(" AI-powered git commit assistant")),console.log(f.cyan("\u2501".repeat(50))),console.log("")});A.argument("[projectPath]","The path to the project",".").argument("[baseMessage]","The base commit message").option("-p, --push","Whether to push after committing",!1).action(async(e,o,n)=>{let t;try{w()?t=C():t=await M()}catch(a){let y=a instanceof Error?a.message:String(a);s.error(`Failed to load configuration: ${y}`),process.exit(1)}s.header(`Gitai v${h}`);let i=oe.resolve(e);s.info(`\u{1F4C1} project_path: ${i}
|
|
130
|
+
`);let r=new x({provider:t.PROVIDER,model:t.MODEL,apiKey:t.API_KEY,language:t.LANGUAGE});try{process.chdir(i)}catch{s.error(`Failed to change directory to ${i}`),process.exit(1)}if(await O(i)){s.warning("Uncommitted local changes detected.");let a=await G(i);I(a);let y=await k(i),b=o||"",j=await r.generateCommitMessage(y,a,b);s.commit(j),await E(j,i),s.success("Gitai successfully committed local changes.")}else s.info("No local changes to commit before git pull.");if(await D(i)||(s.error("Git pull failed due to conflicts. Please resolve the conflicts manually."),process.exit(1)),await O(i)){s.warning("Conflicts or uncommitted changes detected after pull.");let a=await G(i);I(a);let y=await k(i),b=await r.generateCommitMessage(y,a,"Resolving conflicts after git pull");s.commit(b),await E(b,i),s.success("Gitai successfully committed changes after pull.")}else s.info("No changes to commit after git pull.");n.push&&(await T(i)?(await g(["push"],i),s.success("Gitai successfully pushed changes.")):s.info("No changes to push. The local branch is synchronized with the remote."))});A.parse();
|
|
131
131
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/services/ai.ts","../src/utils/logger.ts","../src/utils/config.ts","../src/version.ts","../src/utils/git.ts","../src/utils/language.ts","../src/utils/setup.ts"],"sourcesContent":["#!/usr/bin/env node\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport path from 'path';\n\nimport { AIService } from './services/ai.js';\nimport { checkConfigExists, loadConfig, validateNodeVersion } from './utils/config.js';\nimport { commitChanges, hasUncommittedChanges, isBranchAhead, performGitPull, runGitCommand } from './utils/git.js';\nimport { detectProjectLanguage, printDetectedLanguage } from './utils/language.js';\nimport { logger } from './utils/logger.js';\nimport { runSetup } from './utils/setup.js';\n\nimport { engines, name, version } from './version.js';\n\n// 0. Validate Node Version\nif (!validateNodeVersion()) {\n console.error(chalk.red(`\\n❌ GitAI requires Node.js ${engines.node} or higher.`));\n console.error(chalk.yellow(` Current version: ${process.version}\\n`));\n process.exit(1);\n}\n\nconst program = new Command();\n\nprogram\n .name(name)\n .description('AI-powered git commit assistant')\n .version(version);\n\n// Custom help handler to show version\nprogram.on('--help', () => {\n console.log('');\n console.log(chalk.cyan('━'.repeat(50)));\n console.log(chalk.bold.blue(` GitAI v${version}`));\n console.log(chalk.dim(' AI-powered git commit assistant'));\n console.log(chalk.cyan('━'.repeat(50)));\n console.log('');\n});\n\nprogram\n .argument('[projectPath]', 'The path to the project', '.')\n .argument('[baseMessage]', 'The base commit message')\n .option('-p, --push', 'Whether to push after committing', false)\n .action(async (projectPathArg, baseMessageArg, options) => {\n \n // 1. Configuration Check (Global Only)\n let config;\n try {\n if (!checkConfigExists()) {\n config = await runSetup();\n } else {\n config = loadConfig();\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to load configuration: ${errorMessage}`);\n process.exit(1);\n }\n\n logger.header(`Gitai v${version}`);\n \n const projectPath = path.resolve(projectPathArg);\n logger.info(`📁 project_path: ${projectPath}\\n`);\n\n const aiService = new AIService({\n provider: config.PROVIDER,\n model: config.MODEL,\n apiKey: config.API_KEY,\n language: config.LANGUAGE\n });\n\n // Change process CWD to project path to ensure git commands run there\n try {\n process.chdir(projectPath);\n } catch {\n logger.error(`Failed to change directory to ${projectPath}`);\n process.exit(1);\n }\n\n // 2. Check for uncommitted changes\n if (await hasUncommittedChanges(projectPath)) {\n logger.warning('Uncommitted local changes detected.');\n \n const projectLanguage = await detectProjectLanguage(projectPath);\n printDetectedLanguage(projectLanguage);\n \n const { stdout: diffOutput } = await runGitCommand(['diff'], projectPath);\n \n // Generate commit message\n // Allow empty base message (will rely on git diffs)\n const baseMessage = baseMessageArg || '';\n\n const commitMessage = await aiService.generateCommitMessage(diffOutput, projectLanguage, baseMessage);\n \n logger.commit(commitMessage);\n \n await commitChanges(commitMessage, projectPath);\n logger.success('Gitai successfully committed local changes.');\n \n } else {\n logger.info('No local changes to commit before git pull.');\n }\n\n // 3. Perform Git Pull\n const pullSuccessful = await performGitPull(projectPath);\n \n if (!pullSuccessful) {\n logger.error('Git pull failed due to conflicts. Please resolve the conflicts manually.');\n process.exit(1);\n }\n\n // 4. Check for conflicts/changes after pull\n if (await hasUncommittedChanges(projectPath)) {\n logger.warning('Conflicts or uncommitted changes detected after pull.');\n \n const projectLanguage = await detectProjectLanguage(projectPath);\n printDetectedLanguage(projectLanguage);\n \n const { stdout: diffOutput } = await runGitCommand(['diff'], projectPath);\n \n const commitMessage = await aiService.generateCommitMessage(diffOutput, projectLanguage, \"Resolving conflicts after git pull\");\n logger.commit(commitMessage);\n \n await commitChanges(commitMessage, projectPath);\n logger.success('Gitai successfully committed changes after pull.');\n\n } else {\n logger.info('No changes to commit after git pull.');\n }\n\n // 5. Push if requested\n if (options.push) {\n if (await isBranchAhead(projectPath)) {\n await runGitCommand(['push'], projectPath);\n logger.success('Gitai successfully pushed changes.');\n } else {\n logger.info('No changes to push. The local branch is synchronized with the remote.');\n }\n }\n\n });\n\nprogram.parse();\n","import Anthropic from '@anthropic-ai/sdk';\nimport Groq from 'groq-sdk';\nimport OpenAI from 'openai';\nimport { logger } from '../utils/logger.js';\n\ninterface AIConfig {\n provider: string;\n model: string;\n apiKey: string;\n language: string;\n}\n\nexport class AIService {\n private config: AIConfig;\n private openai?: OpenAI;\n private groq?: Groq;\n private anthropic?: Anthropic;\n\n constructor(config: AIConfig) {\n this.config = config;\n this.initializeClient();\n }\n\n private initializeClient() {\n switch (this.config.provider) {\n case 'openai':\n this.openai = new OpenAI({ apiKey: this.config.apiKey });\n break;\n case 'groq':\n this.groq = new Groq({ apiKey: this.config.apiKey });\n break;\n case 'anthropic':\n this.anthropic = new Anthropic({ apiKey: this.config.apiKey });\n break;\n default:\n logger.error(`Provider ${this.config.provider} is not supported.`);\n process.exit(1);\n }\n }\n\n private getCommitSystemPrompt(): string {\n return `\nYou are an assistant that helps generate commit messages for a Git repository.\nCommit messages must follow the Conventional Commits standard, which uses ONLY these specific prefixes to categorize the type of change made: feat, fix, docs, chore.\nThe description must be concise and clear, explaining what was done, the reason for the change, and, if applicable, the impact of the change.\nThe messages must be generated based on the changes provided by the 'git diff' command and an optional basic description provided by the user.\n\nMandatory rules:\n- DO NOT add any comments or additional explanations beyond the generated commit message.\n- DO NOT use symbols such as \\`\\`\\` or any other formatting to denote the commit message.\n- DO NOT add line breaks or whitespace before the commit message.\n- The output must be ONLY the final commit message as per the instructions.\n- The first line of the message must start with one of these EXACT prefixes: feat, fix, docs, chore.\n- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.\n\n<output_format>\nCRITICAL: Your response must follow this exact structure:\n\nLine 1: [prefix]: [concise description]\n(where prefix must be exactly one of: feat, fix, docs, chore)\nLine 2: [EMPTY LINE - mandatory line break]\nLine 3+: [detailed explanation]\n\nCORRECT format example:\nfeat: add user authentication system\n\nImplement JWT-based authentication with login and registration endpoints. Add middleware for route protection and user session management. This enhancement improves application security and enables personalized user experiences.\n\nINCORRECT format (everything in one line):\nfeat: add user authentication system - Implement JWT-based authentication with login and registration endpoints...\n</output_format>\n\nIf the instructions are not followed correctly, the result will not be accepted.\n`.trim();\n }\n\n private getCommitUserPrompt(diffOutput: string, projectLanguage: string, baseMessage: string): string {\n return `\nBased on the information provided below, create a commit message following the Conventional Commits standard.\n\nThe ONLY accepted prefixes for this project are:\n - feat: A new feature\n - fix: A bug fix\n - docs: Documentation changes\n - chore: Maintenance changes or minor fixes that do not alter functionality\n\nFor your information and better understanding, the project in question uses the programming language ${projectLanguage}.\n\nBasic change description provided by the developer, which you should use as the basis for your message: '${baseMessage}'\n\nBelow are the detailed changes (including modified files and what was added, changed, or removed) generated by the 'git diff' command:\n\n\\`\\`\\`\n${diffOutput}\n\\`\\`\\`\n\nBased on the above information, improve the basic description to create an objective commit message.\nMandatory rules:\n- You must follow the Conventional Commits standard.\n- The first line of the message must start with one of these EXACT prefixes (feat, fix, docs, chore) followed by a concise description explaining what was done.\n- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.\n- Whenever possible, mention only the main modified files in the commit message without including the path.\n- DO NOT add any comments or additional explanations beyond the generated commit message.\n- DO NOT use symbols such as \\`\\`\\` or any other formatting to denote the commit message.\n- DO NOT add line breaks or whitespace before the commit message.\n- The output must be ONLY the final commit message as per the instructions.\n- You must use the language '${this.config.language}' in your response generation.\n\n<output_format>\nYour response must follow this exact format:\n\nLine 1: [prefix]: [concise description]\nLine 2: [empty line]\nLine 3+: [detailed explanation of changes, reasons, and impact]\n</output_format>\n`.trim();\n }\n\n async generateCommitMessage(diffOutput: string, projectLanguage: string, baseMessage: string): Promise<string> {\n const systemPrompt = this.getCommitSystemPrompt();\n const userPrompt = this.getCommitUserPrompt(diffOutput, projectLanguage, baseMessage);\n \n const commitMessage = await this.callApi(systemPrompt, userPrompt);\n const signature = \"\\n\\n🤖 Commit generated with [GitaiJS](https://github.com/leandrosilvaferreira/gitai-js)\";\n return commitMessage + signature;\n }\n \n // Logic for release notes (used by releaser.ts)\n async generateReleaseNotes(commits: string, newVersion: string, tag: string): Promise<string> {\n const systemPrompt = `\nYou are an assistant that helps generate release notes for a Git repository.\nCommit messages should be organized into categories such as New Features, Bug Fixes, and Other Changes.\nThe output must be a markdown-formatted text according to the provided template, with no additional comments or formatting.\n`.trim();\n \n const userPrompt = `\nYou are an assistant that helps generate release notes for a Git repository.\nBelow are the commits since the last tag ${tag}.\nPlease organize the commits into the following categories: New Features, Bug Fixes, and Other Changes.\nGenerate a release message in markdown format in the language '${this.config.language}' using the following template:\n\n\\`\\`\\`\n# Release ${newVersion}\n<SUMMARY/>\n\n### New Features\n- Description of new features (commits).\n\n### Bug Fixes\n- Description of bug fixes (commits).\n\n### Other Changes\n- Description of other changes (commits).\n\nWe thank all the contributors who made this release possible! For more details, please refer to the complete version notes.\n\n**Full Changelog:** [See commits for v${newVersion}](https://github.com/leandrosilvaferreira/gitai-js/compare/${tag}...v${newVersion})\n\\`\\`\\`\n\nCommits:\n${commits}\n\nImportant rules:\n - The generated content must be in the language '${this.config.language}'.\n - Replace <SUMMARY/> in the template with a brief and enthusiastic summary of the changes made since the last tag ${tag}.\n - DO NOT add any additional comments or explanations.\n - DO NOT use symbols like \\`\\`\\` to denote commit messages.\n - The message must be clear, concise, and well-organized.\n - Remember to follow the provided template.\n\nIf the instructions are not followed correctly, the result will not be accepted.\n`.trim();\n\n return this.callApi(systemPrompt, userPrompt);\n\n }\n\n\n private async callApi(systemPrompt: string, userPrompt: string): Promise<string> {\n if (this.config.provider === 'openai' && this.openai) {\n logger.ai(`Provider: openai - Model: ${this.config.model}`);\n \n const isNewModel = ['o1', 'o3', 'gpt-5'].some(prefix => this.config.model.startsWith(prefix));\n const tokenParam = isNewModel ? 'max_completion_tokens' : 'max_tokens';\n \n const completion = await this.openai.chat.completions.create({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt }\n ],\n model: this.config.model,\n temperature: 0.5,\n top_p: 1.0,\n frequency_penalty: 0.0,\n presence_penalty: 0.0,\n [tokenParam]: 500,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n\n return completion.choices[0].message.content?.trim() || '';\n\n } else if (this.config.provider === 'groq' && this.groq) {\n logger.ai(`Provider: groq - Model: ${this.config.model}`);\n const completion = await this.groq.chat.completions.create({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt }\n ],\n model: this.config.model,\n temperature: 0.5,\n max_tokens: 500,\n top_p: 1.0,\n frequency_penalty: 0.0,\n presence_penalty: 0.0\n });\n return completion.choices[0].message.content?.trim() || '';\n\n } else if (this.config.provider === 'anthropic' && this.anthropic) {\n logger.ai(`Provider: anthropic - Model: ${this.config.model}`);\n const message = await this.anthropic.messages.create({\n model: this.config.model,\n max_tokens: 500,\n temperature: 0.5,\n system: systemPrompt,\n messages: [\n { role: 'user', content: userPrompt }\n ]\n });\n const contentBlock = message.content[0];\n if (contentBlock.type === 'text') {\n return contentBlock.text.trim();\n }\n return '';\n }\n\n return '';\n }\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n header: (message: string) => {\n console.log(chalk.cyan.bold(`🚀 ${message}`));\n },\n success: (message: string) => {\n console.log(chalk.green.bold(`✅ ${message}`));\n },\n info: (message: string) => {\n console.log(chalk.blue.bold(`ℹ️ ${message}`));\n },\n warning: (message: string) => {\n console.log(chalk.yellow.bold(`⚠️ ${message}`));\n },\n error: (message: string) => {\n console.log(chalk.red.bold(`❌ ${message}`));\n },\n git: (message: string) => {\n console.log(chalk.magenta.bold(`🔄 ${message}`));\n },\n ai: (message: string) => {\n console.log(chalk.cyan.bold(`🤖 ${message}`));\n },\n commit: (message: string) => {\n console.log('\\n' + chalk.bgBlue.white.bold(' Generated commit message: ') + '\\n');\n console.log(chalk.white.bold(message));\n console.log();\n }\n};\n","import fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport semver from 'semver';\n\nimport { engines } from '../version.js';\n\nexport interface AppConfig {\n LANGUAGE: string;\n PROVIDER: string;\n API_KEY: string;\n MODEL: string;\n}\n\nexport const CONFIG_PATH = path.join(os.homedir(), '.gitai');\n\nexport const checkConfigExists = (): boolean => {\n try {\n return fs.existsSync(CONFIG_PATH);\n } catch {\n return false;\n }\n};\n\nexport const loadConfig = (): AppConfig => {\n if (!checkConfigExists()) {\n throw new Error(`Configuration file not found at ${CONFIG_PATH}`);\n }\n const content = fs.readFileSync(CONFIG_PATH, 'utf-8');\n const config: Record<string, string> = {};\n content.split('\\n').forEach(line => {\n // Simple env parsing\n const [key, ...value] = line.split('=');\n if (key && value && key.trim()) {\n // Rejoin value in case it contained =\n let val = value.join('=').trim();\n \n // Remove quotes if present\n if (val.startsWith('\"') && val.endsWith('\"')) {\n val = val.slice(1, -1);\n }\n if (val.startsWith(\"'\") && val.endsWith(\"'\")) {\n val = val.slice(1, -1);\n }\n\n config[key.trim()] = val;\n }\n });\n return config as unknown as AppConfig;\n};\n\nexport const saveConfig = (config: AppConfig): void => {\n const content = Object.entries(config)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n');\n \n // Write with secure permissions (600 - read/write only by owner) since it contains API keys\n fs.writeFileSync(CONFIG_PATH, content, { mode: 0o600 });\n};\n\nexport const validateNodeVersion = (): boolean => {\n const requiredVersion = engines.node;\n return semver.satisfies(process.version, requiredVersion);\n};\n","export const version = '1.0.1';\nexport const name = 'gitai';\nexport const engines = {\n node: '>=18'\n};\n","import { execa } from 'execa';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport path from 'path';\nimport { logger } from './logger.js';\n\nexport async function runGitCommand(args: string[], cwd: string = process.cwd(), exitOnError: boolean = true): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n try {\n const result = await execa('git', args, { cwd, reject: false });\n \n if (result.exitCode !== 0) {\n if (exitOnError) {\n logger.error(`Error executing command: git ${args.join(' ')}`);\n logger.error(`Standard output: ${result.stdout}`);\n logger.error(`Error output: ${result.stderr}`);\n process.exit(1);\n }\n }\n return {\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n exitCode: result.exitCode ?? 1\n };\n } catch (error: unknown) {\n if (exitOnError) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Unexpected error executing git command: ${errorMessage}`);\n process.exit(1);\n }\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { stdout: '', stderr: errorMessage, exitCode: 1 };\n }\n}\n\nexport async function hasUncommittedChanges(cwd: string): Promise<boolean> {\n const { stdout } = await runGitCommand(['status', '--porcelain'], cwd);\n return stdout.length > 0;\n}\n\nexport async function isBranchAhead(cwd: string): Promise<boolean> {\n const { stdout } = await runGitCommand(['status', '-uno'], cwd);\n return stdout.includes('Your branch is ahead') || stdout.includes('Seu branch está à frente');\n}\n\nexport async function performGitPull(cwd: string): Promise<boolean> {\n const { stdout, stderr, exitCode } = await runGitCommand(['pull'], cwd, false);\n\n if (exitCode !== 0) {\n if (stdout.includes('CONFLICT') || stdout.includes('CONFLITO') || stderr.includes('CONFLICT') || stderr.includes('CONFLITO')) {\n logger.warning(\"Conflitos detectados durante git pull:\");\n logger.error(stdout || stderr);\n return false;\n } else {\n logger.error(`Error executing git pull: ${stdout || stderr}`);\n process.exit(1);\n }\n }\n logger.success(\"Git pull executed successfully.\");\n return true;\n}\n\nexport async function commitChanges(commitMessage: string, cwd: string): Promise<void> {\n await runGitCommand(['add', '.'], cwd);\n \n // Write commit message to temp file to handle special characters correctly\n const tempDir = os.tmpdir();\n const tempFilePath = path.join(tempDir, `gitai_commit_${Date.now()}.txt`);\n \n try {\n await fs.writeFile(tempFilePath, commitMessage, 'utf-8');\n await runGitCommand(['commit', '-F', tempFilePath], cwd);\n } finally {\n try {\n await fs.unlink(tempFilePath);\n } catch {\n // Ignore error if cleanup fails\n }\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { logger } from './logger.js';\n\nconst indicatorFiles: Record<string, string[]> = {\n 'Node.js': ['package.json', 'yarn.lock', 'package-lock.json', 'npm-shrinkwrap.json'],\n 'Python': ['requirements.txt', 'Pipfile', 'pyproject.toml', 'setup.py', 'setup.cfg', 'manage.py'],\n 'Java': ['pom.xml', 'build.gradle', 'build.gradle.kts', 'build.xml', '.java-version'],\n 'Go': ['go.mod', 'Gopkg.lock'],\n 'PHP': ['composer.json', 'composer.lock', 'index.php'],\n 'Ruby': ['Gemfile', 'Gemfile.lock', 'Rakefile', 'config.ru', '.ruby-version'],\n 'Rust': ['Cargo.toml', 'Cargo.lock'],\n 'Haskell': ['stack.yaml', 'cabal.project'],\n 'Swift': ['Package.swift'],\n 'Elixir': ['mix.exs'],\n 'Dart': ['pubspec.yaml'],\n 'Scala': ['build.sbt'],\n 'Perl': ['Makefile.PL', 'Build.PL'],\n 'R': ['.Rproj']\n};\n\nconst extensionIndicators: Record<string, string[]> = {\n 'C#': ['.csproj', '.sln'],\n 'Haskell': ['.cabal'],\n 'Swift': ['.xcodeproj', '.xcworkspace'],\n 'Kotlin': ['.kt', '.kts'],\n 'C/C++': ['.c', '.cpp', '.h', '.hpp'],\n 'JavaScript': ['.js', '.jsx'],\n 'TypeScript': ['.ts', '.tsx'],\n 'Python': ['.py'],\n 'Java': ['.java']\n};\n\nconst languageEmojis: Record<string, string> = {\n 'Node.js': '🟢',\n 'Python': '🐍',\n 'Java': '☕',\n 'Go': '🐹',\n 'PHP': '🐘',\n 'Ruby': '💎',\n 'Rust': '🦀',\n 'Haskell': '🎩',\n 'Swift': '🍎',\n 'Elixir': '💧',\n 'Dart': '🎯',\n 'Scala': '⚖️',\n 'Perl': '🐪',\n 'R': '📊',\n 'C#': '🔷',\n 'C/C++': '⚙️',\n 'JavaScript': '🟨',\n 'TypeScript': '🔷',\n 'Unknown': '❓'\n};\n\nexport function getLanguageEmoji(language: string): string {\n return languageEmojis[language] || '❓';\n}\n\nexport function printDetectedLanguage(language: string): void {\n const emoji = getLanguageEmoji(language);\n logger.info(`${emoji} Linguagem detectada: ${language}\\n`);\n}\n\nexport async function detectProjectLanguage(projectPath: string): Promise<string> {\n try {\n const rootFiles = await fs.readdir(projectPath);\n\n // Check for indicator files in the project root\n for (const [language, indicators] of Object.entries(indicatorFiles)) {\n for (const indicator of indicators) {\n if (indicator.includes(path.sep)) {\n // This logic handles nested paths in indicators if necessary, \n // though node path module might be different. \n // Keeping it simple as per original python logic which used os.path.sep\n // For now, let's assume flat filenames for simplicity unless we see complex ones\n // The python code did: if os.path.sep in indicator...\n } else {\n if (rootFiles.includes(indicator)) {\n return language;\n }\n }\n }\n }\n\n // Check for file extensions in the project root\n for (const [language, extensions] of Object.entries(extensionIndicators)) {\n for (const file of rootFiles) {\n if (extensions.some(ext => file.endsWith(ext))) {\n return language;\n }\n }\n }\n\n // Recursive check logic from python is a bit heavy (os.walk), \n // let's implement a lighter version or skip if not strictly needed.\n // The original scanned the whole tree which can be slow for node_modules.\n // Let's implement a limited depth scan if root check failed.\n // For efficiency, maybe just skip the deep scan for this first version \n // unless the user specifically wants it.\n // Gitai.py uses os.walk which is recursive. \n // Let's assume Unknown for now if not found in root to avoid performance issues in huge JS projects.\n \n return \"Unknown\";\n\n } catch {\n return \"Unknown\";\n }\n}\n","import chalk from 'chalk';\nimport { execa } from 'execa';\nimport inquirer from 'inquirer';\nimport { AppConfig, CONFIG_PATH, checkConfigExists, loadConfig, saveConfig } from './config.js';\n\nimport { version } from '../version.js';\n\nexport async function runSetup(): Promise<AppConfig> {\n console.clear();\n console.log(chalk.bold.blue(`\\n🚀 Welcome to GitAI v${version} Setup! 🚀`));\n console.log(chalk.dim('Let\\'s get you ready to code with AI assistance.\\n'));\n\n // 1. Check Prerequisites\n try {\n await execa('git', ['--version']);\n console.log(chalk.green('✅ Git is installed!'));\n } catch {\n console.log(chalk.red('❌ Git is NOT installed or not accessible from PATH.'));\n console.log(chalk.yellow('Please install Git before proceeding.'));\n process.exit(1);\n }\n \n console.log(chalk.cyan('\\n⚙️ Global Configuration (saved to ' + CONFIG_PATH + ')\\n'));\n\n // 2. Load Existing Configuration\n let currentConfig: Partial<AppConfig> = {};\n if (checkConfigExists()) {\n try {\n currentConfig = loadConfig();\n console.log(chalk.green(`✅ Found existing configuration at ${CONFIG_PATH}`));\n } catch {\n console.log(chalk.yellow('⚠️ Could not load existing configuration, starting fresh.'));\n }\n }\n\n const requiredKeys: (keyof AppConfig)[] = ['LANGUAGE', 'PROVIDER', 'API_KEY', 'MODEL'];\n const missingKeys = requiredKeys.filter(key => !currentConfig[key]);\n\n if (missingKeys.length === 0) {\n console.log(chalk.green('✅ Configuration is complete and valid!'));\n console.log(chalk.dim('You are all set. Running GitAI...\\n'));\n return currentConfig as AppConfig;\n }\n\n if (Object.keys(currentConfig).length > 0) {\n console.log(chalk.yellow(`⚠️ Missing configuration for: ${missingKeys.join(', ')}`));\n console.log(chalk.dim('Please provide the missing details.\\n'));\n }\n\n // 3. Prompts\n const prompts = [\n {\n type: 'list',\n name: 'LANGUAGE',\n message: 'What language should the AI use for commit messages?',\n choices: [\n { name: 'English', value: 'en' },\n { name: 'Portuguese (Brasil)', value: 'pt-br' },\n { name: 'Spanish', value: 'es' },\n { name: 'French', value: 'fr' },\n { name: 'German', value: 'de' },\n { name: 'Italian', value: 'it' },\n { name: 'Chinese', value: 'zh' },\n { name: 'Japanese', value: 'ja' },\n { name: 'Korean', value: 'ko' }\n ],\n default: 'en',\n when: () => !currentConfig.LANGUAGE\n },\n {\n type: 'list',\n name: 'PROVIDER',\n message: 'Which AI Provider do you want to use?',\n choices: [\n { name: 'OpenAI', value: 'openai' },\n { name: 'Anthropic', value: 'anthropic' },\n { name: 'Groq', value: 'groq' }\n ],\n default: 'openai',\n when: () => !currentConfig.PROVIDER\n },\n {\n type: 'password',\n name: 'API_KEY',\n message: 'Enter your API Key:',\n mask: '*',\n validate: (input: string) => input.length > 0 ? true : 'API Key is required',\n when: () => !currentConfig.API_KEY\n },\n {\n type: 'input',\n name: 'MODEL',\n message: 'Model ID (e.g., gpt-4o, claude-3-5-sonnet):',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n default: (answers: any) => {\n const provider = answers.PROVIDER || currentConfig.PROVIDER;\n if (provider === 'openai') return 'gpt-4o';\n if (provider === 'anthropic') return 'claude-3-5-sonnet-20240620';\n if (provider === 'groq') return 'llama3-70b-8192';\n return 'gpt-4o';\n },\n when: () => !currentConfig.MODEL\n }\n ];\n \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const answers = await inquirer.prompt(prompts as any);\n\n const config: AppConfig = {\n LANGUAGE: answers.LANGUAGE || currentConfig.LANGUAGE!,\n PROVIDER: answers.PROVIDER || currentConfig.PROVIDER!,\n API_KEY: answers.API_KEY || currentConfig.API_KEY!,\n MODEL: answers.MODEL || currentConfig.MODEL!\n };\n\n saveConfig(config);\n\n console.log(chalk.green('\\n✨ Configuration saved successfully! ✨'));\n console.log(chalk.dim('You are all set. Running GitAI...\\n'));\n\n return config;\n}\n"],"mappings":"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","names":["chalk","Command","path","Anthropic","Groq","OpenAI","chalk","logger","message","AIService","config","OpenAI","Groq","Anthropic","logger","diffOutput","projectLanguage","baseMessage","systemPrompt","userPrompt","commits","newVersion","tag","tokenParam","prefix","contentBlock","fs","os","path","semver","version","name","engines","CONFIG_PATH","path","os","checkConfigExists","fs","loadConfig","content","config","line","key","value","val","saveConfig","validateNodeVersion","requiredVersion","engines","semver","execa","fs","os","path","runGitCommand","args","cwd","exitOnError","result","execa","logger","error","errorMessage","hasUncommittedChanges","stdout","isBranchAhead","performGitPull","stderr","exitCode","commitChanges","commitMessage","tempDir","os","tempFilePath","path","fs","fs","path","indicatorFiles","extensionIndicators","languageEmojis","getLanguageEmoji","language","printDetectedLanguage","emoji","logger","detectProjectLanguage","projectPath","rootFiles","fs","indicators","indicator","path","extensions","file","ext","chalk","execa","inquirer","runSetup","chalk","version","execa","CONFIG_PATH","currentConfig","checkConfigExists","loadConfig","missingKeys","key","prompts","input","answers","provider","inquirer","config","saveConfig","validateNodeVersion","chalk","engines","program","Command","name","version","projectPathArg","baseMessageArg","options","config","checkConfigExists","loadConfig","runSetup","error","errorMessage","logger","projectPath","path","aiService","AIService","hasUncommittedChanges","projectLanguage","detectProjectLanguage","printDetectedLanguage","diffOutput","runGitCommand","baseMessage","commitMessage","commitChanges","performGitPull","isBranchAhead"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/services/ai.ts","../src/utils/logger.ts","../src/utils/config.ts","../src/version.ts","../src/utils/git.ts","../src/utils/language.ts","../src/utils/setup.ts"],"sourcesContent":["#!/usr/bin/env node\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport path from 'path';\n\nimport { AIService } from './services/ai.js';\nimport { checkConfigExists, loadConfig, validateNodeVersion } from './utils/config.js';\nimport { commitChanges, getDiffWithNewFiles, hasUncommittedChanges, isBranchAhead, performGitPull, runGitCommand } from './utils/git.js';\nimport { detectProjectLanguage, printDetectedLanguage } from './utils/language.js';\nimport { logger } from './utils/logger.js';\nimport { runSetup } from './utils/setup.js';\n\nimport { engines, name, version } from './version.js';\n\n// 0. Validate Node Version\nif (!validateNodeVersion()) {\n console.error(chalk.red(`\\n❌ GitAI requires Node.js ${engines.node} or higher.`));\n console.error(chalk.yellow(` Current version: ${process.version}\\n`));\n process.exit(1);\n}\n\nconst program = new Command();\n\nprogram\n .name(name)\n .description('AI-powered git commit assistant')\n .version(version);\n\n// Custom help handler to show version\nprogram.on('--help', () => {\n console.log('');\n console.log(chalk.cyan('━'.repeat(50)));\n console.log(chalk.bold.blue(` GitAI v${version}`));\n console.log(chalk.dim(' AI-powered git commit assistant'));\n console.log(chalk.cyan('━'.repeat(50)));\n console.log('');\n});\n\nprogram\n .argument('[projectPath]', 'The path to the project', '.')\n .argument('[baseMessage]', 'The base commit message')\n .option('-p, --push', 'Whether to push after committing', false)\n .action(async (projectPathArg, baseMessageArg, options) => {\n \n // 1. Configuration Check (Global Only)\n let config;\n try {\n if (!checkConfigExists()) {\n config = await runSetup();\n } else {\n config = loadConfig();\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Failed to load configuration: ${errorMessage}`);\n process.exit(1);\n }\n\n logger.header(`Gitai v${version}`);\n \n const projectPath = path.resolve(projectPathArg);\n logger.info(`📁 project_path: ${projectPath}\\n`);\n\n const aiService = new AIService({\n provider: config.PROVIDER,\n model: config.MODEL,\n apiKey: config.API_KEY,\n language: config.LANGUAGE\n });\n\n // Change process CWD to project path to ensure git commands run there\n try {\n process.chdir(projectPath);\n } catch {\n logger.error(`Failed to change directory to ${projectPath}`);\n process.exit(1);\n }\n\n // 2. Check for uncommitted changes\n if (await hasUncommittedChanges(projectPath)) {\n logger.warning('Uncommitted local changes detected.');\n\n const projectLanguage = await detectProjectLanguage(projectPath);\n printDetectedLanguage(projectLanguage);\n\n const diffOutput = await getDiffWithNewFiles(projectPath);\n\n // Generate commit message\n // Allow empty base message (will rely on git diffs)\n const baseMessage = baseMessageArg || '';\n\n const commitMessage = await aiService.generateCommitMessage(diffOutput, projectLanguage, baseMessage);\n \n logger.commit(commitMessage);\n \n await commitChanges(commitMessage, projectPath);\n logger.success('Gitai successfully committed local changes.');\n \n } else {\n logger.info('No local changes to commit before git pull.');\n }\n\n // 3. Perform Git Pull\n const pullSuccessful = await performGitPull(projectPath);\n \n if (!pullSuccessful) {\n logger.error('Git pull failed due to conflicts. Please resolve the conflicts manually.');\n process.exit(1);\n }\n\n // 4. Check for conflicts/changes after pull\n if (await hasUncommittedChanges(projectPath)) {\n logger.warning('Conflicts or uncommitted changes detected after pull.');\n\n const projectLanguage = await detectProjectLanguage(projectPath);\n printDetectedLanguage(projectLanguage);\n\n const diffOutput = await getDiffWithNewFiles(projectPath);\n\n const commitMessage = await aiService.generateCommitMessage(diffOutput, projectLanguage, \"Resolving conflicts after git pull\");\n logger.commit(commitMessage);\n \n await commitChanges(commitMessage, projectPath);\n logger.success('Gitai successfully committed changes after pull.');\n\n } else {\n logger.info('No changes to commit after git pull.');\n }\n\n // 5. Push if requested\n if (options.push) {\n if (await isBranchAhead(projectPath)) {\n await runGitCommand(['push'], projectPath);\n logger.success('Gitai successfully pushed changes.');\n } else {\n logger.info('No changes to push. The local branch is synchronized with the remote.');\n }\n }\n\n });\n\nprogram.parse();\n","import Anthropic from '@anthropic-ai/sdk';\nimport Groq from 'groq-sdk';\nimport OpenAI from 'openai';\nimport { logger } from '../utils/logger.js';\n\ninterface AIConfig {\n provider: string;\n model: string;\n apiKey: string;\n language: string;\n}\n\nexport class AIService {\n private config: AIConfig;\n private openai?: OpenAI;\n private groq?: Groq;\n private anthropic?: Anthropic;\n\n constructor(config: AIConfig) {\n this.config = config;\n this.initializeClient();\n }\n\n private initializeClient() {\n switch (this.config.provider) {\n case 'openai':\n this.openai = new OpenAI({ apiKey: this.config.apiKey });\n break;\n case 'groq':\n this.groq = new Groq({ apiKey: this.config.apiKey });\n break;\n case 'anthropic':\n this.anthropic = new Anthropic({ apiKey: this.config.apiKey });\n break;\n default:\n logger.error(`Provider ${this.config.provider} is not supported.`);\n process.exit(1);\n }\n }\n\n private getCommitSystemPrompt(): string {\n return `\nYou are an assistant that helps generate commit messages for a Git repository.\nCommit messages must follow the Conventional Commits standard, which uses ONLY these specific prefixes to categorize the type of change made: feat, fix, docs, chore.\nThe description must be concise and clear, explaining what was done, the reason for the change, and, if applicable, the impact of the change.\nThe messages must be generated based on the changes provided by the 'git diff' command and an optional basic description provided by the user.\n\nMandatory rules:\n- DO NOT add any comments or additional explanations beyond the generated commit message.\n- DO NOT use symbols such as \\`\\`\\` or any other formatting to denote the commit message.\n- DO NOT add line breaks or whitespace before the commit message.\n- The output must be ONLY the final commit message as per the instructions.\n- The first line of the message must start with one of these EXACT prefixes: feat, fix, docs, chore.\n- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.\n\n<output_format>\nCRITICAL: Your response must follow this exact structure:\n\nLine 1: [prefix]: [concise description]\n(where prefix must be exactly one of: feat, fix, docs, chore)\nLine 2: [EMPTY LINE - mandatory line break]\nLine 3+: [detailed explanation]\n\nCORRECT format example:\nfeat: add user authentication system\n\nImplement JWT-based authentication with login and registration endpoints. Add middleware for route protection and user session management. This enhancement improves application security and enables personalized user experiences.\n\nINCORRECT format (everything in one line):\nfeat: add user authentication system - Implement JWT-based authentication with login and registration endpoints...\n</output_format>\n\nIf the instructions are not followed correctly, the result will not be accepted.\n`.trim();\n }\n\n private getCommitUserPrompt(diffOutput: string, projectLanguage: string, baseMessage: string): string {\n return `\nBased on the information provided below, create a commit message following the Conventional Commits standard.\n\nThe ONLY accepted prefixes for this project are:\n - feat: A new feature\n - fix: A bug fix\n - docs: Documentation changes\n - chore: Maintenance changes or minor fixes that do not alter functionality\n\nFor your information and better understanding, the project in question uses the programming language ${projectLanguage}.\n\nBasic change description provided by the developer, which you should use as the basis for your message: '${baseMessage}'\n\nBelow are the detailed changes (including modified files and what was added, changed, or removed) generated by the 'git diff' command:\n\n\\`\\`\\`\n${diffOutput}\n\\`\\`\\`\n\nBased on the above information, improve the basic description to create an objective commit message.\nMandatory rules:\n- You must follow the Conventional Commits standard.\n- The first line of the message must start with one of these EXACT prefixes (feat, fix, docs, chore) followed by a concise description explaining what was done.\n- After the first line, always add an objective explanation of the changes made, the reason for the change, and, if applicable, the impact of the change.\n- Whenever possible, mention only the main modified files in the commit message without including the path.\n- DO NOT add any comments or additional explanations beyond the generated commit message.\n- DO NOT use symbols such as \\`\\`\\` or any other formatting to denote the commit message.\n- DO NOT add line breaks or whitespace before the commit message.\n- The output must be ONLY the final commit message as per the instructions.\n- You must use the language '${this.config.language}' in your response generation.\n\n<output_format>\nYour response must follow this exact format:\n\nLine 1: [prefix]: [concise description]\nLine 2: [empty line]\nLine 3+: [detailed explanation of changes, reasons, and impact]\n</output_format>\n`.trim();\n }\n\n async generateCommitMessage(diffOutput: string, projectLanguage: string, baseMessage: string): Promise<string> {\n const systemPrompt = this.getCommitSystemPrompt();\n const userPrompt = this.getCommitUserPrompt(diffOutput, projectLanguage, baseMessage);\n \n const commitMessage = await this.callApi(systemPrompt, userPrompt);\n const signature = \"\\n\\n🤖 Commit generated with [GitaiJS](https://github.com/leandrosilvaferreira/gitai-js)\";\n return commitMessage + signature;\n }\n \n // Logic for release notes (used by releaser.ts)\n async generateReleaseNotes(commits: string, newVersion: string, tag: string): Promise<string> {\n const systemPrompt = `\nYou are an assistant that helps generate release notes for a Git repository.\nCommit messages should be organized into categories such as New Features, Bug Fixes, and Other Changes.\nThe output must be a markdown-formatted text according to the provided template, with no additional comments or formatting.\n`.trim();\n \n const userPrompt = `\nYou are an assistant that helps generate release notes for a Git repository.\nBelow are the commits since the last tag ${tag}.\nPlease organize the commits into the following categories: New Features, Bug Fixes, and Other Changes.\nGenerate a release message in markdown format in the language '${this.config.language}' using the following template:\n\n\\`\\`\\`\n# Release ${newVersion}\n<SUMMARY/>\n\n### New Features\n- Description of new features (commits).\n\n### Bug Fixes\n- Description of bug fixes (commits).\n\n### Other Changes\n- Description of other changes (commits).\n\nWe thank all the contributors who made this release possible! For more details, please refer to the complete version notes.\n\n**Full Changelog:** [See commits for v${newVersion}](https://github.com/leandrosilvaferreira/gitai-js/compare/${tag}...v${newVersion})\n\\`\\`\\`\n\nCommits:\n${commits}\n\nImportant rules:\n - The generated content must be in the language '${this.config.language}'.\n - Replace <SUMMARY/> in the template with a brief and enthusiastic summary of the changes made since the last tag ${tag}.\n - DO NOT add any additional comments or explanations.\n - DO NOT use symbols like \\`\\`\\` to denote commit messages.\n - The message must be clear, concise, and well-organized.\n - Remember to follow the provided template.\n\nIf the instructions are not followed correctly, the result will not be accepted.\n`.trim();\n\n return this.callApi(systemPrompt, userPrompt);\n\n }\n\n\n private async callApi(systemPrompt: string, userPrompt: string): Promise<string> {\n if (this.config.provider === 'openai' && this.openai) {\n logger.ai(`Provider: openai - Model: ${this.config.model}`);\n \n const isNewModel = ['o1', 'o3', 'gpt-5'].some(prefix => this.config.model.startsWith(prefix));\n const tokenParam = isNewModel ? 'max_completion_tokens' : 'max_tokens';\n \n const completion = await this.openai.chat.completions.create({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt }\n ],\n model: this.config.model,\n temperature: 0.5,\n top_p: 1.0,\n frequency_penalty: 0.0,\n presence_penalty: 0.0,\n [tokenParam]: 500,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n\n return completion.choices[0].message.content?.trim() || '';\n\n } else if (this.config.provider === 'groq' && this.groq) {\n logger.ai(`Provider: groq - Model: ${this.config.model}`);\n const completion = await this.groq.chat.completions.create({\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt }\n ],\n model: this.config.model,\n temperature: 0.5,\n max_tokens: 500,\n top_p: 1.0,\n frequency_penalty: 0.0,\n presence_penalty: 0.0\n });\n return completion.choices[0].message.content?.trim() || '';\n\n } else if (this.config.provider === 'anthropic' && this.anthropic) {\n logger.ai(`Provider: anthropic - Model: ${this.config.model}`);\n const message = await this.anthropic.messages.create({\n model: this.config.model,\n max_tokens: 500,\n temperature: 0.5,\n system: systemPrompt,\n messages: [\n { role: 'user', content: userPrompt }\n ]\n });\n const contentBlock = message.content[0];\n if (contentBlock.type === 'text') {\n return contentBlock.text.trim();\n }\n return '';\n }\n\n return '';\n }\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n header: (message: string) => {\n console.log(chalk.cyan.bold(`🚀 ${message}`));\n },\n success: (message: string) => {\n console.log(chalk.green.bold(`✅ ${message}`));\n },\n info: (message: string) => {\n console.log(chalk.blue.bold(`ℹ️ ${message}`));\n },\n warning: (message: string) => {\n console.log(chalk.yellow.bold(`⚠️ ${message}`));\n },\n error: (message: string) => {\n console.log(chalk.red.bold(`❌ ${message}`));\n },\n git: (message: string) => {\n console.log(chalk.magenta.bold(`🔄 ${message}`));\n },\n ai: (message: string) => {\n console.log(chalk.cyan.bold(`🤖 ${message}`));\n },\n commit: (message: string) => {\n console.log('\\n' + chalk.bgBlue.white.bold(' Generated commit message: ') + '\\n');\n console.log(chalk.white.bold(message));\n console.log();\n }\n};\n","import fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport semver from 'semver';\n\nimport { engines } from '../version.js';\n\nexport interface AppConfig {\n LANGUAGE: string;\n PROVIDER: string;\n API_KEY: string;\n MODEL: string;\n}\n\nexport const CONFIG_PATH = path.join(os.homedir(), '.gitai');\n\nexport const checkConfigExists = (): boolean => {\n try {\n return fs.existsSync(CONFIG_PATH);\n } catch {\n return false;\n }\n};\n\nexport const loadConfig = (): AppConfig => {\n if (!checkConfigExists()) {\n throw new Error(`Configuration file not found at ${CONFIG_PATH}`);\n }\n const content = fs.readFileSync(CONFIG_PATH, 'utf-8');\n const config: Record<string, string> = {};\n content.split('\\n').forEach(line => {\n // Simple env parsing\n const [key, ...value] = line.split('=');\n if (key && value && key.trim()) {\n // Rejoin value in case it contained =\n let val = value.join('=').trim();\n \n // Remove quotes if present\n if (val.startsWith('\"') && val.endsWith('\"')) {\n val = val.slice(1, -1);\n }\n if (val.startsWith(\"'\") && val.endsWith(\"'\")) {\n val = val.slice(1, -1);\n }\n\n config[key.trim()] = val;\n }\n });\n return config as unknown as AppConfig;\n};\n\nexport const saveConfig = (config: AppConfig): void => {\n const content = Object.entries(config)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n');\n \n // Write with secure permissions (600 - read/write only by owner) since it contains API keys\n fs.writeFileSync(CONFIG_PATH, content, { mode: 0o600 });\n};\n\nexport const validateNodeVersion = (): boolean => {\n const requiredVersion = engines.node;\n return semver.satisfies(process.version, requiredVersion);\n};\n","export const version = '1.0.2';\nexport const name = 'gitai';\nexport const engines = {\n node: '>=18'\n};\n","import { execa } from 'execa';\nimport fs from 'fs/promises';\nimport os from 'os';\nimport path from 'path';\nimport { logger } from './logger.js';\n\nexport async function runGitCommand(args: string[], cwd: string = process.cwd(), exitOnError: boolean = true): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n try {\n const result = await execa('git', args, { cwd, reject: false });\n \n if (result.exitCode !== 0) {\n if (exitOnError) {\n logger.error(`Error executing command: git ${args.join(' ')}`);\n logger.error(`Standard output: ${result.stdout}`);\n logger.error(`Error output: ${result.stderr}`);\n process.exit(1);\n }\n }\n return {\n stdout: result.stdout.trim(),\n stderr: result.stderr.trim(),\n exitCode: result.exitCode ?? 1\n };\n } catch (error: unknown) {\n if (exitOnError) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Unexpected error executing git command: ${errorMessage}`);\n process.exit(1);\n }\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { stdout: '', stderr: errorMessage, exitCode: 1 };\n }\n}\n\nexport async function hasUncommittedChanges(cwd: string): Promise<boolean> {\n const { stdout } = await runGitCommand(['status', '--porcelain'], cwd);\n return stdout.length > 0;\n}\n\nexport async function isBranchAhead(cwd: string): Promise<boolean> {\n const { stdout } = await runGitCommand(['status', '-uno'], cwd);\n return stdout.includes('Your branch is ahead') || stdout.includes('Seu branch está à frente');\n}\n\nexport async function performGitPull(cwd: string): Promise<boolean> {\n const { stdout, stderr, exitCode } = await runGitCommand(['pull'], cwd, false);\n\n if (exitCode !== 0) {\n if (stdout.includes('CONFLICT') || stdout.includes('CONFLITO') || stderr.includes('CONFLICT') || stderr.includes('CONFLITO')) {\n logger.warning(\"Conflitos detectados durante git pull:\");\n logger.error(stdout || stderr);\n return false;\n } else {\n logger.error(`Error executing git pull: ${stdout || stderr}`);\n process.exit(1);\n }\n }\n logger.success(\"Git pull executed successfully.\");\n return true;\n}\n\nexport async function commitChanges(commitMessage: string, cwd: string): Promise<void> {\n await runGitCommand(['add', '.'], cwd);\n\n // Write commit message to temp file to handle special characters correctly\n const tempDir = os.tmpdir();\n const tempFilePath = path.join(tempDir, `gitai_commit_${Date.now()}.txt`);\n\n try {\n await fs.writeFile(tempFilePath, commitMessage, 'utf-8');\n await runGitCommand(['commit', '-F', tempFilePath], cwd);\n } finally {\n try {\n await fs.unlink(tempFilePath);\n } catch {\n // Ignore error if cleanup fails\n }\n }\n}\n\nexport async function getDiffWithNewFiles(cwd: string): Promise<string> {\n // Add all changes (including new files) to staging area\n await runGitCommand(['add', '.'], cwd);\n\n // Get diff of staged changes (includes new files with full content)\n // --cached: show staged changes\n // --ignore-all-space: ignore whitespace-only changes\n // Git automatically handles binary files by showing \"Binary files differ\"\n const { stdout } = await runGitCommand(['diff', '--cached', '--ignore-all-space'], cwd);\n\n return stdout;\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { logger } from './logger.js';\n\nconst indicatorFiles: Record<string, string[]> = {\n 'Node.js': ['package.json', 'yarn.lock', 'package-lock.json', 'npm-shrinkwrap.json'],\n 'Python': ['requirements.txt', 'Pipfile', 'pyproject.toml', 'setup.py', 'setup.cfg', 'manage.py'],\n 'Java': ['pom.xml', 'build.gradle', 'build.gradle.kts', 'build.xml', '.java-version'],\n 'Go': ['go.mod', 'Gopkg.lock'],\n 'PHP': ['composer.json', 'composer.lock', 'index.php'],\n 'Ruby': ['Gemfile', 'Gemfile.lock', 'Rakefile', 'config.ru', '.ruby-version'],\n 'Rust': ['Cargo.toml', 'Cargo.lock'],\n 'Haskell': ['stack.yaml', 'cabal.project'],\n 'Swift': ['Package.swift'],\n 'Elixir': ['mix.exs'],\n 'Dart': ['pubspec.yaml'],\n 'Scala': ['build.sbt'],\n 'Perl': ['Makefile.PL', 'Build.PL'],\n 'R': ['.Rproj']\n};\n\nconst extensionIndicators: Record<string, string[]> = {\n 'C#': ['.csproj', '.sln'],\n 'Haskell': ['.cabal'],\n 'Swift': ['.xcodeproj', '.xcworkspace'],\n 'Kotlin': ['.kt', '.kts'],\n 'C/C++': ['.c', '.cpp', '.h', '.hpp'],\n 'JavaScript': ['.js', '.jsx'],\n 'TypeScript': ['.ts', '.tsx'],\n 'Python': ['.py'],\n 'Java': ['.java']\n};\n\nconst languageEmojis: Record<string, string> = {\n 'Node.js': '🟢',\n 'Python': '🐍',\n 'Java': '☕',\n 'Go': '🐹',\n 'PHP': '🐘',\n 'Ruby': '💎',\n 'Rust': '🦀',\n 'Haskell': '🎩',\n 'Swift': '🍎',\n 'Elixir': '💧',\n 'Dart': '🎯',\n 'Scala': '⚖️',\n 'Perl': '🐪',\n 'R': '📊',\n 'C#': '🔷',\n 'C/C++': '⚙️',\n 'JavaScript': '🟨',\n 'TypeScript': '🔷',\n 'Unknown': '❓'\n};\n\nexport function getLanguageEmoji(language: string): string {\n return languageEmojis[language] || '❓';\n}\n\nexport function printDetectedLanguage(language: string): void {\n const emoji = getLanguageEmoji(language);\n logger.info(`${emoji} Linguagem detectada: ${language}\\n`);\n}\n\nexport async function detectProjectLanguage(projectPath: string): Promise<string> {\n try {\n const rootFiles = await fs.readdir(projectPath);\n\n // Check for indicator files in the project root\n for (const [language, indicators] of Object.entries(indicatorFiles)) {\n for (const indicator of indicators) {\n if (indicator.includes(path.sep)) {\n // This logic handles nested paths in indicators if necessary, \n // though node path module might be different. \n // Keeping it simple as per original python logic which used os.path.sep\n // For now, let's assume flat filenames for simplicity unless we see complex ones\n // The python code did: if os.path.sep in indicator...\n } else {\n if (rootFiles.includes(indicator)) {\n return language;\n }\n }\n }\n }\n\n // Check for file extensions in the project root\n for (const [language, extensions] of Object.entries(extensionIndicators)) {\n for (const file of rootFiles) {\n if (extensions.some(ext => file.endsWith(ext))) {\n return language;\n }\n }\n }\n\n // Recursive check logic from python is a bit heavy (os.walk), \n // let's implement a lighter version or skip if not strictly needed.\n // The original scanned the whole tree which can be slow for node_modules.\n // Let's implement a limited depth scan if root check failed.\n // For efficiency, maybe just skip the deep scan for this first version \n // unless the user specifically wants it.\n // Gitai.py uses os.walk which is recursive. \n // Let's assume Unknown for now if not found in root to avoid performance issues in huge JS projects.\n \n return \"Unknown\";\n\n } catch {\n return \"Unknown\";\n }\n}\n","import chalk from 'chalk';\nimport { execa } from 'execa';\nimport inquirer from 'inquirer';\nimport { AppConfig, CONFIG_PATH, checkConfigExists, loadConfig, saveConfig } from './config.js';\n\nimport { version } from '../version.js';\n\nexport async function runSetup(): Promise<AppConfig> {\n console.clear();\n console.log(chalk.bold.blue(`\\n🚀 Welcome to GitAI v${version} Setup! 🚀`));\n console.log(chalk.dim('Let\\'s get you ready to code with AI assistance.\\n'));\n\n // 1. Check Prerequisites\n try {\n await execa('git', ['--version']);\n console.log(chalk.green('✅ Git is installed!'));\n } catch {\n console.log(chalk.red('❌ Git is NOT installed or not accessible from PATH.'));\n console.log(chalk.yellow('Please install Git before proceeding.'));\n process.exit(1);\n }\n \n console.log(chalk.cyan('\\n⚙️ Global Configuration (saved to ' + CONFIG_PATH + ')\\n'));\n\n // 2. Load Existing Configuration\n let currentConfig: Partial<AppConfig> = {};\n if (checkConfigExists()) {\n try {\n currentConfig = loadConfig();\n console.log(chalk.green(`✅ Found existing configuration at ${CONFIG_PATH}`));\n } catch {\n console.log(chalk.yellow('⚠️ Could not load existing configuration, starting fresh.'));\n }\n }\n\n const requiredKeys: (keyof AppConfig)[] = ['LANGUAGE', 'PROVIDER', 'API_KEY', 'MODEL'];\n const missingKeys = requiredKeys.filter(key => !currentConfig[key]);\n\n if (missingKeys.length === 0) {\n console.log(chalk.green('✅ Configuration is complete and valid!'));\n console.log(chalk.dim('You are all set. Running GitAI...\\n'));\n return currentConfig as AppConfig;\n }\n\n if (Object.keys(currentConfig).length > 0) {\n console.log(chalk.yellow(`⚠️ Missing configuration for: ${missingKeys.join(', ')}`));\n console.log(chalk.dim('Please provide the missing details.\\n'));\n }\n\n // 3. Prompts\n const prompts = [\n {\n type: 'list',\n name: 'LANGUAGE',\n message: 'What language should the AI use for commit messages?',\n choices: [\n { name: 'English', value: 'en' },\n { name: 'Portuguese (Brasil)', value: 'pt-br' },\n { name: 'Spanish', value: 'es' },\n { name: 'French', value: 'fr' },\n { name: 'German', value: 'de' },\n { name: 'Italian', value: 'it' },\n { name: 'Chinese', value: 'zh' },\n { name: 'Japanese', value: 'ja' },\n { name: 'Korean', value: 'ko' }\n ],\n default: 'en',\n when: () => !currentConfig.LANGUAGE\n },\n {\n type: 'list',\n name: 'PROVIDER',\n message: 'Which AI Provider do you want to use?',\n choices: [\n { name: 'OpenAI', value: 'openai' },\n { name: 'Anthropic', value: 'anthropic' },\n { name: 'Groq', value: 'groq' }\n ],\n default: 'openai',\n when: () => !currentConfig.PROVIDER\n },\n {\n type: 'password',\n name: 'API_KEY',\n message: 'Enter your API Key:',\n mask: '*',\n validate: (input: string) => input.length > 0 ? true : 'API Key is required',\n when: () => !currentConfig.API_KEY\n },\n {\n type: 'input',\n name: 'MODEL',\n message: 'Model ID (e.g., gpt-4o, claude-3-5-sonnet):',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n default: (answers: any) => {\n const provider = answers.PROVIDER || currentConfig.PROVIDER;\n if (provider === 'openai') return 'gpt-4o';\n if (provider === 'anthropic') return 'claude-3-5-sonnet-20240620';\n if (provider === 'groq') return 'llama3-70b-8192';\n return 'gpt-4o';\n },\n when: () => !currentConfig.MODEL\n }\n ];\n \n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const answers = await inquirer.prompt(prompts as any);\n\n const config: AppConfig = {\n LANGUAGE: answers.LANGUAGE || currentConfig.LANGUAGE!,\n PROVIDER: answers.PROVIDER || currentConfig.PROVIDER!,\n API_KEY: answers.API_KEY || currentConfig.API_KEY!,\n MODEL: answers.MODEL || currentConfig.MODEL!\n };\n\n saveConfig(config);\n\n console.log(chalk.green('\\n✨ Configuration saved successfully! ✨'));\n console.log(chalk.dim('You are all set. Running GitAI...\\n'));\n\n return config;\n}\n"],"mappings":"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","names":["chalk","Command","path","Anthropic","Groq","OpenAI","chalk","logger","message","AIService","config","OpenAI","Groq","Anthropic","logger","diffOutput","projectLanguage","baseMessage","systemPrompt","userPrompt","commits","newVersion","tag","tokenParam","prefix","contentBlock","fs","os","path","semver","version","name","engines","CONFIG_PATH","path","os","checkConfigExists","fs","loadConfig","content","config","line","key","value","val","saveConfig","validateNodeVersion","requiredVersion","engines","semver","execa","fs","os","path","runGitCommand","args","cwd","exitOnError","result","execa","logger","error","errorMessage","hasUncommittedChanges","stdout","isBranchAhead","performGitPull","stderr","exitCode","commitChanges","commitMessage","tempDir","os","tempFilePath","path","fs","getDiffWithNewFiles","fs","path","indicatorFiles","extensionIndicators","languageEmojis","getLanguageEmoji","language","printDetectedLanguage","emoji","logger","detectProjectLanguage","projectPath","rootFiles","fs","indicators","indicator","path","extensions","file","ext","chalk","execa","inquirer","runSetup","chalk","version","execa","CONFIG_PATH","currentConfig","checkConfigExists","loadConfig","missingKeys","key","prompts","input","answers","provider","inquirer","config","saveConfig","validateNodeVersion","chalk","engines","program","Command","name","version","projectPathArg","baseMessageArg","options","config","checkConfigExists","loadConfig","runSetup","error","errorMessage","logger","projectPath","path","aiService","AIService","hasUncommittedChanges","projectLanguage","detectProjectLanguage","printDetectedLanguage","diffOutput","getDiffWithNewFiles","baseMessage","commitMessage","commitChanges","performGitPull","isBranchAhead","runGitCommand"]}
|