UNPKG

@arietta-studio/arietta-compass

Version:

Arietta Compass is a CLI tool that uses ChatGPT to generate Gitmoji-based commit messages

21 lines (19 loc) 25.8 kB
#!/usr/bin/env node import{jsx as s,jsxs as S,Fragment as ae}from"react/jsx-runtime";import{alert as F,useTheme as j,Panel as w,SelectInput as _,SplitView as Z,ConfigPanel as je,render as x}from"@arietta-studio/arietta-cli-ui";import{Command as xe,Option as R}from"commander";import Pe from"update-notifier";import{Spinner as L,Badge as Ae,TextInput as k,MultiSelect as Ee,Alert as P}from"@inkjs/ui";import{Text as d,useInput as N,Box as ne}from"ink";import{useRef as $e,useState as g,useCallback as h,memo as y,useEffect as A,useMemo as B}from"react";import Fe from"swr";import{ChatOpenAI as _e}from"@langchain/openai";import Re from"chalk";import{loadSummarizationChain as Le}from"langchain/chains";import{RecursiveCharacterTextSplitter as Ge}from"langchain/text_splitter";import{execSync as Me}from"node:child_process";import{ChatPromptTemplate as Ne,PromptTemplate as re}from"@langchain/core/prompts";import Oe from"dotenv";import De from"conf";import{encode as Ve}from"gpt-tokenizer";import{kebabCase as ce,upperFirst as Ue,debounce as O}from"lodash-es";import ze from"pangu";import K from"node:fs";import*as He from"node:process";import le from"node:process";import{execaSync as W}from"execa";import me from"node:path";import{shallow as E}from"zustand/shallow";import{createWithEqualityFn as Be}from"zustand/traditional";import{Octokit as Ke}from"octokit";import We from"gitconfig";import Ye from"fast-deep-equal";var Xe="@arietta-studio/arietta-compass",qe="1.0.2",Je="Arietta Compass is a CLI tool that uses ChatGPT to generate Gitmoji-based commit messages",Qe=["ai","git","commit","openai","gpt","gitmoji-cli","git-commits","chatgpt","aicommit","ai-commit"],Ze="https://github.com/arietta-studio/arietta-tools/tree/master/packages/arietta-compass",et={url:"https://github.com/arietta-studio/arietta-tools/issues/new"},tt={type:"git",url:"https://github.com/arietta-studio/arietta-tools.git"},ot="MIT",st="Arietta Studio <info@arietta-studio.ai>",it=!1,at="module",nt={"@":"./src"},rt={acgit:"dist/cli.js","arietta-compass":"dist/cli.js"},ct=["dist"],lt={build:"bun run type-check && pkgroll --minify -p tsconfig.prod.json --env.NODE_ENV=production && bun run shebang",dev:"pkgroll -p tsconfig.prod.json --env.NODE_ENV=development --watch",link:"bun run build && bun link -f",shebang:"arietta-shebang -t ./dist/cli.js",start:"node ./dist/cli.js",test:"vitest --passWithNoTests","test:coverage":"vitest run --coverage --passWithNoTests","type-check":"tsc --noEmit"},mt={"@arietta-studio/arietta-cli-ui":"1.0.2","@inkjs/ui":"^1","@langchain/core":"latest","@langchain/openai":"latest",chalk:"^5",commander:"^11",conf:"^12",dotenv:"^16",execa:"^8","fast-deep-equal":"^3",gitconfig:"^2","gpt-tokenizer":"^2",ink:"^4.2",langchain:"latest","lodash-es":"^4",octokit:"^3",pangu:"^4","path-exists":"^5",react:"^18",swr:"^2","update-notifier":"^7",zustand:"^4"},ut={ink:">=4",react:">=18"},pt={node:">=18"},dt={access:"public",registry:"https://registry.npmjs.org/"},ee={name:Xe,version:qe,description:Je,keywords:Qe,homepage:Ze,bugs:et,repository:tt,license:ot,author:st,sideEffects:it,type:at,imports:nt,bin:rt,files:ct,scripts:lt,dependencies:mt,peerDependencies:ut,engines:pt,publishConfig:dt};const D=[{code:":sparkles:",desc:"Introduce new features",emoji:"\u2728",name:"sparkles",type:"feat"},{code:":bug:",desc:"Fix a bug",emoji:"\u{1F41B}",name:"bug",type:"fix"},{code:":recycle:",desc:"Refactor code that neither fixes a bug nor adds a feature",emoji:"\u267B\uFE0F",name:"recycle",type:"refactor"},{code:":zap:",desc:"A code change that improves performance",emoji:"\u26A1",name:"zap",type:"perf"},{code:":lipstick:",desc:"Add or update style files that do not affect the meaning of the code",emoji:"\u{1F484}",name:"lipstick",type:"style"},{code:":white_check_mark:",desc:"Adding missing tests or correcting existing tests",emoji:"\u2705",name:"white-check-mark",type:"test"},{code:":memo:",desc:"Documentation only changes",emoji:"\u{1F4DD}",name:"memo",type:"docs"},{code:":construction_worker:",desc:"Changes to our CI configuration files and scripts",emoji:"\u{1F477}",name:"construction-worker",type:"ci"},{code:":wrench:",desc:"Other changes that dont modify src or test file",emoji:"\u{1F527}",name:"wrench",type:"chore"},{code:":package:",desc:"Make architectural changes",emoji:"\u{1F4E6}",name:"package",type:"build"}],ht=e=>{const o=/^(\S+)\s/,t=/\s(\w+)(?=\(|:)/,i=/\(([^)]+)\)/,a=/:\s([^\n:]+)/s;return{body:e.indexOf(` `)>0?e.slice(Math.max(0,e.indexOf(` `)+1)).trim():void 0,emoji:o.test(e)&&e.match(o)?.[1]||"\u{1F527}",scope:i.test(e)?e.match(i)?.[1]:void 0,subject:a.test(e)&&e.match(a)?.[1]||"Nothing",type:t.test(e)&&e.match(t)?.[1]||"chore"}},ft=({emoji:e,type:o,scope:t,subject:i,issues:a,body:r,issuesType:m})=>{if(!o)return"waiting for selection...";const c=o.toLowerCase(),n=t&&ce(t).replaceAll(/\s+/g," "),u=Ue(ze.spacing(i).replaceAll(/\s+/g," ")),f=a&&a.replace("#","").replaceAll(/\s+/g," ").replaceAll(/[ ./|,]/g,",").split(",").filter(Boolean).map(l=>`${m?`${m} `:""}#${l}`);return`${e} ${c}${n?`(${n})`:""}: ${u}${f&&f?.length>0?` (${f.join(",")})`:""}${r?` ${r}`:""}`},gt=e=>{const[o,...t]=e.split(": ");let i="\u{1F527}";for(const a of D)o.includes(a.type)&&(i=a.emoji);return`${i} ${o}: ${t.join(": ")}`},yt=/^https?:\/\/github\.com\/(.+?)\/(.+?)\.git$|^git@github\.com:(.+?)\/(.+?)\.git$/;var ue=async()=>{try{const o=(await We.get({location:"local"}))?.remote?.origin?.url;if(!o)return;const t=yt.exec(o),[i,a]=t.slice(3);return{owner:i,repoName:a}}catch{return}},bt=async()=>{try{const e=await ue();if(!e)return;const o=new Ke({auth:v.getGithubToken()}),{data:t}=await o.rest.issues.listForRepo({owner:e.owner,repo:e.repoName,state:"open"});return t}catch{return}};const C=Be((e,o)=>({body:"",emoji:"",fetchIssuesList:async()=>{if(await ue()){e({isGithubRepo:!0,issuesLoading:!0});const a=(await bt())?.filter(r=>r.state==="open")||[];a?.length>0?e({issueList:a,issuesLoading:!1}):e({isGithubRepo:!1,issuesLoading:!1})}},isGithubRepo:!1,issueList:[],issues:"",issuesLoading:!1,issuesType:"",message:"",refreshMessage:()=>{const{issues:t,scope:i,subject:a,type:r,emoji:m,body:c,issuesType:n}=o(),u=ft({body:c,emoji:m,issues:t,issuesType:n,scope:i,subject:a,type:r});e({message:u})},scope:"",setEmoji:t=>{e({emoji:t}),o().refreshMessage()},setIssues:t=>{e({issues:t}),o().refreshMessage()},setIssuesType:t=>{e({issuesType:t}),o().refreshMessage()},setMessage:t=>{const i=ht(t);e({...i}),o().refreshMessage()},setScope:t=>{e({scope:ce(t)}),o().refreshMessage()},setStep:t=>{e({step:t}),o().refreshMessage()},setSubject:t=>{e({subject:t}),o().refreshMessage()},setType:t=>{e({type:t}),o().refreshMessage()},step:"type",subject:"",type:""}));var b=(e=>(e.GPT3_5="gpt-3.5-turbo",e.GPT3_5_1106="gpt-3.5-turbo-1106",e.GPT3_5_16K="gpt-3.5-turbo-16k",e.GPT4="gpt-4",e.GPT4_32K="gpt-4-32k",e.GPT4_PREVIEW="gpt-4-1106-preview",e.GPT4_VISION_PREVIEW="gpt-4-vision-preview",e))(b||{});const te={"gpt-3.5-turbo":4096,"gpt-3.5-turbo-1106":16385,"gpt-3.5-turbo-16k":16385,"gpt-4":8196,"gpt-4-1106-preview":128e3,"gpt-4-vision-preview":128e3,"gpt-4-32k":32768},pe={apiBaseUrl:{default:"",type:"string"},diffChunkSize:{default:te[b.GPT3_5]-512,type:"number"},emoji:{default:"emoji",type:"string"},githubToken:{default:"",type:"string"},locale:{default:"",type:"string"},maxLength:{default:100,type:"number"},modelName:{default:b.GPT3_5,type:"string"},openaiToken:{default:"",type:"string"},prompt:{default:"",type:"string"}},oe=new De({projectName:"arietta-compass",schema:pe});Oe.config();const G=e=>oe.get(e),vt=e=>pe[e].default,kt=(e,o)=>oe.set(e,o),de=()=>process.env.OPENAI_API_KEY||G("openaiToken"),he=()=>process.env.OPENAI_PROXY_URL||G("apiBaseUrl"),fe=()=>process.env.GITHUB_TOKEN||process.env.GH_TOKEN||G("githubToken"),St=()=>te[G("modelName")],Tt=()=>{let e=St()-512;const o=G("diffChunkSize");return e>o?e:o},It=()=>({...oe.store,apiBaseUrl:he(),diffChunkSize:Tt(),githubToken:fe(),openaiToken:de()});var v={getCommitConfig:It,getConfig:G,getDefulatConfig:vt,getGithubToken:fe,getOpenAIApiKey:de,getOpenAIProxyUrl:he,setConfig:kt};const Ct=()=>({get:v.getConfig,getDefault:v.getDefulatConfig,set:v.setConfig,store:v.getCommitConfig()}),wt=`You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain WHAT were the changes and WHY the changes were done.I'll enter a git diff summary, and your job is to convert it into a useful commit message.Add a short description of the changes are done after the commit message. Don't start it with "This commit", just describe the changes.Use the present tense. Lines must not be longer than 74 characters.`,ge=D.map(e=>`- ${e.type}: ${e.desc}`).join(` `),jt=v.getConfig("prompt")||wt,Y=v.getConfig("locale"),ye=v.getConfig("maxLength"),xt=()=>Ne.fromMessages([["system",[jt,"## Rules",`- Choose only 1 type from the type-to-description below: <${ge}>`,`- Commit message must be a maximum of ${ye} characters.`,Y&&`- Commit message language: ${Y}`].filter(Boolean).join(` `)],["human","Return only 1 type commit message describes the git diff summary: {summary}"]]),be=["You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain WHAT were the changes and WHY the changes were done.","I'll enter a git diff summary, and your job is to convert it into a useful commit message.","--------","{text}","--------",`Add a short description of the changes are done after the commit message. Don't start it with "This commit", just return only 1 type commit message describes the git diff summary.`].filter(Boolean).join(` `),Pt=[be,"## Rules",`- Choose only 1 type from the type-to-description below: <${ge}>`,`- Commit message must be a maximum of ${ye} characters.`,Y&&`- Commit message language: ${Y}`].filter(Boolean).join(` `),At=re.fromTemplate(be),Et=re.fromTemplate(Pt),ve=e=>Ve(String(e)).length;class $t{model;config;textSplitter;prompt;constructor(){this.config=v.getCommitConfig(),this.config.openaiToken||F.error(`Please set the OpenAI Token by ${Re.bold.yellow("arietta-compass --config")}`,!0),this.model=new _e({configuration:{baseURL:this.config.apiBaseUrl},maxRetries:10,modelName:this.config.modelName,openAIApiKey:this.config.openaiToken,temperature:.5}),this.textSplitter=new Ge({chunkOverlap:0,chunkSize:this.config.diffChunkSize,lengthFunction:o=>ve(o)}),this.prompt=xt()}async genCommit({setLoadingInfo:o,setSummary:t,cacheSummary:i}){o(" Generating...");const a=i||await this.genSummary({setLoadingInfo:o,setSummary:t}),r=await this.prompt.formatMessages({summary:a}),m=await this.model.call(r);return m.text||F.error("Diff summary failed, please check your network or try again...",!0),gt(m.text.replace(/\((.*?)\):/,(c,n)=>c&&`(${n.toLowerCase()}):`))}async checkDiffMaxToken(o){const t=await this.prompt.formatMessages({summary:o});return ve(JSON.stringify(t))>te[this.config.modelName]-1024}async genSummary({setLoadingInfo:o,setSummary:t}){let i;const a=this.getDiff();if(await this.checkDiffMaxToken(a)){a||F.warn("No changes to commit",!0);const m=await this.textSplitter.createDocuments([a]);i=a,o(` [1/3] Split diff info to (${m.length}) by ${this.config.diffChunkSize} chunk size...`);const c=Le(this.model,{questionPrompt:At,refinePrompt:Et,type:"refine"});o(` [2/3] Split diff info to (${m.length} * ${this.config.diffChunkSize} chunk-size), generate summary...`);const n=await c.call({input_documents:m});n.text||F.error("Diff summary failed, please check your network or try again...",!0),i=String(n.text),o(" [3/3] Generate commit message..."),t(i)}else i=a;return i}getDiff(){return Me("git diff --staged --ignore-all-space --diff-algorithm=minimal --function-context --no-ext-diff --no-color",{maxBuffer:1024**6}).toString()}}const ke=({setMessage:e,onSuccess:o,onError:t,...i}={})=>{const a=$e(new $t),[r,m]=g(""),[c,n]=g(" Generating..."),[u,f]=g(!1),[l,T]=g(!0),[J,z]=g(Date.now().toString()),{data:H,isLoading:p}=Fe(u?J:null,async()=>a.current.genCommit({cacheSummary:r,setLoadingInfo:n,setSummary:m}),{onError:($,...Q)=>{t?.($,...Q),F.error($,!0)},onErrorRetry:()=>!1,onSuccess:($,...Q)=>{f(!1),$&&e?.($),o?.($,...Q),T(!1)},...i}),I=h(()=>{z(Date.now().toString()),T(!0),f(!0)},[]),Ce=h(()=>{m(""),z(Date.now().toString()),T(!0),f(!0)},[]),we=h(()=>{T(!1),f(!1)},[]);return{loading:p||l,loadingInfo:c,message:H,restart:Ce,start:I,stop:we,summary:r}},Ft=y(()=>{const[e,o]=g(""),t=j(),{summary:i,start:a,loadingInfo:r,loading:m}=ke({setMessage:o});return A(()=>{a()},[a]),s(w,{footer:i&&S(d,{color:t.colorTextDescription,children:[s(d,{bold:!0,children:"\u{1F449} DIFF SUMMARY: "}),i]}),reverse:!0,title:"\u{1F92F} AI Commit Generator",children:!m&&e?s(d,{children:e}):s(L,{label:r})})});var _t=Ft;const V={CONTENTS:`#!/usr/bin/env sh # arietta-compass as a commit hook if npx -v >&/dev/null then exec < /dev/tty npx -c "arietta-compass --hook $1 $2" else exec < /dev/tty arietta-compass --hook $1 $2 fi`,FILENAME:"prepare-commit-msg",PERMISSIONS:509},X="not git";var se=e=>{try{try{const{stdout:o}=W("git",["config","--get","core.hooksPath"]);return me.resolve(o,e)}catch{const{stdout:o}=W("git",["rev-parse","--absolute-git-dir"]);return me.resolve(o+"/hooks",e)}}catch{return F.error("Please check if this is a git folder",!0),X}};const Rt=y(()=>{const{message:e,setMessage:o,setStep:t}=C(l=>({message:l.message,setMessage:l.setMessage,setStep:l.setStep}));N(h((l,T)=>T.tab&&t("type"),[]));const i=j(),{summary:a,start:r,loadingInfo:m,loading:c,restart:n}=ke({setMessage:o}),u=h(l=>{switch(l.value){case"reloadFromSummary":{r();break}case"reload":{n();break}case"edit":{t("type");break}case"confirm":{t("commit");break}}},[r,n]);A(()=>{r()},[r]);const f=B(()=>[a&&{label:"\u{1F504}\uFE0F Regenerate commit message from summary [FAST]",value:"reloadFromSummary"},{label:"\u{1F504}\uFE0F Regenerate full commit message [SLOW]",value:"reload"},{label:"\u270F\uFE0F Edit this message",value:"edit"},{label:"\u2705 Use this message",value:"confirm"}].filter(Boolean),[a]);return S(w,{footer:!c&&e&&s(_,{items:f,onSelect:u}),title:"\u{1F92F} AI Commit Generator",children:[a&&s(Z,{direction:"bottom",children:S(d,{color:i.colorTextDescription,children:[s(d,{bold:!0,children:"\u{1F449} DIFF SUMMARY: "}),a]})}),!c&&e?s(d,{children:e}):s(L,{label:m})]})});var Lt=Rt;const Gt=y(({step:e,steps:o,title:t})=>{const i=j();return S(d,{children:[s(Ae,{color:i.colorText,children:`${e}/${o}`}),s(d,{bold:!0,children:` ${t.toUpperCase()}`})]})});var U=Gt;const Mt=y(()=>{const{message:e,setIssues:o,setStep:t,issues:i,fetchIssuesList:a,isGithubRepo:r,issuesLoading:m}=C(p=>({fetchIssuesList:p.fetchIssuesList,isGithubRepo:p.isGithubRepo,issues:p.issues,issuesLoading:p.issuesLoading,message:p.message,refreshMessage:p.refreshMessage,setIssues:p.setIssues,setStep:p.setStep}),E),c=C(p=>p.issueList,Ye);N(h((p,I)=>I.tab&&t("subject"),[]));const[n,u]=g(""),f=j();A(()=>{a()},[]);const l=B(()=>{let p=c;return n&&(p=p.filter(I=>I.title.toLowerCase().includes(n)||String(I.number).includes(n))),p.map(I=>({label:S(ae,{children:[s(d,{backgroundColor:f.colorBgLayout,color:f.colorText,children:` #${I.number} `}),` ${I.title}`]}),value:String(I.number)}))},[n,c]),T=h(p=>{u(p.replaceAll(" ",""))},[]),J=h(p=>{o(p.join(",")),u("")},[]),z=h(()=>s(k,{defaultValue:n,onChange:O(T,100),placeholder:"Input to keywords to filter issues, press [Space] to multi-select..."}),[i]),H=h(()=>{t(i?"issuesType":"commit")},[i]);return s(w,{footer:s(d,{children:e}),header:s(U,{step:4,steps:4,title:"Link issues (optional)"}),children:r?m?s(L,{label:" Loading issues..."}):S(ae,{children:[s(z,{}),S(Z,{children:[s(Ee,{defaultValue:i.split(","),onChange:J,onSubmit:H,options:l}),l.length===0&&s(d,{color:f.colorWarning,children:"No issues found, press [Enter] to skip..."})]})]}):s(k,{defaultValue:i,onChange:O(o,100),onSubmit:H,placeholder:"Input number to link issues, press [Enter] to confirm or skip..."})})});var Nt=Mt;const Ot=[{label:"Only link issues",value:""},{label:"close #X",value:"close"},{label:"fix #X",value:"fix"},{label:"resolve #X",value:"resolve"}],Dt=y(()=>{const{message:e,setIssuesType:o,setStep:t}=C(i=>({message:i.message,setIssuesType:i.setIssuesType,setStep:i.setStep}),E);return N(h((i,a)=>a.tab&&t("issues"),[])),s(w,{footer:s(d,{children:e}),header:s(U,{step:4,steps:4,title:"Link issues (optional)"}),children:s(_,{items:Ot,onHighlight:i=>o(i.value),onSelect:()=>t("commit")})})});var Vt=Dt;const q=y(({item:e})=>{const o=j();return S(ne,{children:[s(ne,{marginRight:1,width:20,children:s(d,{backgroundColor:o.colorBgLayout,color:o.colorText,children:` ${[e.emoji,e.type].filter(Boolean).join(" ")} `})}),s(d,{color:o.colorTextDescription,children:`- ${e.desc}`})]},e.name)}),Ut=y(()=>s(w,{title:"\u{1F92F} Gitmoji list",children:D.map(e=>s(q,{item:e},e.name))}));var zt=Ut;const Se="Use Input Value",Ht=[{label:"Input commit scope",value:Se},{label:"Package management changes, such as adding, updating, or removing dependencies",value:"deps"},{label:"Configuration file changes, such as adding, updating, or removing configuration options",value:"config"},{label:"User interface changes, such as layout, style, or interaction modifications",value:"ui"},{label:"API interface changes, such as adding, modifying, or removing API endpoints",value:"api"},{label:"Database changes, such as adding, modifying, or removing tables, fields, or indexes",value:"database"},{label:"Data model changes, such as adding, modifying, or removing data models",value:"model"},{label:"Controller changes, such as adding, modifying, or removing controllers",value:"controller"},{label:"View changes, such as adding, modifying, or removing views",value:"view"},{label:"Route changes, such as adding, modifying, or removing routes",value:"route"},{label:"Test changes, such as adding, modifying, or removing test cases",value:"test"}],Bt=Ht.map(e=>({label:s(q,{item:{desc:e.label,name:e.value,type:e.value}}),value:e.value})),Kt=y(()=>{const{message:e,setScope:o,setStep:t,scope:i}=C(l=>({message:l.message,scope:l.scope,setScope:l.setScope,setStep:l.setStep}),E);N(h((l,T)=>T.tab&&t("type"),[]));const[a,r]=g(!0),[m,c]=g(""),n=h(()=>{t("subject")},[]),u=h(l=>{a&&(o(l),c(l))},[a]),f=h(l=>{l.value===Se?(r(!0),o(m)):(r(!1),o(l.value))},[]);return S(w,{footer:s(d,{children:e}),header:s(U,{step:2,steps:4,title:"Input commit scope (optional)"}),children:[s(k,{defaultValue:i,onChange:O(u,100),onSubmit:n,placeholder:"Input commit <scope>, or select below, press [Enter] to skip..."}),s(Z,{children:s(_,{itemComponent:({label:l})=>l,items:Bt,onHighlight:f,onSelect:n})})]})});var Wt=Kt;const Yt=y(()=>{const{message:e,setSubject:o,setStep:t,subject:i}=C(a=>({message:a.message,setStep:a.setStep,setSubject:a.setSubject,subject:a.subject}),E);return N(h((a,r)=>r.tab&&t("scope"),[])),s(w,{footer:s(d,{children:e}),header:s(U,{step:3,steps:4,title:"Input commit subject"}),children:s(k,{defaultValue:i,onChange:O(o,100),onSubmit:()=>i&&t("issues"),placeholder:"Input commit <subject>..."})})});var Xt=Yt;const qt=v.getConfig("emoji")==="emoji",Jt="ai",Qt={label:s(q,{item:{desc:"generate commit message by ChatGPT",emoji:"\u{1F92F}",name:"ai",type:"Use AI Commit"}}),value:"ai"},Zt=y(()=>{const{setType:e,setStep:o,setEmoji:t,type:i}=C(n=>({setEmoji:n.setEmoji,setStep:n.setStep,setType:n.setType,type:n.type}),E),[a,r]=g(i),m=B(()=>{let n=D;return a?n=n.filter(u=>u.type.includes(a)):i&&(n=n.filter(u=>u.type.includes(i))),n.map(u=>({label:s(q,{item:u}),value:`${qt?u.emoji:u.code} ${u.type}`}))},[a,i]),c=h(n=>{if(n.value===Jt)o("ai");else{const u=n.value.split(" ");t(u[0]),e(u[1]),o("scope")}},[]);return s(w,{footer:s(k,{defaultValue:i,onChange:O(r,100),placeholder:"Search commit <type>..."}),header:s(U,{step:1,steps:4,title:"Select commit type"}),reverse:!0,children:s(_,{itemComponent:({label:n})=>n,items:[...m,Qt],onSelect:c})})});var eo=Zt;const to=y(({hook:e})=>{const{message:o}=C(a=>({message:a.message}),E),[t,i]=g(!0);try{return A(()=>{e?(K.writeFileSync(process.argv[3],o),i(!1)):(W("git",["add","--all"]),W("git",["commit","-m",o],{buffer:!1,stdio:"inherit"}),i(!1))},[]),t?s(L,{label:" Committing..."}):s(P,{variant:"success",children:" Successfully committed!"})}catch(a){return s(P,{variant:"error",children:` ${a.message}`})}});var oo=to;const so=y(({hook:e})=>{const[o,t]=g(!1),{step:i}=C(a=>({step:a.step}),E);if(A(()=>{const a=se(V.FILENAME);a===X&&He.exit(1),K.existsSync(a)&&t(!0)},[]),!e&&o)return s(P,{variant:"warning",children:'Arietta Compass is in hook mode, use "git commit" instead.'});if(i==="type")return s(eo,{});if(i==="scope")return s(Wt,{});if(i==="subject")return s(Xt,{});if(i==="issues")return s(Nt,{});if(i==="issuesType")return s(Vt,{});if(i==="ai")return s(Lt,{});if(i==="commit")return s(oo,{hook:e})});var Te=so;D.map(e=>`- ${e.type}: ${e.desc}`).join(` `),v.getConfig("prompt"),v.getConfig("locale"),v.getConfig("maxLength");const ie=`You are to act as the author of a commit message in git. Your mission is to create clean and comprehensive commit messages in the conventional commit convention and explain WHAT were the changes and WHY the changes were done.I'll enter a git diff summary, and your job is to convert it into a useful commit message.Add a short description of the changes are done after the commit message. Don't start it with "This commit", just describe the changes.Use the present tense. Lines must not be longer than 74 characters.`,io=y(()=>{const[e,o]=g(),{store:t,set:i,getDefault:a}=Ct(),r=(c,n)=>{i(c,n),o("")},m=B(()=>[{children:s(_,{items:[{label:"\u{1F604}",value:"emoji"},{label:":smile:",value:"code"}],onSelect:c=>r("emoji",c.value)}),defaultValue:a("emoji"),key:"emoji",label:"Emoji format",value:t.emoji},{children:s(k,{defaultValue:t.locale,onSubmit:c=>r("locale",c),placeholder:"Input commit message locale..."}),defaultValue:a("locale")||"en_US",desc:"Commit message locale, default as en_US",key:"local",label:"AI message locale",value:t.locale||"en_US"},{children:s(k,{defaultValue:t.prompt,onSubmit:c=>r("prompt",c),placeholder:"Input ChatGPT prompt..."}),defaultValue:a("prompt")||ie,desc:ie,key:"prompt",label:"Custom prompt",showValue:!1,value:t.prompt||ie},{children:s(_,{items:[{label:b.GPT3_5,value:b.GPT3_5},{label:b.GPT3_5_1106,value:b.GPT3_5_1106},{label:b.GPT3_5_16K,value:b.GPT3_5_16K},{label:b.GPT4,value:b.GPT4},{label:b.GPT4_PREVIEW,value:b.GPT4_PREVIEW},{label:b.GPT4_32K,value:b.GPT4_32K}],onSelect:c=>r("modelName",c.value)}),defaultValue:a("modelName"),desc:`Default model as ${a("modelName")}`,key:"modelName",label:"Model Name",value:t.modelName},{children:s(k,{defaultValue:String(t.diffChunkSize),onSubmit:c=>r("diffChunkSize",Number(c)),placeholder:"Input diff split chunk size ..."}),defaultValue:a("diffChunkSize"),desc:`Default chunk size as ${a("diffChunkSize")}`,key:"diffChunkSize",label:"Diff split chunk size",value:t.diffChunkSize},{children:s(k,{defaultValue:String(t.maxLength),onSubmit:c=>r("maxLength",Number(c)),placeholder:"Input maximum character length of the generated commit message..."}),defaultValue:a("maxLength"),desc:`The maximum character length of the generated commit message, default max-length as ${a("maxLength")}`,key:"maxLength",label:"Commit message max-length",value:t.maxLength},{children:s(k,{defaultValue:t.openaiToken,onSubmit:c=>r("openaiToken",c),placeholder:"Input OpenAI token..."}),defaultValue:a("openaiToken"),key:"openaiToken",label:"OpenAI token",showValue:!1,value:t.openaiToken},{children:s(k,{defaultValue:t.apiBaseUrl,onSubmit:c=>r("apiBaseUrl",c),placeholder:"Set openAI API proxy, default value: https://api.openai.com/v1/..."}),defaultValue:a("apiBaseUrl"),desc:"OpenAI API proxy, default value: https://api.openai.com/v1/",key:"apiBaseUrl",label:"OpenAI API proxy",showValue:!1,value:t.apiBaseUrl},{children:s(k,{defaultValue:t.githubToken,onSubmit:c=>r("githubToken",c),placeholder:"Input Github token..."}),defaultValue:a("githubToken"),key:"githubToken",label:"Github token",showValue:!1,value:t.githubToken}],[t]);return s(je,{active:e,items:m,logo:"\u{1F92F}",setActive:o,title:"Arietta Compass Config"})});var ao=io;const no=y(()=>{const[e,o]=g(!0),t=j();try{return A(()=>{const i=se(V.FILENAME);i===X&&le.exit(1),K.writeFileSync(i,V.CONTENTS,{mode:V.PERMISSIONS}),o(!1)},[]),e?s(L,{label:" Loading..."}):S(P,{variant:"success",children:[" arietta-compass hook ",s(d,{color:t.colorSuccess,children:"created"})," successfully!"]})}catch{return s(P,{variant:"error",children:" arietta-compass commit hook is not created"})}});var ro=no;const co=y(()=>{const[e,o]=g(!0),t=j();try{return A(()=>{const i=se(V.FILENAME);i===X&&le.exit(1),K.unlinkSync(i),o(!1)},[]),e?s(L,{label:" Loading..."}):S(P,{variant:"success",children:[" arietta-compass hook ",s(d,{color:t.colorError,children:"removed"})," successfully!"]})}catch{return s(P,{variant:"error",children:" arietta-compass commit hook is not found"})}});var lo=co;const mo=Pe({pkg:ee,shouldNotifyInNpmScript:!0});mo.notify({isGlobal:!0});const Ie=new xe;Ie.name("arietta-compass").description(ee.description).version(ee.version).addOption(new R("--hook","Interactively commit using the prompts")).addOption(new R("-a, --ai","Generate prompts by ChatGPT")).addOption(new R("-o, --option","Setup arietta-compass preferences")).addOption(new R("-i, --init","Initialize arietta-compass as a commit hook")).addOption(new R("-r, --remove","Remove a previously initialized commit hook")).addOption(new R("-l, --list","List all commit types supported")).parse();const M=Ie.opts();M.ai?x(s(_t,{})):M.option?x(s(ao,{})):M.init?x(s(ro,{})):M.remove?x(s(lo,{})):M.list?x(s(zt,{})):M.hook?x(s(Te,{hook:!0})):x(s(Te,{}));