lazycommitt 1.0.14 → 1.0.15

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.
Files changed (2) hide show
  1. package/dist/cli.mjs +41 -35
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- var we=Object.defineProperty;var l=(t,e)=>we(t,"name",{value:e,configurable:!0});import{command as B,cli as $e}from"cleye";import{readFileSync as be}from"fs";import{fileURLToPath as q,pathToFileURL as ve}from"url";import G,{dirname as ke,join as Ae}from"path";import{execa as k}from"execa";import{dim as O,bgCyan as J,black as X,green as _,red as F}from"kolorist";import{intro as V,spinner as D,outro as x,confirm as Z,isCancel as Y,select as xe}from"@clack/prompts";import $ from"fs/promises";import Pe from"os";import ee from"ini";import te from"groq-sdk";var Ce="1.0.14",_e={version:Ce};const Q=class Q extends Error{};l(Q,"KnownError");let w=Q;const z=" ",T=l(t=>{t instanceof Error&&!(t instanceof w)&&(t.stack&&console.error(O(t.stack.split(`
2
+ var Ce=Object.defineProperty;var l=(t,e)=>Ce(t,"name",{value:e,configurable:!0});import{command as se,cli as Pe}from"cleye";import{readFileSync as _e}from"fs";import{fileURLToPath as ie,pathToFileURL as De}from"url";import N,{dirname as Se,join as We}from"path";import{execa as x}from"execa";import{dim as F,bgCyan as oe,black as ne,green as W,red as T}from"kolorist";import{intro as ae,spinner as E,outro as v,confirm as I,isCancel as P,text as L,select as ue}from"@clack/prompts";import A from"fs/promises";import Ee from"os";import ce from"ini";import re from"groq-sdk";var Ie="1.0.15",Me={version:Ie};const q=class q extends Error{};l(q,"KnownError");let b=q;const U=" ",R=l(t=>{t instanceof Error&&!(t instanceof b)&&(t.stack&&console.error(F(t.stack.split(`
3
3
  `).slice(1).join(`
4
4
  `))),console.error(`
5
- ${z}${O(`lazycommit v${_e.version}`)}`),console.error(`
6
- ${z}Please open a Bug report with the information above:`),console.error(`${z}https://github.com/KartikLabhshetwar/lazycommit/issues/new/choose`))},"handleCliError"),se=l(async()=>{const{stdout:t,failed:e}=await k("git",["rev-parse","--show-toplevel"],{reject:!1});if(e)throw new w("The current directory must be a Git repository!");return t},"assertGitRepo"),M=l(t=>`:(exclude)${t}`,"excludeFromDiff"),N=["package-lock.json","pnpm-lock.yaml","node_modules/**","dist/**","build/**",".next/**","coverage/**",".nyc_output/**","*.log","*.tmp","*.temp","*.cache",".DS_Store","Thumbs.db","*.min.js","*.min.css","*.bundle.js","*.bundle.css","*.lock"].map(M),oe=l(async t=>{const e=["diff","--cached","--diff-algorithm=minimal"],{stdout:s}=await k("git",[...e,"--name-only",...N,...t?t.map(M):[]]);if(!s)return;const{stdout:i}=await k("git",[...e,...N,...t?t.map(M):[]]);return{files:s.split(`
7
- `),diff:i}},"getStagedDiff"),ie=l(t=>`Detected ${t.length.toLocaleString()} staged file${t.length>1?"s":""}`,"getDetectedMessage"),ne=l(async t=>{const e=["diff","--cached","--diff-algorithm=minimal"],{stdout:s}=await k("git",[...e,"--name-only",...N,...t?t.map(M):[]]);if(!s)return null;const i=s.split(`
8
- `).filter(Boolean),o=await Promise.all(i.map(async n=>{try{const{stdout:u}=await k("git",[...e,"--numstat","--",n]),[a,r]=u.split(" ").slice(0,2).map(Number);return{file:n,additions:a||0,deletions:r||0,changes:(a||0)+(r||0)}}catch{return{file:n,additions:0,deletions:0,changes:0}}}));return{files:i,fileStats:o,totalChanges:o.reduce((n,u)=>n+u.changes,0)}},"getDiffSummary"),ue=l(async(t,e=20)=>{const s=await ne(t);if(!s)return null;const{fileStats:i}=s,o=[...i].sort((p,m)=>m.changes-p.changes),n=o.slice(0,Math.max(1,e)),u=s.files.length,a=s.totalChanges,r=i.reduce((p,m)=>p+(m.additions||0),0),h=i.reduce((p,m)=>p+(m.deletions||0),0),y=[];y.push(`Files changed: ${u}`),y.push(`Additions: ${r}, Deletions: ${h}, Total changes: ${a}`),y.push("Top files by changes:");for(const p of n)y.push(`- ${p.file} (+${p.additions} / -${p.deletions}, ${p.changes} changes)`);return o.length>n.length&&y.push(`\u2026and ${o.length-n.length} more files`),y.join(`
9
- `)},"buildCompactSummary"),ae=l(t=>$.lstat(t).then(()=>!0,()=>!1),"fileExists"),De=["","conventional"],{hasOwnProperty:We}=Object.prototype,re=l((t,e)=>We.call(t,e),"hasOwn"),v=l((t,e,s)=>{if(!e)throw new w(`Invalid config property ${t}: ${s}`)},"parseAssert"),E={GROQ_API_KEY(t){if(!t)throw new w("Please set your Groq API key via `lazycommit config set GROQ_API_KEY=<your token>`");return v("GROQ_API_KEY",t.startsWith("gsk_"),'Must start with "gsk_"'),t},locale(t){return t?(v("locale",t,"Cannot be empty"),v("locale",/^[a-z-]+$/i.test(t),"Must be a valid locale (letters and dashes/underscores). You can consult the list of codes in: https://wikipedia.org/wiki/List_of_ISO_639-1_codes"),t):"en"},generate(t){if(!t)return 1;v("generate",/^\d+$/.test(t),"Must be an integer");const e=Number(t);return v("generate",e>0,"Must be greater than 0"),v("generate",e<=5,"Must be less or equal to 5"),e},type(t){return t?(v("type",De.includes(t),"Invalid commit type"),t):""},proxy(t){if(!(!t||t.length===0))return v("proxy",/^https?:\/\//.test(t),"Must be a valid URL"),t},model(t){return!t||t.length===0?"openai/gpt-oss-20b":t},timeout(t){if(!t)return 1e4;v("timeout",/^\d+$/.test(t),"Must be an integer");const e=Number(t);return v("timeout",e>=500,"Must be greater than 500ms"),e},"max-length"(t){if(!t)return 50;v("max-length",/^\d+$/.test(t),"Must be an integer");const e=Number(t);return v("max-length",e>=20,"Must be greater than 20 characters"),e}},L=G.join(Pe.homedir(),".lazycommit"),ce=l(async()=>{if(!await ae(L))return Object.create(null);const e=await $.readFile(L,"utf8");return ee.parse(e)},"readConfigFile"),U=l(async(t,e)=>{const s=await ce(),i={};for(const o of Object.keys(E)){const n=E[o],u=t?.[o]??s[o];if(e)try{i[o]=n(u)}catch{}else i[o]=n(u)}return i},"getConfig"),Se=l(async t=>{const e=await ce();for(const[s,i]of t){if(!re(E,s))throw new w(`Invalid config property: ${s}`);const o=E[s](i);e[s]=o}await $.writeFile(L,ee.stringify(e),"utf8")},"setConfigs"),Ie={"":"<commit message>",conventional:"<type>(<optional scope>): <commit message>"},le={"":"",conventional:`Choose the most appropriate type from the following categories that best describes the git diff:
5
+ ${U}${F(`lazycommit v${Me.version}`)}`),console.error(`
6
+ ${U}Please open a Bug report with the information above:`),console.error(`${U}https://github.com/KartikLabhshetwar/lazycommit/issues/new/choose`))},"handleCliError"),le=l(async()=>{const{stdout:t,failed:e}=await x("git",["rev-parse","--show-toplevel"],{reject:!1});if(e)throw new b("The current directory must be a Git repository!");return t},"assertGitRepo"),G=l(t=>`:(exclude)${t}`,"excludeFromDiff"),H=["package-lock.json","node_modules/**","dist/**","build/**",".next/**","coverage/**",".nyc_output/**","*.log","*.tmp","*.temp","*.cache",".DS_Store","Thumbs.db","*.min.js","*.min.css","*.bundle.js","*.bundle.css","*.lock"].map(G),me=l(async t=>{const e=["diff","--cached","--diff-algorithm=minimal"],{stdout:s}=await x("git",[...e,"--name-only",...H,...t?t.map(G):[]]);if(!s)return;const{stdout:o}=await x("git",[...e,...H,...t?t.map(G):[]]);return{files:s.split(`
7
+ `),diff:o}},"getStagedDiff"),de=l(t=>`Detected ${t.length.toLocaleString()} staged file${t.length>1?"s":""}`,"getDetectedMessage"),fe=l(async t=>{const e=["diff","--cached","--diff-algorithm=minimal"],{stdout:s}=await x("git",[...e,"--name-only",...H,...t?t.map(G):[]]);if(!s)return null;const o=s.split(`
8
+ `).filter(Boolean),i=await Promise.all(o.map(async n=>{try{const{stdout:a}=await x("git",[...e,"--numstat","--",n]),[c,r]=a.split(" ").slice(0,2).map(Number);return{file:n,additions:c||0,deletions:r||0,changes:(c||0)+(r||0)}}catch{return{file:n,additions:0,deletions:0,changes:0}}}));return{files:o,fileStats:i,totalChanges:i.reduce((n,a)=>n+a.changes,0)}},"getDiffSummary"),ge=l(async(t,e=20)=>{const s=await fe(t);if(!s)return null;const{fileStats:o}=s,i=[...o].sort((g,m)=>m.changes-g.changes),n=i.slice(0,Math.max(1,e)),a=s.files.length,c=s.totalChanges,r=o.reduce((g,m)=>g+(m.additions||0),0),y=o.reduce((g,m)=>g+(m.deletions||0),0),w=[];w.push(`Files changed: ${a}`),w.push(`Additions: ${r}, Deletions: ${y}, Total changes: ${c}`),w.push("Top files by changes:");for(const g of n)w.push(`- ${g.file} (+${g.additions} / -${g.deletions}, ${g.changes} changes)`);return i.length>n.length&&w.push(`\u2026and ${i.length-n.length} more files`),w.join(`
9
+ `)},"buildCompactSummary"),pe=l(t=>A.lstat(t).then(()=>!0,()=>!1),"fileExists"),je=["","conventional"],{hasOwnProperty:Oe}=Object.prototype,he=l((t,e)=>Oe.call(t,e),"hasOwn"),k=l((t,e,s)=>{if(!e)throw new b(`Invalid config property ${t}: ${s}`)},"parseAssert"),Y={GROQ_API_KEY(t){if(!t)throw new b("Please set your Groq API key via `lazycommit config set GROQ_API_KEY=<your token>`");return k("GROQ_API_KEY",t.startsWith("gsk_"),'Must start with "gsk_"'),t},locale(t){return t?(k("locale",t,"Cannot be empty"),k("locale",/^[a-z-]+$/i.test(t),"Must be a valid locale (letters and dashes/underscores). You can consult the list of codes in: https://wikipedia.org/wiki/List_of_ISO_639-1_codes"),t):"en"},generate(t){if(!t)return 1;k("generate",/^\d+$/.test(t),"Must be an integer");const e=Number(t);return k("generate",e>0,"Must be greater than 0"),k("generate",e<=5,"Must be less or equal to 5"),e},type(t){return t?(k("type",je.includes(t),"Invalid commit type"),t):""},proxy(t){if(!(!t||t.length===0))return k("proxy",/^https?:\/\//.test(t),"Must be a valid URL"),t},model(t){return!t||t.length===0?"openai/gpt-oss-20b":t},timeout(t){if(!t)return 1e4;k("timeout",/^\d+$/.test(t),"Must be an integer");const e=Number(t);return k("timeout",e>=500,"Must be greater than 500ms"),e},"max-length"(t){if(!t)return 50;k("max-length",/^\d+$/.test(t),"Must be an integer");const e=Number(t);return k("max-length",e>=20,"Must be greater than 20 characters"),e}},Q=N.join(Ee.homedir(),".lazycommit"),ye=l(async()=>{if(!await pe(Q))return Object.create(null);const e=await A.readFile(Q,"utf8");return ce.parse(e)},"readConfigFile"),K=l(async(t,e)=>{const s=await ye(),o={};for(const i of Object.keys(Y)){const n=Y[i],a=t?.[i]??s[i];if(e)try{o[i]=n(a)}catch{}else o[i]=n(a)}return o},"getConfig"),Fe=l(async t=>{const e=await ye();for(const[s,o]of t){if(!he(Y,s))throw new b(`Invalid config property: ${s}`);const i=Y[s](o);e[s]=i}await A.writeFile(Q,ce.stringify(e),"utf8")},"setConfigs"),Te={"":"<commit message>",conventional:"<type>(<optional scope>): <commit message>"},we={"":"",conventional:`Choose the most appropriate type from the following categories that best describes the git diff:
10
10
 
11
11
  ${JSON.stringify({feat:"A new feature for the user",fix:"A bug fix",docs:"Documentation only changes",style:"Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)",refactor:"A code change that neither fixes a bug nor adds a feature",perf:"A code change that improves performance",test:"Adding missing tests or correcting existing tests",build:"Changes that affect the build system or external dependencies",ci:"Changes to our CI configuration files and scripts",chore:"Other changes that don't modify src or test files",revert:"Reverts a previous commit"},null,2)}
12
12
 
13
- IMPORTANT: Use the exact type name from the list above.`},je=l((t,e,s)=>`You are an expert software engineer and git commit message writer. Your task is to analyze git diffs and generate clear, concise, and professional commit messages.
13
+ IMPORTANT: Use the exact type name from the list above.`},Re=l((t,e,s)=>`You are an expert software engineer and git commit message writer. Your task is to analyze git diffs and generate clear, concise, and professional commit messages.
14
14
 
15
15
  ## Instructions:
16
16
  1. Analyze the provided git diff carefully
@@ -31,11 +31,11 @@ IMPORTANT: Use the exact type name from the list above.`},je=l((t,e,s)=>`You are
31
31
 
32
32
  ## Language: ${t}
33
33
  ## Maximum length: ${e} characters
34
- ## Output format: ${Ie[s]||"<commit message>"}
34
+ ## Output format: ${Te[s]||"<commit message>"}
35
35
 
36
- ${le[s]?`
36
+ ${we[s]?`
37
37
  ## Commit Type Guidelines:
38
- ${le[s]}`:""}
38
+ ${we[s]}`:""}
39
39
 
40
40
  ## Examples of good commit messages:
41
41
  - feat: Add user authentication with JWT tokens
@@ -52,21 +52,21 @@ ${le[s]}`:""}
52
52
  - WIP
53
53
  - Stuff
54
54
 
55
- Remember: Your response will be used directly as the git commit message. Do NOT wrap the message in quotes. Make it professional and informative.`,"generatePrompt"),Oe=l(async(t,e,s,i,o,n,u,a,r,h,y)=>{const p=new te({apiKey:t,timeout:h});try{return r>1?{choices:(await Promise.all(Array.from({length:r},()=>p.chat.completions.create({model:e,messages:s,temperature:i,top_p:o,frequency_penalty:n,presence_penalty:u,max_tokens:a,n:1})))).flatMap(d=>d.choices)}:await p.chat.completions.create({model:e,messages:s,temperature:i,top_p:o,frequency_penalty:n,presence_penalty:u,max_tokens:a,n:1})}catch(m){if(m instanceof te.APIError){let g=`Groq API Error: ${m.status} - ${m.name}`;throw m.message&&(g+=`
55
+ Remember: Your response will be used directly as the git commit message. Do NOT wrap the message in quotes. Make it professional and informative.`,"generatePrompt"),Ge=l(async(t,e,s,o,i,n,a,c,r,y,w)=>{const g=new re({apiKey:t,timeout:y});try{return r>1?{choices:(await Promise.all(Array.from({length:r},()=>g.chat.completions.create({model:e,messages:s,temperature:o,top_p:i,frequency_penalty:n,presence_penalty:a,max_tokens:c,n:1})))).flatMap(d=>d.choices)}:await g.chat.completions.create({model:e,messages:s,temperature:o,top_p:i,frequency_penalty:n,presence_penalty:a,max_tokens:c,n:1})}catch(m){if(m instanceof re.APIError){let p=`Groq API Error: ${m.status} - ${m.name}`;throw m.message&&(p+=`
56
56
 
57
- ${m.message}`),m.status===500&&(g+=`
57
+ ${m.message}`),m.status===500&&(p+=`
58
58
 
59
- Check the API status: https://console.groq.com/status`),(m.status===413||m.message&&m.message.includes("rate_limit_exceeded"))&&(g+=`
59
+ Check the API status: https://console.groq.com/status`),(m.status===413||m.message&&m.message.includes("rate_limit_exceeded"))&&(p+=`
60
60
 
61
61
  \u{1F4A1} Tip: Your diff is too large. Try:
62
62
  1. Commit files in smaller batches
63
63
  2. Exclude large files with --exclude
64
64
  3. Use a different model with --model
65
- 4. Check if you have build artifacts staged (dist/, .next/, etc.)`),new w(g)}throw m.code==="ENOTFOUND"?new w(`Error connecting to ${m.hostname} (${m.syscall}). Are you connected to the internet?`):m}},"createChatCompletion"),me=l(t=>t.trim().replace(/^["']|["']\.?$/g,"").replace(/[\n\r]/g,"").replace(/(\w)\.$/,"$1"),"sanitizeMessage"),Fe=l(t=>Array.from(new Set(t)),"deduplicateMessages"),Te=["feat:","fix:","docs:","style:","refactor:","perf:","test:","build:","ci:","chore:","revert:"],Me=l((t,e)=>{const s=t.replace(/\s+/g," ").trim(),i=s.match(/\b(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)\b\s*:?\s+[^.\n]+/i);let o=i?i[0]:s.split(/[.!?]/)[0];const n=o.toLowerCase();for(const u of Te){const a=u.slice(0,-1);if(n.startsWith(a+" ")&&!n.startsWith(u)){o=a+": "+o.slice(a.length+1);break}}return o=me(o),o?(o.length>e&&(o=o.slice(0,e)),o):null},"deriveMessageFromReasoning"),W=l(async(t,e,s,i,o,n,u,a,r)=>{const h=`This is a compact summary of staged changes. Generate a single, concise commit message within ${n} characters that reflects the overall intent.
65
+ 4. Check if you have build artifacts staged (dist/, .next/, etc.)`),new b(p)}throw m.code==="ENOTFOUND"?new b(`Error connecting to ${m.hostname} (${m.syscall}). Are you connected to the internet?`):m}},"createChatCompletion"),$e=l(t=>t.trim().replace(/^["']|["']\.?$/g,"").replace(/[\n\r]/g,"").replace(/(\w)\.$/,"$1"),"sanitizeMessage"),Ye=l(t=>Array.from(new Set(t)),"deduplicateMessages"),ze=["feat:","fix:","docs:","style:","refactor:","perf:","test:","build:","ci:","chore:","revert:"],Ne=l((t,e)=>{const s=t.replace(/\s+/g," ").trim(),o=s.match(/\b(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)\b\s*:?\s+[^.\n]+/i);let i=o?o[0]:s.split(/[.!?]/)[0];const n=i.toLowerCase();for(const a of ze){const c=a.slice(0,-1);if(n.startsWith(c+" ")&&!n.startsWith(a)){i=c+": "+i.slice(c.length+1);break}}return i=$e(i),i?(i.length>e&&(i=i.slice(0,e)),i):null},"deriveMessageFromReasoning"),M=l(async(t,e,s,o,i,n,a,c,r)=>{const y=`This is a compact summary of staged changes. Generate a single, concise commit message within ${n} characters that reflects the overall intent.
66
66
 
67
- ${i}`,y=await Oe(t,e,[{role:"system",content:je(s,n,u)},{role:"user",content:h}],.7,1,0,0,Math.max(200,n*8),o,a),p=(y.choices||[]).map(g=>g.message?.content||"").map(g=>me(g)).filter(Boolean);if(p.length>0)return Fe(p);const m=y.choices.map(g=>g.message?.reasoning||"").filter(Boolean);for(const g of m){const d=Me(g,n);if(d)return[d]}return[]},"generateCommitMessageFromSummary"),Ee=l(t=>{const e=t.toLowerCase();return t.split("/"),e.endsWith(".md")||e.startsWith("docs/")||e.includes("/docs/")||e.includes("readme")||e.includes("changelog")||e.includes("license")||e.endsWith(".rst")||e.endsWith(".adoc")?{type:"docs",scope:void 0}:e.startsWith(".github/")||e.startsWith(".gitlab/")||(e.endsWith(".yml")||e.endsWith(".yaml"))&&(e.includes("workflow")||e.includes("pipeline")||e.includes("action")||e.includes("ci")||e.includes("deploy"))?{type:"ci",scope:void 0}:e.endsWith("package.json")||e.endsWith("pnpm-lock.yaml")||e.endsWith("yarn.lock")||e.endsWith("package-lock.json")||e.endsWith("tsconfig.json")||e.endsWith("jsconfig.json")||e.endsWith("vite.config.js")||e.endsWith("webpack.config.js")||e.endsWith("rollup.config.js")||e.endsWith("babel.config.js")||e.endsWith(".config.js")||e.endsWith(".config.ts")||e.endsWith("dockerfile")||e.endsWith("docker-compose.yml")||e.endsWith("makefile")||e.endsWith(".mk")||e.includes("webpack")||e.includes("rollup")||e.includes("vite")||e.includes("babel")||e.startsWith("config/")?{type:"build",scope:void 0}:e.includes("/test/")||e.includes("__tests__")||e.includes("/tests/")||e.match(/\.(test|spec)\.[jt]sx?$/)||e.includes(".test.")||e.includes(".spec.")||e.startsWith("test/")||e.startsWith("tests/")||e.includes("cypress/")||e.includes("jest/")||e.includes("vitest/")?{type:"test",scope:void 0}:e.includes("analytics")||e.includes("metrics")||e.includes("tracking")?{type:"feat",scope:"analytics"}:e.includes("auth")||e.includes("login")||e.includes("security")||e.includes("permission")||e.includes("role")?{type:"feat",scope:"auth"}:e.startsWith("app/api/")||e.includes("/api/")||e.includes("routes/")||e.includes("endpoint")||e.includes("handler")?{type:"feat",scope:"api"}:e.includes("database")||e.includes("/db/")||e.includes("migration")||e.includes("schema")||e.includes("model")||e.includes("entity")||e.endsWith(".sql")||e.includes("prisma/")?{type:"feat",scope:"db"}:e.includes("component")||e.includes("ui/")||e.includes("style")||e.endsWith(".css")||e.endsWith(".scss")||e.endsWith(".less")||e.endsWith(".styl")||e.includes("theme")?{type:"feat",scope:"ui"}:e.includes("util")||e.includes("helper")||e.includes("lib/")||e.includes("common/")||e.includes("shared/")?{type:"refactor",scope:"utils"}:e.startsWith("app/")||e.startsWith("src/app/")||e.includes("page")||e.includes("layout")||e.includes("route")?{type:"feat",scope:"app"}:e.startsWith("src/")?{type:"feat",scope:"core"}:{type:"chore",scope:void 0}},"classifyFile"),Re=l(t=>{const e=t.split("/");if(e.length>1)return e[0]},"topLevelScope"),Ge=l(t=>{const e=new Map;for(const o of t){const n=Ee(o),u=n.scope||Re(o),a=`${n.type}:${u||"general"}`,r=e.get(a)||{meta:{type:n.type,scope:u},files:[]};r.files.push(o),e.set(a,r)}const s=[];for(const{meta:o,files:n}of e.values()){const{type:u,scope:a}=o;let r="update files";u==="docs"?r="update documentation":u==="ci"?r="update CI workflows":u==="build"?r="update build/configuration":u==="test"?r="update tests":u==="feat"?r="add or update features":u==="chore"&&(r="maintenance updates");const h=a?`${r} in ${a}`:r;s.push({type:u,scope:a,title:h,files:n})}const i={feat:0,fix:1,refactor:2,perf:3,test:4,docs:5,build:6,ci:7,chore:8};return s.sort((o,n)=>(i[o.type]??99)-(i[n.type]??99)),s},"groupFiles"),Ye=l(t=>{const e=t.split("/");if(e.length>=4&&e[0]==="app"&&e[1]==="api")return e[2];if(e.length>=2)return e[1]},"getSecondLevelDir"),ze=l(async t=>{if(t.length===0)return"";const e=["diff","--cached","--numstat","--",...t],{stdout:s}=await k("git",e),i=[];let o=0,n=0;const u=s.split(`
68
- `).filter(Boolean);for(const r of u){const[h,y,p]=r.split(" "),m=Number(h)||0,g=Number(y)||0;o+=m,n+=g,i.push(`- ${p} (+${m} / -${g})`)}return[`Files: ${t.length}, Additions: ${o}, Deletions: ${n}`,...i.slice(0,25)].join(`
69
- `)},"summarizeFiles"),Ne=`\u2554\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2557
67
+ ${o}`,w=await Ge(t,e,[{role:"system",content:Re(s,n,a)},{role:"user",content:y}],.7,1,0,0,Math.max(200,n*8),i,c),g=(w.choices||[]).map(p=>p.message?.content||"").map(p=>$e(p)).filter(Boolean);if(g.length>0)return Ye(g);const m=w.choices.map(p=>p.message?.reasoning||"").filter(Boolean);for(const p of m){const d=Ne(p,n);if(d)return[d]}return[]},"generateCommitMessageFromSummary"),Le=l(t=>{const e=t.toLowerCase();return t.split("/"),e.endsWith(".md")||e.startsWith("docs/")||e.includes("/docs/")||e.includes("readme")||e.includes("changelog")||e.includes("license")||e.endsWith(".rst")||e.endsWith(".adoc")?{type:"docs",scope:void 0}:e.startsWith(".github/")||e.startsWith(".gitlab/")||(e.endsWith(".yml")||e.endsWith(".yaml"))&&(e.includes("workflow")||e.includes("pipeline")||e.includes("action")||e.includes("ci")||e.includes("deploy"))?{type:"ci",scope:void 0}:e.endsWith("package.json")||e.endsWith("pnpm-lock.yaml")||e.endsWith("yarn.lock")||e.endsWith("package-lock.json")||e.endsWith("tsconfig.json")||e.endsWith("jsconfig.json")||e.endsWith("vite.config.js")||e.endsWith("webpack.config.js")||e.endsWith("rollup.config.js")||e.endsWith("babel.config.js")||e.endsWith(".config.js")||e.endsWith(".config.ts")||e.endsWith("dockerfile")||e.endsWith("docker-compose.yml")||e.endsWith("makefile")||e.endsWith(".mk")||e.includes("webpack")||e.includes("rollup")||e.includes("vite")||e.includes("babel")||e.startsWith("config/")?{type:"build",scope:void 0}:e.includes("/test/")||e.includes("__tests__")||e.includes("/tests/")||e.match(/\.(test|spec)\.[jt]sx?$/)||e.includes(".test.")||e.includes(".spec.")||e.startsWith("test/")||e.startsWith("tests/")||e.includes("cypress/")||e.includes("jest/")||e.includes("vitest/")?{type:"test",scope:void 0}:e.includes("analytics")||e.includes("metrics")||e.includes("tracking")?{type:"feat",scope:"analytics"}:e.includes("auth")||e.includes("login")||e.includes("security")||e.includes("permission")||e.includes("role")?{type:"feat",scope:"auth"}:e.startsWith("app/api/")||e.includes("/api/")||e.includes("routes/")||e.includes("endpoint")||e.includes("handler")?{type:"feat",scope:"api"}:e.includes("database")||e.includes("/db/")||e.includes("migration")||e.includes("schema")||e.includes("model")||e.includes("entity")||e.endsWith(".sql")||e.includes("prisma/")?{type:"feat",scope:"db"}:e.includes("component")||e.includes("ui/")||e.includes("style")||e.endsWith(".css")||e.endsWith(".scss")||e.endsWith(".less")||e.endsWith(".styl")||e.includes("theme")?{type:"feat",scope:"ui"}:e.includes("util")||e.includes("helper")||e.includes("lib/")||e.includes("common/")||e.includes("shared/")?{type:"refactor",scope:"utils"}:e.startsWith("app/")||e.startsWith("src/app/")||e.includes("page")||e.includes("layout")||e.includes("route")?{type:"feat",scope:"app"}:e.startsWith("src/")?{type:"feat",scope:"core"}:{type:"chore",scope:void 0}},"classifyFile"),Ue=l(t=>{const e=t.split("/");if(e.length>1)return e[0]},"topLevelScope"),He=l(t=>{const e=new Map;for(const i of t){const n=Le(i),a=n.scope||Ue(i),c=`${n.type}:${a||"general"}`,r=e.get(c)||{meta:{type:n.type,scope:a},files:[]};r.files.push(i),e.set(c,r)}const s=[];for(const{meta:i,files:n}of e.values()){const{type:a,scope:c}=i;let r="update files";a==="docs"?r="update documentation":a==="ci"?r="update CI workflows":a==="build"?r="update build/configuration":a==="test"?r="update tests":a==="feat"?r="add or update features":a==="chore"&&(r="maintenance updates");const y=c?`${r} in ${c}`:r;s.push({type:a,scope:c,title:y,files:n})}const o={feat:0,fix:1,refactor:2,perf:3,test:4,docs:5,build:6,ci:7,chore:8};return s.sort((i,n)=>(o[i.type]??99)-(o[n.type]??99)),s},"groupFiles"),Qe=l(t=>{const e=t.split("/");if(e.length>=4&&e[0]==="app"&&e[1]==="api")return e[2];if(e.length>=2)return e[1]},"getSecondLevelDir"),Ke=l(async t=>{if(t.length===0)return"";const e=["diff","--cached","--numstat","--",...t],{stdout:s}=await x("git",e),o=[];let i=0,n=0;const a=s.split(`
68
+ `).filter(Boolean);for(const r of a){const[y,w,g]=r.split(" "),m=Number(y)||0,p=Number(w)||0;i+=m,n+=p,o.push(`- ${g} (+${m} / -${p})`)}return[`Files: ${t.length}, Additions: ${i}, Deletions: ${n}`,...o.slice(0,25)].join(`
69
+ `)},"summarizeFiles"),Be=`\u2554\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2557
70
70
  \u2502 \u2502
71
71
  \u2502 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2502
72
72
  \u2502 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D \u2502
@@ -75,28 +75,34 @@ ${i}`,y=await Oe(t,e,[{role:"system",content:je(s,n,u)},{role:"user",content:h}]
75
75
  \u2502 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2502
76
76
  \u2502 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u2502
77
77
  \u2502 \u2502
78
- \u255A\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u255D`;var Le=l(async(t,e,s,i,o,n)=>(async()=>{console.log(Ne),console.log(),V(J(X(" lazycommit "))),await se();const u=D();s&&await k("git",["add","--update"]),u.start("Detecting staged files");const a=await oe(e);if(!a)throw u.stop("Detecting staged files"),new w("No staged changes found. Stage your changes manually, or automatically stage all changes with the `--all` flag.");const r=await ne(e),h=a.diff.length>5e4,y=a.files.length>=5,p=r&&r.fileStats.some(c=>c.changes>500),m=h||y||p;if(m&&r){let c="Large diff detected";y?c="Many files detected":p&&(c="Large file changes detected"),u.stop(`${ie(a.files)} (${r.totalChanges.toLocaleString()} changes):
79
- ${a.files.map(b=>` ${b}`).join(`
78
+ \u255A\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u255D`;var qe=l(async(t,e,s,o,i,n)=>(async()=>{console.log(Be),console.log(),ae(oe(ne(" lazycommit "))),await le();const a=E();s&&await x("git",["add","--update"]),a.start("Detecting staged files");const c=await me(e);if(!c)throw a.stop("Detecting staged files"),new b("No staged changes found. Stage your changes manually, or automatically stage all changes with the `--all` flag.");const r=await fe(e),y=c.diff.length>5e4,w=c.files.length>=5,g=r&&r.fileStats.some(u=>u.changes>500),m=y||w||g;if(m&&r){let u="Large diff detected";w?u="Many files detected":g&&(u="Large file changes detected"),a.stop(`${de(c.files)} (${r.totalChanges.toLocaleString()} changes):
79
+ ${c.files.map(h=>` ${h}`).join(`
80
80
  `)}
81
81
 
82
- \u{1F3AF} ${c} - using smart grouping for better commit history`)}else u.stop(`${ie(a.files)}:
83
- ${a.files.map(c=>` ${c}`).join(`
84
- `)}`);const{env:g}=process,d=await U({GROQ_API_KEY:g.GROQ_API_KEY,proxy:g.https_proxy||g.HTTPS_PROXY||g.http_proxy||g.HTTP_PROXY,generate:t?.toString(),type:i?.toString()});if(o||m){let c=Ge(a.files);if(c.length===1&&c[0].files.length>=5){const b=new Map;for(const A of c[0].files){const f=Ye(A)||"general";b.set(f,[...b.get(f)||[],A])}c=Array.from(b.entries()).map(([A,f])=>({type:c[0].type,scope:A,title:`update files in ${A}`,files:f}))}if(c.length===1)x(`${O("Only one group detected, falling back to single commit...")}`),o=!1;else{const b=D();b.start(`Generating commit messages for ${c.length} groups`);try{for(const f of c){const P=await ze(f.files),I=`Generate a single conventional commit message for this group of files. Follow commitlint (type(scope): subject). Keep <= ${d["max-length"]} chars.
82
+ \u{1F3AF} ${u} - using smart grouping for better commit history`)}else a.stop(`${de(c.files)}:
83
+ ${c.files.map(u=>` ${u}`).join(`
84
+ `)}`);const{env:p}=process,d=await K({GROQ_API_KEY:p.GROQ_API_KEY,proxy:p.https_proxy||p.HTTPS_PROXY||p.http_proxy||p.HTTP_PROXY,generate:t?.toString(),type:o?.toString()});if(i||m){let u=He(c.files);if(u.length===1&&u[0].files.length>=5){const h=new Map;for(const $ of u[0].files){const f=Qe($)||"general";h.set(f,[...h.get(f)||[],$])}u=Array.from(h.entries()).map(([$,f])=>({type:u[0].type,scope:$,title:`update files in ${$}`,files:f}))}if(u.length===1)v(`${F("Only one group detected, falling back to single commit...")}`),i=!1;else{const h=E();h.start(`Generating commit messages for ${u.length} groups`);try{for(const f of u){const D=await Ke(f.files),j=`Generate a single conventional commit message for this group of files. Follow commitlint (type(scope): subject). Keep <= ${d["max-length"]} chars.
85
85
 
86
- ${P}`;try{const j=await W(d.GROQ_API_KEY,d.model,d.locale,I,1,d["max-length"],"conventional",d.timeout,d.proxy);if(j.length>0)f.message=j[0];else{const ye=f.scope?`(${f.scope})`:"";f.message=`${f.type}${ye}: ${f.title}`}}catch{const j=f.scope?`(${f.scope})`:"";f.message=`${f.type}${j}: ${f.title}`}}}finally{b.stop("Commit messages generated")}console.log(`
87
- \u{1F4CB} Commit Plan:`),c.forEach((f,P)=>{console.log(`
88
- ${P+1}. ${_(f.message)}`),console.log(` Files: ${f.files.join(", ")}`)});const A=await Z({message:`
89
- Proceed with ${c.length} commits?`});if(!A||Y(A)){x("Commits cancelled");return}for(let f=0;f<c.length;f++){const P=c[f],I=D();I.start(`Creating commit ${f+1}/${c.length}: ${P.message}`);try{await k("git",["reset","HEAD","--"]),await k("git",["add",...P.files]),await k("git",["commit","-m",P.message,...n])}finally{I.stop(`Commit ${f+1} created`)}}x(`${_("\u2714")} Successfully created ${c.length} commits!`);return}}const K=D();K.start("The AI is analyzing your changes");let C;try{const c=await ue(e,25);if(c)C=await W(d.GROQ_API_KEY,d.model,d.locale,c,d.generate,d["max-length"],d.type,d.timeout,d.proxy);else{const A=`Generate a commit message for these files: ${a.files.join(", ")}`;C=await W(d.GROQ_API_KEY,d.model,d.locale,A,d.generate,d["max-length"],d.type,d.timeout,d.proxy)}}finally{K.stop("Changes analyzed")}if(C.length===0)throw new w("No commit messages were generated. Try again.");let S;if(C.length===1){[S]=C;const c=await Z({message:`Use this commit message?
86
+ ${D}`;try{const C=await M(d.GROQ_API_KEY,d.model,d.locale,j,1,d["max-length"],"conventional",d.timeout,d.proxy);if(C.length>0)f.message=C[0];else{const O=f.scope?`(${f.scope})`:"";f.message=`${f.type}${O}: ${f.title}`}}catch{const C=f.scope?`(${f.scope})`:"";f.message=`${f.type}${C}: ${f.title}`}}}finally{h.stop("Commit messages generated")}console.log(`
87
+ \u{1F4CB} Commit Plan:`),u.forEach((f,D)=>{console.log(`
88
+ ${D+1}. ${W(f.message)}`),console.log(` Files: ${f.files.join(", ")}`)});const $=await I({message:`
89
+ Proceed with ${u.length} commits?`});if(!$||P($)){v("Commits cancelled");return}for(let f=0;f<u.length;f++){const D=u[f],j=E();j.start(`Creating commit ${f+1}/${u.length}: ${D.message}`);try{let C=D.message;const O=await I({message:`Edit commit ${f+1} message before committing?`});if(O&&!P(O)){const ee=await L({message:"Edit commit message:",initialValue:C,validate:l(te=>te&&te.trim().length>0?void 0:"Message cannot be empty","validate")});if(P(ee)){v("Commits cancelled");return}C=String(ee).trim(),D.message=C}const Z=await I({message:`Proceed with commit ${f+1}/${u.length} message?
90
90
 
91
- ${S}
92
- `});if(!c||Y(c)){x("Commit cancelled");return}}else{const c=await xe({message:`Pick a commit message to use: ${O("(Ctrl+c to exit)")}`,options:C.map(b=>({label:b,value:b}))});if(Y(c)){x("Commit cancelled");return}S=c}await k("git",["commit","-m",S,...n]),x(`${_("\u2714")} Successfully committed!`)})().catch(u=>{x(`${F("\u2716")} ${u.message}`),T(u),process.exit(1)}),"lazycommit");const[H,Ue]=process.argv.slice(2);var He=l(()=>(async()=>{if(!H)throw new w('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook');if(Ue)return;const t=await oe();if(!t)return;V(J(X(" lazycommit ")));const{env:e}=process,s=await U({GROQ_API_KEY:e.GROQ_API_KEY,proxy:e.https_proxy||e.HTTPS_PROXY||e.http_proxy||e.HTTP_PROXY}),i=D();i.start("The AI is analyzing your changes");let o;try{const h=await ue();if(h)o=await W(s.GROQ_API_KEY,s.model,s.locale,h,s.generate,s["max-length"],s.type,s.timeout,s.proxy);else{const p=`Generate a commit message for these files: ${t.files.join(", ")}`;o=await W(s.GROQ_API_KEY,s.model,s.locale,p,s.generate,s["max-length"],s.type,s.timeout,s.proxy)}}finally{i.stop("Changes analyzed")}const u=await $.readFile(H,"utf8")!=="",a=o.length>1;let r="";u&&(r=`# \u{1F916} AI generated commit${a?"s":""}
93
- `),a?(u&&(r+=`# Select one of the following messages by uncommeting:
91
+ ${C}
92
+ `});if(!Z||P(Z)){v("Commits cancelled");return}await x("git",["reset","HEAD","--"]),await x("git",["add",...D.files]),await x("git",["commit","-m",C,...n])}finally{j.stop(`Commit ${f+1} created`)}}v(`${W("\u2714")} Successfully created ${u.length} commits!`);return}}const J=E();J.start("The AI is analyzing your changes");let S;try{const u=await ge(e,25);if(u)S=await M(d.GROQ_API_KEY,d.model,d.locale,u,d.generate,d["max-length"],d.type,d.timeout,d.proxy);else{const $=`Generate a commit message for these files: ${c.files.join(", ")}`;S=await M(d.GROQ_API_KEY,d.model,d.locale,$,d.generate,d["max-length"],d.type,d.timeout,d.proxy)}}finally{J.stop("Changes analyzed")}if(S.length===0)throw new b("No commit messages were generated. Try again.");let _,V=!1;if(S.length===1){[_]=S;const u=await ue({message:`Review generated commit message:
93
+
94
+ ${_}
95
+ `,options:[{label:"Use as-is",value:"use"},{label:"Edit",value:"edit"},{label:"Cancel",value:"cancel"}]});if(P(u)||u==="cancel"){v("Commit cancelled");return}if(u==="edit"){const h=await L({message:"Edit commit message:",initialValue:_,validate:l($=>$&&$.trim().length>0?void 0:"Message cannot be empty","validate")});if(P(h)){v("Commit cancelled");return}_=String(h).trim(),V=!0}}else{const u=await ue({message:`Pick a commit message to use: ${F("(Ctrl+c to exit)")}`,options:S.map(h=>({label:h,value:h}))});if(P(u)){v("Commit cancelled");return}_=u}if(!V){const u=await I({message:"Edit the commit message before committing?"});if(u&&!P(u)){const h=await L({message:"Edit commit message:",initialValue:_,validate:l($=>$&&$.trim().length>0?void 0:"Message cannot be empty","validate")});if(P(h)){v("Commit cancelled");return}_=String(h).trim()}}const X=await I({message:`Proceed with this commit message?
96
+
97
+ ${_}
98
+ `});if(!X||P(X)){v("Commit cancelled");return}await x("git",["commit","-m",_,...n]),v(`${W("\u2714")} Successfully committed!`)})().catch(a=>{v(`${T("\u2716")} ${a.message}`),R(a),process.exit(1)}),"lazycommit");const[B,Je]=process.argv.slice(2);var Ve=l(()=>(async()=>{if(!B)throw new b('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook');if(Je)return;const t=await me();if(!t)return;ae(oe(ne(" lazycommit ")));const{env:e}=process,s=await K({GROQ_API_KEY:e.GROQ_API_KEY,proxy:e.https_proxy||e.HTTPS_PROXY||e.http_proxy||e.HTTP_PROXY}),o=E();o.start("The AI is analyzing your changes");let i;try{const y=await ge();if(y)i=await M(s.GROQ_API_KEY,s.model,s.locale,y,s.generate,s["max-length"],s.type,s.timeout,s.proxy);else{const g=`Generate a commit message for these files: ${t.files.join(", ")}`;i=await M(s.GROQ_API_KEY,s.model,s.locale,g,s.generate,s["max-length"],s.type,s.timeout,s.proxy)}}finally{o.stop("Changes analyzed")}const a=await A.readFile(B,"utf8")!=="",c=i.length>1;let r="";a&&(r=`# \u{1F916} AI generated commit${c?"s":""}
99
+ `),c?(a&&(r+=`# Select one of the following messages by uncommeting:
94
100
  `),r+=`
95
- ${o.map(h=>`# ${h}`).join(`
96
- `)}`):(u&&(r+=`# Edit the message below and commit:
101
+ ${i.map(y=>`# ${y}`).join(`
102
+ `)}`):(a&&(r+=`# Edit the message below and commit:
97
103
  `),r+=`
98
- ${o[0]}
99
- `),await $.appendFile(H,r),x(`${_("\u2714")} Saved commit message!`)})().catch(t=>{x(`${F("\u2716")} ${t.message}`),T(t),process.exit(1)}),"prepareCommitMessageHook"),Qe=B({name:"config",parameters:["<mode>","<key=value...>"]},t=>{(async()=>{const{mode:e,keyValue:s}=t._;if(e==="get"){const i=await U({},!0);for(const o of s)re(i,o)&&console.log(`${o}=${i[o]}`);return}if(e==="set"){await Se(s.map(i=>i.split("=")));return}throw new w(`Invalid mode: ${e}`)})().catch(e=>{console.error(`${F("\u2716")} ${e.message}`),T(e),process.exit(1)})});const de="prepare-commit-msg",fe=`.git/hooks/${de}`,R=q(new URL("cli.mjs",import.meta.url)),Ke=process.argv[1].replace(/\\/g,"/").endsWith(`/${fe}`),pe=process.platform==="win32",ge=`
104
+ ${i[0]}
105
+ `),await A.appendFile(B,r),v(`${W("\u2714")} Saved commit message!`)})().catch(t=>{v(`${T("\u2716")} ${t.message}`),R(t),process.exit(1)}),"prepareCommitMessageHook"),Xe=se({name:"config",parameters:["<mode>","<key=value...>"]},t=>{(async()=>{const{mode:e,keyValue:s}=t._;if(e==="get"){const o=await K({},!0);for(const i of s)he(o,i)&&console.log(`${i}=${o[i]}`);return}if(e==="set"){await Fe(s.map(o=>o.split("=")));return}throw new b(`Invalid mode: ${e}`)})().catch(e=>{console.error(`${T("\u2716")} ${e.message}`),R(e),process.exit(1)})});const be="prepare-commit-msg",ve=`.git/hooks/${be}`,z=ie(new URL("cli.mjs",import.meta.url)),Ze=process.argv[1].replace(/\\/g,"/").endsWith(`/${ve}`),Ae=process.platform==="win32",ke=`
100
106
  #!/usr/bin/env node
101
- import(${JSON.stringify(ve(R))})
102
- `.trim();var Be=B({name:"hook",parameters:["<install/uninstall>"]},t=>{(async()=>{const e=await se(),{installUninstall:s}=t._,i=G.join(e,fe),o=await ae(i);if(s==="install"){if(o){if(await $.realpath(i).catch(()=>{})===R){console.warn("The hook is already installed");return}throw new w(`A different ${de} hook seems to be installed. Please remove it before installing lazycommit.`)}await $.mkdir(G.dirname(i),{recursive:!0}),pe?await $.writeFile(i,ge):(await $.symlink(R,i,"file"),await $.chmod(i,493)),console.log(`${_("\u2714")} Hook installed`);return}if(s==="uninstall"){if(!o){console.warn("Hook is not installed");return}if(pe){if(await $.readFile(i,"utf8")!==ge){console.warn("Hook is not installed");return}}else if(await $.realpath(i)!==R){console.warn("Hook is not installed");return}await $.rm(i),console.log(`${_("\u2714")} Hook uninstalled`);return}throw new w(`Invalid mode: ${s}`)})().catch(e=>{console.error(`${F("\u2716")} ${e.message}`),T(e),process.exit(1)})});const qe=q(import.meta.url),Je=ke(qe),Xe=JSON.parse(be(Ae(Je,"../package.json"),"utf8")),{description:Ve,version:Ze}=Xe,he=process.argv.slice(2);$e({name:"lazycommit",version:Ze,flags:{generate:{type:Number,description:"Number of messages to generate (Warning: generating multiple costs more) (default: 1)",alias:"g"},exclude:{type:[String],description:"Files to exclude from AI analysis",alias:"x"},all:{type:Boolean,description:"Automatically stage changes in tracked files for the commit",alias:"a",default:!1},type:{type:String,description:"Type of commit message to generate",alias:"t"},split:{type:Boolean,description:"Create multiple commits by grouping files logically",alias:"s",default:!1}},commands:[Qe,Be],help:{description:Ve},ignoreArgv:l(t=>t==="unknown-flag"||t==="argument","ignoreArgv")},t=>{Ke?He():Le(t.flags.generate,t.flags.exclude,t.flags.all,t.flags.type,t.flags.split,he)},he);
107
+ import(${JSON.stringify(De(z))})
108
+ `.trim();var et=se({name:"hook",parameters:["<install/uninstall>"]},t=>{(async()=>{const e=await le(),{installUninstall:s}=t._,o=N.join(e,ve),i=await pe(o);if(s==="install"){if(i){if(await A.realpath(o).catch(()=>{})===z){console.warn("The hook is already installed");return}throw new b(`A different ${be} hook seems to be installed. Please remove it before installing lazycommit.`)}await A.mkdir(N.dirname(o),{recursive:!0}),Ae?await A.writeFile(o,ke):(await A.symlink(z,o,"file"),await A.chmod(o,493)),console.log(`${W("\u2714")} Hook installed`);return}if(s==="uninstall"){if(!i){console.warn("Hook is not installed");return}if(Ae){if(await A.readFile(o,"utf8")!==ke){console.warn("Hook is not installed");return}}else if(await A.realpath(o)!==z){console.warn("Hook is not installed");return}await A.rm(o),console.log(`${W("\u2714")} Hook uninstalled`);return}throw new b(`Invalid mode: ${s}`)})().catch(e=>{console.error(`${T("\u2716")} ${e.message}`),R(e),process.exit(1)})});const tt=ie(import.meta.url),st=Se(tt),it=JSON.parse(_e(We(st,"../package.json"),"utf8")),{description:ot,version:nt}=it,xe=process.argv.slice(2);Pe({name:"lazycommit",version:nt,flags:{generate:{type:Number,description:"Number of messages to generate (Warning: generating multiple costs more) (default: 1)",alias:"g"},exclude:{type:[String],description:"Files to exclude from AI analysis",alias:"x"},all:{type:Boolean,description:"Automatically stage changes in tracked files for the commit",alias:"a",default:!1},type:{type:String,description:"Type of commit message to generate",alias:"t"},split:{type:Boolean,description:"Create multiple commits by grouping files logically",alias:"s",default:!1}},commands:[Xe,et],help:{description:ot},ignoreArgv:l(t=>t==="unknown-flag"||t==="argument","ignoreArgv")},t=>{Ze?Ve():qe(t.flags.generate,t.flags.exclude,t.flags.all,t.flags.type,t.flags.split,xe)},xe);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lazycommitt",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "Writes your git commit messages for you with AI using Groq",
5
5
  "main": "index.js",
6
6
  "keywords": [