copilot-api-node20 0.9.0 → 0.9.1

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/main.js +1 -1
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{CompletionLogger as I,GITHUB_API_BASE_URL as L,GITHUB_APP_SCOPES as me,GITHUB_BASE_URL as J,GITHUB_CLIENT_ID as K,HTTPError as y,PATHS as k,copilotBaseUrl as j,copilotHeaders as N,ensurePaths as q,forwardError as A,getGitHubUser as fe,githubHeaders as W,initializeVSCodeIdentifiers as he,standardHeaders as V,state as s}from"./get-user-BJ4s6iMX.js";import{defineCommand as x,runMain as ge}from"citty";import r from"consola";import S from"node:fs/promises";import z from"node:os";import ye from"clipboardy";import h from"node:process";import{serve as we}from"srvx";import ke from"tiny-invariant";import{execSync as be}from"node:child_process";import{Hono as b}from"hono";import{cors as _e}from"hono/cors";import{streamSSE as Q}from"hono/streaming";import{events as ve}from"fetch-event-stream";import{request as Ce}from"undici";var Te=class extends EventTarget{isOnline=!0;lastChecked=new Date().toISOString();consecutiveFailures=0;lastErrorType;lastErrorMessage;lastSuccessfulEndpoint;endpointFailureStats={};checkInterval;abortController;on(e,t){return this.addEventListener(e,t),this}off(e,t){return this.removeEventListener(e,t),this}start(){if(!s.connectivity.enabled){r.debug("Network monitoring disabled");return}r.info("Starting network monitor",{probeEndpoints:s.connectivity.probeEndpoints,fastInterval:s.connectivity.fastProbeInterval}),this.scheduleNextCheck();let e=()=>{this.stop(),process.exit(0)};process.on("SIGINT",e),process.on("SIGTERM",e)}stop(){r.debug("Stopping connectivity monitor"),this.checkInterval&&=(clearTimeout(this.checkInterval),void 0),this.abortController&&=(this.abortController.abort(),void 0)}scheduleNextCheck(){this.checkInterval&&clearTimeout(this.checkInterval);let e=this.isOnline?s.connectivity.slowProbeInterval:s.connectivity.fastProbeInterval,t=Math.random()*s.connectivity.jitterMaxMs,o=e+t;this.checkInterval=setTimeout(()=>{this.performConnectivityCheck().catch(n=>{r.error("Connectivity check failed:",n)})},o)}async performConnectivityCheck(){this.abortController=new AbortController;let e=setTimeout(()=>this.abortController?.abort(),s.connectivity.timeoutMs);try{let t=!1;for(let o of s.connectivity.probeEndpoints)try{if((await fetch(o,{method:"HEAD",signal:this.abortController.signal,headers:{"\u0055\u0073\u0065\u0072\u002d\u0041\u0067\u0065\u006e\u0074":"service-api-connectivity-monitor/1.0",...s.connectivity.dnsCache&&{"Cache-Control":"max-age=300"}}})).ok){t=!0,this.lastSuccessfulEndpoint=o;break}}catch(n){this.endpointFailureStats[o]=(this.endpointFailureStats[o]||0)+1,r.debug(`Probe failed for ${o}:`,n)}this.updateConnectivityState(t)}catch(t){this.handleConnectivityError(t)}finally{clearTimeout(e),this.scheduleNextCheck()}}updateConnectivityState(e){let t=this.isOnline;this.isOnline=e,this.lastChecked=new Date().toISOString(),e?(this.consecutiveFailures>0&&r.info(`Connectivity restored after ${this.consecutiveFailures} failures`),this.consecutiveFailures=0,this.lastErrorType=void 0,this.lastErrorMessage=void 0,t||this.dispatchEvent(new CustomEvent("online"))):(this.consecutiveFailures++,t&&(r.warn("Network lost"),this.dispatchEvent(new CustomEvent("offline"))))}handleConnectivityError(e){this.lastErrorType=e.name,this.lastErrorMessage=e.message,r.error("Connectivity check failed:",e),this.updateConnectivityState(!1)}getConnectivityStats(){return{isOnline:this.isOnline,lastChecked:this.lastChecked,consecutiveFailures:this.consecutiveFailures,lastErrorType:this.lastErrorType,lastErrorMessage:this.lastErrorMessage}}getPerformanceStats(){let e=this.isOnline?s.connectivity.slowProbeInterval:s.connectivity.fastProbeInterval,t=new Date(Date.now()+e+Math.random()*s.connectivity.jitterMaxMs).toISOString();return{currentInterval:e,nextCheckEstimate:t,lastSuccessfulEndpoint:this.lastSuccessfulEndpoint,endpointFailureStats:{...this.endpointFailureStats},jitterEnabled:s.connectivity.jitterMaxMs>0,connectionPooling:s.connectivity.connectionPooling,dnsCache:s.connectivity.dnsCache}}};const C=new Te,X=async()=>{let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${L}/\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/v2/token`,{headers:W(s),signal:e.signal});if(!n.ok)throw new y("\u0046\u0061\u0069\u006c\u0065\u0064\u0020\u0074\u006f\u0020\u0067\u0065\u0074\u0020\u0043\u006f\u0070\u0069\u006c\u006f\u0074\u0020\u0074\u006f\u006b\u0065\u006e",n);return await n.json()}finally{clearTimeout(o)}};async function xe(){let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${J}/login/device/code`,{method:"POST",headers:V(),body:JSON.stringify({client_id:K,scope:me}),signal:e.signal});if(!n.ok)throw new y("Failed to get device code",n);return await n.json()}finally{clearTimeout(o)}}const Se=async()=>{let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${j(s)}/models`,{headers:N(s),signal:e.signal});if(!n.ok)throw new y("Failed to get models",n);return await n.json()}finally{clearTimeout(o)}};function Y(){return"1.105.0-insider"}Y();const E=e=>new Promise(t=>{setTimeout(t,e)}),$e=e=>e==null;async function Z(){let e=await Se();s.models=e}const Ie=()=>{let e=Y();s.vsCodeVersion=e,r.info(`Using VSCode version:${e}`)};async function Ae(e){let t=(e.interval+1)*1e3;for(r.debug(`Polling access token with interval of ${t}ms`);;){let o=new AbortController,n=s.timeoutMs??12e4,a=setTimeout(()=>{o.abort()},n);try{let i=await fetch(`${J}/login/oauth/access_token`,{method:"POST",headers:V(),body:JSON.stringify({client_id:K,device_code:e.device_code,grant_type:"urn:ietf:params:oauth:grant-type:device_code"}),signal:o.signal});if(!i.ok){await E(t),r.error("Failed to poll access token:",await i.text());continue}let l=await i.json();r.debug("Polling access token response:",l);let{access_token:u}=l;if(u)return u;await E(t)}catch(i){if(i instanceof Error&&i.name==="AbortError"){r.error("Access token polling timed out"),await E(t);continue}throw i}finally{clearTimeout(a)}}}let H,F=!1,O,P;function Ee(){r.debug("Cleaning up token management"),H&&=(clearInterval(H),void 0),O&&=(C.off("online",O),void 0),P&&=(C.off("offline",P),void 0)}const Oe=()=>S.readFile(k.GITHUB_TOKEN_PATH,"utf8"),Pe=e=>S.writeFile(k.GITHUB_TOKEN_PATH,e),je=async()=>{let{token:e,refresh_in:t}=await X();s.copilotToken=e,r.debug("GitHub Copilot Token fetched successfully!"),s.showToken&&r.info("Copilot token:",e);let o=(t-60)*1e3,n=async(a=5,i=1e3,l="scheduled")=>{if(F){r.debug("Service refresh already in progress,skipping");return}F=!0;try{for(let u=1;u<=a;u++)try{r.debug(`Refreshing Copilot token (${l},attempt ${u}/${a})`);let{token:c}=await X();s.copilotToken=c,r.debug("Copilot token refreshed successfully"),s.showToken&&r.info("Refreshed Copilot token:",c);return}catch(c){let f=u===a;if(r.error(`Failed to refresh Copilot token (attempt ${u}/${a}):`,c),f){r.error("All token refresh attempts failed. Service may be unavailable until next scheduled refresh.");return}let p=i*2**(u-1);r.debug(`Retrying token refresh in ${p}ms...`),await new Promise(d=>setTimeout(d,p))}}finally{F=!1}};H=setInterval(()=>{n(5,1e3,"scheduled").catch(a=>{r.error("Unexpected error in scheduled token refresh:",a)})},o),C.start(),O=()=>{r.debug("Network status restored,attempting immediate token refresh"),n(3,500,"network-restored").catch(a=>{r.error("Unexpected error in network-restored token refresh:",a)})},P=()=>{r.debug("Network status lost")},C.on("online",O),C.on("offline",P)};async function D(e){try{let t=await Oe();if(t&&!e?.force){s.githubToken=t,s.showToken&&r.info("GitHub token:",t),await ee();return}r.info("Authentication required");let o=await xe();r.debug("Device code response:",o),r.info(`Please enter the code "${o.user_code}" in ${o.verification_uri}`);let n=await Ae(o);await Pe(n),s.githubToken=n,s.showToken&&r.info("GitHub token:",n),await ee()}catch(t){throw t instanceof y?(r.error("Failed to get GitHub token:",await t.response.json()),t):(r.error("Failed to get GitHub token:",t),t)}}async function ee(){let e=await fe();r.info(`Logged in as ${e.login}`)}async function Ne(e){e.verbose&&(r.level=5,r.info("Verbose logging enabled")),s.showToken=e.showToken,await q(),await D({force:!0}),r.success("GitHub token written to",k.GITHUB_TOKEN_PATH)}const qe=x({meta:{name:"auth",description:"Run GitHub auth flow without running the server"},args:{verbose:{alias:"v",type:"boolean",default:!1,description:"Enable verbose logging"},"show-token":{type:"boolean",default:!1,description:"Show GitHub token on auth"}},run({args:e}){return Ne({verbose:e.verbose,showToken:e["show-token"]})}}),te=async()=>{let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${L}/\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/user`,{headers:W(s),signal:e.signal});if(!n.ok)throw new y("Failed to get Copilot usage",n);return await n.json()}finally{clearTimeout(o)}},He=x({meta:{name:"check-usage",description:"Show current GitHub Copilot usage/quota information"},async run(){await q(),await D();try{let u=function(d,w){if(!w)return`${d}:N/A`;let v=w.entitlement,g=v-w.remaining,de=v>0?g/v*100:0,pe=w.percent_remaining;return`${d}:${g}/${v} used (${de.toFixed(1)}% used,${pe.toFixed(1)}% remaining)`};var e=u;let t=await te(),o=t.quota_snapshots.premium_interactions,n=o.entitlement,a=n-o.remaining,i=n>0?a/n*100:0,l=o.percent_remaining,c=`Premium:${a}/${n} used (${i.toFixed(1)}% used,${l.toFixed(1)}% remaining)`,f=u("Chat",t.quota_snapshots.chat),p=u("Completions",t.quota_snapshots.completions);r.box(`Copilot Usage (plan:${t.copilot_plan})Quota resets:${t.quota_reset_date}Quotas:${c} ${f} ${p}`)}catch(t){r.error("Failed to fetch Copilot usage:",t),process.exit(1)}}});async function Fe(){try{let e=new URL("../package.json",import.meta.url).pathname,t=await S.readFile(e);return JSON.parse(t.toString()).version}catch{return"unknown"}}function De(){let e=typeof Bun<"u";return{name:e?"bun":"node",version:e?Bun.version:process.version.slice(1),platform:z.platform(),arch:z.arch()}}async function Me(){try{return(await S.stat(k.GITHUB_TOKEN_PATH)).isFile()?(await S.readFile(k.GITHUB_TOKEN_PATH,"utf8")).trim().length>0:!1}catch{return!1}}async function Ue(){let[e,t]=await Promise.all([Fe(),Me()]);return{version:e,runtime:De(),paths:{APP_DIR:k.APP_DIR,GITHUB_TOKEN_PATH:k.GITHUB_TOKEN_PATH},tokenExists:t}}function Be(e){r.info(`copilot-api debugVersion:${e.version}Runtime:${e.runtime.name} ${e.runtime.version} (${e.runtime.platform} ${e.runtime.arch})Paths:- APP_DIR:${e.paths.APP_DIR}- GITHUB_TOKEN_PATH:${e.paths.GITHUB_TOKEN_PATH}Token exists:${e.tokenExists?"Yes":"No"}`)}function Ge(e){console.log(JSON.stringify(e,null,2))}async function Re(e){let t=await Ue();e.json?Ge(t):Be(t)}const Le=x({meta:{name:"debug",description:"Print debug information about the application"},args:{json:{type:"boolean",default:!1,description:"Output debug information as JSON"}},run({args:e}){return Re({json:e.json})}});function Je(){let{platform:e,ppid:t,env:o}=h;if(e==="win32"){try{let n=`wmic process get ParentProcessId,Name | findstr "${t}"`;if(be(n,{stdio:"pipe"}).toString().toLowerCase().includes("powershell.exe"))return"powershell"}catch{return"cmd"}return"cmd"}else{let n=o.SHELL;if(n){if(n.endsWith("zsh"))return"zsh";if(n.endsWith("fish"))return"fish";if(n.endsWith("bash"))return"bash"}return"sh"}}function Ke(e,t=""){let o=Je(),n=Object.entries(e).filter(([,i])=>i!==void 0),a;switch(o){case"powershell":a=n.map(([i,l])=>`$env:${i} =${l}`).join(";");break;case"cmd":a=n.map(([i,l])=>`set ${i}=${l}`).join(" & ");break;case"fish":a=n.map(([i,l])=>`set -gx ${i} ${l}`).join(";");break;default:{let i=n.map(([l,u])=>`${l}=${u}`).join(" ");a=n.length>0?`export ${i}`:"";break}}return a&&t?`${a}${o==="cmd"?" & ":" && "}${t}`:a||t}function We(){return`req_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}function Ve(){return async(e,t)=>{let o=Date.now(),n=We();e.set("requestId",n),e.header("x-request-id",n),I.registerCompletion(n,e,o),await t(),e.get("requestData")?.tokenUsage&&I.executeCompletion(n)}}const ne=async()=>{if(!await r.prompt("Accept incoming request?",{type:"confirm"}))throw new y("Request rejected",Response.json({message:"Request rejected"},{status:403}))},oe={input:3e-6,output:15e-6};function _(e){let t=e.prompt_tokens||0,o=e.completion_tokens||0,n=e.total_tokens||t+o,a=t*oe.input+o*oe.output;return{inputTokens:t,outputTokens:o,totalTokens:n,estimatedCost:a,cachedTokens:e.prompt_tokens_details?.cached_tokens,acceptedPredictionTokens:e.completion_tokens_details?.accepted_prediction_tokens,rejectedPredictionTokens:e.completion_tokens_details?.rejected_prediction_tokens}}const ze=[{pattern:/haiku/i,family:"haiku"},{pattern:/(sonnet-4[.-]5|[.-]?3[.-]5[.-]?sonnet|[.-]?3[.-]7[.-]?sonnet)/i,family:"sonnet-4.5"},{pattern:/sonnet-4(?![.-]5|[.-]1)/i,family:"sonnet-4"},{pattern:/opus/i,family:"opus"}],Qe={haiku:"claude-haiku-4.5","sonnet-4.5":"claude-sonnet-4.5","sonnet-4":"claude-sonnet-4",opus:"claude-opus-41"};function Xe(e){return e.startsWith("anthropic/")?e.slice(10):e}function Ye(e){for(let t of ze)if(t.pattern.test(e))return t.family;return null}function Ze(e,t){let o=Qe[e];if(!o)return null;if(t.includes(o))return o;if(e==="sonnet-4.5"){let n=["claude-3.5-sonnet"];for(let a of n)if(t.includes(a))return a}return null}function et(e,t){let o=Xe(e);if(t.includes(o))return o;let n=Ye(o);if(!n)return null;let a=o.replace(/-\d{8}(?::.*)?$/,"");for(let i of t){let l=i.replace(/-\d{8}(?::.*)?$/,""),u=a.toLowerCase().replaceAll(/(\d)-(\d)/g,"$1.$2");if(l.toLowerCase().replaceAll(/(\d)-(\d)/g,"$1.$2")===u)return i}return Ze(n,t)}var T=class extends Error{statusCode;constructor(e,t=400){super(e),this.name="ModelValidationError",this.statusCode=t}};function M(e){if(!e||typeof e!="string")throw new T("Model name is required and must be a string");if(!s.models?.data)throw new T("Models not available. Please try again later.",503);let t=s.models.data.map(n=>n.id),o=et(e,t);if(!o)throw new T(`Invalid model:'${e}'. Available models:${t.join(",")}`);return o}function tt(e){M(e)}async function ie(e){if(e.rateLimitSeconds===void 0)return;let t=Date.now();if(!e.lastRequestTimestamp){e.lastRequestTimestamp=t;return}let o=(t-e.lastRequestTimestamp)/1e3;if(o>e.rateLimitSeconds){e.lastRequestTimestamp=t;return}let n=Math.ceil(e.rateLimitSeconds-o);if(!e.rateLimitWait)throw r.warn(`Rate limit exceeded. Need to wait ${n} more seconds.`),new y("Rate limit exceeded",Response.json({message:"Rate limit exceeded"},{status:429}));let a=n*1e3;r.warn(`Rate limit reached. Waiting ${n} seconds before proceeding...`),await E(a),e.lastRequestTimestamp=t,r.info("Rate limit wait completed,proceeding with request")}function nt(e){let t=e,o=String.fromCodePoint(27),n=t.split(o);if(n.length>1){t=n[0];for(let a=1;a<n.length;a++){let i=n[a],l=i.match(/^\[[0-9;]*[a-z]/i);t+=l?i.slice(l[0].length):o+i}}return t.replaceAll(/[\u200B-\u200D\uFEFF]/g,"").replaceAll(/[\u2060-\u2064]/g,"").replaceAll(/[\u206A-\u206F]/g,"").replaceAll(/[\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/g,"").replaceAll(/[\uFFF0-\uFFFF]/g,"").replaceAll(/[\x00-\x08\v\f\x0E-\x1F]/g,"")}function U(e){if(typeof e=="string")return nt(e);if(Array.isArray(e))return e.map(o=>U(o));if(e&&typeof e=="object"){let t={};for(let[o,n]of Object.entries(e))t[o]=U(n);return t}return e}const re=async e=>{if(!s.copilotToken)throw Error("\u0043\u006f\u0070\u0069\u006c\u006f\u0074\u0020\u0074\u006f\u006b\u0065\u006e\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");let t=U(e),o=t.messages.some(c=>typeof c.content!="string"&&c.content?.some(f=>f.type==="image_url")),n=t.messages.some(c=>["assistant","tool"].includes(c.role)),a={...N(s,o),"X-Initiator":n?"agent":"user"},i=new AbortController,l=s.timeoutMs??12e4,u=setTimeout(()=>{i.abort()},l);try{let{statusCode:c,headers:f,body:p}=await Ce(`${j(s)}/\u0063\u0068\u0061\u0074\u002f\u0063\u006f\u006d\u0070\u006c\u0065\u0074\u0069\u006f\u006e\u0073`,{method:"POST",headers:a,body:JSON.stringify(t),signal:i.signal,headersTimeout:l,bodyTimeout:l*3}),d=new Response(p,{status:c,headers:f});if(!d.ok)throw new y("Failed to create chat completions",d);return t.stream?ve(d):await d.json()}finally{clearTimeout(u)}};function ot(e){let t=M(e.model);return t===e.model?e:(r.debug(`Normalized model from '${e.model}' to '${t}'`),{...e,model:t})}async function it(e){await ie(s);let t=await e.req.json();r.debug("Request data:",JSON.stringify(t).slice(-400));try{t=ot(t)}catch(i){if(i instanceof T)return e.json({error:{message:i.message,type:"invalid_request_error",code:"invalid_model"}},i.statusCode);throw i}if(e.set("requestData",{model:t.model}),s.manualApprove&&await ne(),$e(t.max_tokens)){let i=s.models?.data.find(l=>l.id===t.model);t={...t,max_tokens:i?.capabilities.limits.max_output_tokens},r.debug("Set max_tokens to:",JSON.stringify(t.max_tokens))}let o=performance.now(),n=await re(t),a=performance.now()-o;if(rt(n)){let i=e.get("requestData")||{};return n.usage&&(i.tokenUsage=_(n.usage)),i.copilotDuration=a,e.set("requestData",i),r.debug("Response data:",JSON.stringify(n)),e.json(n)}return Q(e,async i=>{let l=null;for await(let c of n){let f=c;if(c.data&&c.data!=="[DONE]")try{let p=JSON.parse(c.data);if(p.usage){l=p.usage;let d=e.get("requestData")||{};d.tokenUsage=_(l),d.copilotDuration=a,e.set("requestData",d)}if(p.usage?.prompt_tokens_details?.cached_tokens!==void 0){let d={...p,usage:{...p.usage,prompt_tokens_details:void 0}};f={...c,data:JSON.stringify(d)}}}catch{}await i.writeSSE(f)}if(l){let c=e.get("requestData")||{};c.tokenUsage||(c.tokenUsage=_(l),c.copilotDuration=a,e.set("requestData",c))}let u=e.get("requestId");u&&I.executeCompletion(u)})}const rt=e=>Object.hasOwn(e,"choices"),B=new b;B.post("/",async e=>{try{return await it(e)}catch(t){return await A(e,t)}});const at=async e=>{if(!s.copilotToken)throw Error("\u0043\u006f\u0070\u0069\u006c\u006f\u0074\u0020\u0074\u006f\u006b\u0065\u006e\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");let t=new AbortController,o=s.timeoutMs??12e4,n=setTimeout(()=>{t.abort()},o);try{let a=await fetch(`${j(s)}/embeddings`,{method:"POST",headers:N(s),body:JSON.stringify(e),signal:t.signal});if(!a.ok)throw new y("Failed to create embeddings",a);return await a.json()}finally{clearTimeout(n)}},G=new b;G.post("/",async e=>{try{let t=await e.req.json();try{tt(t.model)}catch(l){if(l instanceof T)return e.json({error:{message:l.message,type:"invalid_request_error",code:"invalid_model"}},l.statusCode);throw l}e.set("requestData",{model:t.model});let o=performance.now(),n=await at(t),a=performance.now()-o,i=e.get("requestData")||{};return i.tokenUsage=_(n.usage),i.copilotDuration=a,e.set("requestData",i),e.json(n)}catch(t){return await A(e,t)}});function ae(e){return e===null?null:{stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"end_turn"}[e]}function st(e){return{model:e.model,messages:lt(e.messages,e.system),max_tokens:e.max_tokens,stop:e.stop_sequences,stream:e.stream,temperature:e.temperature,top_p:e.top_p,user:e.metadata?.user_id,tools:pt(e.tools),tool_choice:mt(e.tool_choice)}}function Gt(e){return e}function lt(e,t){let o=ct(t),n=e.flatMap(a=>a.role==="user"?ut(a):dt(a));return[...o,...n]}function ct(e){return e?typeof e=="string"?[{role:"system",content:e}]:[{role:"system",content:e.map(o=>o.text).join(``)}]:[]}function ut(e){let t=[];if(Array.isArray(e.content)){let o=e.content.filter(a=>a.type==="tool_result"),n=e.content.filter(a=>a.type!=="tool_result");for(let a of o)t.push({role:"tool",tool_call_id:a.tool_use_id,content:$(a.content)});n.length>0&&t.push({role:"user",content:$(n)})}else t.push({role:"user",content:$(e.content)});return t}function dt(e){if(!Array.isArray(e.content))return[{role:"assistant",content:$(e.content)}];let t=e.content.filter(i=>i.type==="tool_use"),o=e.content.filter(i=>i.type==="text"),n=e.content.filter(i=>i.type==="thinking"),a=[...o.map(i=>i.text),...n.map(i=>i.thinking)].join(``);return t.length>0?[{role:"assistant",content:a||null,tool_calls:t.map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.input)}}))}]:[{role:"assistant",content:$(e.content)}]}function $(e){if(typeof e=="string")return e;if(!Array.isArray(e))return null;if(!e.some(n=>n.type==="image"))return e.filter(n=>n.type==="text"||n.type==="thinking").map(n=>n.type==="text"?n.text:n.thinking).join(``);let o=[];for(let n of e)switch(n.type){case"text":o.push({type:"text",text:n.text});break;case"thinking":o.push({type:"text",text:n.thinking});break;case"image":o.push({type:"image_url",image_url:{url:`data:${n.source.media_type};base64,${n.source.data}`}});break}return o}function pt(e){if(e)return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.input_schema}}))}function mt(e){if(e)switch(e.type){case"auto":return"auto";case"any":return"required";case"tool":return e.name?{type:"function",function:{name:e.name}}:void 0;case"none":return"none";default:return}}function ft(e){let t=[],o=[],n=null;n=e.choices[0]?.finish_reason??n;for(let a of e.choices){let i=ht(a.message.content),l=gt(a.message.tool_calls);t.push(...i),o.push(...l),(a.finish_reason==="tool_calls"||n==="stop")&&(n=a.finish_reason)}return{id:e.id,type:"message",role:"assistant",model:e.model,content:[...t,...o],stop_reason:ae(n),stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}}}function ht(e){return typeof e=="string"?[{type:"text",text:e}]:Array.isArray(e)?e.filter(t=>t.type==="text").map(t=>({type:"text",text:t.text})):[]}function gt(e){return e?e.map(t=>({type:"tool_use",id:t.id,name:t.function.name,input:JSON.parse(t.function.arguments)})):[]}function yt(e){return e.contentBlockOpen?Object.values(e.toolCalls).some(t=>t.anthropicBlockIndex===e.contentBlockIndex):!1}function wt(e,t){let o=[];if(e.choices.length===0)return o;let n=e.choices[0],{delta:a}=n;if(t.messageStartSent||=(o.push({type:"message_start",message:{id:e.id,type:"message",role:"assistant",content:[],model:e.model,stop_reason:null,stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:0}}}),!0),a.content&&(yt(t)&&(o.push({type:"content_block_stop",index:t.contentBlockIndex}),t.contentBlockIndex++,t.contentBlockOpen=!1),t.contentBlockOpen||=(o.push({type:"content_block_start",index:t.contentBlockIndex,content_block:{type:"text",text:""}}),!0),o.push({type:"content_block_delta",index:t.contentBlockIndex,delta:{type:"text_delta",text:a.content}})),a.tool_calls)for(let i of a.tool_calls){if(i.id&&i.function?.name){t.contentBlockOpen&&=(o.push({type:"content_block_stop",index:t.contentBlockIndex}),t.contentBlockIndex++,!1);let l=t.contentBlockIndex;t.toolCalls[i.index]={id:i.id,name:i.function.name,anthropicBlockIndex:l},o.push({type:"content_block_start",index:l,content_block:{type:"tool_use",id:i.id,name:i.function.name,input:{}}}),t.contentBlockOpen=!0}if(i.function?.arguments){let l=t.toolCalls[i.index];l&&o.push({type:"content_block_delta",index:l.anthropicBlockIndex,delta:{type:"input_json_delta",partial_json:i.function.arguments}})}}return n.finish_reason&&(t.contentBlockOpen&&=(o.push({type:"content_block_stop",index:t.contentBlockIndex}),!1),o.push({type:"message_delta",delta:{stop_reason:ae(n.finish_reason),stop_sequence:null},usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}},{type:"message_stop"})),o}function kt(e,t){try{let o=M(t.model);return o===t.model?t:(r.debug(`Normalized model from '${t.model}' to '${o}'`),{...t,model:o})}catch(o){if(o instanceof T)return e.json({type:"error",error:{type:"invalid_request_error",message:o.message}},o.statusCode),null;throw o}}async function bt(e){await ie(s);let t=await e.req.json();r.debug("API request payload:",JSON.stringify(t));let o=kt(e,t);if(!o)return;t=o;let n=st(t);r.debug("Processed API request payload:",JSON.stringify(n)),e.set("requestData",{model:n.model});let a=performance.now();s.manualApprove&&await ne();let i=await re(n),l=performance.now()-a;if(_t(i)){let u=e.get("requestData")||{};i.usage&&(u.tokenUsage=_(i.usage)),u.copilotDuration=l,e.set("requestData",u),r.debug("Non-streaming response from Copilot:",JSON.stringify(i).slice(-400));let c=ft(i);return r.debug("Processed API response:",JSON.stringify(c)),e.json(c)}return r.debug("Streaming response from service"),Q(e,async u=>{let c=null,f={messageStartSent:!1,contentBlockIndex:0,contentBlockOpen:!1,toolCalls:{}};for await(let d of i){if(r.debug("Copilot raw stream event:",JSON.stringify(d)),d.data==="[DONE]")break;if(!d.data)continue;let w=JSON.parse(d.data);if(w.usage){c=w.usage;let g=e.get("requestData")||{};g.tokenUsage=_(c),g.copilotDuration=l,e.set("requestData",g)}let v=wt(w,f);for(let g of v)r.debug("Processed API event:",JSON.stringify(g)),await u.writeSSE({event:g.type,data:JSON.stringify(g)})}if(c){let d=e.get("requestData")||{};d.tokenUsage||(d.tokenUsage=_(c),d.copilotDuration=l,e.set("requestData",d))}let p=e.get("requestId");p&&I.executeCompletion(p)})}const _t=e=>Object.hasOwn(e,"choices"),se=new b;se.post("/",async e=>{try{return await bt(e)}catch(t){return await A(e,t)}});const R=new b;R.get("/",async e=>{try{s.models||await Z();let t=s.models?.data.map(o=>({id:o.id,object:"model",type:"model",created:0,created_at:new Date(0).toISOString(),owned_by:o.vendor,display_name:o.name,context_length:o.capabilities.limits?.max_context_window_tokens}));return e.json({object:"list",data:t,has_more:!1})}catch(t){return await A(e,t)}});const le=new b;le.get("/",e=>{try{return e.json({token:s.copilotToken})}catch(t){return console.error("Error fetching token:",t),e.json({error:"Failed to fetch token",token:null},500)}});const ce=new b;ce.get("/",async e=>{try{let t=await te();return e.json(t)}catch(t){return console.error("Error fetching Copilot usage:",t),e.json({error:"Failed to fetch Copilot usage"},500)}});const m=new b;m.use(Ve()),m.use(_e()),m.get("/",e=>e.text("Server running")),m.route("/chat/completions",B),m.route("\u002f\u006d\u006f\u0064\u0065\u006c\u0073",R),m.route("\u002f\u0065\u006d\u0062\u0065\u0064\u0064\u0069\u006e\u0067\u0073",G),m.route("/usage",ce),m.route("/token",le),m.route("\u002f\u0076\u0031\u002f\u0063\u0068\u0061\u0074\u002f\u0063\u006f\u006d\u0070\u006c\u0065\u0074\u0069\u006f\u006e\u0073",B),m.route("\u002f\u0076\u0031\u002f\u006d\u006f\u0064\u0065\u006c\u0073",R),m.route("\u002f\u0076\u0031\u002f\u0065\u006d\u0062\u0065\u0064\u0064\u0069\u006e\u0067\u0073",G),m.route("\u002f\u0076\u0031\u002f\u006d\u0065\u0073\u0073\u0061\u0067\u0065\u0073",se),m.post("/v1/messages/count_tokens",e=>e.json({input_tokens:1}));const ue=[];function vt(){let e=async()=>{r.info("Gracefully shutting down...");for(let t of ue)try{await t()}catch(o){r.error("Error during cleanup:",o)}r.info("Shutdown complete"),h.exit(0)};h.on("SIGINT",e),h.on("SIGTERM",e),h.on("uncaughtException",t=>{r.error("Uncaught exception:",t),e().finally(()=>h.exit(1))}),h.on("unhandledRejection",(t,o)=>{r.error("Unhandled promise rejection at:",o,"reason:",t),e().finally(()=>h.exit(1))})}async function Ct(e,t){if(!e.claudeCode)return;ke(s.models,"Models should be loaded by now");let o,n;if(e.model&&e.smallModel){let i=s.models.data.map(l=>l.id);i.includes(e.model)||(r.error(`Invalid model:${e.model}`),r.info(`Available models:${i.join(``)}`),h.exit(1)),i.includes(e.smallModel)||(r.error(`Invalid small model:${e.smallModel}`),r.info(`Available models:${i.join(``)}`),h.exit(1)),o=e.model,n=e.smallModel,r.info(`Using model:${o}`),r.info(`Using small model:${n}`)}else e.model||e.smallModel?(r.error("Both --model and --small-model must be specified when using command-line model selection"),h.exit(1)):(o=await r.prompt("Select a model to use with Claude Code",{type:"select",options:s.models.data.map(i=>i.id)}),n=await r.prompt("Select a small model to use with Claude Code",{type:"select",options:s.models.data.map(i=>i.id)}));let a=Ke({ANTHROPIC_BASE_URL:t,ANTHROPIC_AUTH_TOKEN:"dummy",ANTHROPIC_MODEL:o,ANTHROPIC_SMALL_FAST_MODEL:n},"claude");try{ye.writeSync(a),r.success("Copied Claude Code command to clipboard!")}catch{r.warn("Failed to copy to clipboard. Here is the Claude Code command:"),r.log(a)}}async function Tt(e){vt(),ue.push(()=>{r.debug("Cleaning up connectivity monitor"),C.stop()},()=>{r.debug("Cleaning up token management"),Ee()}),e.verbose&&(r.level=5,r.info("Verbose logging enabled")),s.accountType=e.accountType,e.accountType!=="individual"&&r.info(`Using ${e.accountType} plan GitHub account`),s.manualApprove=e.manual,s.rateLimitSeconds=e.rateLimit,s.rateLimitWait=e.rateLimitWait,s.showToken=e.showToken,s.timeoutMs=e.timeout,s.connectivity.enabled=!e.disableConnectivityMonitoring,await q(),Ie(),e.githubToken?(s.githubToken=e.githubToken,r.info("Using provided auth token")):await D();try{let{getGitHubUser:o}=await import("./get-user-BT-kLu95.js"),n=await o();await he(s,n.login)}catch(o){r.error("Failed to get GitHub user info for machine ID generation:",o),r.error("Cannot proceed without GitHub user information"),h.exit(1)}await je(),await Z(),r.info("Available services:");for(let o of s.models?.data??[]){let n=o.capabilities.limits?.max_context_window_tokens,a=n?` (${n.toLocaleString()} tokens)`:"";r.info(`- ${o.id}${a}`)}let t=`http://localhost:${e.port}`;await Ct(e,t),r.box(`\u{1F310} Usage Viewer:https://ericc-ch.\u0067\u0069\u0074\u0068\u0075\u0062.io/copilot-api?endpoint=${t}/usage`),we({fetch:m.fetch,port:e.port})}const xt=x({meta:{name:"start",description:"Start the Copilot API server"},args:{port:{alias:"p",type:"string",default:"4141",description:"Port to listen on"},verbose:{alias:"v",type:"boolean",default:!1,description:"Enable verbose logging"},"account-type":{alias:"a",type:"string",default:"individual",description:"Account type to use (individual,business,enterprise)"},manual:{type:"boolean",default:!1,description:"Enable manual request approval"},"rate-limit":{alias:"r",type:"string",description:"Rate limit in seconds between requests"},wait:{alias:"w",type:"boolean",default:!1,description:"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"},"\u0067\u0069\u0074\u0068\u0075\u0062\u002d\u0074\u006f\u006b\u0065\u006e":{alias:"g",type:"string",description:"Provide GitHub token directly (must be generated using the `auth` subcommand)"},"claude-code":{alias:"c",type:"boolean",default:!1,description:"Generate a command to launch Claude Code with Copilot API config"},model:{alias:"m",type:"string",description:"Model to use with Claude Code (requires --claude-code)"},"small-model":{alias:"s",type:"string",description:"Small/fast model to use with Claude Code (requires --claude-code)"},"show-token":{type:"boolean",default:!1,description:"Show GitHub and Copilot tokens on fetch and refresh"},timeout:{alias:"t",type:"string",description:"API timeout in milliseconds (default:120000)"},"disable-connectivity-monitoring":{type:"boolean",default:!1,description:"Disable automatic network connectivity monitoring for token refresh"}},run({args:e}){let t=e["rate-limit"],o=t===void 0?void 0:Number.parseInt(t,10),n=e.timeout,a=n===void 0?12e4:Number.parseInt(n,10);return Tt({port:Number.parseInt(e.port,10),verbose:e.verbose,accountType:e["account-type"],manual:e.manual,rateLimit:o,rateLimitWait:e.wait,githubToken:e["\u0067\u0069\u0074\u0068\u0075\u0062\u002d\u0074\u006f\u006b\u0065\u006e"],claudeCode:e["claude-code"],model:e.model,smallModel:e["small-model"],showToken:e["show-token"],timeout:a,disableConnectivityMonitoring:e["disable-connectivity-monitoring"]})}}),St=x({meta:{name:"\u0063\u006f\u0070\u0069\u006c\u006f\u0074\u002d\u0061\u0070\u0069",description:"A wrapper around GitHub Copilot API to make it OpenAI compatible,making it usable for other tools."},subCommands:{auth:qe,start:xt,"check-usage":He,debug:Le}});await ge(St);
2
+ import{CompletionLogger as I,GITHUB_API_BASE_URL as L,GITHUB_APP_SCOPES as fe,GITHUB_BASE_URL as J,GITHUB_CLIENT_ID as W,HTTPError as y,PATHS as k,copilotBaseUrl as j,copilotHeaders as N,ensurePaths as q,forwardError as A,getGitHubUser as he,githubHeaders as K,initializeVSCodeIdentifiers as ge,standardHeaders as V,state as s}from"./get-user-BJ4s6iMX.js";import{defineCommand as x,runMain as ye}from"citty";import r from"consola";import S from"node:fs/promises";import z from"node:os";import we from"clipboardy";import h from"node:process";import{serve as ke}from"srvx";import be from"tiny-invariant";import{execSync as _e}from"node:child_process";import{Hono as b}from"hono";import{cors as ve}from"hono/cors";import{streamSSE as Q}from"hono/streaming";import{events as Ce}from"fetch-event-stream";import{request as Te}from"undici";var xe=class extends EventTarget{isOnline=!0;lastChecked=new Date().toISOString();consecutiveFailures=0;lastErrorType;lastErrorMessage;lastSuccessfulEndpoint;endpointFailureStats={};checkInterval;abortController;on(e,t){return this.addEventListener(e,t),this}off(e,t){return this.removeEventListener(e,t),this}start(){if(!s.connectivity.enabled){r.debug("Network monitoring disabled");return}r.info("Starting network monitor",{probeEndpoints:s.connectivity.probeEndpoints,fastInterval:s.connectivity.fastProbeInterval}),this.scheduleNextCheck();let e=()=>{this.stop(),process.exit(0)};process.on("SIGINT",e),process.on("SIGTERM",e)}stop(){r.debug("Stopping connectivity monitor"),this.checkInterval&&=(clearTimeout(this.checkInterval),void 0),this.abortController&&=(this.abortController.abort(),void 0)}scheduleNextCheck(){this.checkInterval&&clearTimeout(this.checkInterval);let e=this.isOnline?s.connectivity.slowProbeInterval:s.connectivity.fastProbeInterval,t=Math.random()*s.connectivity.jitterMaxMs,o=e+t;this.checkInterval=setTimeout(()=>{this.performConnectivityCheck().catch(n=>{r.error("Connectivity check failed:",n)})},o)}async performConnectivityCheck(){this.abortController=new AbortController;let e=setTimeout(()=>this.abortController?.abort(),s.connectivity.timeoutMs);try{let t=!1;for(let o of s.connectivity.probeEndpoints)try{if((await fetch(o,{method:"HEAD",signal:this.abortController.signal,headers:{"\u0055\u0073\u0065\u0072\u002d\u0041\u0067\u0065\u006e\u0074":"service-api-connectivity-monitor/1.0",...s.connectivity.dnsCache&&{"Cache-Control":"max-age=300"}}})).ok){t=!0,this.lastSuccessfulEndpoint=o;break}}catch(n){this.endpointFailureStats[o]=(this.endpointFailureStats[o]||0)+1,r.debug(`Probe failed for ${o}:`,n)}this.updateConnectivityState(t)}catch(t){this.handleConnectivityError(t)}finally{clearTimeout(e),this.scheduleNextCheck()}}updateConnectivityState(e){let t=this.isOnline;this.isOnline=e,this.lastChecked=new Date().toISOString(),e?(this.consecutiveFailures>0&&r.info(`Connectivity restored after ${this.consecutiveFailures} failures`),this.consecutiveFailures=0,this.lastErrorType=void 0,this.lastErrorMessage=void 0,t||this.dispatchEvent(new CustomEvent("online"))):(this.consecutiveFailures++,t&&(r.warn("Network lost"),this.dispatchEvent(new CustomEvent("offline"))))}handleConnectivityError(e){this.lastErrorType=e.name,this.lastErrorMessage=e.message,r.error("Connectivity check failed:",e),this.updateConnectivityState(!1)}getConnectivityStats(){return{isOnline:this.isOnline,lastChecked:this.lastChecked,consecutiveFailures:this.consecutiveFailures,lastErrorType:this.lastErrorType,lastErrorMessage:this.lastErrorMessage}}getPerformanceStats(){let e=this.isOnline?s.connectivity.slowProbeInterval:s.connectivity.fastProbeInterval,t=new Date(Date.now()+e+Math.random()*s.connectivity.jitterMaxMs).toISOString();return{currentInterval:e,nextCheckEstimate:t,lastSuccessfulEndpoint:this.lastSuccessfulEndpoint,endpointFailureStats:{...this.endpointFailureStats},jitterEnabled:s.connectivity.jitterMaxMs>0,connectionPooling:s.connectivity.connectionPooling,dnsCache:s.connectivity.dnsCache}}};const C=new xe,X=async()=>{let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${L}/\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/v2/token`,{headers:K(s),signal:e.signal});if(!n.ok)throw new y("\u0046\u0061\u0069\u006c\u0065\u0064\u0020\u0074\u006f\u0020\u0067\u0065\u0074\u0020\u0043\u006f\u0070\u0069\u006c\u006f\u0074\u0020\u0074\u006f\u006b\u0065\u006e",n);return await n.json()}finally{clearTimeout(o)}};async function Se(){let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${J}/login/device/code`,{method:"POST",headers:V(),body:JSON.stringify({client_id:W,scope:fe}),signal:e.signal});if(!n.ok)throw new y("Failed to get device code",n);return await n.json()}finally{clearTimeout(o)}}const $e=async()=>{let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${j(s)}/models`,{headers:N(s),signal:e.signal});if(!n.ok)throw new y("Failed to get models",n);return await n.json()}finally{clearTimeout(o)}};function Y(){return"1.105.0-insider"}Y();const E=e=>new Promise(t=>{setTimeout(t,e)}),Ie=e=>e==null;async function Z(){let e=await $e();s.models=e}const Ae=()=>{let e=Y();s.vsCodeVersion=e,r.info(`Using VSCode version:${e}`)};async function Ee(e){let t=(e.interval+1)*1e3;for(r.debug(`Polling access token with interval of ${t}ms`);;){let o=new AbortController,n=s.timeoutMs??12e4,a=setTimeout(()=>{o.abort()},n);try{let i=await fetch(`${J}/login/oauth/access_token`,{method:"POST",headers:V(),body:JSON.stringify({client_id:W,device_code:e.device_code,grant_type:"urn:ietf:params:oauth:grant-type:device_code"}),signal:o.signal});if(!i.ok){await E(t),r.error("Failed to poll access token:",await i.text());continue}let l=await i.json();r.debug("Polling access token response:",l);let{access_token:u}=l;if(u)return u;await E(t)}catch(i){if(i instanceof Error&&i.name==="AbortError"){r.error("Access token polling timed out"),await E(t);continue}throw i}finally{clearTimeout(a)}}}let H,F=!1,O,P;function Oe(){r.debug("Cleaning up token management"),H&&=(clearInterval(H),void 0),O&&=(C.off("online",O),void 0),P&&=(C.off("offline",P),void 0)}const Pe=()=>S.readFile(k.GITHUB_TOKEN_PATH,"utf8"),je=e=>S.writeFile(k.GITHUB_TOKEN_PATH,e),Ne=async()=>{let{token:e,refresh_in:t}=await X();s.copilotToken=e,r.debug("GitHub Copilot Token fetched successfully!"),s.showToken&&r.info("Copilot token:",e);let o=(t-60)*1e3,n=async(a=5,i=1e3,l="scheduled")=>{if(F){r.debug("Service refresh already in progress,skipping");return}F=!0;try{for(let u=1;u<=a;u++)try{r.debug(`Refreshing Copilot token (${l},attempt ${u}/${a})`);let{token:c}=await X();s.copilotToken=c,r.debug("Copilot token refreshed successfully"),s.showToken&&r.info("Refreshed Copilot token:",c);return}catch(c){let f=u===a;if(r.error(`Failed to refresh Copilot token (attempt ${u}/${a}):`,c),f){r.error("All token refresh attempts failed. Service may be unavailable until next scheduled refresh.");return}let p=i*2**(u-1);r.debug(`Retrying token refresh in ${p}ms...`),await new Promise(d=>setTimeout(d,p))}}finally{F=!1}};H=setInterval(()=>{n(5,1e3,"scheduled").catch(a=>{r.error("Unexpected error in scheduled token refresh:",a)})},o),C.start(),O=()=>{r.debug("Network status restored,attempting immediate token refresh"),n(3,500,"network-restored").catch(a=>{r.error("Unexpected error in network-restored token refresh:",a)})},P=()=>{r.debug("Network status lost")},C.on("online",O),C.on("offline",P)};async function D(e){try{let t=await Pe();if(t&&!e?.force){s.githubToken=t,s.showToken&&r.info("GitHub token:",t),await ee();return}r.info("Authentication required");let o=await Se();r.debug("Device code response:",o),r.info(`Please enter the code "${o.user_code}" in ${o.verification_uri}`);let n=await Ee(o);await je(n),s.githubToken=n,s.showToken&&r.info("GitHub token:",n),await ee()}catch(t){throw t instanceof y?(r.error("Failed to get GitHub token:",await t.response.json()),t):(r.error("Failed to get GitHub token:",t),t)}}async function ee(){let e=await he();r.info(`Logged in as ${e.login}`)}async function qe(e){e.verbose&&(r.level=5,r.info("Verbose logging enabled")),s.showToken=e.showToken,await q(),await D({force:!0}),r.success("GitHub token written to",k.GITHUB_TOKEN_PATH)}const He=x({meta:{name:"auth",description:"Run GitHub auth flow without running the server"},args:{verbose:{alias:"v",type:"boolean",default:!1,description:"Enable verbose logging"},"show-token":{type:"boolean",default:!1,description:"Show GitHub token on auth"}},run({args:e}){return qe({verbose:e.verbose,showToken:e["show-token"]})}}),te=async()=>{let e=new AbortController,t=s.timeoutMs??12e4,o=setTimeout(()=>{e.abort()},t);try{let n=await fetch(`${L}/\u0063\u006f\u0070\u0069\u006c\u006f\u0074_internal/user`,{headers:K(s),signal:e.signal});if(!n.ok)throw new y("Failed to get Copilot usage",n);return await n.json()}finally{clearTimeout(o)}},Fe=x({meta:{name:"check-usage",description:"Show current GitHub Copilot usage/quota information"},async run(){await q(),await D();try{let u=function(d,w){if(!w)return`${d}:N/A`;let v=w.entitlement,g=v-w.remaining,pe=v>0?g/v*100:0,me=w.percent_remaining;return`${d}:${g}/${v} used (${pe.toFixed(1)}% used,${me.toFixed(1)}% remaining)`};var e=u;let t=await te(),o=t.quota_snapshots.premium_interactions,n=o.entitlement,a=n-o.remaining,i=n>0?a/n*100:0,l=o.percent_remaining,c=`Premium:${a}/${n} used (${i.toFixed(1)}% used,${l.toFixed(1)}% remaining)`,f=u("Chat",t.quota_snapshots.chat),p=u("Completions",t.quota_snapshots.completions);r.box(`Copilot Usage (plan:${t.copilot_plan})Quota resets:${t.quota_reset_date}Quotas:${c} ${f} ${p}`)}catch(t){r.error("Failed to fetch Copilot usage:",t),process.exit(1)}}});async function De(){try{let e=new URL("../package.json",import.meta.url).pathname,t=await S.readFile(e);return JSON.parse(t.toString()).version}catch{return"unknown"}}function Me(){let e=typeof Bun<"u";return{name:e?"bun":"node",version:e?Bun.version:process.version.slice(1),platform:z.platform(),arch:z.arch()}}async function Ue(){try{return(await S.stat(k.GITHUB_TOKEN_PATH)).isFile()?(await S.readFile(k.GITHUB_TOKEN_PATH,"utf8")).trim().length>0:!1}catch{return!1}}async function Be(){let[e,t]=await Promise.all([De(),Ue()]);return{version:e,runtime:Me(),paths:{APP_DIR:k.APP_DIR,GITHUB_TOKEN_PATH:k.GITHUB_TOKEN_PATH},tokenExists:t}}function Ge(e){r.info(`copilot-api debugVersion:${e.version}Runtime:${e.runtime.name} ${e.runtime.version} (${e.runtime.platform} ${e.runtime.arch})Paths:- APP_DIR:${e.paths.APP_DIR}- GITHUB_TOKEN_PATH:${e.paths.GITHUB_TOKEN_PATH}Token exists:${e.tokenExists?"Yes":"No"}`)}function Re(e){console.log(JSON.stringify(e,null,2))}async function Le(e){let t=await Be();e.json?Re(t):Ge(t)}const Je=x({meta:{name:"debug",description:"Print debug information about the application"},args:{json:{type:"boolean",default:!1,description:"Output debug information as JSON"}},run({args:e}){return Le({json:e.json})}});function We(){let{platform:e,ppid:t,env:o}=h;if(e==="win32"){try{let n=`wmic process get ParentProcessId,Name | findstr "${t}"`;if(_e(n,{stdio:"pipe"}).toString().toLowerCase().includes("powershell.exe"))return"powershell"}catch{return"cmd"}return"cmd"}else{let n=o.SHELL;if(n){if(n.endsWith("zsh"))return"zsh";if(n.endsWith("fish"))return"fish";if(n.endsWith("bash"))return"bash"}return"sh"}}function Ke(e,t=""){let o=We(),n=Object.entries(e).filter(([,i])=>i!==void 0),a;switch(o){case"powershell":a=n.map(([i,l])=>`$env:${i} =${l}`).join(";");break;case"cmd":a=n.map(([i,l])=>`set ${i}=${l}`).join(" & ");break;case"fish":a=n.map(([i,l])=>`set -gx ${i} ${l}`).join(";");break;default:{let i=n.map(([l,u])=>`${l}=${u}`).join(" ");a=n.length>0?`export ${i}`:"";break}}return a&&t?`${a}${o==="cmd"?" & ":" && "}${t}`:a||t}function Ve(){return`req_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}function ze(){return async(e,t)=>{let o=Date.now(),n=Ve();e.set("requestId",n),e.header("x-request-id",n),I.registerCompletion(n,e,o),await t(),e.get("requestData")?.tokenUsage&&I.executeCompletion(n)}}const ne=async()=>{if(!await r.prompt("Accept incoming request?",{type:"confirm"}))throw new y("Request rejected",Response.json({message:"Request rejected"},{status:403}))},oe={input:3e-6,output:15e-6};function _(e){let t=e.prompt_tokens||0,o=e.completion_tokens||0,n=e.total_tokens||t+o,a=t*oe.input+o*oe.output;return{inputTokens:t,outputTokens:o,totalTokens:n,estimatedCost:a,cachedTokens:e.prompt_tokens_details?.cached_tokens,acceptedPredictionTokens:e.completion_tokens_details?.accepted_prediction_tokens,rejectedPredictionTokens:e.completion_tokens_details?.rejected_prediction_tokens}}const Qe=[{pattern:/haiku/i,family:"haiku"},{pattern:/(sonnet-4[.-]5|[.-]?3[.-]5[.-]?sonnet|[.-]?3[.-]7[.-]?sonnet)/i,family:"sonnet-4.5"},{pattern:/sonnet-4(?![.-]5|[.-]1)/i,family:"sonnet-4"},{pattern:/opus/i,family:"opus"}],Xe={haiku:"claude-haiku-4.5","sonnet-4.5":"claude-sonnet-4.5","sonnet-4":"claude-sonnet-4",opus:"claude-opus-41"};function Ye(e){return e.startsWith("anthropic/")?e.slice(10):e}function Ze(e){for(let t of Qe)if(t.pattern.test(e))return t.family;return null}function et(e,t){let o=Xe[e];if(!o)return null;if(t.includes(o))return o;if(e==="sonnet-4.5"){let n=["claude-3.5-sonnet"];for(let a of n)if(t.includes(a))return a}return null}function tt(e,t){let o=Ye(e);if(t.includes(o))return o;let n=Ze(o);if(!n)return null;let a=o.replace(/-\d{8}(?::.*)?$/,"");for(let i of t){let l=i.replace(/-\d{8}(?::.*)?$/,""),u=a.toLowerCase().replaceAll(/(\d)-(\d)/g,"$1.$2");if(l.toLowerCase().replaceAll(/(\d)-(\d)/g,"$1.$2")===u)return i}return et(n,t)}var T=class extends Error{statusCode;constructor(e,t=400){super(e),this.name="ModelValidationError",this.statusCode=t}};function M(e){if(!e||typeof e!="string")throw new T("Model name is required and must be a string");if(!s.models?.data)throw new T("Models not available. Please try again later.",503);let t=s.models.data.map(n=>n.id),o=tt(e,t);if(!o)throw new T(`Invalid model:'${e}'. Available models:${t.join(",")}`);return o}function nt(e){M(e)}async function ie(e){if(e.rateLimitSeconds===void 0)return;let t=Date.now();if(!e.lastRequestTimestamp){e.lastRequestTimestamp=t;return}let o=(t-e.lastRequestTimestamp)/1e3;if(o>e.rateLimitSeconds){e.lastRequestTimestamp=t;return}let n=Math.ceil(e.rateLimitSeconds-o);if(!e.rateLimitWait)throw r.warn(`Rate limit exceeded. Need to wait ${n} more seconds.`),new y("Rate limit exceeded",Response.json({message:"Rate limit exceeded"},{status:429}));let a=n*1e3;r.warn(`Rate limit reached. Waiting ${n} seconds before proceeding...`),await E(a),e.lastRequestTimestamp=t,r.info("Rate limit wait completed,proceeding with request")}function ot(e){let t=e,o=String.fromCodePoint(27),n=t.split(o);if(n.length>1){t=n[0];for(let a=1;a<n.length;a++){let i=n[a],l=i.match(/^\[[0-9;]*[a-z]/i);t+=l?i.slice(l[0].length):o+i}}return t.replaceAll(/[\u200B-\u200D\uFEFF]/g,"").replaceAll(/[\u2060-\u2064]/g,"").replaceAll(/[\u206A-\u206F]/g,"").replaceAll(/[\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/g,"").replaceAll(/[\uFFF0-\uFFFF]/g,"").replaceAll(/[\x00-\x08\v\f\x0E-\x1F]/g,"")}function U(e){if(typeof e=="string")return ot(e);if(Array.isArray(e))return e.map(o=>U(o));if(e&&typeof e=="object"){let t={};for(let[o,n]of Object.entries(e))t[o]=U(n);return t}return e}const re=async e=>{if(!s.copilotToken)throw Error("\u0043\u006f\u0070\u0069\u006c\u006f\u0074\u0020\u0074\u006f\u006b\u0065\u006e\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");let t=U(e),o=t.messages.some(c=>typeof c.content!="string"&&c.content?.some(f=>f.type==="image_url")),n=t.messages.some(c=>["assistant","tool"].includes(c.role)),a={...N(s,o),"X-Initiator":n?"agent":"user"},i=new AbortController,l=s.timeoutMs??12e4,u=setTimeout(()=>{i.abort()},l);try{let{statusCode:c,headers:f,body:p}=await Te(`${j(s)}/\u0063\u0068\u0061\u0074\u002f\u0063\u006f\u006d\u0070\u006c\u0065\u0074\u0069\u006f\u006e\u0073`,{method:"POST",headers:a,body:JSON.stringify(t),signal:i.signal,headersTimeout:l,bodyTimeout:l*3}),d=new Response(p,{status:c,headers:f});if(!d.ok)throw new y("Failed to create chat completions",d);return t.stream?Ce(d):await d.json()}finally{clearTimeout(u)}};function it(e){let t=M(e.model);return t===e.model?e:(r.debug(`Normalized model from '${e.model}' to '${t}'`),{...e,model:t})}async function rt(e){await ie(s);let t=await e.req.json();r.debug("Request data:",JSON.stringify(t).slice(-400));try{t=it(t)}catch(i){if(i instanceof T)return e.json({error:{message:i.message,type:"invalid_request_error",code:"invalid_model"}},i.statusCode);throw i}if(e.set("requestData",{model:t.model}),s.manualApprove&&await ne(),Ie(t.max_tokens)){let i=s.models?.data.find(l=>l.id===t.model);t={...t,max_tokens:i?.capabilities.limits.max_output_tokens},r.debug("Set max_tokens to:",JSON.stringify(t.max_tokens))}let o=performance.now(),n=await re(t),a=performance.now()-o;if(at(n)){let i=e.get("requestData")||{};return n.usage&&(i.tokenUsage=_(n.usage)),i.copilotDuration=a,e.set("requestData",i),r.debug("Response data:",JSON.stringify(n)),e.json(n)}return Q(e,async i=>{let l=null;for await(let c of n){let f=c;if(c.data&&c.data!=="[DONE]")try{let p=JSON.parse(c.data);if(p.usage){l=p.usage;let d=e.get("requestData")||{};d.tokenUsage=_(l),d.copilotDuration=a,e.set("requestData",d)}if(p.usage?.prompt_tokens_details?.cached_tokens!==void 0){let d={...p,usage:{...p.usage,prompt_tokens_details:void 0}};f={...c,data:JSON.stringify(d)}}}catch{}await i.writeSSE(f)}if(l){let c=e.get("requestData")||{};c.tokenUsage||(c.tokenUsage=_(l),c.copilotDuration=a,e.set("requestData",c))}let u=e.get("requestId");u&&I.executeCompletion(u)})}const at=e=>Object.hasOwn(e,"choices"),B=new b;B.post("/",async e=>{try{return await rt(e)}catch(t){return await A(e,t)}});const st=async e=>{if(!s.copilotToken)throw Error("\u0043\u006f\u0070\u0069\u006c\u006f\u0074\u0020\u0074\u006f\u006b\u0065\u006e\u0020\u006e\u006f\u0074\u0020\u0066\u006f\u0075\u006e\u0064");let t=new AbortController,o=s.timeoutMs??12e4,n=setTimeout(()=>{t.abort()},o);try{let a=await fetch(`${j(s)}/embeddings`,{method:"POST",headers:N(s),body:JSON.stringify(e),signal:t.signal});if(!a.ok)throw new y("Failed to create embeddings",a);return await a.json()}finally{clearTimeout(n)}},G=new b;G.post("/",async e=>{try{let t=await e.req.json();try{nt(t.model)}catch(l){if(l instanceof T)return e.json({error:{message:l.message,type:"invalid_request_error",code:"invalid_model"}},l.statusCode);throw l}e.set("requestData",{model:t.model});let o=performance.now(),n=await st(t),a=performance.now()-o,i=e.get("requestData")||{};return i.tokenUsage=_(n.usage),i.copilotDuration=a,e.set("requestData",i),e.json(n)}catch(t){return await A(e,t)}});function ae(e){return e===null?null:{stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"end_turn"}[e]}function lt(e){return{model:e.model,messages:ct(e.messages,e.system),max_tokens:e.max_tokens,stop:e.stop_sequences,stream:e.stream,temperature:e.temperature,top_p:e.top_p,user:e.metadata?.user_id,tools:mt(e.tools),tool_choice:ft(e.tool_choice)}}function Rt(e){return e}function ct(e,t){let o=ut(t),n=e.flatMap(a=>a.role==="user"?dt(a):pt(a));return[...o,...n]}function se(e){return e.startsWith("x-anthropic-billing-header")?e.replace(/^x-anthropic-billing-header:[^\n]*\n+/,""):e}function ut(e){if(!e)return[];if(typeof e=="string")return[{role:"system",content:se(e)}];{let t=e.map(o=>o.text).join(``);return[{role:"system",content:se(t)}]}}function dt(e){let t=[];if(Array.isArray(e.content)){let o=e.content.filter(a=>a.type==="tool_result"),n=e.content.filter(a=>a.type!=="tool_result");for(let a of o)t.push({role:"tool",tool_call_id:a.tool_use_id,content:$(a.content)});n.length>0&&t.push({role:"user",content:$(n)})}else t.push({role:"user",content:$(e.content)});return t}function pt(e){if(!Array.isArray(e.content))return[{role:"assistant",content:$(e.content)}];let t=e.content.filter(i=>i.type==="tool_use"),o=e.content.filter(i=>i.type==="text"),n=e.content.filter(i=>i.type==="thinking"),a=[...o.map(i=>i.text),...n.map(i=>i.thinking)].join(``);return t.length>0?[{role:"assistant",content:a||null,tool_calls:t.map(i=>({id:i.id,type:"function",function:{name:i.name,arguments:JSON.stringify(i.input)}}))}]:[{role:"assistant",content:$(e.content)}]}function $(e){if(typeof e=="string")return e;if(!Array.isArray(e))return null;if(!e.some(n=>n.type==="image"))return e.filter(n=>n.type==="text"||n.type==="thinking").map(n=>n.type==="text"?n.text:n.thinking).join(``);let o=[];for(let n of e)switch(n.type){case"text":o.push({type:"text",text:n.text});break;case"thinking":o.push({type:"text",text:n.thinking});break;case"image":o.push({type:"image_url",image_url:{url:`data:${n.source.media_type};base64,${n.source.data}`}});break}return o}function mt(e){if(e)return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.input_schema}}))}function ft(e){if(e)switch(e.type){case"auto":return"auto";case"any":return"required";case"tool":return e.name?{type:"function",function:{name:e.name}}:void 0;case"none":return"none";default:return}}function ht(e){let t=[],o=[],n=null;n=e.choices[0]?.finish_reason??n;for(let a of e.choices){let i=gt(a.message.content),l=yt(a.message.tool_calls);t.push(...i),o.push(...l),(a.finish_reason==="tool_calls"||n==="stop")&&(n=a.finish_reason)}return{id:e.id,type:"message",role:"assistant",model:e.model,content:[...t,...o],stop_reason:ae(n),stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}}}function gt(e){return typeof e=="string"?[{type:"text",text:e}]:Array.isArray(e)?e.filter(t=>t.type==="text").map(t=>({type:"text",text:t.text})):[]}function yt(e){return e?e.map(t=>({type:"tool_use",id:t.id,name:t.function.name,input:JSON.parse(t.function.arguments)})):[]}function wt(e){return e.contentBlockOpen?Object.values(e.toolCalls).some(t=>t.anthropicBlockIndex===e.contentBlockIndex):!1}function kt(e,t){let o=[];if(e.choices.length===0)return o;let n=e.choices[0],{delta:a}=n;if(t.messageStartSent||=(o.push({type:"message_start",message:{id:e.id,type:"message",role:"assistant",content:[],model:e.model,stop_reason:null,stop_sequence:null,usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:0}}}),!0),a.content&&(wt(t)&&(o.push({type:"content_block_stop",index:t.contentBlockIndex}),t.contentBlockIndex++,t.contentBlockOpen=!1),t.contentBlockOpen||=(o.push({type:"content_block_start",index:t.contentBlockIndex,content_block:{type:"text",text:""}}),!0),o.push({type:"content_block_delta",index:t.contentBlockIndex,delta:{type:"text_delta",text:a.content}})),a.tool_calls)for(let i of a.tool_calls){if(i.id&&i.function?.name){t.contentBlockOpen&&=(o.push({type:"content_block_stop",index:t.contentBlockIndex}),t.contentBlockIndex++,!1);let l=t.contentBlockIndex;t.toolCalls[i.index]={id:i.id,name:i.function.name,anthropicBlockIndex:l},o.push({type:"content_block_start",index:l,content_block:{type:"tool_use",id:i.id,name:i.function.name,input:{}}}),t.contentBlockOpen=!0}if(i.function?.arguments){let l=t.toolCalls[i.index];l&&o.push({type:"content_block_delta",index:l.anthropicBlockIndex,delta:{type:"input_json_delta",partial_json:i.function.arguments}})}}return n.finish_reason&&(t.contentBlockOpen&&=(o.push({type:"content_block_stop",index:t.contentBlockIndex}),!1),o.push({type:"message_delta",delta:{stop_reason:ae(n.finish_reason),stop_sequence:null},usage:{input_tokens:e.usage?.prompt_tokens??0,output_tokens:e.usage?.completion_tokens??0}},{type:"message_stop"})),o}function bt(e,t){try{let o=M(t.model);return o===t.model?t:(r.debug(`Normalized model from '${t.model}' to '${o}'`),{...t,model:o})}catch(o){if(o instanceof T)return e.json({type:"error",error:{type:"invalid_request_error",message:o.message}},o.statusCode),null;throw o}}async function _t(e){await ie(s);let t=await e.req.json();r.debug("API request payload:",JSON.stringify(t));let o=bt(e,t);if(!o)return;t=o;let n=lt(t);r.debug("Processed API request payload:",JSON.stringify(n)),e.set("requestData",{model:n.model});let a=performance.now();s.manualApprove&&await ne();let i=await re(n),l=performance.now()-a;if(vt(i)){let u=e.get("requestData")||{};i.usage&&(u.tokenUsage=_(i.usage)),u.copilotDuration=l,e.set("requestData",u),r.debug("Non-streaming response from Copilot:",JSON.stringify(i).slice(-400));let c=ht(i);return r.debug("Processed API response:",JSON.stringify(c)),e.json(c)}return r.debug("Streaming response from service"),Q(e,async u=>{let c=null,f={messageStartSent:!1,contentBlockIndex:0,contentBlockOpen:!1,toolCalls:{}};for await(let d of i){if(r.debug("Copilot raw stream event:",JSON.stringify(d)),d.data==="[DONE]")break;if(!d.data)continue;let w=JSON.parse(d.data);if(w.usage){c=w.usage;let g=e.get("requestData")||{};g.tokenUsage=_(c),g.copilotDuration=l,e.set("requestData",g)}let v=kt(w,f);for(let g of v)r.debug("Processed API event:",JSON.stringify(g)),await u.writeSSE({event:g.type,data:JSON.stringify(g)})}if(c){let d=e.get("requestData")||{};d.tokenUsage||(d.tokenUsage=_(c),d.copilotDuration=l,e.set("requestData",d))}let p=e.get("requestId");p&&I.executeCompletion(p)})}const vt=e=>Object.hasOwn(e,"choices"),le=new b;le.post("/",async e=>{try{return await _t(e)}catch(t){return await A(e,t)}});const R=new b;R.get("/",async e=>{try{s.models||await Z();let t=s.models?.data.map(o=>({id:o.id,object:"model",type:"model",created:0,created_at:new Date(0).toISOString(),owned_by:o.vendor,display_name:o.name,context_length:o.capabilities.limits?.max_context_window_tokens}));return e.json({object:"list",data:t,has_more:!1})}catch(t){return await A(e,t)}});const ce=new b;ce.get("/",e=>{try{return e.json({token:s.copilotToken})}catch(t){return console.error("Error fetching token:",t),e.json({error:"Failed to fetch token",token:null},500)}});const ue=new b;ue.get("/",async e=>{try{let t=await te();return e.json(t)}catch(t){return console.error("Error fetching Copilot usage:",t),e.json({error:"Failed to fetch Copilot usage"},500)}});const m=new b;m.use(ze()),m.use(ve()),m.get("/",e=>e.text("Server running")),m.route("/chat/completions",B),m.route("\u002f\u006d\u006f\u0064\u0065\u006c\u0073",R),m.route("\u002f\u0065\u006d\u0062\u0065\u0064\u0064\u0069\u006e\u0067\u0073",G),m.route("/usage",ue),m.route("/token",ce),m.route("\u002f\u0076\u0031\u002f\u0063\u0068\u0061\u0074\u002f\u0063\u006f\u006d\u0070\u006c\u0065\u0074\u0069\u006f\u006e\u0073",B),m.route("\u002f\u0076\u0031\u002f\u006d\u006f\u0064\u0065\u006c\u0073",R),m.route("\u002f\u0076\u0031\u002f\u0065\u006d\u0062\u0065\u0064\u0064\u0069\u006e\u0067\u0073",G),m.route("\u002f\u0076\u0031\u002f\u006d\u0065\u0073\u0073\u0061\u0067\u0065\u0073",le),m.post("/v1/messages/count_tokens",e=>e.json({input_tokens:1}));const de=[];function Ct(){let e=async()=>{r.info("Gracefully shutting down...");for(let t of de)try{await t()}catch(o){r.error("Error during cleanup:",o)}r.info("Shutdown complete"),h.exit(0)};h.on("SIGINT",e),h.on("SIGTERM",e),h.on("uncaughtException",t=>{r.error("Uncaught exception:",t),e().finally(()=>h.exit(1))}),h.on("unhandledRejection",(t,o)=>{r.error("Unhandled promise rejection at:",o,"reason:",t),e().finally(()=>h.exit(1))})}async function Tt(e,t){if(!e.claudeCode)return;be(s.models,"Models should be loaded by now");let o,n;if(e.model&&e.smallModel){let i=s.models.data.map(l=>l.id);i.includes(e.model)||(r.error(`Invalid model:${e.model}`),r.info(`Available models:${i.join(``)}`),h.exit(1)),i.includes(e.smallModel)||(r.error(`Invalid small model:${e.smallModel}`),r.info(`Available models:${i.join(``)}`),h.exit(1)),o=e.model,n=e.smallModel,r.info(`Using model:${o}`),r.info(`Using small model:${n}`)}else e.model||e.smallModel?(r.error("Both --model and --small-model must be specified when using command-line model selection"),h.exit(1)):(o=await r.prompt("Select a model to use with Claude Code",{type:"select",options:s.models.data.map(i=>i.id)}),n=await r.prompt("Select a small model to use with Claude Code",{type:"select",options:s.models.data.map(i=>i.id)}));let a=Ke({ANTHROPIC_BASE_URL:t,ANTHROPIC_AUTH_TOKEN:"dummy",ANTHROPIC_MODEL:o,ANTHROPIC_SMALL_FAST_MODEL:n},"claude");try{we.writeSync(a),r.success("Copied Claude Code command to clipboard!")}catch{r.warn("Failed to copy to clipboard. Here is the Claude Code command:"),r.log(a)}}async function xt(e){Ct(),de.push(()=>{r.debug("Cleaning up connectivity monitor"),C.stop()},()=>{r.debug("Cleaning up token management"),Oe()}),e.verbose&&(r.level=5,r.info("Verbose logging enabled")),s.accountType=e.accountType,e.accountType!=="individual"&&r.info(`Using ${e.accountType} plan GitHub account`),s.manualApprove=e.manual,s.rateLimitSeconds=e.rateLimit,s.rateLimitWait=e.rateLimitWait,s.showToken=e.showToken,s.timeoutMs=e.timeout,s.connectivity.enabled=!e.disableConnectivityMonitoring,await q(),Ae(),e.githubToken?(s.githubToken=e.githubToken,r.info("Using provided auth token")):await D();try{let{getGitHubUser:o}=await import("./get-user-BT-kLu95.js"),n=await o();await ge(s,n.login)}catch(o){r.error("Failed to get GitHub user info for machine ID generation:",o),r.error("Cannot proceed without GitHub user information"),h.exit(1)}await Ne(),await Z(),r.info("Available services:");for(let o of s.models?.data??[]){let n=o.capabilities.limits?.max_context_window_tokens,a=n?` (${n.toLocaleString()} tokens)`:"";r.info(`- ${o.id}${a}`)}let t=`http://localhost:${e.port}`;await Tt(e,t),r.box(`\u{1F310} Usage Viewer:https://ericc-ch.\u0067\u0069\u0074\u0068\u0075\u0062.io/copilot-api?endpoint=${t}/usage`),ke({fetch:m.fetch,port:e.port})}const St=x({meta:{name:"start",description:"Start the Copilot API server"},args:{port:{alias:"p",type:"string",default:"4141",description:"Port to listen on"},verbose:{alias:"v",type:"boolean",default:!1,description:"Enable verbose logging"},"account-type":{alias:"a",type:"string",default:"individual",description:"Account type to use (individual,business,enterprise)"},manual:{type:"boolean",default:!1,description:"Enable manual request approval"},"rate-limit":{alias:"r",type:"string",description:"Rate limit in seconds between requests"},wait:{alias:"w",type:"boolean",default:!1,description:"Wait instead of error when rate limit is hit. Has no effect if rate limit is not set"},"\u0067\u0069\u0074\u0068\u0075\u0062\u002d\u0074\u006f\u006b\u0065\u006e":{alias:"g",type:"string",description:"Provide GitHub token directly (must be generated using the `auth` subcommand)"},"claude-code":{alias:"c",type:"boolean",default:!1,description:"Generate a command to launch Claude Code with Copilot API config"},model:{alias:"m",type:"string",description:"Model to use with Claude Code (requires --claude-code)"},"small-model":{alias:"s",type:"string",description:"Small/fast model to use with Claude Code (requires --claude-code)"},"show-token":{type:"boolean",default:!1,description:"Show GitHub and Copilot tokens on fetch and refresh"},timeout:{alias:"t",type:"string",description:"API timeout in milliseconds (default:120000)"},"disable-connectivity-monitoring":{type:"boolean",default:!1,description:"Disable automatic network connectivity monitoring for token refresh"}},run({args:e}){let t=e["rate-limit"],o=t===void 0?void 0:Number.parseInt(t,10),n=e.timeout,a=n===void 0?12e4:Number.parseInt(n,10);return xt({port:Number.parseInt(e.port,10),verbose:e.verbose,accountType:e["account-type"],manual:e.manual,rateLimit:o,rateLimitWait:e.wait,githubToken:e["\u0067\u0069\u0074\u0068\u0075\u0062\u002d\u0074\u006f\u006b\u0065\u006e"],claudeCode:e["claude-code"],model:e.model,smallModel:e["small-model"],showToken:e["show-token"],timeout:a,disableConnectivityMonitoring:e["disable-connectivity-monitoring"]})}}),$t=x({meta:{name:"\u0063\u006f\u0070\u0069\u006c\u006f\u0074\u002d\u0061\u0070\u0069",description:"A wrapper around GitHub Copilot API to make it OpenAI compatible,making it usable for other tools."},subCommands:{auth:He,start:St,"check-usage":Fe,debug:Je}});await ye($t);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-api-node20",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Turn GitHub Copilot into OpenAI/Anthropic API compatible server. Usable with Claude Code! (Node v20+ fork)",
5
5
  "keywords": [
6
6
  "proxy",