aicommit2
Version:
A Reactive CLI that generates commit messages for Git and Jujutsu with various AI
2 lines (1 loc) • 4.69 kB
JavaScript
import k from"chalk";import{Ollama as H}from"ollama";import{concatMap as w,from as A,map as C,catchError as v}from"rxjs";import{fromPromise as P}from"rxjs/internal/observable/innerFrom";import{fetch as L,Agent as z}from"undici";import{A as U,l as x,a as M,b as O,c as R,d as S,e as _}from"./ai.service-d8e94c3a.mjs";import{u as E,t as b,c as I,P as N,b as B,g as T,H as G}from"./cli-8ee62906.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";class J extends U{constructor(s){super(s),this.params=s,this.host=E,this.model="",this.key="",this.auth="",this.generateStreamingCommitMessage$=()=>{const{generate:t,type:e}=this.params.config;return this.createStreamingCommitMessages$(o=>{this.streamChunks(o).catch(a=>o.error(a))},e,t)},this.streamChunks=async t=>{const e=this.params.stagedDiff.diff,{logging:o}=this.params.config,a=this.buildCommitPrompt();await this.checkIsAvailableOllama();const h=`Here is the diff: ${e}`,i=`Ollama_${this.model}`,l=`${this.host}/api/chat`,r=this.key?{Authorization:`${this.auth} ${this.key}`}:{};x(e,"commit",i,this.model,l,r,o),M(e,"commit",i,a,h,o);const{numCtx:m,temperature:n,topP:c,timeout:f,maxTokens:p}=this.params.config,g={model:this.model,messages:[{role:"system",content:a},{role:"user",content:h}],stream:!0,keep_alive:f,options:{num_ctx:m,temperature:n,top_p:c,seed:b(10,1e3),num_predict:p??-1}};O(e,"commit",i,g,o);const d=Date.now();let $="";try{const u=await this.ollama.chat(g);for await(const F of u){const y=F.message.content;y&&($+=y,t.next(y))}const D=Date.now()-d;R(e,"commit",i,{streamed:!0,totalLength:$.length},o),S(e,"commit",i,D,$,o),t.complete()}catch(u){_(e,"commit",i,u,o),t.error(u)}},this.setupFetch=(t,e={})=>L(t,{...e,dispatcher:new z({headersTimeout:this.params.config.timeout})}),this.colors={primary:"#FFF",secondary:"#000"},this.model=this.params.keyName,this.serviceName=k.bgHex(this.colors.primary).hex(this.colors.secondary).bold(`[${I(this.model)}]`),this.errorPrefix=k.red.bold(`[${I(this.model)}]`),this.host=this.params.config.host||E,this.auth=this.params.config.auth||"Bearer",this.key=this.params.config.key||"",this.ollama=new H({host:this.host,fetch:this.setupFetch,...this.key&&{headers:{Authorization:`${this.auth} ${this.key}`}}})}getServiceSpecificErrorMessage(s){const t=s.message||"";return t.includes("ECONNREFUSED")||t.includes("connection refused")?N.ollamaNotRunning():t.includes("model")&&(t.includes("not found")||t.includes("404"))?N.ollamaModelNotPulled(this.model):null}generateCommitMessage$(){return this.params.config.stream||!1?this.generateStreamingCommitMessage$():P(this.generateMessage("commit")).pipe(w(t=>A(t)),C(this.formatAsChoice),v(this.handleError$))}generateCodeReview$(){return P(this.generateMessage("review")).pipe(w(s=>A(s)),C(this.formatCodeReviewAsChoice),v(this.handleError$))}async generateMessage(s){const t=this.params.stagedDiff.diff,{logging:e,generate:o,type:a}=this.params.config,h=this.buildPromptOptions(),i=s==="review"?B(h):T(h);await this.checkIsAvailableOllama();const l=`Here is the diff: ${t}`,r=`Ollama_${this.model}`,m=`${this.host}/api/chat`,n=this.key?{Authorization:`${this.auth} ${this.key}`}:{};x(t,s,r,this.model,m,n,e),M(t,s,r,i,l,e);const c=await this.createChatCompletions(i,l,s);return s==="review"?this.parseCodeReview(c):this.parseMessage(c,a,o)}async checkIsAvailableOllama(){const s=new G({method:"GET",baseURL:`${this.host}`,timeout:this.params.config.timeout});return this.key&&s.setHeaders({Authorization:`${this.auth} ${this.key}`}),(await s.execute()).data}async createChatCompletions(s,t,e){const{numCtx:o,temperature:a,topP:h,timeout:i,maxTokens:l,logging:r}=this.params.config,m=this.params.stagedDiff.diff,n=`Ollama_${this.model}`,c={model:this.model,messages:[{role:"system",content:s},{role:"user",content:t}],stream:!1,keep_alive:i,options:{num_ctx:o,temperature:a,top_p:h,seed:b(10,1e3),num_predict:l??-1}};O(m,e,n,c,r);const f=Date.now();try{const p=await this.ollama.chat(c),g=Date.now()-f,d=p.message.content;return R(m,e,n,{response:d,fullResponse:p},r),S(m,e,n,g,d,r),d}catch(p){throw _(m,e,n,p,r),p}}}export{J as OllamaService};