aicommit2 2.2.7 → 2.2.8

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 +3 -3
  2. package/package.json +7 -5
package/dist/cli.mjs CHANGED
@@ -29,7 +29,7 @@ ${o.message}`:g,I=[v,e,t].filter(Boolean).join(`
29
29
 
30
30
  ${l.body}`:""}${l.footer?`
31
31
 
32
- ${l.footer}`:""}`})).slice(0,o)}catch{return[]}}extractMessageAsType(e,r){switch(r){case"conventional":const o=/(\w+)(?:\(.*?\))?:\s*(.*)/,n=e.subject.match(o),s=n?n[0]:e.subject;return{...e,subject:this.normalizeCommitMessage(s)};case"gitmoji":const i=/:\w*:\s*(.*)/,u=e.subject.match(i);return{...e,subject:u?u[0].toLowerCase():e.subject};default:return e}}normalizeCommitMessage(e){const r=/^(\w+)(\(.*?\))?:\s(.*)$/,o=e.match(r);if(o){const[,n,s,i]=o,u=n.toLowerCase(),a=i.charAt(0).toLowerCase()+i.slice(1);e=`${u}${s||""}: ${a}`}return e}sanitizeResponse(e){if(typeof e=="string")try{return[{title:`${Eo(e)}...`,value:e}]}catch{return[]}return e.map(r=>{try{return{title:`${Eo(r)}...`,value:r}}catch{return{title:"",value:""}}})}}var Fo="2.2.7",yu="A Reactive CLI that generates git commit messages with various AI";class E extends Error{}const Nt=" ",te=t=>{t instanceof Error&&(t instanceof E||(t.stack&&console.error(C.dim(t.stack.split(`
32
+ ${l.footer}`:""}`})).slice(0,o)}catch{return[]}}extractMessageAsType(e,r){switch(r){case"conventional":const o=/(\w+)(?:\(.*?\))?:\s*(.*)/,n=e.subject.match(o),s=n?n[0]:e.subject;return{...e,subject:this.normalizeCommitMessage(s)};case"gitmoji":const i=/:\w*:\s*(.*)/,u=e.subject.match(i);return{...e,subject:u?u[0].toLowerCase():e.subject};default:return e}}normalizeCommitMessage(e){const r=/^(\w+)(\(.*?\))?:\s(.*)$/,o=e.match(r);if(o){const[,n,s,i]=o,u=n.toLowerCase(),a=i.charAt(0).toLowerCase()+i.slice(1);e=`${u}${s||""}: ${a}`}return e}sanitizeResponse(e){if(typeof e=="string")try{return[{title:`${Eo(e)}...`,value:e}]}catch{return[]}return e.map(r=>{try{return{title:`${Eo(r)}...`,value:r}}catch{return{title:"",value:""}}})}}var Fo="2.2.8",yu="A Reactive CLI that generates git commit messages with various AI";class E extends Error{}const Nt=" ",te=t=>{t instanceof Error&&(t instanceof E||(t.stack&&console.error(C.dim(t.stack.split(`
33
33
  `).slice(1).join(`
34
34
  `))),console.error(`
35
35
  ${Nt}${C.dim(`aicommit2 v${Fo}`)}`),console.error(`
@@ -120,7 +120,7 @@ ${C.bold.yellow("\u26A0")} ${C.red(`${e}`)}`)}printSetupGitEvent(e){console.log(
120
120
  ${C.bold.green("\u2714")} ${C.bold(`Git ${e} hook has been set up`)}`)}moveCursorUp(){const e=Me.createInterface({input:process.stdin,output:process.stdout});Me.moveCursor(process.stdout,0,-1),e.close()}moveCursorDown(){const e=Me.createInterface({input:process.stdin,output:process.stdout});Me.moveCursor(process.stdout,0,2),e.close()}}const Dc={isLoading:!1,startOption:{text:"AI is analyzing your changes"}},en={isLoading:!1,startOption:{text:"AI is performing a code review"}},or="No commit messages were generated",tn="No code reviews were generated",nr={type:"reactiveListPrompt",name:"aicommit2Prompt",message:"Pick a commit message to use: ",emptyMessage:`\u26A0 ${or}`,loop:!1,descPageSize:15,showDescription:!0,pickKey:"short",isDescriptionDim:!0,stopMessage:"Changes analyzed"};class sr{constructor(e){this.choices$=new gr([]),this.destroyed$=new $n(1),this.stopMessage="Changes analyzed",this.inquirerInstance=null,this.loader$=new gr(e)}initPrompt(e=nr){return this.stopMessage=e.stopMessage,Ae.registerPrompt("reactiveListPrompt",Gn),this.inquirerInstance=Ae.prompt({choices$:this.choices$,loader$:this.loader$,...e}),this.inquirerInstance}startLoader(){this.loader$.next({isLoading:!0})}clearLoader(){this.inquirerInstance&&this.loader$.next({isLoading:!1,clear:!0})}refreshChoices(e){const{value:r,isError:o}=e;!e||!r||this.choices$.next([...this.currentChoices,e].sort(pu))}checkErrorOnChoices(e=!0){if(this.choices$.getValue().map(o=>o).every(o=>o?.isError||o?.disabled)){this.alertNoGeneratedMessage(),this.logEmptyCommitMessage(),e&&process.exit(1);return}this.stopLoaderOnSuccess()}completeSubject(){this.choices$.complete(),this.loader$.complete(),this.destroyed$.next(!0),this.destroyed$.complete()}closeInquirerInstance(){this.inquirerInstance&&this.inquirerInstance.ui.close()}cancel(){this.inquirerInstance?.ui?.activePrompt&&this.inquirerInstance.ui.activePrompt.abortPrompt()}alertNoGeneratedMessage(){this.loader$.next({isLoading:!1,message:or,stopOption:{doneFrame:"\u26A0",color:"yellow"}})}stopLoaderOnSuccess(){this.loader$.next({isLoading:!1,message:this.stopMessage})}logEmptyCommitMessage(){console.log(`${C.bold.yellow("\u26A0")} ${C.yellow(`${or}`)}`)}get currentChoices(){return this.choices$.getValue().map(e=>e)}}const K=new Y;var mc=async(t,e,r,o,n,s,i,u,a)=>(async()=>{K.printTitle(),await tr(),o&&await ee("git",["add","--update"]);const l=await ye({locale:t?.toString(),generate:e?.toString(),commitType:n?.toString(),systemPrompt:u?.toString()},a);await Ao(l);const m=K.displaySpinner("Detecting staged files"),c=await rr(r,l.exclude);if(m.stop(),!c)throw new E("No staged changes found. Stage your changes manually, or automatically stage all changes with the `--all` flag.");K.printStagedFiles(c);const D=rn(l,"commit");if(D.length===0)throw new E("Please set at least one API key via the `aicommit2 config set` command");const d=new Xe(l,c),f=rn(l,"review");f.length>0&&await dc(d,f);const h=await pc(d,D);i&&(li("copy-paste").copy(h),K.printCopied(),process.exit()),s&&(await on(h,a),process.exit());const{confirmationPrompt:g}=await Ae.prompt([{type:"confirm",name:"confirmationPrompt",message:"Use selected message?",default:!0}]);g?await on(h,a):K.printCancelledCommit(),process.exit()})().catch(l=>{K.printError(l.message),te(l),process.exit(1)});function rn(t,e){return Object.entries(t).map(([r,o])=>[r,o]).filter(([r,o])=>!o.disabled).filter(([r,o])=>V.includes(r)||o.compatible===!0).filter(([r,o])=>{switch(e){case"commit":return r==="OLLAMA"?!!o&&!!o.model&&o.model.length>0:r==="HUGGINGFACE"?!!o&&!!o.cookie:!!o.key&&o.key.length>0;case"review":const n=t.codeReview||o.codeReview;return r==="OLLAMA"?!!o&&!!o.model&&o.model.length>0&&n:r==="HUGGINGFACE"?!!o&&!!o.cookie&&n:!!o.key&&o.key.length>0&&n}}).map(([r])=>r)}async function dc(t,e){const r=new sr(en),o=r.initPrompt({...nr,name:"codeReviewPrompt",message:"Please check code reviews: ",emptyMessage:`\u26A0 ${tn}`,isDescriptionDim:!1,stopMessage:"Code review completed",descPageSize:20});r.startLoader();const n=t.createCodeReviewRequests$(e).subscribe(a=>r.refreshChoices(a),()=>{},()=>r.checkErrorOnChoices());if(!(await o).codeReviewPrompt?.value)throw new E("An error occurred! No selected code review");n.unsubscribe(),r.completeSubject(),K.moveCursorUp();const{continuePrompt:u}=await Ae.prompt([{type:"confirm",name:"continuePrompt",message:"Will you continue without changing the code?",default:!0}]);u||(K.printCancelledCommit(),process.exit())}async function pc(t,e){const r=new sr(Dc),o=r.initPrompt();r.startLoader();const n=t.createCommitMsgRequests$(e).subscribe(u=>r.refreshChoices(u),()=>{},()=>r.checkErrorOnChoices()),s=await o;n.unsubscribe(),r.completeSubject(),K.moveCursorUp();const i=s.aicommit2Prompt?.value;if(!i)throw new E("An error occurred! No selected message");return i}async function on(t,e){const r=it("Committing with the generated message").start();await ee("git",["commit","-m",t,...e]),r.stop(),r.clear(),K.printCommitted()}var fc=gt({name:"config",parameters:["<mode>","<key=value...>"]},t=>{(async()=>{const{mode:e,keyValue:r}=t._;if(e==="get"){const o=await ye({},[]);for(const n of r)if(Ke(o,n)){if(V.includes(n)){console.log(n,o[n]);return}console.log(`${n}=${o[n]}`)}return}if(e==="set"){await Mu(r.map(o=>o.split("=")));return}if(e==="add"){await Su(r.map(o=>o.split("=")));return}throw new E(`Invalid mode: ${e}`)})().catch(e=>{new Y().printError(e.message),te(e),process.exit(1)})});const nn="prepare-commit-msg",sn=`.git/hooks/${nn}`,Qe=Tn(new URL("cli.mjs",import.meta.url)),hc=process.argv[1].replace(/\\/g,"/").endsWith(`/${sn}`),an=process.platform==="win32",un=`
121
121
  #!/usr/bin/env node
122
122
  import(${JSON.stringify(_n(Qe))})
123
- `.trim();var gc=gt({name:"hook",parameters:["<install/uninstall>"]},t=>{(async()=>{const e=await tr(),{installUninstall:r}=t._,o=k.join(e,sn),n=await To(o);if(r==="install"){if(n){if(await M.realpath(o).catch(()=>{})===Qe){console.warn("The hook is already installed");return}throw new E(`A different ${nn} hook seems to be installed. Please remove it before installing aicommit2.`)}await M.mkdir(k.dirname(o),{recursive:!0}),an?await M.writeFile(o,un):(await M.symlink(Qe,o,"file"),await M.chmod(o,493)),console.log(`${C.green("\u2714")} Hook installed`);return}if(r==="uninstall"){if(!n){console.warn("Hook is not installed");return}if(an){if(await M.readFile(o,"utf8")!==un){console.warn("Hook is not installed");return}}else if(await M.realpath(o)!==Qe){console.warn("Hook is not installed");return}await M.rm(o),console.log(`${C.green("\u2714")} Hook uninstalled`);return}throw new E(`Invalid mode: ${r}`)})().catch(e=>{console.error(`${C.red("\u2716")} ${e.message}`),te(e),process.exit(1)})}),Cc=gt({name:"log",parameters:["<removeAll>"]},t=>{(async()=>{const{removeAll:e}=t._;if(e==="removeAll"){await Hn(wo,{recursive:!0,force:!0}),console.log(`${C.green("\u2714")} All Log files are removed!`);return}throw new E(`Invalid mode: ${e}`)})().catch(e=>{new Y().printError(e.message),te(e),process.exit(1)})});const yc=process.argv.slice(2).filter(t=>!t.startsWith("--")),[et,ir]=yc;var Ec=()=>(async()=>{if(!et)throw new E('Commit message file path is missing. This file should be called from the "pre-commit framework"');if(ir&&["message","template","merge","squash"].includes(ir)){console.log(`Skipping aicommit2 message generation for ${ir} commit`);return}const t=await rr();if(!t)return;const e=new Y;e.printTitle();const r=await ye({});if(r.systemPromptPath)try{await M.readFile(k.resolve(r.systemPromptPath),"utf-8")}catch{throw new E(`Error reading system prompt file: ${r.systemPromptPath}`)}const o=Object.entries(r).filter(([d])=>V.includes(d)).map(([d,f])=>[d,f]).filter(([d,f])=>!f.disabled).filter(([d,f])=>d==="OLLAMA"?!!f&&!!f.model&&f.model.length>0:d==="HUGGINGFACE"?!!f&&!!f.cookie:!!f.key&&f.key.length>0).map(([d])=>d);if(o.length===0)throw new E("Please set at least one API key via the `aicommit2 config set` command");const s=new Xe(r,t);let i;try{i=await Cr(s.createCommitMsgRequests$(o).pipe(yr(d=>!d.isError),b(d=>d.value),Er()))}finally{e.printAnalyzed()}const a=await M.readFile(et,"utf8")!=="",l=i.length>1;let m="";a&&(m=`# \u{1F916} Generated by aicommit2 (https://github.com/tak-bro/aicommit2)
123
+ `.trim();var gc=gt({name:"hook",parameters:["<install/uninstall>"]},t=>{(async()=>{const e=await tr(),{installUninstall:r}=t._,o=k.join(e,sn),n=await To(o);if(r==="install"){if(n){if(await M.realpath(o).catch(()=>{})===Qe){console.warn("The hook is already installed");return}throw new E(`A different ${nn} hook seems to be installed. Please remove it before installing aicommit2.`)}await M.mkdir(k.dirname(o),{recursive:!0}),an?await M.writeFile(o,un):(await M.symlink(Qe,o,"file"),await M.chmod(o,493)),console.log(`${C.green("\u2714")} Hook installed`);return}if(r==="uninstall"){if(!n){console.warn("Hook is not installed");return}if(an){if(await M.readFile(o,"utf8")!==un){console.warn("Hook is not installed");return}}else if(await M.realpath(o)!==Qe){console.warn("Hook is not installed");return}await M.rm(o),console.log(`${C.green("\u2714")} Hook uninstalled`);return}throw new E(`Invalid mode: ${r}`)})().catch(e=>{console.error(`${C.red("\u2716")} ${e.message}`),te(e),process.exit(1)})}),Cc=gt({name:"log",parameters:["<removeAll>"]},t=>{(async()=>{const{removeAll:e}=t._;if(e==="removeAll"){await Hn(wo,{recursive:!0,force:!0}),console.log(`${C.green("\u2714")} All Log files are removed!`);return}throw new E(`Invalid mode: ${e}`)})().catch(e=>{new Y().printError(e.message),te(e),process.exit(1)})});const yc=process.argv.slice(2).filter(t=>!t.startsWith("--pre-commit")),[et,ir]=yc;var Ec=()=>(async()=>{if(!et)throw new E('Commit message file path is missing. This file should be called from the "pre-commit framework"');if(ir&&["message","template","merge","squash"].includes(ir)){console.log(`Skipping aicommit2 message generation for ${ir} commit`);return}const t=await rr();if(!t)return;const e=new Y;e.printTitle();const r=await ye({});if(r.systemPromptPath)try{await M.readFile(k.resolve(r.systemPromptPath),"utf-8")}catch{throw new E(`Error reading system prompt file: ${r.systemPromptPath}`)}const o=Object.entries(r).filter(([d])=>V.includes(d)).map(([d,f])=>[d,f]).filter(([d,f])=>!f.disabled).filter(([d,f])=>d==="OLLAMA"?!!f&&!!f.model&&f.model.length>0:d==="HUGGINGFACE"?!!f&&!!f.cookie:!!f.key&&f.key.length>0).map(([d])=>d);if(o.length===0)throw new E("Please set at least one API key via the `aicommit2 config set` command");const s=new Xe(r,t);let i;try{i=await Cr(s.createCommitMsgRequests$(o).pipe(yr(d=>!d.isError),b(d=>d.value),Er()))}finally{e.printAnalyzed()}const a=await M.readFile(et,"utf8")!=="",l=i.length>1;let m="";a&&(m=`# \u{1F916} Generated by aicommit2 (https://github.com/tak-bro/aicommit2)
124
124
  `,m+=`# ----------------------------------------
125
125
  `,m+=`# How to use:
126
126
  `,l?(m+=`# 1. Remove the "#" from your chosen message
@@ -139,7 +139,7 @@ ${i.map(d=>`# ${d}`).join(`
139
139
  `),m+=`
140
140
  ${i[0]}
141
141
  `);const c=await M.readFile(et,"utf8"),D=m+`
142
- `+c;await M.writeFile(et,D),e.printSavedCommitMessage()})().catch(t=>{new Y().printError(t.message),te(t),process.exit(1)});const Fc=process.argv.slice(2).filter(t=>!t.startsWith("--")),[tt,ar]=Fc;var wc=()=>(async()=>{if(!tt)throw new E('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook or with --hook-mode flag');if(ar&&["message","template","merge","squash"].includes(ar)){console.log(`Skipping aicommit2 message generation for ${ar} commit`);return}const t=await rr();if(!t)return;const e=new Y;e.printTitle();const r=await ye({});if(r.systemPromptPath)try{await M.readFile(k.resolve(r.systemPromptPath),"utf-8")}catch{throw new E(`Error reading system prompt file: ${r.systemPromptPath}`)}const o=Object.entries(r).filter(([f])=>V.includes(f)).map(([f,h])=>[f,h]).filter(([f,h])=>!h.disabled).filter(([f,h])=>f==="OLLAMA"?!!h&&!!h.model&&h.model.length>0:f==="HUGGINGFACE"?!!h&&!!h.cookie:!!h.key&&h.key.length>0).map(([f])=>f);if(o.length===0)throw new E("Please set at least one API key via the `aicommit2 config set` command");const s=new Xe(r,t),i=e.displaySpinner("The AI is analyzing your changes");let u;try{u=await Cr(s.createCommitMsgRequests$(o).pipe(yr(f=>!f.isError),b(f=>f.value),Er()))}finally{i.stop(),i.clear(),e.printAnalyzed()}const l=await M.readFile(tt,"utf8")!=="",m=u.length>1;let c="";l&&(c=`# \u{1F916} Generated by aicommit2 (https://github.com/tak-bro/aicommit2)
142
+ `+c;await M.writeFile(et,D),e.printSavedCommitMessage()})().catch(t=>{new Y().printError(t.message),te(t),process.exit(1)});const Fc=process.argv.slice(2).filter(t=>!t.startsWith("--hook-mode")),[tt,ar]=Fc;var wc=()=>(async()=>{if(!tt)throw new E('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook or with --hook-mode flag');if(ar&&["message","template","merge","squash"].includes(ar)){console.log(`Skipping aicommit2 message generation for ${ar} commit`);return}const t=await rr();if(!t)return;const e=new Y;e.printTitle();const r=await ye({});if(r.systemPromptPath)try{await M.readFile(k.resolve(r.systemPromptPath),"utf-8")}catch{throw new E(`Error reading system prompt file: ${r.systemPromptPath}`)}const o=Object.entries(r).filter(([f])=>V.includes(f)).map(([f,h])=>[f,h]).filter(([f,h])=>!h.disabled).filter(([f,h])=>f==="OLLAMA"?!!h&&!!h.model&&h.model.length>0:f==="HUGGINGFACE"?!!h&&!!h.cookie:!!h.key&&h.key.length>0).map(([f])=>f);if(o.length===0)throw new E("Please set at least one API key via the `aicommit2 config set` command");const s=new Xe(r,t),i=e.displaySpinner("The AI is analyzing your changes");let u;try{u=await Cr(s.createCommitMsgRequests$(o).pipe(yr(f=>!f.isError),b(f=>f.value),Er()))}finally{i.stop(),i.clear(),e.printAnalyzed()}const l=await M.readFile(tt,"utf8")!=="",m=u.length>1;let c="";l&&(c=`# \u{1F916} Generated by aicommit2 (https://github.com/tak-bro/aicommit2)
143
143
  `,c+=`# ----------------------------------------
144
144
  `,c+=`# How to use:
145
145
  `,m?(c+=`# 1. Remove the "#" from your chosen message
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicommit2",
3
- "version": "2.2.7",
3
+ "version": "2.2.8",
4
4
  "description": "A Reactive CLI that generates git commit messages with various AI",
5
5
  "keywords": [
6
6
  "cli",
@@ -14,10 +14,8 @@
14
14
  "aicommit",
15
15
  "aicommits",
16
16
  "aicommit2",
17
- "aicommits2",
18
17
  "openai",
19
18
  "huggingface",
20
- "hugging face",
21
19
  "anthropic",
22
20
  "claude",
23
21
  "claude3",
@@ -27,14 +25,18 @@
27
25
  "mistral",
28
26
  "ollama",
29
27
  "llama3",
30
- "llama3.1",
28
+ "llama3.2",
29
+ "llama3.3",
30
+ "gemma",
31
31
  "llm",
32
32
  "chatgpt",
33
33
  "cohere",
34
34
  "groq",
35
35
  "codestral",
36
36
  "perplexity",
37
- "deepseek"
37
+ "deepseek",
38
+ "deepseek-r1",
39
+ "pre-commit"
38
40
  ],
39
41
  "license": "MIT",
40
42
  "repository": "tak-bro/aicommit2",