@gilbert_oliveira/commit-wizard 2.12.1 → 2.12.3-canary.1

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.
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- var qe=Object.defineProperty;var A=(e,t)=>()=>(e&&(t=e(e=0)),t);var j=(e,t)=>{for(var o in t)qe(e,o,{get:t[o],enumerable:!0})};import Te from"path";import{fileURLToPath as Ne}from"url";var Le,Ue,C,f=A(()=>{"use strict";Le=()=>Ne(import.meta.url),Ue=()=>Te.dirname(Le()),C=Ue()});import{existsSync as ae,readFileSync as ce}from"fs";import{join as me}from"path";function ue(e){let t;try{t=me(process.cwd(),".commit-wizardrc")}catch{t="/tmp/.commit-wizardrc"}let o=me(process.env.HOME||process.env.USERPROFILE||"/tmp",".commit-wizardrc"),i={..._e};try{if(ae(o)){let s=ce(o,"utf-8"),a=JSON.parse(s);i=le(i,a)}}catch{console.warn("\u26A0\uFE0F Erro ao ler configura\xE7\xE3o global: Erro desconhecido")}let n=e||t;try{if(ae(n)){let s=ce(n,"utf-8"),a=JSON.parse(s);i=le(i,a)}}catch{console.warn("\u26A0\uFE0F Erro ao ler .commit-wizardrc: Erro desconhecido")}return i.openai.apiKey=process.env.OPENAI_API_KEY,process.env.COMMIT_WIZARD_DEBUG,process.env.COMMIT_WIZARD_DRY_RUN==="true"&&(i.dryRun=!0),i}function le(e,t){return{...e,...t,openai:{...e.openai,...t.openai},smartSplit:{...e.smartSplit,...t.smartSplit},cache:{...e.cache,...t.cache}}}function fe(e){let t=[];return e.openai.apiKey||t.push("OPENAI_API_KEY n\xE3o encontrada nas vari\xE1veis de ambiente"),(e.openai.maxTokens<10||e.openai.maxTokens>4e3)&&t.push("maxTokens deve estar entre 10 e 4000"),(e.openai.temperature<0||e.openai.temperature>2)&&t.push("temperature deve estar entre 0 e 2"),["pt","en","es","fr","de","it","ja","ko","zh"].includes(e.language)||t.push("language deve ser um idioma suportado (pt, en, es, fr, de, it, ja, ko, zh)"),["conventional","simple","detailed"].includes(e.commitStyle)||t.push("commitStyle deve ser conventional, simple ou detailed"),e.smartSplit.minGroupSize<1&&t.push("smartSplit.minGroupSize deve ser pelo menos 1"),(e.smartSplit.maxGroups<1||e.smartSplit.maxGroups>10)&&t.push("smartSplit.maxGroups deve estar entre 1 e 10"),(e.smartSplit.confidenceThreshold<0||e.smartSplit.confidenceThreshold>1)&&t.push("smartSplit.confidenceThreshold deve estar entre 0 e 1"),e.cache.ttl<1&&t.push("cache.ttl deve ser pelo menos 1 minuto"),e.cache.maxSize<1&&t.push("cache.maxSize deve ser pelo menos 1"),t}var _e,pe=A(()=>{"use strict";f();_e={openai:{model:"gpt-4o",maxTokens:150,temperature:.7,timeout:3e4,retries:2},language:"pt",commitStyle:"conventional",autoCommit:!1,splitCommits:!1,dryRun:!1,smartSplit:{enabled:!0,minGroupSize:1,maxGroups:5,confidenceThreshold:.7},cache:{enabled:!0,ttl:60,maxSize:100}}});var M={};j(M,{escapeShellArg:()=>D,executeCommit:()=>z,executeFileCommit:()=>k,getDiffStats:()=>K,getFileDiff:()=>Ve,getGitStatus:()=>J,isGitRepository:()=>H});import{execSync as E}from"child_process";function D(e){return`'${e.replace(/'/g,`'"'"'`)}'`}function H(){try{return E("git rev-parse --git-dir",{stdio:"ignore"}),!0}catch{return!1}}function J(){try{let t=E("git diff --cached --name-only",{encoding:"utf-8",stdio:"pipe"}).trim().split(`
3
- `).filter(i=>i.length>0),o=t.length>0?E("git diff --cached",{encoding:"utf-8",stdio:"pipe"}):"";return{hasStaged:t.length>0,stagedFiles:t,diff:o.trim()}}catch(e){throw new Error(`Erro ao obter status do Git: ${e instanceof Error?e.message:"Erro desconhecido"}`)}}function Ve(e){try{return E(`git diff --cached -- "${e}"`,{encoding:"utf-8",stdio:"pipe"})}catch(t){throw new Error(`Erro ao obter diff do arquivo ${e}: ${t instanceof Error?t.message:"Erro desconhecido"}`)}}function z(e){try{let t=D(e);return E(`git commit -m ${t}`,{stdio:"pipe"}),{success:!0,hash:E("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:e}}catch(t){return{success:!1,error:t instanceof Error?t.message:"Erro desconhecido ao executar commit"}}}function k(e,t){try{let o=D(t),i=D(e);return E(`git commit ${i} -m ${o}`,{stdio:"pipe"}),{success:!0,hash:E("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:t}}catch(o){return{success:!1,error:o instanceof Error?o.message:"Erro desconhecido ao executar commit do arquivo"}}}function K(){try{let t=E("git diff --cached --numstat",{encoding:"utf-8",stdio:"pipe"}).trim().split(`
2
+ var qe=Object.defineProperty;var A=(e,t)=>()=>(e&&(t=e(e=0)),t);var j=(e,t)=>{for(var o in t)qe(e,o,{get:t[o],enumerable:!0})};import ft from"path";import{fileURLToPath as dt}from"url";var f=A(()=>{"use strict"});import{existsSync as ae,readFileSync as ce}from"fs";import{join as me}from"path";function ue(e){let t;try{t=me(process.cwd(),".commit-wizardrc")}catch{t="/tmp/.commit-wizardrc"}let o=me(process.env.HOME||process.env.USERPROFILE||"/tmp",".commit-wizardrc"),i={...Te};try{if(ae(o)){let s=ce(o,"utf-8"),a=JSON.parse(s);i=le(i,a)}}catch{console.warn("\u26A0\uFE0F Erro ao ler configura\xE7\xE3o global: Erro desconhecido")}let n=e||t;try{if(ae(n)){let s=ce(n,"utf-8"),a=JSON.parse(s);i=le(i,a)}}catch{console.warn("\u26A0\uFE0F Erro ao ler .commit-wizardrc: Erro desconhecido")}return i.openai.apiKey=process.env.OPENAI_API_KEY,process.env.COMMIT_WIZARD_DEBUG,process.env.COMMIT_WIZARD_DRY_RUN==="true"&&(i.dryRun=!0),i}function le(e,t){return{...e,...t,openai:{...e.openai,...t.openai},smartSplit:{...e.smartSplit,...t.smartSplit},cache:{...e.cache,...t.cache}}}function fe(e){let t=[];return e.openai.apiKey||t.push("OPENAI_API_KEY n\xE3o encontrada nas vari\xE1veis de ambiente"),(e.openai.maxTokens<10||e.openai.maxTokens>4e3)&&t.push("maxTokens deve estar entre 10 e 4000"),(e.openai.temperature<0||e.openai.temperature>2)&&t.push("temperature deve estar entre 0 e 2"),["pt","en","es","fr","de","it","ja","ko","zh"].includes(e.language)||t.push("language deve ser um idioma suportado (pt, en, es, fr, de, it, ja, ko, zh)"),["conventional","simple","detailed"].includes(e.commitStyle)||t.push("commitStyle deve ser conventional, simple ou detailed"),e.smartSplit.minGroupSize<1&&t.push("smartSplit.minGroupSize deve ser pelo menos 1"),(e.smartSplit.maxGroups<1||e.smartSplit.maxGroups>10)&&t.push("smartSplit.maxGroups deve estar entre 1 e 10"),(e.smartSplit.confidenceThreshold<0||e.smartSplit.confidenceThreshold>1)&&t.push("smartSplit.confidenceThreshold deve estar entre 0 e 1"),e.cache.ttl<1&&t.push("cache.ttl deve ser pelo menos 1 minuto"),e.cache.maxSize<1&&t.push("cache.maxSize deve ser pelo menos 1"),t}var Te,pe=A(()=>{"use strict";f();Te={openai:{model:"gpt-4o",maxTokens:150,temperature:.7,timeout:3e4,retries:2},language:"pt",commitStyle:"conventional",autoCommit:!1,splitCommits:!1,dryRun:!1,smartSplit:{enabled:!0,minGroupSize:1,maxGroups:5,confidenceThreshold:.7},cache:{enabled:!0,ttl:60,maxSize:100}}});var M={};j(M,{escapeShellArg:()=>D,executeCommit:()=>z,executeFileCommit:()=>k,getDiffStats:()=>K,getFileDiff:()=>Ne,getGitStatus:()=>J,isGitRepository:()=>H});import{execSync as E}from"child_process";function D(e){return`'${e.replace(/'/g,`'"'"'`)}'`}function H(){try{return E("git rev-parse --git-dir",{stdio:"ignore"}),!0}catch{return!1}}function J(){try{let t=E("git diff --cached --name-only",{encoding:"utf-8",stdio:"pipe"}).trim().split(`
3
+ `).filter(i=>i.length>0),o=t.length>0?E("git diff --cached",{encoding:"utf-8",stdio:"pipe"}):"";return{hasStaged:t.length>0,stagedFiles:t,diff:o.trim()}}catch(e){throw new Error(`Erro ao obter status do Git: ${e instanceof Error?e.message:"Erro desconhecido"}`)}}function Ne(e){try{return E(`git diff --cached -- "${e}"`,{encoding:"utf-8",stdio:"pipe"})}catch(t){throw new Error(`Erro ao obter diff do arquivo ${e}: ${t instanceof Error?t.message:"Erro desconhecido"}`)}}function z(e){try{let t=D(e);return E(`git commit -m ${t}`,{stdio:"pipe"}),{success:!0,hash:E("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:e}}catch(t){return{success:!1,error:t instanceof Error?t.message:"Erro desconhecido ao executar commit"}}}function k(e,t){try{let o=D(t),i=D(e);return E(`git commit ${i} -m ${o}`,{stdio:"pipe"}),{success:!0,hash:E("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:t}}catch(o){return{success:!1,error:o instanceof Error?o.message:"Erro desconhecido ao executar commit do arquivo"}}}function K(){try{let t=E("git diff --cached --numstat",{encoding:"utf-8",stdio:"pipe"}).trim().split(`
4
4
  `).filter(n=>n.length>0),o=0,i=0;return t.forEach(n=>{let[s,a]=n.split(" ");s&&s!=="-"&&(o+=parseInt(s)||0),a&&a!=="-"&&(i+=parseInt(a)||0)}),{added:o,removed:i,files:t.length}}catch{return{added:0,removed:0,files:0}}}var w=A(()=>{"use strict";f()});var Se={};j(Se,{buildPrompt:()=>ge,detectCommitType:()=>ye,extractCommitTypeFromMessage:()=>he,generateCommitMessage:()=>Ce,generateWithRetry:()=>q,processOpenAIMessage:()=>xe,smartFilterDiff:()=>de});function de(e,t){if(e.length<=t)return e;let o=[/^diff --git a\/package-lock\.json/m,/^diff --git a\/yarn\.lock/m,/^diff --git a\/pnpm-lock\.yaml/m,/^diff --git a\/composer\.lock/m,/^diff --git a\/Gemfile\.lock/m,/^diff --git a\/Cargo\.lock/m,/^diff --git a\/poetry\.lock/m,/^diff --git a\/go\.sum/m,/^diff --git a\/requirements(?:\.txt)?\.lock/m,/^diff --git a\/.*\.min\.js/m,/^diff --git a\/.*\.min\.css/m,/^diff --git a\/.*\.map/m,/^diff --git a\/dist\//m,/^diff --git a\/build\//m],i=e.split(/(?=^diff --git)/m).filter(m=>m.trim()),n=[],s=[];i.forEach(m=>{o.some(h=>h.test(m))?s.push(m):n.push(m)});let a="",c=t;for(let m of n)if(m.length<=c)a+=m,c-=m.length;else if(c>200){a+=m.substring(0,c-50),c=t-a.length;break}else break;if(!a&&s.length>0&&c>0)for(let m of s)if(m.length<=c)a+=m,c-=m.length;else if(c>200){a+=m.substring(0,c-50),c=t-a.length;break}else break;let r=`
5
5
  ... (diff otimizado para focar em mudan\xE7as principais)`;if(c>200&&s.length>0){let m=`
6
6
 
7
- ... (${s.length} arquivo(s) de depend\xEAncias/build omitido(s): ${s.map(h=>{let b=h.match(/^diff --git a\/(.*?) b\//);return b?b[1]:""}).filter(Boolean).join(", ")})`,p=c-r.length;m.length<p&&(a+=m)}return a.trim()!==e.trim()?a+r:a}function ge(e,t,o){let i=t.language==="pt"?"portugu\xEAs":"english",n=He(t.commitStyle,t.language),a=de(e,6e3),c=o.length>10?`${o.length} arquivos: ${o.slice(0,5).join(", ")}...`:o.join(", ");return`Gere mensagem de commit em ${i} (${t.commitStyle}).
7
+ ... (${s.length} arquivo(s) de depend\xEAncias/build omitido(s): ${s.map(h=>{let S=h.match(/^diff --git a\/(.*?) b\//);return S?S[1]:""}).filter(Boolean).join(", ")})`,p=c-r.length;m.length<p&&(a+=m)}return a.trim()!==e.trim()?a+r:a}function ge(e,t,o){let i=t.language==="pt"?"portugu\xEAs":"english",n=Le(t.commitStyle,t.language),a=de(e,6e3),c=o.length>10?`${o.length} arquivos: ${o.slice(0,5).join(", ")}...`:o.join(", ");return`Gere mensagem de commit em ${i} (${t.commitStyle}).
8
8
 
9
9
  Arquivos: ${c}
10
10
 
@@ -15,7 +15,7 @@ Diff:
15
15
  ${a}
16
16
  \`\`\`
17
17
 
18
- Mensagem:`}function He(e,t){let o={pt:{conventional:`- Use formato: tipo(escopo): descri\xE7\xE3o
18
+ Mensagem:`}function Le(e,t){let o={pt:{conventional:`- Use formato: tipo(escopo): descri\xE7\xE3o
19
19
  - Tipos v\xE1lidos: feat, fix, docs, style, refactor, test, chore, build, ci
20
20
  - Exemplo: "feat(auth): adicionar valida\xE7\xE3o de email"
21
21
  - Mantenha a primeira linha com at\xE9 50 caracteres`,simple:`- Use formato simples e direto
@@ -35,17 +35,17 @@ Mensagem:`}function He(e,t){let o={pt:{conventional:`- Use formato: tipo(escopo)
35
35
  - Use imperative mood
36
36
  - Be descriptive but concise`}},i=t==="pt"?"pt":"en";return o[i][e]||o[i].conventional}function he(e){let t={feat:/^(feat|feature)(\([^)]+\))?:/i,fix:/^(fix|bugfix)(\([^)]+\))?:/i,docs:/^(docs|documentation)(\([^)]+\))?:/i,style:/^(style|format)(\([^)]+\))?:/i,refactor:/^(refactor|refactoring)(\([^)]+\))?:/i,test:/^(test|testing)(\([^)]+\))?:/i,chore:/^(chore|maintenance)(\([^)]+\))?:/i,build:/^(build|ci)(\([^)]+\))?:/i,ci:/^(ci|continuous-integration)(\([^)]+\))?:/i};for(let[o,i]of Object.entries(t))if(i.test(e))return o;return null}function ye(e,t){let o=e.toLowerCase(),i=t.join(" ").toLowerCase();return i.includes("test")||i.includes("spec")||o.includes("test(")?"test":i.includes("readme")||i.includes(".md")||i.includes("docs")?"docs":i.includes("package.json")||i.includes("dockerfile")||i.includes(".yml")||i.includes(".yaml")||i.includes("webpack")||i.includes("tsconfig")?"build":i.includes(".css")||i.includes(".scss")||o.includes("style")||o.includes("format")?"style":o.includes("fix")||o.includes("bug")||o.includes("error")||o.includes("issue")?"fix":o.includes("add")||o.includes("new")||o.includes("create")||o.includes("implement")?"feat":o.includes("refactor")||o.includes("restructure")||o.includes("rename")?"refactor":"chore"}function xe(e){if(e.startsWith("```")){let t=e.match(/^```[^\n`]*\n([\s\S]*?)\n\s*```([\s\S]*)$/);if(t){let o=t[1].trim(),i=t[2].trim();e=i?`${o}
37
37
 
38
- ${i}`:o}else e.match(/^```[\s\S]*```$/)&&(e=e.replace(/^```(?:plaintext|javascript|typescript|python|java|html|css|json|xml|yaml|yml|bash|shell|text)?\s*/,"").replace(/\s*```$/,""))}return e=e.trim(),e}async function Ce(e,t,o){try{if(!t.openai.apiKey)return{success:!1,error:"Chave da OpenAI n\xE3o encontrada. Configure OPENAI_API_KEY nas vari\xE1veis de ambiente."};let i=ge(e,t,o),n=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{Authorization:`Bearer ${t.openai.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:t.openai.model,messages:[{role:"user",content:i}],max_tokens:Math.min(t.openai.maxTokens,150),temperature:t.openai.temperature})});if(!n.ok){let l=await n.json().catch(()=>({}));return{success:!1,error:`Erro da OpenAI (${n.status}): ${l.error?.message||"Erro desconhecido"}`}}let a=(await n.json()).choices?.[0]?.message?.content?.trim();if(!a)return{success:!1,error:"OpenAI retornou resposta vazia"};a=xe(a);let c=he(a),r=ye(e,o);return{success:!0,suggestion:{message:a,type:c||r,confidence:.8}}}catch(i){return{success:!1,error:`Erro ao conectar com OpenAI: ${i instanceof Error?i.message:"Erro desconhecido"}`}}}async function q(e,t,o,i=3){let n="";for(let s=0;s<i;s++){let a=await Ce(e,t,o);if(a.success)return a;n=a.error||"Erro desconhecido",s<i-1&&await new Promise(c=>setTimeout(c,Math.pow(2,s)*1e3))}return{success:!1,error:`Falha ap\xF3s ${i} tentativas. \xDAltimo erro: ${n}`}}var W=A(()=>{"use strict";f()});var Q={};j(Q,{askContinueCommits:()=>Y,confirmCommit:()=>Ye,copyToClipboard:()=>U,editCommitMessage:()=>L,selectFilesForCommit:()=>B,showCancellation:()=>R,showCommitPreview:()=>N,showCommitResult:()=>S});import{text as Je,select as Ke,confirm as T,log as F,note as be,cancel as We,isCancel as P}from"@clack/prompts";import Be from"clipboardy";async function N(e){be(`Tipo: ${e.type}
39
- Mensagem: "${e.message}"`,"\u{1F4AD} Sugest\xE3o de Commit");let t=await Ke({message:"O que voc\xEA gostaria de fazer?",options:[{value:"commit",label:"\u2705 Fazer commit com esta mensagem",hint:"Executar git commit imediatamente"},{value:"edit",label:"\u270F\uFE0F Editar mensagem",hint:"Modificar a mensagem antes de commitar"},{value:"copy",label:"\u{1F4CB} Copiar para clipboard",hint:"Copiar mensagem e sair sem commitar"},{value:"cancel",label:"\u274C Cancelar",hint:"Sair sem fazer nada"}]});return P(t)?{action:"cancel"}:{action:t}}async function L(e){let t=await Je({message:"Edite a mensagem do commit:",initialValue:e,placeholder:"Digite a mensagem do commit...",validate:i=>{if(!i||i.trim().length===0)return"A mensagem n\xE3o pode estar vazia";if(i.trim().length>72)return"A mensagem est\xE1 muito longa (m\xE1ximo 72 caracteres recomendado)"}});if(P(t))return{action:"cancel"};let o=await T({message:`Confirma a mensagem editada: "${t}"?`});return P(o)||!o?{action:"cancel"}:{action:"commit",message:t}}async function U(e){try{return await Be.write(e),F.success("\u2705 Mensagem copiada para a \xE1rea de transfer\xEAncia!"),!0}catch(t){return F.error(`\u274C Erro ao copiar: ${t instanceof Error?t.message:"Erro desconhecido"}`),!1}}async function Ye(e){be(`"${e}"`,"\u{1F680} Confirmar Commit");let t=await T({message:"Executar o commit agora?"});return P(t)?!1:t}function S(e,t,o){e&&t?(F.success("\u2705 Commit realizado com sucesso!"),F.info(`\u{1F517} Hash: ${t.substring(0,8)}`)):F.error(`\u274C Erro ao realizar commit: ${o||"Erro desconhecido"}`)}async function B(e){F.info("\u{1F4CB} Modo Split: Selecione os arquivos para este commit");let t=[];for(let o of e){let i=await T({message:`Incluir "${o}" neste commit?`});if(P(i))break;i&&t.push(o)}return t}async function Y(e){if(e.length===0)return!1;F.info(`\u{1F4C4} Arquivos restantes: ${e.join(", ")}`);let t=await T({message:"Gerar commit para os arquivos restantes?"});return P(t)?!1:t}function R(){We("Opera\xE7\xE3o cancelada pelo usu\xE1rio")}var O=A(()=>{"use strict";f()});var Ae={};j(Ae,{chooseSplitMode:()=>X,confirmGroupCommit:()=>Xe,showSmartSplitGroups:()=>Ze,showSmartSplitProgress:()=>et});import{select as we,confirm as Qe,log as ve,note as $e,isCancel as Z}from"@clack/prompts";async function X(){let e=await we({message:"Como voc\xEA gostaria de organizar os commits?",options:[{value:"smart",label:"\u{1F9E0} Smart Split (Recomendado)",hint:"IA analisa contexto e agrupa automaticamente"},{value:"manual",label:"\u270B Split Manual",hint:"Voc\xEA escolhe arquivos manualmente"},{value:"cancel",label:"\u274C Cancelar",hint:"Voltar ao modo normal"}]});return Z(e)?{action:"cancel"}:e==="manual"?{action:"manual"}:e==="smart"?{action:"proceed"}:{action:"cancel"}}async function Ze(e){$e(`Identificamos ${e.length} grupo(s) l\xF3gico(s) para seus commits:
38
+ ${i}`:o}else e.match(/^```[\s\S]*```$/)&&(e=e.replace(/^```(?:plaintext|javascript|typescript|python|java|html|css|json|xml|yaml|yml|bash|shell|text)?\s*/,"").replace(/\s*```$/,""))}return e=e.trim(),e}async function Ce(e,t,o){try{if(!t.openai.apiKey)return{success:!1,error:"Chave da OpenAI n\xE3o encontrada. Configure OPENAI_API_KEY nas vari\xE1veis de ambiente."};let i=ge(e,t,o),n=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{Authorization:`Bearer ${t.openai.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:t.openai.model,messages:[{role:"user",content:i}],max_tokens:Math.min(t.openai.maxTokens,150),temperature:t.openai.temperature})});if(!n.ok){let l=await n.json().catch(()=>({}));return{success:!1,error:`Erro da OpenAI (${n.status}): ${l.error?.message||"Erro desconhecido"}`}}let a=(await n.json()).choices?.[0]?.message?.content?.trim();if(!a)return{success:!1,error:"OpenAI retornou resposta vazia"};a=xe(a);let c=he(a),r=ye(e,o);return{success:!0,suggestion:{message:a,type:c||r,confidence:.8}}}catch(i){return{success:!1,error:`Erro ao conectar com OpenAI: ${i instanceof Error?i.message:"Erro desconhecido"}`}}}async function q(e,t,o,i=3){let n="";for(let s=0;s<i;s++){let a=await Ce(e,t,o);if(a.success)return a;n=a.error||"Erro desconhecido",s<i-1&&await new Promise(c=>setTimeout(c,Math.pow(2,s)*1e3))}return{success:!1,error:`Falha ap\xF3s ${i} tentativas. \xDAltimo erro: ${n}`}}var W=A(()=>{"use strict";f()});var Q={};j(Q,{askContinueCommits:()=>Y,confirmCommit:()=>Je,copyToClipboard:()=>U,editCommitMessage:()=>L,selectFilesForCommit:()=>B,showCancellation:()=>R,showCommitPreview:()=>N,showCommitResult:()=>C});import{text as Ue,select as _e,confirm as T,log as P,note as be,cancel as Ve,isCancel as F}from"@clack/prompts";import He from"clipboardy";async function N(e){be(`Tipo: ${e.type}
39
+ Mensagem: "${e.message}"`,"\u{1F4AD} Sugest\xE3o de Commit");let t=await _e({message:"O que voc\xEA gostaria de fazer?",options:[{value:"commit",label:"\u2705 Fazer commit com esta mensagem",hint:"Executar git commit imediatamente"},{value:"edit",label:"\u270F\uFE0F Editar mensagem",hint:"Modificar a mensagem antes de commitar"},{value:"copy",label:"\u{1F4CB} Copiar para clipboard",hint:"Copiar mensagem e sair sem commitar"},{value:"cancel",label:"\u274C Cancelar",hint:"Sair sem fazer nada"}]});return F(t)?{action:"cancel"}:{action:t}}async function L(e){let t=await Ue({message:"Edite a mensagem do commit:",initialValue:e,placeholder:"Digite a mensagem do commit...",validate:i=>{if(!i||i.trim().length===0)return"A mensagem n\xE3o pode estar vazia";if(i.trim().length>72)return"A mensagem est\xE1 muito longa (m\xE1ximo 72 caracteres recomendado)"}});if(F(t))return{action:"cancel"};let o=await T({message:`Confirma a mensagem editada: "${t}"?`});return F(o)||!o?{action:"cancel"}:{action:"commit",message:t}}async function U(e){try{return await He.write(e),P.success("\u2705 Mensagem copiada para a \xE1rea de transfer\xEAncia!"),!0}catch(t){return P.error(`\u274C Erro ao copiar: ${t instanceof Error?t.message:"Erro desconhecido"}`),!1}}async function Je(e){be(`"${e}"`,"\u{1F680} Confirmar Commit");let t=await T({message:"Executar o commit agora?"});return F(t)?!1:t}function C(e,t,o){e&&t?(P.success("\u2705 Commit realizado com sucesso!"),P.info(`\u{1F517} Hash: ${t.substring(0,8)}`)):P.error(`\u274C Erro ao realizar commit: ${o||"Erro desconhecido"}`)}async function B(e){P.info("\u{1F4CB} Modo Split: Selecione os arquivos para este commit");let t=[];for(let o of e){let i=await T({message:`Incluir "${o}" neste commit?`});if(F(i))break;i&&t.push(o)}return t}async function Y(e){if(e.length===0)return!1;P.info(`\u{1F4C4} Arquivos restantes: ${e.join(", ")}`);let t=await T({message:"Gerar commit para os arquivos restantes?"});return F(t)?!1:t}function R(){Ve("Opera\xE7\xE3o cancelada pelo usu\xE1rio")}var O=A(()=>{"use strict";f()});var Ae={};j(Ae,{chooseSplitMode:()=>X,confirmGroupCommit:()=>Be,showSmartSplitGroups:()=>We,showSmartSplitProgress:()=>Ye});import{select as we,confirm as Ke,log as ve,note as $e,isCancel as Z}from"@clack/prompts";async function X(){let e=await we({message:"Como voc\xEA gostaria de organizar os commits?",options:[{value:"smart",label:"\u{1F9E0} Smart Split (Recomendado)",hint:"IA analisa contexto e agrupa automaticamente"},{value:"manual",label:"\u270B Split Manual",hint:"Voc\xEA escolhe arquivos manualmente"},{value:"cancel",label:"\u274C Cancelar",hint:"Voltar ao modo normal"}]});return Z(e)?{action:"cancel"}:e==="manual"?{action:"manual"}:e==="smart"?{action:"proceed"}:{action:"cancel"}}async function We(e){$e(`Identificamos ${e.length} grupo(s) l\xF3gico(s) para seus commits:
40
40
 
41
41
  `+e.map((o,i)=>`${i+1}. **${o.name}**
42
42
  \u{1F4C4} ${o.files.join(", ")}
43
43
  \u{1F4A1} ${o.description}
44
44
  \u{1F3AF} Confian\xE7a: ${Math.round(o.confidence*100)}%`).join(`
45
45
 
46
- `),"\u{1F9E0} An\xE1lise de Contexto");let t=await we({message:"O que voc\xEA gostaria de fazer?",options:[{value:"proceed",label:"\u2705 Prosseguir com esta organiza\xE7\xE3o",hint:"Usar os grupos como sugeridos pela IA"},{value:"manual",label:"\u270B Fazer split manual",hint:"Escolher arquivos manualmente"},{value:"cancel",label:"\u274C Cancelar",hint:"Voltar ao modo normal"}]});return Z(t)?{action:"cancel"}:t==="proceed"?{action:"proceed",groups:e}:{action:t}}async function Xe(e,t){$e(`**Grupo:** ${e.name}
46
+ `),"\u{1F9E0} An\xE1lise de Contexto");let t=await we({message:"O que voc\xEA gostaria de fazer?",options:[{value:"proceed",label:"\u2705 Prosseguir com esta organiza\xE7\xE3o",hint:"Usar os grupos como sugeridos pela IA"},{value:"manual",label:"\u270B Fazer split manual",hint:"Escolher arquivos manualmente"},{value:"cancel",label:"\u274C Cancelar",hint:"Voltar ao modo normal"}]});return Z(t)?{action:"cancel"}:t==="proceed"?{action:"proceed",groups:e}:{action:t}}async function Be(e,t){$e(`**Grupo:** ${e.name}
47
47
  **Arquivos:** ${e.files.join(", ")}
48
- **Mensagem:** "${t}"`,"\u{1F680} Confirmar Commit do Grupo");let o=await Qe({message:`Fazer commit para "${e.name}"?`});return Z(o)?!1:o}function et(e,t,o){let i=Math.round(e/t*100),n="\u2588".repeat(Math.floor(i/10))+"\u2591".repeat(10-Math.floor(i/10));ve.info(`\u{1F504} Progresso: [${n}] ${i}% (${e}/${t})`),ve.info(`\u{1F4CB} Processando: ${o}`)}var ee=A(()=>{"use strict";f()});import tt from"crypto";function Me(e){Ee=new te(e)}function ze(){return Ee}function Fe(e,t){let o=ze();return o?o.get(e,t):{hit:!1}}function Pe(e,t,o){let i=ze();i&&i.set(e,t,o)}var te,Ee,ie=A(()=>{"use strict";f();te=class{cache=new Map;config;constructor(t){this.config=t}generateHash(t,o){let i={files:t.sort(),diff:o.substring(0,1e3),model:this.config.openai.model,temperature:this.config.openai.temperature};return tt.createHash("md5").update(JSON.stringify(i)).digest("hex")}get(t,o){if(!this.config.cache.enabled)return{hit:!1};let i=this.generateHash(t,o),n=this.cache.get(i);if(!n)return{hit:!1};let s=Date.now(),a=this.config.cache.ttl*60*1e3;return s-n.timestamp>a?(this.cache.delete(i),{hit:!1}):{hit:!0,groups:n.groups}}set(t,o,i){if(!this.config.cache.enabled||(this.cache.size>=this.config.cache.maxSize&&this.cleanup(),this.cache.size>=this.config.cache.maxSize))return;let n=this.generateHash(t,o),s={groups:i,timestamp:Date.now(),hash:n};this.cache.set(n,s)}cleanup(){let t=Date.now(),o=this.config.cache.ttl*60*1e3;for(let[i,n]of this.cache.entries())t-n.timestamp>o&&this.cache.delete(i);if(this.cache.size>=this.config.cache.maxSize){let n=Array.from(this.cache.entries()).sort((s,a)=>s[1].timestamp-a[1].timestamp).slice(0,Math.ceil(this.config.cache.maxSize*.5));for(let[s]of n)this.cache.delete(s)}}clear(){this.cache.clear()}getStats(){return{size:this.cache.size,maxSize:this.config.cache.maxSize,enabled:this.config.cache.enabled}}},Ee=null});import{log as g}from"@clack/prompts";function it(e,t){let i=t.length>8e3?t.substring(0,8e3)+`
48
+ **Mensagem:** "${t}"`,"\u{1F680} Confirmar Commit do Grupo");let o=await Ke({message:`Fazer commit para "${e.name}"?`});return Z(o)?!1:o}function Ye(e,t,o){let i=Math.round(e/t*100),n="\u2588".repeat(Math.floor(i/10))+"\u2591".repeat(10-Math.floor(i/10));ve.info(`\u{1F504} Progresso: [${n}] ${i}% (${e}/${t})`),ve.info(`\u{1F4CB} Processando: ${o}`)}var ee=A(()=>{"use strict";f()});import Qe from"crypto";function Me(e){Ee=new te(e)}function ze(){return Ee}function Pe(e,t){let o=ze();return o?o.get(e,t):{hit:!1}}function Fe(e,t,o){let i=ze();i&&i.set(e,t,o)}var te,Ee,ie=A(()=>{"use strict";f();te=class{cache=new Map;config;constructor(t){this.config=t}generateHash(t,o){let i={files:t.sort(),diff:o.substring(0,1e3),model:this.config.openai.model,temperature:this.config.openai.temperature};return Qe.createHash("md5").update(JSON.stringify(i)).digest("hex")}get(t,o){if(!this.config.cache.enabled)return{hit:!1};let i=this.generateHash(t,o),n=this.cache.get(i);if(!n)return{hit:!1};let s=Date.now(),a=this.config.cache.ttl*60*1e3;return s-n.timestamp>a?(this.cache.delete(i),{hit:!1}):{hit:!0,groups:n.groups}}set(t,o,i){if(!this.config.cache.enabled||(this.cache.size>=this.config.cache.maxSize&&this.cleanup(),this.cache.size>=this.config.cache.maxSize))return;let n=this.generateHash(t,o),s={groups:i,timestamp:Date.now(),hash:n};this.cache.set(n,s)}cleanup(){let t=Date.now(),o=this.config.cache.ttl*60*1e3;for(let[i,n]of this.cache.entries())t-n.timestamp>o&&this.cache.delete(i);if(this.cache.size>=this.config.cache.maxSize){let n=Array.from(this.cache.entries()).sort((s,a)=>s[1].timestamp-a[1].timestamp).slice(0,Math.ceil(this.config.cache.maxSize*.5));for(let[s]of n)this.cache.delete(s)}}clear(){this.cache.clear()}getStats(){return{size:this.cache.size,maxSize:this.config.cache.maxSize,enabled:this.config.cache.enabled}}},Ee=null});import{log as g}from"@clack/prompts";function Ze(e,t){let i=t.length>8e3?t.substring(0,8e3)+`
49
49
  ... (diff truncado)`:t,n=e.length,s=e.reduce((c,r)=>{let l=r.split(".").pop()||"sem-extensao";return c[l]=(c[l]||0)+1,c},{}),a=Object.entries(s).map(([c,r])=>`${c}: ${r}`).join(", ");return`Analise os arquivos modificados e agrupe em commits l\xF3gicos.
50
50
 
51
51
  ARQUIVOS (${n}): ${e.join(", ")}
@@ -67,7 +67,7 @@ Agrupe arquivos relacionados. M\xE1ximo 5 grupos. Responda em JSON:
67
67
  "confidence": 0.8
68
68
  }
69
69
  ]
70
- }`}function ot(e){let t=e.reduce((i,n)=>{let s=n.split("/").slice(0,-1).join("/")||"root";return i[s]||(i[s]=[]),i[s].push(n),i},{});return`Agrupe estes arquivos em commits l\xF3gicos baseado nos diret\xF3rios:
70
+ }`}function Xe(e){let t=e.reduce((i,n)=>{let s=n.split("/").slice(0,-1).join("/")||"root";return i[s]||(i[s]=[]),i[s].push(n),i},{});return`Agrupe estes arquivos em commits l\xF3gicos baseado nos diret\xF3rios:
71
71
 
72
72
  ARQUIVOS POR DIRET\xD3RIO:
73
73
  ${Object.entries(t).map(([i,n])=>`${i}: ${n.length} arquivo(s)`).join(`
@@ -86,7 +86,7 @@ Agrupe por funcionalidade relacionada. M\xE1ximo 5 grupos. JSON:
86
86
  "confidence": 0.7
87
87
  }
88
88
  ]
89
- }`}async function st(e,t,o){try{if(!o.openai.apiKey)return{success:!1,error:"Chave da OpenAI n\xE3o encontrada"};let i=Fe(e,t);if(i.hit&&i.groups)return{success:!0,groups:i.groups};let s=t.length>6e3,a=s?ot(e):it(e,t);s&&console.warn(`\u26A0\uFE0F Diff muito grande (${t.length} chars), usando an\xE1lise baseada em nomes de arquivos`);let c=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{Authorization:`Bearer ${o.openai.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:o.openai.model,messages:[{role:"user",content:a}],max_tokens:800,temperature:.3})});if(!c.ok){let d=await c.json().catch(()=>({}));return{success:!1,error:`Erro da OpenAI (${c.status}): ${d.error?.message||"Erro desconhecido"}`}}let l=(await c.json()).choices?.[0]?.message?.content?.trim();if(!l)return{success:!1,error:"OpenAI retornou resposta vazia"};let m=l.match(/\{[\s\S]*\}/);if(!m)return{success:!1,error:"Resposta da OpenAI n\xE3o cont\xE9m JSON v\xE1lido"};let p=JSON.parse(m[0]);if(!p.groups||!Array.isArray(p.groups))return{success:!1,error:"Formato de resposta inv\xE1lido da OpenAI"};let h=p.groups.flatMap(d=>d.files||[]),b=e.filter(d=>!h.includes(d));b.length>0&&(p.groups[0].files=[...p.groups[0].files||[],...b]);let y=p.groups.map(d=>({id:d.id||`group-${Math.random().toString(36).substr(2,9)}`,name:d.name||"Grupo sem nome",description:d.description||"Sem descri\xE7\xE3o",files:d.files||[],diff:"",confidence:d.confidence||.5}));return Pe(e,t,y),{success:!0,groups:y}}catch(i){return{success:!1,error:`Erro ao analisar contexto: ${i instanceof Error?i.message:"Erro desconhecido"}`}}}async function nt(e){let{getFileDiff:t}=await Promise.resolve().then(()=>(w(),M)),o=e.files.map(s=>{try{let a=t(s),c=4e3;return a.length>c?a.substring(0,c)+`
89
+ }`}async function et(e,t,o){try{if(!o.openai.apiKey)return{success:!1,error:"Chave da OpenAI n\xE3o encontrada"};let i=Pe(e,t);if(i.hit&&i.groups)return{success:!0,groups:i.groups};let s=t.length>6e3,a=s?Xe(e):Ze(e,t);s&&console.warn(`\u26A0\uFE0F Diff muito grande (${t.length} chars), usando an\xE1lise baseada em nomes de arquivos`);let c=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{Authorization:`Bearer ${o.openai.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify({model:o.openai.model,messages:[{role:"user",content:a}],max_tokens:800,temperature:.3})});if(!c.ok){let d=await c.json().catch(()=>({}));return{success:!1,error:`Erro da OpenAI (${c.status}): ${d.error?.message||"Erro desconhecido"}`}}let l=(await c.json()).choices?.[0]?.message?.content?.trim();if(!l)return{success:!1,error:"OpenAI retornou resposta vazia"};let m=l.match(/\{[\s\S]*\}/);if(!m)return{success:!1,error:"Resposta da OpenAI n\xE3o cont\xE9m JSON v\xE1lido"};let p=JSON.parse(m[0]);if(!p.groups||!Array.isArray(p.groups))return{success:!1,error:"Formato de resposta inv\xE1lido da OpenAI"};let h=p.groups.flatMap(d=>d.files||[]),S=e.filter(d=>!h.includes(d));S.length>0&&(p.groups[0].files=[...p.groups[0].files||[],...S]);let y=p.groups.map(d=>({id:d.id||`group-${Math.random().toString(36).substr(2,9)}`,name:d.name||"Grupo sem nome",description:d.description||"Sem descri\xE7\xE3o",files:d.files||[],diff:"",confidence:d.confidence||.5}));return Fe(e,t,y),{success:!0,groups:y}}catch(i){return{success:!1,error:`Erro ao analisar contexto: ${i instanceof Error?i.message:"Erro desconhecido"}`}}}async function tt(e){let{getFileDiff:t}=await Promise.resolve().then(()=>(w(),M)),o=e.files.map(s=>{try{let a=t(s),c=4e3;return a.length>c?a.substring(0,c)+`
90
90
  ... (diff truncado)`:a}catch{return""}}).filter(s=>s.length>0);if(o.length===0&&e.files.length>0){let{execSync:s}=await import("child_process"),a=e.files.filter(r=>{try{return s(`test -f "${r}"`,{stdio:"ignore"}),s(`git status --porcelain -- "${r}"`,{encoding:"utf-8",stdio:"pipe"}).trim().startsWith("??")}catch{return!1}});if(a.length>0)return a.map(r=>{try{let l=s(`cat "${r}"`,{encoding:"utf-8",stdio:"pipe"}),m=2e3,p=l.length>m?l.substring(0,m)+`
91
91
  ... (conte\xFAdo truncado)`:l;return`diff --git a/${r} b/${r}
92
92
  new file mode 100644
@@ -111,9 +111,9 @@ ${p.split(`
111
111
  `)}`}catch{return""}}).filter(r=>r.length>0).join(`
112
112
  `)}let i=o.join(`
113
113
  `),n=8e3;return i.length>n?i.substring(0,n)+`
114
- ... (diff total truncado)`:i}async function oe(e,t,o){o.silent||g.info("\u{1F9E0} Modo Smart Split ativado - Agrupando arquivos por contexto"),o.silent||g.info("\u{1F916} Analisando contexto das mudan\xE7as...");let i=await st(e.stagedFiles,e.diff,t);if(!i.success){o.silent||g.error(`\u274C Erro na an\xE1lise de contexto: ${i.error}`);return}if(!i.groups||i.groups.length===0){o.silent||g.error("\u274C Nenhum grupo foi criado pela an\xE1lise");return}if(o.silent||(g.success(`\u2705 ${i.groups.length} grupo(s) identificado(s):`),i.groups.forEach((n,s)=>{g.info(` ${s+1}. ${n.name} (${n.files.length} arquivo(s))`),g.info(` \u{1F4C4} ${n.files.join(", ")}`)})),!o.yes&&!o.silent){let{showSmartSplitGroups:n}=await Promise.resolve().then(()=>(ee(),Ae)),s=await n(i.groups);if(s.action==="cancel"){o.silent||g.info("\u274C Opera\xE7\xE3o cancelada pelo usu\xE1rio");return}if(s.action==="manual"){let a={...o,split:!0,smartSplit:!1},{main:c}=await Promise.resolve().then(()=>(se(),Ge));await c(a);return}}for(let n=0;n<i.groups.length;n++){let s=i.groups[n];if(!s){o.silent||g.error(`\u274C Grupo ${n+1} \xE9 undefined`);continue}o.silent||g.info(`
115
- \u{1F504} Processando grupo ${n+1}/${i.groups.length}: ${s.name}`);let a=await nt(s);if(!a){o.silent||(g.warn(`\u26A0\uFE0F Nenhum diff encontrado para o grupo: ${s.name}`),g.info(` \u{1F4C4} Arquivos: ${s.files.join(", ")}`),g.info(" \u{1F4A1} Poss\xEDvel causa: arquivos novos, deletados/recriados, ou sem mudan\xE7as"));continue}o.silent||g.info(`\u{1F916} Gerando commit para: ${s.name}`);let{generateWithRetry:c}=await Promise.resolve().then(()=>(W(),Se)),r=await c(a,t,s.files);if(!r.success){o.silent||g.error(`\u274C Erro ao gerar commit para ${s.name}: ${r.error}`);continue}if(!r.suggestion){o.silent||g.error(`\u274C Nenhuma sugest\xE3o gerada para ${s.name}`);continue}if(t.dryRun){o.silent||(g.info(`\u{1F50D} Dry Run - Grupo: ${s.name}`),g.info(`\u{1F4C4} Arquivos: ${s.files.join(", ")}`),g.info(`\u{1F4AD} Mensagem: "${r.suggestion.message}"`));continue}if(o.yes){let{executeFileCommit:l}=await Promise.resolve().then(()=>(w(),M)),m;if(s.files.length===1&&s.files[0])m=l(s.files[0],r.suggestion.message||"");else{let{execSync:p}=await import("child_process"),{escapeShellArg:h}=await Promise.resolve().then(()=>(w(),M));try{let b=s.files.map(x=>h(x)).join(" "),y=h(r.suggestion.message||"");p(`git commit ${b} -m ${y}`,{stdio:"pipe"}),m={success:!0,hash:p("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:r.suggestion.message||""}}catch(b){m={success:!1,error:b instanceof Error?b.message:"Erro desconhecido ao executar commit"}}}S(m.success,m.hash,m.error)}else{let{showCommitPreview:l,editCommitMessage:m,copyToClipboard:p,showCancellation:h}=await Promise.resolve().then(()=>(O(),Q));switch((await l(r.suggestion)).action){case"commit":{let{executeFileCommit:y}=await Promise.resolve().then(()=>(w(),M)),d,x=r.suggestion.message||"Atualiza\xE7\xE3o de arquivos";if(s.files.length===1&&s.files[0])d=y(s.files[0],x);else{let{execSync:G}=await import("child_process"),{escapeShellArg:I}=await Promise.resolve().then(()=>(w(),M));try{let $=s.files.map(V=>I(V)).join(" "),_=I(x);G(`git commit ${$} -m ${_}`,{stdio:"pipe"}),d={success:!0,hash:G("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:x}}catch($){d={success:!1,error:$ instanceof Error?$.message:"Erro desconhecido ao executar commit"}}}S(d.success,d.hash,d.error);break}case"edit":{let y=await m(r.suggestion.message);if(y.action==="commit"&&y.message){let{executeFileCommit:d}=await Promise.resolve().then(()=>(w(),M)),x;if(s.files.length===1&&s.files[0])x=d(s.files[0],y.message||"");else{let{execSync:G}=await import("child_process"),{escapeShellArg:I}=await Promise.resolve().then(()=>(w(),M));try{let $=s.files.map(V=>I(V)).join(" "),_=I(y.message||"");G(`git commit ${$} -m ${_}`,{stdio:"pipe"}),x={success:!0,hash:G("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:y.message||""}}catch($){x={success:!1,error:$ instanceof Error?$.message:"Erro desconhecido ao executar commit"}}}S(x.success,x.hash,x.error)}break}case"copy":{await p(r.suggestion.message),o.silent||g.info("\u{1F3AF} Mensagem copiada para clipboard");break}case"cancel":{h();return}}}if(n<i.groups.length-1&&!o.yes){let{askContinueCommits:l}=await Promise.resolve().then(()=>(O(),Q)),m=i.groups.slice(n+1).filter(h=>h!==void 0).map(h=>h.name);if(!await l(m))break}}o.silent||g.success("\u2705 Smart Split conclu\xEDdo!")}var Re=A(()=>{"use strict";f();ie();O()});var Ge={};j(Ge,{main:()=>ne});import{log as u}from"@clack/prompts";async function ne(e={silent:!1,yes:!1,auto:!1,split:!1,smartSplit:!1,dryRun:!1,help:!1,version:!1}){e.silent||u.info("\u{1F680} Commit Wizard iniciado!"),H()||(u.error("\u274C N\xE3o foi encontrado um reposit\xF3rio Git neste diret\xF3rio."),e.silent||u.info("\u{1F4A1} Execute o comando em um diret\xF3rio com reposit\xF3rio Git inicializado."),process.exit(1)),e.silent||u.info("\u2699\uFE0F Carregando configura\xE7\xE3o...");let t=ue();Me(t),e.split&&(t.splitCommits=!0),e.dryRun&&(t.dryRun=!0);let o=fe(t);o.length>0&&(u.error("\u274C Erros na configura\xE7\xE3o:"),o.forEach(a=>u.error(` \u2022 ${a}`)),process.exit(1)),e.silent||u.success(`\u2705 Configura\xE7\xE3o carregada (modelo: ${t.openai.model}, idioma: ${t.language})`),e.silent||u.info("\u{1F4CB} Verificando arquivos staged...");let i=J();i.hasStaged||(u.warn("\u26A0\uFE0F Nenhum arquivo foi encontrado no stage."),e.silent||u.info("\u{1F4A1} Use `git add <arquivo>` para adicionar arquivos ao stage antes de gerar o commit."),process.exit(0));let n=K();if(e.silent||(u.success(`\u2705 Encontrados ${i.stagedFiles.length} arquivo(s) staged:`),i.stagedFiles.forEach(a=>u.info(` \u{1F4C4} ${a}`)),u.info(`\u{1F4CA} Estat\xEDsticas: +${n.added} -${n.removed} linhas`)),t.splitCommits||e.smartSplit){if(e.yes)return await oe(i,t,e);switch((await X()).action){case"proceed":return await oe(i,t,e);case"manual":return await rt(i,t,e);case"cancel":R();return}}e.silent||u.info("\u{1F916} Gerando mensagem de commit com IA...");let s=await q(i.diff,t,i.stagedFiles);if(s.success||(u.error(`\u274C Erro ao gerar commit: ${s.error}`),process.exit(1)),s.suggestion||(u.error("\u274C Nenhuma sugest\xE3o foi gerada"),process.exit(1)),e.silent||u.success("\u2728 Mensagem de commit gerada!"),t.dryRun){u.info("\u{1F50D} Modo Dry Run - Mensagem gerada:"),u.info(`"${s.suggestion.message}"`),u.info("\u{1F4A1} Execute sem --dry-run para fazer o commit");return}if(e.yes){let a=z(s.suggestion.message);S(a.success,a.hash,a.error);return}for(;;)switch((await N(s.suggestion)).action){case"commit":{let c=z(s.suggestion.message);S(c.success,c.hash,c.error);return}case"edit":{let c=await L(s.suggestion.message);if(c.action==="cancel"){R();return}if(c.action==="commit"&&c.message){let r=z(c.message);S(r.success,r.hash,r.error);return}break}case"copy":{await U(s.suggestion.message),e.silent||u.info('\u{1F3AF} Voc\xEA pode usar a mensagem copiada com: git commit -m "mensagem"');return}case"cancel":{R();return}}}async function rt(e,t,o){o.silent||u.info("\u{1F504} Modo Split ativado - Commits separados por arquivo");let i=[...e.stagedFiles];for(;i.length>0;){let n=o.yes?[i[0]]:await B(i);if(n.length===0){o.silent||u.info("\u274C Nenhum arquivo selecionado");break}let{getFileDiff:s}=await Promise.resolve().then(()=>(w(),M)),a=n.filter(r=>r!==void 0).map(r=>{try{return s(r)}catch(l){return u.error(`\u274C Erro ao obter diff do arquivo ${r}: ${l instanceof Error?l.message:"Erro desconhecido"}`),""}}).filter(r=>r.length>0).join(`
116
- `);if(!a){o.silent||u.warn("\u26A0\uFE0F Nenhum diff encontrado para os arquivos selecionados"),i=i.filter(r=>!n.includes(r));continue}o.silent||u.info(`\u{1F916} Gerando commit para: ${n.join(", ")}`);let c=await q(a,t,n.filter(r=>r!==void 0));if(!c.success){u.error(`\u274C Erro ao gerar commit: ${c.error}`),i=i.filter(r=>!n.includes(r));continue}if(!c.suggestion){u.error("\u274C Nenhuma sugest\xE3o foi gerada"),i=i.filter(r=>!n.includes(r));continue}if(t.dryRun){u.info(`\u{1F50D} Dry Run - Mensagem para ${n.join(", ")}:`),u.info(`"${c.suggestion.message}"`),i=i.filter(r=>!n.includes(r));continue}if(o.yes){let r=n.length===1&&n[0]?await k(n[0],c.suggestion.message):await z(c.suggestion.message);S(r.success,r.hash,r.error)}else{let r=await N(c.suggestion);if(r.action==="commit"){let l=n.length===1&&n[0]?await k(n[0],c.suggestion.message):await z(c.suggestion.message);S(l.success,l.hash,l.error)}else if(r.action==="edit"){let l=await L(c.suggestion.message);if(l.action==="commit"&&l.message){let m=n.length===1&&n[0]?await k(n[0],l.message):await z(l.message);S(m.success,m.hash,m.error)}}else if(r.action==="copy")await U(c.suggestion.message),o.silent||u.info("\u{1F3AF} Mensagem copiada para clipboard");else if(r.action==="cancel"){R();return}}if(i=i.filter(r=>!n.includes(r)),i.length>0&&!o.yes&&!await Y(i))break}o.silent||u.success("\u2705 Modo Split conclu\xEDdo!")}var se=A(()=>{"use strict";f();pe();w();W();O();ee();Re();ie()});f();se();import{intro as ct,outro as mt,log as lt}from"@clack/prompts";f();f();import{readFileSync as at}from"fs";import{join as re}from"path";function Ie(){try{let e=[re(process.cwd(),"package.json"),re(process.cwd(),"..","package.json"),re(C,"..","..","package.json")];for(let t of e)try{let o=at(t,"utf-8"),i=JSON.parse(o);if(i.name==="@gilbert_oliveira/commit-wizard")return i.version}catch{continue}throw new Error("Package.json n\xE3o encontrado")}catch{return console.warn("\u26A0\uFE0F N\xE3o foi poss\xEDvel ler a vers\xE3o do package.json, usando vers\xE3o padr\xE3o"),"0.0.0"}}function je(e){return{silent:e.includes("--silent")||e.includes("-s"),yes:e.includes("--yes")||e.includes("-y"),auto:e.includes("--auto")||e.includes("-a"),split:e.includes("--split"),smartSplit:e.includes("--smart-split"),dryRun:e.includes("--dry-run")||e.includes("-n"),help:e.includes("--help")||e.includes("-h"),version:e.includes("--version")||e.includes("-v")}}function ke(){console.log(`
114
+ ... (diff total truncado)`:i}async function oe(e,t,o){o.silent||g.info("\u{1F9E0} Modo Smart Split ativado - Agrupando arquivos por contexto"),o.silent||g.info("\u{1F916} Analisando contexto das mudan\xE7as...");let i=await et(e.stagedFiles,e.diff,t);if(!i.success){o.silent||g.error(`\u274C Erro na an\xE1lise de contexto: ${i.error}`);return}if(!i.groups||i.groups.length===0){o.silent||g.error("\u274C Nenhum grupo foi criado pela an\xE1lise");return}if(o.silent||(g.success(`\u2705 ${i.groups.length} grupo(s) identificado(s):`),i.groups.forEach((n,s)=>{g.info(` ${s+1}. ${n.name} (${n.files.length} arquivo(s))`),g.info(` \u{1F4C4} ${n.files.join(", ")}`)})),!o.yes&&!o.silent){let{showSmartSplitGroups:n}=await Promise.resolve().then(()=>(ee(),Ae)),s=await n(i.groups);if(s.action==="cancel"){o.silent||g.info("\u274C Opera\xE7\xE3o cancelada pelo usu\xE1rio");return}if(s.action==="manual"){let a={...o,split:!0,smartSplit:!1},{main:c}=await Promise.resolve().then(()=>(se(),Ge));await c(a);return}}for(let n=0;n<i.groups.length;n++){let s=i.groups[n];if(!s){o.silent||g.error(`\u274C Grupo ${n+1} \xE9 undefined`);continue}o.silent||g.info(`
115
+ \u{1F504} Processando grupo ${n+1}/${i.groups.length}: ${s.name}`);let a=await tt(s);if(!a){o.silent||(g.warn(`\u26A0\uFE0F Nenhum diff encontrado para o grupo: ${s.name}`),g.info(` \u{1F4C4} Arquivos: ${s.files.join(", ")}`),g.info(" \u{1F4A1} Poss\xEDvel causa: arquivos novos, deletados/recriados, ou sem mudan\xE7as"));continue}o.silent||g.info(`\u{1F916} Gerando commit para: ${s.name}`);let{generateWithRetry:c}=await Promise.resolve().then(()=>(W(),Se)),r=await c(a,t,s.files);if(!r.success){o.silent||g.error(`\u274C Erro ao gerar commit para ${s.name}: ${r.error}`);continue}if(!r.suggestion){o.silent||g.error(`\u274C Nenhuma sugest\xE3o gerada para ${s.name}`);continue}if(t.dryRun){o.silent||(g.info(`\u{1F50D} Dry Run - Grupo: ${s.name}`),g.info(`\u{1F4C4} Arquivos: ${s.files.join(", ")}`),g.info(`\u{1F4AD} Mensagem: "${r.suggestion.message}"`));continue}if(o.yes){let{executeFileCommit:l}=await Promise.resolve().then(()=>(w(),M)),m;if(s.files.length===1&&s.files[0])m=l(s.files[0],r.suggestion.message||"");else{let{execSync:p}=await import("child_process"),{escapeShellArg:h}=await Promise.resolve().then(()=>(w(),M));try{let S=s.files.map(x=>h(x)).join(" "),y=h(r.suggestion.message||"");p(`git commit ${S} -m ${y}`,{stdio:"pipe"}),m={success:!0,hash:p("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:r.suggestion.message||""}}catch(S){m={success:!1,error:S instanceof Error?S.message:"Erro desconhecido ao executar commit"}}}C(m.success,m.hash,m.error)}else{let{showCommitPreview:l,editCommitMessage:m,copyToClipboard:p,showCancellation:h}=await Promise.resolve().then(()=>(O(),Q));switch((await l(r.suggestion)).action){case"commit":{let{executeFileCommit:y}=await Promise.resolve().then(()=>(w(),M)),d,x=r.suggestion.message||"Atualiza\xE7\xE3o de arquivos";if(s.files.length===1&&s.files[0])d=y(s.files[0],x);else{let{execSync:G}=await import("child_process"),{escapeShellArg:I}=await Promise.resolve().then(()=>(w(),M));try{let $=s.files.map(V=>I(V)).join(" "),_=I(x);G(`git commit ${$} -m ${_}`,{stdio:"pipe"}),d={success:!0,hash:G("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:x}}catch($){d={success:!1,error:$ instanceof Error?$.message:"Erro desconhecido ao executar commit"}}}C(d.success,d.hash,d.error);break}case"edit":{let y=await m(r.suggestion.message);if(y.action==="commit"&&y.message){let{executeFileCommit:d}=await Promise.resolve().then(()=>(w(),M)),x;if(s.files.length===1&&s.files[0])x=d(s.files[0],y.message||"");else{let{execSync:G}=await import("child_process"),{escapeShellArg:I}=await Promise.resolve().then(()=>(w(),M));try{let $=s.files.map(V=>I(V)).join(" "),_=I(y.message||"");G(`git commit ${$} -m ${_}`,{stdio:"pipe"}),x={success:!0,hash:G("git rev-parse HEAD",{encoding:"utf-8",stdio:"pipe"}).trim(),message:y.message||""}}catch($){x={success:!1,error:$ instanceof Error?$.message:"Erro desconhecido ao executar commit"}}}C(x.success,x.hash,x.error)}break}case"copy":{await p(r.suggestion.message),o.silent||g.info("\u{1F3AF} Mensagem copiada para clipboard");break}case"cancel":{h();return}}}if(n<i.groups.length-1&&!o.yes){let{askContinueCommits:l}=await Promise.resolve().then(()=>(O(),Q)),m=i.groups.slice(n+1).filter(h=>h!==void 0).map(h=>h.name);if(!await l(m))break}}o.silent||g.success("\u2705 Smart Split conclu\xEDdo!")}var Re=A(()=>{"use strict";f();ie();O()});var Ge={};j(Ge,{main:()=>ne});import{log as u}from"@clack/prompts";async function ne(e={silent:!1,yes:!1,auto:!1,split:!1,smartSplit:!1,dryRun:!1,help:!1,version:!1}){e.silent||u.info("\u{1F680} Commit Wizard iniciado!"),H()||(u.error("\u274C N\xE3o foi encontrado um reposit\xF3rio Git neste diret\xF3rio."),e.silent||u.info("\u{1F4A1} Execute o comando em um diret\xF3rio com reposit\xF3rio Git inicializado."),process.exit(1)),e.silent||u.info("\u2699\uFE0F Carregando configura\xE7\xE3o...");let t=ue();Me(t),e.split&&(t.splitCommits=!0),e.dryRun&&(t.dryRun=!0);let o=fe(t);o.length>0&&(u.error("\u274C Erros na configura\xE7\xE3o:"),o.forEach(a=>u.error(` \u2022 ${a}`)),process.exit(1)),e.silent||u.success(`\u2705 Configura\xE7\xE3o carregada (modelo: ${t.openai.model}, idioma: ${t.language})`),e.silent||u.info("\u{1F4CB} Verificando arquivos staged...");let i=J();i.hasStaged||(u.warn("\u26A0\uFE0F Nenhum arquivo foi encontrado no stage."),e.silent||u.info("\u{1F4A1} Use `git add <arquivo>` para adicionar arquivos ao stage antes de gerar o commit."),process.exit(0));let n=K();if(e.silent||(u.success(`\u2705 Encontrados ${i.stagedFiles.length} arquivo(s) staged:`),i.stagedFiles.forEach(a=>u.info(` \u{1F4C4} ${a}`)),u.info(`\u{1F4CA} Estat\xEDsticas: +${n.added} -${n.removed} linhas`)),t.splitCommits||e.smartSplit){if(e.yes)return await oe(i,t,e);switch((await X()).action){case"proceed":return await oe(i,t,e);case"manual":return await it(i,t,e);case"cancel":R();return}}e.silent||u.info("\u{1F916} Gerando mensagem de commit com IA...");let s=await q(i.diff,t,i.stagedFiles);if(s.success||(u.error(`\u274C Erro ao gerar commit: ${s.error}`),process.exit(1)),s.suggestion||(u.error("\u274C Nenhuma sugest\xE3o foi gerada"),process.exit(1)),e.silent||u.success("\u2728 Mensagem de commit gerada!"),t.dryRun){u.info("\u{1F50D} Modo Dry Run - Mensagem gerada:"),u.info(`"${s.suggestion.message}"`),u.info("\u{1F4A1} Execute sem --dry-run para fazer o commit");return}if(e.yes){let a=z(s.suggestion.message);C(a.success,a.hash,a.error);return}for(;;)switch((await N(s.suggestion)).action){case"commit":{let c=z(s.suggestion.message);C(c.success,c.hash,c.error);return}case"edit":{let c=await L(s.suggestion.message);if(c.action==="cancel"){R();return}if(c.action==="commit"&&c.message){let r=z(c.message);C(r.success,r.hash,r.error);return}break}case"copy":{await U(s.suggestion.message),e.silent||u.info('\u{1F3AF} Voc\xEA pode usar a mensagem copiada com: git commit -m "mensagem"');return}case"cancel":{R();return}}}async function it(e,t,o){o.silent||u.info("\u{1F504} Modo Split ativado - Commits separados por arquivo");let i=[...e.stagedFiles];for(;i.length>0;){let n=o.yes?[i[0]]:await B(i);if(n.length===0){o.silent||u.info("\u274C Nenhum arquivo selecionado");break}let{getFileDiff:s}=await Promise.resolve().then(()=>(w(),M)),a=n.filter(r=>r!==void 0).map(r=>{try{return s(r)}catch(l){return u.error(`\u274C Erro ao obter diff do arquivo ${r}: ${l instanceof Error?l.message:"Erro desconhecido"}`),""}}).filter(r=>r.length>0).join(`
116
+ `);if(!a){o.silent||u.warn("\u26A0\uFE0F Nenhum diff encontrado para os arquivos selecionados"),i=i.filter(r=>!n.includes(r));continue}o.silent||u.info(`\u{1F916} Gerando commit para: ${n.join(", ")}`);let c=await q(a,t,n.filter(r=>r!==void 0));if(!c.success){u.error(`\u274C Erro ao gerar commit: ${c.error}`),i=i.filter(r=>!n.includes(r));continue}if(!c.suggestion){u.error("\u274C Nenhuma sugest\xE3o foi gerada"),i=i.filter(r=>!n.includes(r));continue}if(t.dryRun){u.info(`\u{1F50D} Dry Run - Mensagem para ${n.join(", ")}:`),u.info(`"${c.suggestion.message}"`),i=i.filter(r=>!n.includes(r));continue}if(o.yes){let r=n.length===1&&n[0]?await k(n[0],c.suggestion.message):await z(c.suggestion.message);C(r.success,r.hash,r.error)}else{let r=await N(c.suggestion);if(r.action==="commit"){let l=n.length===1&&n[0]?await k(n[0],c.suggestion.message):await z(c.suggestion.message);C(l.success,l.hash,l.error)}else if(r.action==="edit"){let l=await L(c.suggestion.message);if(l.action==="commit"&&l.message){let m=n.length===1&&n[0]?await k(n[0],l.message):await z(l.message);C(m.success,m.hash,m.error)}}else if(r.action==="copy")await U(c.suggestion.message),o.silent||u.info("\u{1F3AF} Mensagem copiada para clipboard");else if(r.action==="cancel"){R();return}}if(i=i.filter(r=>!n.includes(r)),i.length>0&&!o.yes&&!await Y(i))break}o.silent||u.success("\u2705 Modo Split conclu\xEDdo!")}var se=A(()=>{"use strict";f();pe();w();W();O();ee();Re();ie()});f();se();import{intro as rt,outro as at,log as ct}from"@clack/prompts";f();f();import{readFileSync as ot}from"fs";import{join as re,dirname as st}from"path";import{fileURLToPath as nt}from"url";function Ie(){try{let e=nt(import.meta.url),t=st(e),o=[re(t,"..","package.json"),re(t,"..","..","package.json"),re(process.cwd(),"package.json")];for(let i of o)try{let n=ot(i,"utf-8"),s=JSON.parse(n);if(s.name==="@gilbert_oliveira/commit-wizard")return s.version}catch{continue}throw new Error("Package.json n\xE3o encontrado")}catch{return console.warn("\u26A0\uFE0F N\xE3o foi poss\xEDvel ler a vers\xE3o do package.json, usando vers\xE3o padr\xE3o"),"0.0.0"}}function je(e){return{silent:e.includes("--silent")||e.includes("-s"),yes:e.includes("--yes")||e.includes("-y"),auto:e.includes("--auto")||e.includes("-a"),split:e.includes("--split"),smartSplit:e.includes("--smart-split"),dryRun:e.includes("--dry-run")||e.includes("-n"),help:e.includes("--help")||e.includes("-h"),version:e.includes("--version")||e.includes("-v")}}function ke(){console.log(`
117
117
  \u{1F9D9}\u200D\u2642\uFE0F Commit Wizard - Gerador inteligente de mensagens de commit
118
118
 
119
119
  USAGE:
@@ -138,4 +138,4 @@ EXAMPLES:
138
138
  commit-wizard --auto # Modo totalmente autom\xE1tico
139
139
 
140
140
  Para mais informa\xE7\xF5es, visite: https://github.com/user/commit-wizard
141
- `)}function Oe(){let e=Ie();console.log(`commit-wizard v${e}`)}async function ut(){try{let e=je(process.argv.slice(2));e.help&&(ke(),process.exit(0)),e.version&&(Oe(),process.exit(0)),e.auto&&(e.silent=!0,e.yes=!0),e.silent||ct("\u{1F9D9}\u200D\u2642\uFE0F Commit Wizard"),await ne(e),e.silent||mt("At\xE9 logo! \u2728")}catch(e){lt.error(`Erro: ${e instanceof Error?e.message:"Erro desconhecido"}`),process.exit(1)}}ut();
141
+ `)}function Oe(){let e=Ie();console.log(`commit-wizard v${e}`)}async function mt(){try{let e=je(process.argv.slice(2));e.help&&(ke(),process.exit(0)),e.version&&(Oe(),process.exit(0)),e.auto&&(e.silent=!0,e.yes=!0),e.silent||rt("\u{1F9D9}\u200D\u2642\uFE0F Commit Wizard"),await ne(e),e.silent||at("At\xE9 logo! \u2728")}catch(e){ct.error(`Erro: ${e instanceof Error?e.message:"Erro desconhecido"}`),process.exit(1)}}mt();
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "displayName": "Commit Wizard",
4
4
  "publisher": "gilbert-oliveira",
5
5
  "description": "CLI inteligente para gerar mensagens de commit usando OpenAI",
6
- "version": "2.12.1",
6
+ "version": "2.12.3-canary.1",
7
7
  "categories": [
8
8
  "Other",
9
9
  "SCM Providers"
@@ -1,19 +1,24 @@
1
1
  import { readFileSync } from 'fs';
2
- import { join } from 'path';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
3
4
 
4
5
  /**
5
6
  * Lê a versão do package.json dinamicamente
6
7
  */
7
8
  export function getVersion(): string {
8
9
  try {
10
+ // Resolver __dirname de forma compatível com ESM e CJS
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+
9
14
  // Tentar diferentes caminhos para encontrar o package.json
10
15
  const possiblePaths = [
11
- // Caminho relativo ao arquivo atual (para desenvolvimento)
12
- join(process.cwd(), 'package.json'),
13
- // Caminho relativo ao binário compilado (para produção)
14
- join(process.cwd(), '..', 'package.json'),
15
- // Caminho absoluto baseado no __dirname
16
+ // Caminho absoluto baseado no __dirname (prioridade máxima - para instalação global)
17
+ join(__dirname, '..', 'package.json'),
18
+ // Fallback para estrutura de desenvolvimento/build alternativa
16
19
  join(__dirname, '..', '..', 'package.json'),
20
+ // Último recurso: diretório atual
21
+ join(process.cwd(), 'package.json'),
17
22
  ];
18
23
 
19
24
  for (const packagePath of possiblePaths) {