aicommit2 2.1.3 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +2 -2
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -33,7 +33,7 @@ ${i.footer}`:""}`}));return s.length>o?s.slice(0,o):s}catch{const s=/\[[\s\S]*?\
|
|
|
33
33
|
|
|
34
34
|
${m.body}`:""}${m.footer?`
|
|
35
35
|
|
|
36
|
-
${m.footer}`:""}`}));return l.length>o?l.slice(0,o):l}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:`${Qr(e)}...`,value:e}]}catch{return[]}return e.map(r=>{try{return{title:`${Qr(r)}...`,value:r}}catch{return{title:"",value:""}}})}}var Zr="2.1.
|
|
36
|
+
${m.footer}`:""}`}));return l.length>o?l.slice(0,o):l}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:`${Qr(e)}...`,value:e}]}catch{return[]}return e.map(r=>{try{return{title:`${Qr(r)}...`,value:r}}catch{return{title:"",value:""}}})}}var Zr="2.1.4",Ku="A Reactive CLI that generates git commit messages with various AI";class y extends Error{}const bt=" ",de=t=>{t instanceof Error&&(t instanceof y||(t.stack&&console.error(C.dim(t.stack.split(`
|
|
37
37
|
`).slice(1).join(`
|
|
38
38
|
`))),console.error(`
|
|
39
39
|
${bt}${C.dim(`aicommit2 v${Zr}`)}`),console.error(`
|
|
@@ -121,7 +121,7 @@ ${C.bold.yellow("\u26A0")} ${C.yellow("Commit cancelled")}`)}printErrorMessage(e
|
|
|
121
121
|
${C.bold.red("\u2716")} ${C.red(`${e}`)}`)}moveCursorUp(){const e=be.createInterface({input:process.stdin,output:process.stdout});be.moveCursor(process.stdout,0,-1),e.close()}moveCursorDown(){const e=be.createInterface({input:process.stdin,output:process.stdout});be.moveCursor(process.stdout,0,1),e.close()}}const La={isLoading:!1,startOption:{text:"AI is analyzing your changes"}},Ta={isLoading:!1,startOption:{text:"AI is performing a code review"}},zt="No commit messages were generated",_a="No code reviews were generated",ko={type:"reactiveListPrompt",name:"aicommit2Prompt",message:"Pick a commit message to use: ",emptyMessage:`\u26A0 ${zt}`,loop:!1,descPageSize:15,showDescription:!0,pickKey:"short",isDescriptionDim:!0,stopMessage:"Changes analyzed"};class No{constructor(e){this.choices$=new Zt([]),this.destroyed$=new tn(1),this.stopMessage="Changes analyzed",this.loader$=new Zt(e)}initPrompt(e=ko){return this.stopMessage=e.stopMessage,Fe.registerPrompt("reactiveListPrompt",yn),Fe.prompt({...e,choices$:this.choices$,loader$:this.loader$})}startLoader(){this.loader$.next({isLoading:!0})}refreshChoices(e){const{value:r,isError:o}=e;!e||!r||this.choices$.next([...this.currentChoices,e].sort(Wu))}checkErrorOnChoices(){if(this.choices$.getValue().map(r=>r).every(r=>r?.isError||r?.disabled)){this.alertNoGeneratedMessage(),this.logEmptyCommitMessage(),process.exit(1);return}this.stopLoaderOnSuccess()}completeSubject(){this.choices$.complete(),this.loader$.complete(),this.destroyed$.next(!0),this.destroyed$.complete()}alertNoGeneratedMessage(){this.loader$.next({isLoading:!1,message:zt,stopOption:{doneFrame:"\u26A0",color:"yellow"}})}stopLoaderOnSuccess(){this.loader$.next({isLoading:!1,message:this.stopMessage})}logEmptyCommitMessage(){console.log(`${C.bold.yellow("\u26A0")} ${C.yellow(`${zt}`)}`)}get currentChoices(){return this.choices$.getValue().map(e=>e)}}const q=new Ee;var ja=async(t,e,r,o,n,s,i,u,a)=>(async()=>{q.printTitle(),await Oo(),o&&await me("git",["add","--update"]);const l=await Mt({locale:t?.toString(),generate:e?.toString(),commitType:n?.toString(),systemPrompt:u?.toString()},a);await Ga(l);const m=q.displaySpinner("Detecting staged files"),c=await Io(r,l.exclude);if(m.stop(),!c)throw new y("No staged changes found. Stage your changes manually, or automatically stage all changes with the `--all` flag.");q.printStagedFiles(c);const D=Lo(l,"commit");if(D.length===0)throw new y("Please set at least one API key via the `aicommit2 config set` command");const d=new Mo(l,c),f=Lo(l,"review");f.length>0&&await Ha(d,f);const h=await Ua(d,D);i&&(Hs("copy-paste").copy(h),q.printCopied(),process.exit()),s&&(await To(h,a),process.exit());const{confirmationPrompt:g}=await Fe.prompt([{type:"confirm",name:"confirmationPrompt",message:"Use selected message?",default:!0}]);g?await To(h,a):q.printCancelledCommit(),process.exit()})().catch(l=>{q.printErrorMessage(l.message),de(l),process.exit(1)});async function Ga(t){if(t.systemPromptPath)try{T.readFileSync(N.resolve(t.systemPromptPath),"utf-8")}catch{throw new y(`Error reading system prompt file: ${t.systemPromptPath}`)}if(t.codeReview&&t.codeReviewPromptPath)try{T.readFileSync(N.resolve(t.codeReviewPromptPath),"utf-8")}catch{throw new y(`Error reading code review prompt file: ${t.codeReviewPromptPath}`)}}function Lo(t,e){return Object.entries(t).filter(([r])=>xt.includes(r)).map(([r,o])=>[r,o]).filter(([r,o])=>!o.disabled).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}return!1}).map(([r])=>r)}async function Ha(t,e){const r=new No(Ta),o=r.initPrompt({...ko,name:"codeReviewPrompt",message:"Please check code reviews: ",emptyMessage:`\u26A0 ${_a}`,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 y("An error occurred! No selected code review");n.unsubscribe(),r.completeSubject(),q.moveCursorUp();const{continuePrompt:u}=await Fe.prompt([{type:"confirm",name:"continuePrompt",message:"Will you continue without changing the code?",default:!0}]);u||(q.printCancelledCommit(),process.exit())}async function Ua(t,e){const r=new No(La),o=r.initPrompt();r.startLoader();const n=t.createCommitMsgRequests$(e).subscribe(u=>r.refreshChoices(u),()=>{},()=>r.checkErrorOnChoices()),s=await o;n.unsubscribe(),r.completeSubject(),q.moveCursorUp();const i=s.aicommit2Prompt?.value;if(!i)throw new y("An error occurred! No selected message");return i}async function To(t,e){const r=Qt("Committing with the generated message").start();await me("git",["commit","-m",t,...e]),r.stop(),r.clear(),q.printCommitted()}var za=nt({name:"config",parameters:["<mode>","<key=value...>"]},t=>{(async()=>{const{mode:e,keyValue:r}=t._;if(e==="get"){const o=await Mt({},[]);for(const n of r)if(je(o,n)){if(xt.includes(n)){console.log(n,o[n]);return}console.log(`${n}=${o[n]}`)}return}if(e==="set"){await oa(r.map(o=>o.split("=")));return}if(e==="add"){await na(r.map(o=>o.split("=")));return}throw new y(`Invalid mode: ${e}`)})().catch(e=>{new Ee().printErrorMessage(e.message),de(e),process.exit(1)})});const _o="prepare-commit-msg",jo=`.git/hooks/${_o}`,ze=Cn(new URL("cli.mjs",import.meta.url)),qa=process.argv[1].replace(/\\/g,"/").endsWith(`/${jo}`),Go=process.platform==="win32",Ho=`
|
|
122
122
|
#!/usr/bin/env node
|
|
123
123
|
import(${JSON.stringify(En(ze))})
|
|
124
|
-
`.trim();var Wa=nt({name:"hook",parameters:["<install/uninstall>"]},t=>{(async()=>{const e=await Oo(),{installUninstall:r}=t._,o=N.join(e,jo),n=await ho(o);if(r==="install"){if(n){if(await I.realpath(o).catch(()=>{})===ze){console.warn("The hook is already installed");return}throw new y(`A different ${_o} hook seems to be installed. Please remove it before installing aicommit2.`)}await I.mkdir(N.dirname(o),{recursive:!0}),Go?await I.writeFile(o,Ho):(await I.symlink(ze,o,"file"),await I.chmod(o,493)),console.log(`${C.green("\u2714")} Hook installed`);return}if(r==="uninstall"){if(!n){console.warn("Hook is not installed");return}if(Go){if(await I.readFile(o,"utf8")!==Ho){console.warn("Hook is not installed");return}}else if(await I.realpath(o)!==ze){console.warn("Hook is not installed");return}await I.rm(o),console.log(`${C.green("\u2714")} Hook uninstalled`);return}throw new y(`Invalid mode: ${r}`)})().catch(e=>{console.error(`${C.red("\u2716")} ${e.message}`),de(e),process.exit(1)})}),Ka=nt({name:"log",parameters:["<removeAll>"]},t=>{(async()=>{const{removeAll:e}=t._;if(e==="removeAll"){await wn(eo,{recursive:!0,force:!0}),console.log(`${C.green("\u2714")} All Log files are removed!`);return}throw new y(`Invalid mode: ${e}`)})().catch(e=>{new Ee().printErrorMessage(e.message),de(e),process.exit(1)})});const[qe,Va]=process.argv.slice(2);var Ja=()=>(async()=>{if(!qe)throw new y('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook');if(Va)return;const t=await Io();if(!t)return;const e=new Ee;e.printTitle();const r=await Mt({});if(r.systemPromptPath)try{await I.readFile(N.resolve(r.systemPromptPath),"utf-8")}catch{throw new y(`Error reading system prompt file: ${r.systemPromptPath}`)}const o=Object.entries(r).filter(([f])=>xt.includes(f)).map(([f,h])=>[f,h]).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 y("Please set at least one API key via the `aicommit2 config set` command");const s=new Mo(r,t),i=e.displaySpinner("The AI is analyzing your changes");let u;try{u=await rn(s.createCommitMsgRequests$(o).pipe(on(f=>!f.isError),A(f=>f.value),nn()))}finally{i.stop(),i.clear(),e.printAnalyzed()}const l=await I.readFile(qe,"utf8")!=="",m=u.length>1;let c="";l&&(c=`# \u{1F916} AI generated commit${m?"s":""}
|
|
124
|
+
`.trim();var Wa=nt({name:"hook",parameters:["<install/uninstall>"]},t=>{(async()=>{const e=await Oo(),{installUninstall:r}=t._,o=N.join(e,jo),n=await ho(o);if(r==="install"){if(n){if(await I.realpath(o).catch(()=>{})===ze){console.warn("The hook is already installed");return}throw new y(`A different ${_o} hook seems to be installed. Please remove it before installing aicommit2.`)}await I.mkdir(N.dirname(o),{recursive:!0}),Go?await I.writeFile(o,Ho):(await I.symlink(ze,o,"file"),await I.chmod(o,493)),console.log(`${C.green("\u2714")} Hook installed`);return}if(r==="uninstall"){if(!n){console.warn("Hook is not installed");return}if(Go){if(await I.readFile(o,"utf8")!==Ho){console.warn("Hook is not installed");return}}else if(await I.realpath(o)!==ze){console.warn("Hook is not installed");return}await I.rm(o),console.log(`${C.green("\u2714")} Hook uninstalled`);return}throw new y(`Invalid mode: ${r}`)})().catch(e=>{console.error(`${C.red("\u2716")} ${e.message}`),de(e),process.exit(1)})}),Ka=nt({name:"log",parameters:["<removeAll>"]},t=>{(async()=>{const{removeAll:e}=t._;if(e==="removeAll"){await wn(eo,{recursive:!0,force:!0}),console.log(`${C.green("\u2714")} All Log files are removed!`);return}throw new y(`Invalid mode: ${e}`)})().catch(e=>{new Ee().printErrorMessage(e.message),de(e),process.exit(1)})});const[qe,Va]=process.argv.slice(2);var Ja=()=>(async()=>{if(!qe)throw new y('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook');if(Va)return;const t=await Io();if(!t)return;const e=new Ee;e.printTitle();const r=await Mt({});if(r.systemPromptPath)try{await I.readFile(N.resolve(r.systemPromptPath),"utf-8")}catch{throw new y(`Error reading system prompt file: ${r.systemPromptPath}`)}const o=Object.entries(r).filter(([f])=>xt.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 y("Please set at least one API key via the `aicommit2 config set` command");const s=new Mo(r,t),i=e.displaySpinner("The AI is analyzing your changes");let u;try{u=await rn(s.createCommitMsgRequests$(o).pipe(on(f=>!f.isError),A(f=>f.value),nn()))}finally{i.stop(),i.clear(),e.printAnalyzed()}const l=await I.readFile(qe,"utf8")!=="",m=u.length>1;let c="";l&&(c=`# \u{1F916} AI generated commit${m?"s":""}
|
|
125
125
|
`),m?(l&&(c+=`# Select one of the following messages by uncommenting:
|
|
126
126
|
`),c+=`
|
|
127
127
|
${u.map(f=>`# ${f}`).join(`
|