aicommit2
Version:
A Reactive CLI that generates commit messages for Git and Jujutsu with various AI
6 lines (3 loc) • 6.21 kB
JavaScript
import _ from"chalk";import{concatMap as A,from as D,map as N,catchError as O}from"rxjs";import{fromPromise as S}from"rxjs/internal/observable/innerFrom";import{A as T,l as R,a as x,b as C,e as E,c as L,d as $}from"./ai.service-d8e94c3a.mjs";import{G as k,b as v,g as U,w as y,x as P,y as F,z as B}from"./cli-8ee62906.mjs";import{i as j}from"./openai-5eabc0ae.mjs";import"fs";import"path";import"@pacote/xxhash";import"winston";import"cleye";import"module";import"crypto";import"os";import"node:buffer";import"node:path";import"node:child_process";import"node:process";import"child_process";import"node:url";import"node:os";import"assert";import"events";import"node:fs";import"buffer";import"stream";import"util";import"node:util";import"inquirer";import"fs/promises";import"readline";import"figlet";import"gradient-string";import"ora";import"inquirer-reactive-list-prompt";import"winston-daily-rotate-file";import"axios";import"url";import"node:fs/promises";import"chokidar";import"rxjs/operators";import"http";import"https";import"net";import"tls";import"tty";class V extends T{constructor(r){super(r),this.params=r,this.baseURL=k,this.colors={primary:"#24292e",secondary:"#FFF"},this.serviceName=_.bgHex(this.colors.primary).hex(this.colors.secondary).bold(`[GitHub Models${this.formatModelSuffix()}]`),this.errorPrefix=_.red.bold(`[GitHub Models${this.formatModelSuffix()}]`)}getServiceSpecificErrorMessage(r){switch(r.code){case"MISSING_TOKEN":return"GitHub token is required. Run: aicommit2 github-login";case"AUTHENTICATION_FAILED":return"Authentication failed. Your GitHub token may be expired or invalid. Run: aicommit2 github-login";case"ACCESS_DENIED":return'Access denied. Make sure your token has "models: read" permission in GitHub settings';case"INVALID_MODEL_ID":return'Invalid model ID. Use format "publisher/model" (example: openai/gpt-4o-mini)';case"MODEL_NOT_FOUND":return"Model not found in GitHub Models catalog. Check with: gh models list";case"NO_CONTENT":return"No content received from GitHub Models. The model may have failed to generate a response";default:return null}}generateCommitMessage$(){return S(this.generateMessage("commit")).pipe(A(r=>D(r)),N(this.formatAsChoice),O(this.handleError$))}generateCodeReview$(){return S(this.generateMessage("review")).pipe(A(r=>D(r)),N(this.formatCodeReviewAsChoice),O(this.handleError$))}async generateMessage(r){if(!this.params.config.key){const u=new Error("GitHub token is required for GitHub Models. Use: aicommit2 github-login");throw u.code="MISSING_TOKEN",u}const s=this.params.stagedDiff.diff,{generate:i,type:f}=this.params.config,n=this.buildPromptOptions(),M=r==="review"?v(n):U(n),p=await this.makeRequest(M,s,r);return r==="review"?this.parseCodeReview(p):this.parseMessage(p,f,i)}async makeRequest(r,s,i){const f=Array.isArray(this.params.config.model)?this.params.config.model[0]:this.params.config.model||y;let n;try{n=P(f)}catch(o){const e=new Error(o instanceof Error?o.message:String(o));throw e.code="INVALID_MODEL_ID",e}const M=[{role:"system",content:r},{role:"user",content:i==="review"?s:`Here's the diff:
${s}`}],p=j(n),u={messages:M,model:n,stream:!1,...p?{max_completion_tokens:this.params.config.maxTokens||1024,temperature:1}:{max_tokens:this.params.config.maxTokens||1024,top_p:this.params.config.topP||.95,temperature:this.params.config.temperature||.7}},b=`${this.baseURL}${F}`,I={"Content-Type":"application/json",Accept:"application/vnd.github+json","X-GitHub-Api-Version":B,Authorization:`Bearer ${this.params.config.key}`},{logging:m}=this.params.config;R(s,i,"GitHub Models",n,b,I,m),x(s,i,"GitHub Models",r,i==="review"?s:`Here's the diff:
${s}`,m),C(s,i,"GitHub Models",u,m);const H=new AbortController,G=setTimeout(()=>H.abort(),this.params.config.timeout);try{const o=Date.now(),e=await fetch(b,{method:"POST",headers:I,body:JSON.stringify(u),signal:H.signal});if(clearTimeout(G),!e.ok){const a=await e.text(),d={status:e.status,statusText:e.statusText,url:b,headers:Object.fromEntries(e.headers),body:a};E(s,i,"GitHub Models",d,m);let h=`GitHub API request failed: ${e.status} ${e.statusText}`;try{const t=JSON.parse(a);t.error?.message?h+=` - ${t.error.message}`:t.message&&(h+=` - ${t.message}`)}catch{a&&(h+=` - ${a}`)}if(e.status===401){const t=new Error("GitHub authentication failed. Please run: aicommit2 github-login");throw t.status=e.status,t.code="AUTHENTICATION_FAILED",t.content=a,t}else if(e.status===403){const t=new Error('GitHub Models access denied. Make sure your token has "models: read" permission.');throw t.status=e.status,t.code="ACCESS_DENIED",t.content=a,t}else if(e.status===404){const t=new Error(`Model "${n}" not found in GitHub Models catalog. Check with: gh models list`);throw t.status=e.status,t.code="MODEL_NOT_FOUND",t.content=a,t}else if(e.status===422){const t=new Error(`GitHub Models rejected model "${n}". Use format "publisher/model" (example: openai/gpt-4o-mini).`);throw t.status=e.status,t.code="INVALID_MODEL_ID",t.content=a,t}else if(e.status===429){const t=new Error("Rate limit exceeded. Please try again later.");throw t.status=e.status,t.code="RATE_LIMIT_EXCEEDED",t.content=a,t}const g=new Error(h);throw g.status=e.status,g.code="API_ERROR",g.content=a,g}const c=await e.json(),w=Date.now()-o;L(s,i,"GitHub Models",c,m);const l=c.choices?.[0]?.message?.content?.trim();if(!l){E(s,i,"GitHub Models",{message:"No content found in GitHub Models response",result:c},m);const d=new Error("No response content received from GitHub Models");throw d.code="NO_CONTENT",d.content=JSON.stringify(c,null,2),d}return $(s,i,"GitHub Models",w,l,m),l}catch(o){if(clearTimeout(G),o instanceof Error&&o.name==="AbortError"){const w={message:`GitHub Models request timeout after ${this.params.config.timeout}ms`,error:o};E(s,i,"GitHub Models",w,m);const l=new Error(`GitHub Models request timed out after ${this.params.config.timeout}ms`);throw l.code="REQUEST_TIMEOUT",l.originalError=o,l}if(o.code)throw o;E(s,i,"GitHub Models",{message:"GitHub Models request failed",error:o},m);const c=new Error(`GitHub Models request failed: ${o instanceof Error?o.message:String(o)}`);throw c.code="REQUEST_FAILED",c.originalError=o,c}}}export{V as GitHubModelsService};