copilot-api-node20 0.15.1 → 0.15.2

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.
@@ -1 +1 @@
1
- import e from"consola";import t from"node:fs/promises";import n from"node:os";import r from"node:path";import{SpanKind as i,SpanStatusCode as a,metrics as o,trace as s}from"@opentelemetry/api";import{SeverityNumber as c,logs as l}from"@opentelemetry/api-logs";import{OTLPLogExporter as u}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as d}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as f}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as p}from"@opentelemetry/resources";import{BatchLogRecordProcessor as m}from"@opentelemetry/sdk-logs";import{PeriodicExportingMetricReader as h}from"@opentelemetry/sdk-metrics";import{NodeSDK as ee}from"@opentelemetry/sdk-node";import{ATTR_SERVICE_NAME as te,ATTR_SERVICE_VERSION as ne}from"@opentelemetry/semantic-conventions";import{request as re}from"undici";import{createHash as ie,randomBytes as g,randomUUID as _}from"node:crypto";const v=r.join(n.homedir(),`.local`,`share`,`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),ae=r.join(v,`\u0067\u0069\u0074\u0068\u0075\u0062_token`),oe=r.join(v,`machine_id`),se=r.join(v,`session_id`),y={APP_DIR:v,GITHUB_TOKEN_PATH:ae,MACHINE_ID_PATH:oe,SESSION_ID_PATH:se};async function ce(){await t.mkdir(y.APP_DIR,{recursive:!0}),await b(y.GITHUB_TOKEN_PATH),await b(y.SESSION_ID_PATH)}async function b(e){try{await t.access(e,t.constants.W_OK)}catch{await t.writeFile(e,``),await t.chmod(e,384)}}const x=6e5,S={accountType:`individual`,manualApprove:!1,rateLimitWait:!1,showToken:!1,timeoutMs:x,connectivity:{enabled:!0,probeEndpoints:[`https://api.\u0067\u0069\u0074\u0068\u0075\u0062.com`,`https://www.google.com`,`https://1.1.1.1`],fastProbeInterval:5e3,slowProbeInterval:6e4,timeoutMs:5e3,jitterMaxMs:1e3,connectionPooling:!0,dnsCache:!0}},C=e=>e>=1e5||e>=1e4?`${Math.round(e/1e3)}K`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toString(),w=(e,t)=>e.padEnd(t),le=(e,t)=>{if(!S.models)return``;let n=S.models.data.find(e=>e.id===t);if(!n)return``;let r=n.capabilities.limits?.max_context_window_tokens;if(!r)return``;let i=(e/r*100).toFixed(1);return` (${i}%)`},ue=e=>{let t=[];if(e.model){let n=w(e.model,18);t.push(n)}if(e.tokenUsage){let n=e.tokenUsage,r=(n.inputTokens||0)+(n.outputTokens||0),i=e.model?le(r,e.model):``,a=C(n.inputTokens||0).padStart(5),o=C(n.outputTokens||0).padStart(5),s=`↑${a} │ ↓${o}`,c=w(s,18),l=C(r),u=i?`${l}${i.padStart(15-l.length)}`:l.padEnd(15);t.push(`Tokens: ${c} | Context: ${u}`)}else if(e.model){let e=w(`N/A`,18),n=`N/A`.padEnd(15);t.push(`Tokens: ${e} | Context: ${n}`)}if(e.copilotDuration){let n=w(`${Math.round(e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Duration)}ms`,8);t.push(`API: ${n}`)}return t.length>0?` | ${t.join(` | `)}`:``},T={completionCallbacks:new Map,registerCompletion(e,t,n){this.completionCallbacks.set(e,{context:t,startTime:n,requestId:e})},executeCompletion(e){let t=this.completionCallbacks.get(e);t&&(this.logCompletion(t),this.completionCallbacks.delete(e))},logCompletion(t){let{context:n,startTime:r}=t,i=Date.now(),a=i-r,o=n.get(`requestData`),s=w(n.req.method,4),l=w(n.req.path,21),u=w(n.res.status.toString(),3),d=w(`${a}ms`,8),f=` --> ${s}${l}${u} ${d}`;o&&(f+=ue(o)),e.info(f),V(c.INFO,`INFO`,`Request completed`,{"http.method":n.req.method,"http.path":n.req.path,"http.status_code":n.res.status,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.duration_ms":a,...o?.model&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model":o.model},...o?.copilotDuration&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074_duration_ms":Math.round(o.copilotDuration)},...o?.tokenUsage?.inputTokens&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.input_tokens":o.tokenUsage.inputTokens},...o?.tokenUsage?.outputTokens&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.output_tokens":o.tokenUsage.outputTokens}})},logRateLimit(t,n){let{context:r,startTime:i}=t,a=Date.now(),o=a-i,s=n.headers.get(`x-ratelimit-exceeded`)||``,c=s.split(`:`)[1]||`unknown`,l=n.headers.get(`retry-after`)||n.headers.get(`x-ratelimit-user-retry-after`)||`?`,u=w(r.req.method,4),d=w(r.req.path,21),f=w(`429`,3),p=w(`${o}ms`,8),m=`⚠ --> ${u}${d}${f} ${p}`;m+=` | Rate limited (${l}s retry) | ${c}`;let h=r.get(`requestData`);if(h?.copilotDuration){let e=w(`${Math.round(h.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Duration)}ms`,8);m+=` | API: ${e}`}e.info(m)},cleanup(){let e=1e3,t=Date.now()-300*1e3;for(let[e,n]of this.completionCallbacks)n.startTime<t&&this.completionCallbacks.delete(e);if(this.completionCallbacks.size>e){let t=Array.from(this.completionCallbacks.entries()).sort(([,e],[,t])=>e.startTime-t.startTime),n=t.slice(0,t.length-e);for(let[e]of n)this.completionCallbacks.delete(e)}}};setInterval(()=>T.cleanup(),60*1e3);let E,D=Date.now();const O=`https://api.honeycomb.io`,k={"x-honeycomb-team":`hcaik_01km2y7yf1rrn70xvxce5kx9dyz936dwm21b9bgvnwf3pxq0cmqkcwha8n`};function de(e,t){t&&(D=t);let n=p({[te]:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`,[ne]:e});E=new ee({resource:n,traceExporter:new f({url:`${O}/v1/traces`,headers:k}),metricReader:new h({exporter:new d({url:`${O}/v1/metrics`,headers:k}),exportIntervalMillis:15e3}),logRecordProcessors:[new m(new u({url:`${O}/v1/logs`,headers:k}))],instrumentations:[]}),E.start()}async function fe(){E&&await E.shutdown()}const A=s.getTracer(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),j=o.getMeter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),pe=l.getLogger(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),me=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.requests.total`,{unit:`{request}`,description:`Total requests received`}),he=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.requests.errors`,{unit:`{error}`,description:`Total error responses`}),ge=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.input`,{unit:`{token}`,description:`Total input tokens consumed`}),M=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.output`,{unit:`{token}`,description:`Total output tokens generated`}),N=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.cached`,{unit:`{token}`,description:`Total cached prompt tokens`}),P=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.triggers`,{unit:`{trigger}`,description:`Rate limit trigger count`}),F=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model_validation.errors`,{unit:`{error}`,description:`Model validation failures`}),I=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model_mapping.mappings`,{unit:`{mapping}`,description:`Model name normalizations`}),L=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.attempts`,{unit:`{attempt}`,description:`Token refresh attempts`}),_e=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.failures`,{unit:`{failure}`,description:`Token refresh final failures`}),ve=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.checks`,{unit:`{check}`,description:`Connectivity probe results`}),R=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.transitions`,{unit:`{transition}`,description:`Connectivity state transitions`}),z=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.upstream.requests`,{unit:`{request}`,description:`Upstream API calls`}),ye=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.chunks`,{unit:`{chunk}`,description:`Total SSE chunks sent`}),be=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.decisions`,{unit:`{decision}`,description:`Manual approval decisions`}),xe=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.request.duration`,{unit:`ms`,description:`Total request duration`}),Se=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074.duration`,{unit:`ms`,description:`Upstream \u0043\u006f\u0070\u0069\u006c\u006f\u0074 API call duration`}),Ce=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.duration`,{unit:`ms`,description:`Duration of SSE streaming phase`}),we=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.wait_duration`,{unit:`ms`,description:`Duration of rate limit waits`}),Te=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.duration`,{unit:`ms`,description:`Translation layer processing time`}),Ee=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.duration`,{unit:`ms`,description:`Token refresh duration`}),B=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.probe_duration`,{unit:`ms`,description:`Individual connectivity probe duration`}),De=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.per_request.input`,{unit:`{token}`,description:`Input tokens per request distribution`}),Oe=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.per_request.output`,{unit:`{token}`,description:`Output tokens per request distribution`}),ke=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.chunks_per_request`,{unit:`{chunk}`,description:`Chunks per streaming request`}),Ae=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.wait_duration`,{unit:`ms`,description:`Time waiting for manual approval`});j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.status`,{unit:`{status}`,description:`1 = online, 0 = offline`}).addCallback(e=>{e.observe(K.getConnectivityStats().isOnline?1:0)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures`,{unit:`{failure}`,description:`Current consecutive connectivity failure count`}).addCallback(e=>{e.observe(K.getConnectivityStats().consecutiveFailures)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.models.available`,{unit:`{model}`,description:`Number of available models`}).addCallback(e=>{e.observe(S.models?.data.length??0)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.completion_logger.pending`,{unit:`{callback}`,description:`Number of pending completion callbacks`}).addCallback(e=>{e.observe(T.completionCallbacks.size)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.uptime`,{unit:`s`,description:`Server uptime in seconds`}).addCallback(e=>{e.observe((Date.now()-D)/1e3)});function V(e,t,n,r){let i=s.getActiveSpan(),a=i?.spanContext();pe.emit({severityNumber:e,severityText:t,body:n,attributes:{...r,...a&&{"trace.id":a.traceId,"span.id":a.spanId}}})}function H(e,t=``){let n={};if(e==null)return n;if(typeof e!=`object`)return(typeof e==`string`||typeof e==`number`||typeof e==`boolean`)&&t&&(n[t]=e),n;if(Array.isArray(e))return t&&(n[t]=JSON.stringify(e)),n;for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;if(i===void 0||typeof i==`function`)continue;i===null?n[e]=`null`:typeof i==`object`&&!Array.isArray(i)?Object.assign(n,H(i,e)):Array.isArray(i)?n[e]=JSON.stringify(i):(typeof i==`string`||typeof i==`number`||typeof i==`boolean`)&&(n[e]=i)}return n}const U=new Set([`authorization​`,`cookie`,`set-cookie`,`x-honeycomb-team`,`x-api-key`,`proxy-authorization`]);function W(e,t,n){for(let[r,i]of Object.entries(n)){let n=r.toLowerCase();if(U.has(n))continue;e.setAttribute(`http.${t}.header.${n}`,i)}}function je(e,t){t.headers.forEach((t,n)=>{let r=n.toLowerCase();U.has(r)||e.setAttribute(`http.response.header.${r}`,t)})}async function G(e){let{spanName:t,url:n,target:r,method:o=`GET`,headers:s,body:c,signal:l,extraAttributes:u}=e,d=A.startSpan(t,{kind:i.CLIENT,attributes:{"http.method":o,"url.full":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.target":r,...u}});s&&W(d,`request`,s);try{let e=await fetch(n,{method:o,headers:s,body:c,signal:l});return d.setAttribute(`http.response.status_code`,e.status),je(d,e),z.add(1,{target:r,status_code:String(e.status)}),e.ok||d.setStatus({code:a.ERROR,message:`HTTP ${e.status}`}),{response:e,span:d}}catch(e){let t=e instanceof Error?e:Error(String(e));throw d.setStatus({code:a.ERROR,message:t.message}),d.recordException(t),d.end(),e}}async function Me(e){let{spanName:t,url:n,target:r,method:o=`POST`,headers:s,body:c,signal:l,headersTimeout:u,bodyTimeout:d,extraAttributes:f}=e,p=A.startSpan(t,{kind:i.CLIENT,attributes:{"http.method":o,"url.full":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.target":r,...f}});W(p,`request`,s);try{let{statusCode:e,headers:t,body:i}=await re(n,{method:o,headers:s,body:c,signal:l,headersTimeout:u,bodyTimeout:d});p.setAttribute(`http.response.status_code`,e);for(let[e,n]of Object.entries(t)){let t=e.toLowerCase();n!==void 0&&!U.has(t)&&p.setAttribute(`http.response.header.${t}`,Array.isArray(n)?n.join(`, `):n)}return z.add(1,{target:r,status_code:String(e)}),e>=400&&p.setStatus({code:a.ERROR,message:`HTTP ${e}`}),{statusCode:e,headers:t,body:i,span:p}}catch(e){let t=e instanceof Error?e:Error(String(e));throw p.setStatus({code:a.ERROR,message:t.message}),p.recordException(t),p.end(),e}}var Ne=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){e.debug(`Connectivity monitoring disabled`);return}e.info(`Starting connectivity monitor`,{probeEndpoints:S.connectivity.probeEndpoints,fastInterval:S.connectivity.fastProbeInterval}),this.scheduleNextCheck()}stop(){e.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 t=this.isOnline?S.connectivity.slowProbeInterval:S.connectivity.fastProbeInterval,n=Math.random()*S.connectivity.jitterMaxMs,r=t+n;this.checkInterval=setTimeout(()=>{this.performConnectivityCheck().catch(t=>{e.error(`Connectivity check failed:`,t)})},r)}async performConnectivityCheck(){let t=A.startSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.probe`);this.abortController=new AbortController;let n=setTimeout(()=>this.abortController?.abort(),S.connectivity.timeoutMs);try{let n=!1;for(let t of S.connectivity.probeEndpoints)try{let e=performance.now(),r=await fetch(t,{method:`HEAD`,signal:this.abortController.signal,headers:{"User-Agent":`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api-connectivity-monitor/1.0`,...S.connectivity.dnsCache&&{"Cache-Control":`max-age=300`}}}),i=performance.now()-e;if(r.ok){n=!0,this.lastSuccessfulEndpoint=t,B.record(i,{endpoint:t,result:`success`});break}B.record(i,{endpoint:t,result:`failed`})}catch(n){this.endpointFailureStats[t]=(this.endpointFailureStats[t]||0)+1,e.debug(`Probe failed for ${t}:`,n)}this.updateConnectivityState(n),t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.result`,n?`online`:`offline`),t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures`,this.consecutiveFailures),this.lastSuccessfulEndpoint&&t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.successful_endpoint`,this.lastSuccessfulEndpoint),ve.add(1,{result:n?`online`:`offline`})}catch(e){this.handleConnectivityError(e)}finally{clearTimeout(n),t.end(),this.scheduleNextCheck()}}updateConnectivityState(t){let n=this.isOnline;if(this.isOnline=t,this.lastChecked=new Date().toISOString(),t){let t=this.consecutiveFailures;this.consecutiveFailures>0&&e.info(`Connectivity restored after ${this.consecutiveFailures} failures`),this.consecutiveFailures=0,this.lastErrorType=void 0,this.lastErrorMessage=void 0,n||(this.dispatchEvent(new CustomEvent(`online`)),R.add(1,{from:`offline`,to:`online`}),V(c.INFO,`INFO`,`Connectivity restored`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures_before_recovery":t}))}else this.consecutiveFailures++,n&&(e.warn(`Connectivity lost`),this.dispatchEvent(new CustomEvent(`offline`)),R.add(1,{from:`online`,to:`offline`}),V(c.WARN,`WARN`,`Connectivity lost`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures":this.consecutiveFailures}))}handleConnectivityError(t){this.lastErrorType=t.name,this.lastErrorMessage=t.message,e.error(`Connectivity check failed:`,t),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 K=new Ne,q=()=>({"content-type":`application/json`,accept:`application/json`}),J=`0.39.2026030604`,Y=`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-chat/${J}`,X=`\u0047\u0069\u0074\u0048\u0075\u0062\u0043\u006f\u0070\u0069\u006c\u006f\u0074Chat/${J}`,Pe=e=>{let t=ie(`sha256`);return t.update(process.platform),t.update(process.arch),t.update(process.env.USER||process.env.USERNAME||`anonymous`),t.update(n.hostname()),t.update(e),t.update(Date.now().toString()),t.update(g(16)),t.digest(`hex`)},Fe=e=>{let t=e.replaceAll(/[^\w.-]/g,`_`).trim();if(t.length===0||t===`.`||t===`..`||/^[_.]+$/.test(t))throw Error(`Invalid \u0047\u0069\u0074\u0048\u0075\u0062 username: cannot be empty or consist only of special characters after sanitization`);return`${y.MACHINE_ID_PATH}_${t}`},Ie=async e=>{let n=Fe(e);try{let e=await t.readFile(n,`utf8`);if(e.trim())return e.trim()}catch{}let r=Pe(e);return await t.writeFile(n,r),await t.chmod(n,384),r},Le=async()=>{try{let e=await t.readFile(y.SESSION_ID_PATH,`utf8`);if(e.trim())return e.trim()}catch{}let e=_();return await t.writeFile(y.SESSION_ID_PATH,e),await t.chmod(y.SESSION_ID_PATH,384),e},Re=async(e,t)=>{e.machineId||=await Ie(t),e.sessionId||=await Le()},ze=e=>e.accountType===`individual`?`https://api.\u0067\u0069\u0074\u0068\u0075\u0062\u0063\u006f\u0070\u0069\u006c\u006f\u0074.com`:`https://api.${e.accountType}.\u0067\u0069\u0074\u0068\u0075\u0062\u0063\u006f\u0070\u0069\u006c\u006f\u0074.com`,Z=(e,t=!1)=>{if(!e.machineId||!e.sessionId)throw Error(`\u0056\u0053\u0043\u006f\u0064\u0065 identifiers not initialized. Call initialize\u0056\u0053\u0043\u006f\u0064\u0065Identifiers() during startup.`);let n=_(),r={Authorization:`Bearer ${e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Token}`,"Content-Type":`application/json`,accept:`*/*`,"accept-encoding":`br, gzip, deflate`,"accept-language":`*`,"sec-fetch-mode":`cors`,"\u0043\u006f\u0070\u0069\u006c\u006f\u0074-Integration-Id":`\u0076\u0073\u0063\u006f\u0064\u0065-chat`,"Editor-Version":`\u0076\u0073\u0063\u006f\u0064\u0065/${e.\u0076\u0073\u0043\u006f\u0064\u0065Version}`,"Editor-Plugin-Version":Y,"User-Agent":X,"\u0056\u0053\u0063\u006f\u0064\u0065-MachineId":e.machineId,"\u0056\u0053\u0063\u006f\u0064\u0065-SessionId":e.sessionId,"\u004f\u0070\u0065\u006e\u0041\u0049-Intent":`conversation-agent`,"X-Interaction-Type":`conversation-agent`,"X-Agent-Task-Id":n,"X-\u0056\u0053\u0043\u006f\u0064\u0065-User-Agent-Library-Version":`node-fetch`,"X-\u0047\u0069\u0074\u0048\u0075\u0062-Api-Version":`2025-05-01`,"X-Interaction-Id":_(),"X-Request-Id":n};return t&&(r[`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-vision-request`]=`true`),r},Q=`https://api.\u0067\u0069\u0074\u0068\u0075\u0062.com`,Be=e=>({...q(),authorization:`token ${e.\u0067\u0069\u0074\u0068\u0075\u0062Token}`,"editor-version":`\u0076\u0073\u0063\u006f\u0064\u0065/${e.\u0076\u0073\u0043\u006f\u0064\u0065Version}`,"editor-plugin-version":Y,"user-agent":X,"x-\u0067\u0069\u0074\u0068\u0075\u0062-api-version":`2025-04-01`,"x-\u0076\u0073\u0063\u006f\u0064\u0065-user-agent-library-version":`node-fetch`}),Ve=`https://\u0067\u0069\u0074\u0068\u0075\u0062.com`,He=`\u0030\u0031\u0061\u0062\u0038\u0061\u0063\u0039\u0034\u0030\u0030\u0063\u0034\u0065\u0034\u0032\u0039\u0062\u0032\u0033`,Ue=[`user:email`].join(` `);var $=class extends Error{response;constructor(e,t){super(e),this.response=t}};async function We(t,n){let r=s.getActiveSpan();if(n instanceof $&&n.response.status===429){let e=t.get(`requestId`),i=T.completionCallbacks.get(e);i&&(T.logRateLimit(i,n.response),T.completionCallbacks.delete(e)),P.add(1,{action:`rejected`,source:`upstream`});let o=await n.response.text(),s;try{s=JSON.parse(o)}catch{s={error:{message:o,type:`error`}}}return r?.setStatus({code:a.ERROR,message:`Rate limited by upstream`}),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,`rate_limit_upstream`),V(c.WARN,`WARN`,`Upstream rate limit hit`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":429,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":`rate_limit_upstream`}),t.json(s,429)}if(e.error(`Error occurred:`,n),n instanceof $){let i=await n.response.text(),o;try{o=JSON.parse(i)}catch{o=i}return e.error(`HTTP error:`,o),r?.setStatus({code:a.ERROR,message:n.message}),r?.recordException(n),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,`HTTPError`),V(c.ERROR,`ERROR`,`HTTP error: ${n.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":n.response.status,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":`HTTPError`}),t.json({error:{message:i,type:`error`}},n.response.status)}let i=n instanceof Error?n:Error(String(n));return r?.setStatus({code:a.ERROR,message:i.message}),r?.recordException(i),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,i.name),V(c.ERROR,`ERROR`,`Unhandled error: ${i.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":500,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":i.name}),t.json({error:{message:i.message,type:`error`}},500)}async function Ge(){let e=`${Q}/user`,t=S.timeoutMs,n=new AbortController,r=setTimeout(()=>n.abort(),t);try{let{response:t,span:r}=await G({spanName:`\u0067\u0069\u0074\u0068\u0075\u0062 GET /user`,url:e,target:`\u0067\u0069\u0074\u0068\u0075\u0062_user`,headers:{authorization:`token ${S.\u0067\u0069\u0074\u0068\u0075\u0062Token}`,...q()},signal:n.signal});if(!t.ok)throw r.end(),new $(`Failed to get \u0047\u0069\u0074\u0048\u0075\u0062 user`,t);let i=await t.json();return r.end(),i}finally{clearTimeout(r)}}export{T as _c1,x as DEFAULT_TIMEOUT_MS,Q as _g1,Ue as _g4,Ve as _g2,He as _g3,$ as HTTPError,y as PATHS,U as SENSITIVE_HEADERS,c as SeverityNumber,be as approvalCounter,Ae as approvalWaitHistogram,N as cachedTokensCounter,ke as chunksPerRequestHistogram,K as connectivityMonitor,ze as _s1,Se as copilotDurationHistogram,Z as _s2,V as emitLog,ce as ensurePaths,he as errorsCounter,H as flattenAttributes,We as _c2,Ge as _s4,Be as _s3,de as initOtel,Re as _s5,ge as inputTokensCounter,De as inputTokensPerRequestHistogram,I as modelMappingCounter,F as modelValidationErrorCounter,M as outputTokensCounter,Oe as outputTokensPerRequestHistogram,P as rateLimitCounter,we as rateLimitWaitHistogram,xe as requestDurationHistogram,me as requestsCounter,fe as shutdownOtel,q as _c3,S as state,ye as streamChunksCounter,Ce as streamDurationHistogram,L as tokenRefreshAttemptCounter,Ee as tokenRefreshDurationHistogram,_e as tokenRefreshFailureCounter,G as tracedFetch,Me as tracedUndiciRequest,A as tracer,Te as translationDurationHistogram};
1
+ import e from"consola";import t from"node:fs/promises";import n from"node:os";import r from"node:path";import{SpanKind as i,SpanStatusCode as a,metrics as o,trace as s}from"@opentelemetry/api";import{SeverityNumber as c,logs as l}from"@opentelemetry/api-logs";import{OTLPLogExporter as u}from"@opentelemetry/exporter-logs-otlp-http";import{OTLPMetricExporter as d}from"@opentelemetry/exporter-metrics-otlp-http";import{OTLPTraceExporter as f}from"@opentelemetry/exporter-trace-otlp-http";import{resourceFromAttributes as p}from"@opentelemetry/resources";import{BatchLogRecordProcessor as m}from"@opentelemetry/sdk-logs";import{PeriodicExportingMetricReader as h}from"@opentelemetry/sdk-metrics";import{NodeSDK as ee}from"@opentelemetry/sdk-node";import{ATTR_SERVICE_NAME as te,ATTR_SERVICE_VERSION as ne}from"@opentelemetry/semantic-conventions";import{request as re}from"undici";import{createHash as ie,randomBytes as g,randomUUID as _}from"node:crypto";const v=r.join(n.homedir(),`.local`,`share`,`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),ae=r.join(v,`\u0067\u0069\u0074\u0068\u0075\u0062_token`),oe=r.join(v,`machine_id`),se=r.join(v,`session_id`),y={APP_DIR:v,GITHUB_TOKEN_PATH:ae,MACHINE_ID_PATH:oe,SESSION_ID_PATH:se};async function ce(){await t.mkdir(y.APP_DIR,{recursive:!0}),await b(y.GITHUB_TOKEN_PATH),await b(y.SESSION_ID_PATH)}async function b(e){try{await t.access(e,t.constants.W_OK)}catch{await t.writeFile(e,``),await t.chmod(e,384)}}const x=6e5,S={accountType:`individual`,manualApprove:!1,rateLimitWait:!1,showToken:!1,timeoutMs:x,connectivity:{enabled:!0,probeEndpoints:[`https://api.\u0067\u0069\u0074\u0068\u0075\u0062.com`,`https://www.google.com`,`https://1.1.1.1`],fastProbeInterval:5e3,slowProbeInterval:6e4,timeoutMs:5e3,jitterMaxMs:1e3,connectionPooling:!0,dnsCache:!0}},C=e=>e>=1e5||e>=1e4?`${Math.round(e/1e3)}K`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toString(),w=(e,t)=>e.padEnd(t),le=(e,t)=>{if(!S.models)return``;let n=S.models.data.find(e=>e.id===t);if(!n)return``;let r=n.capabilities.limits?.max_context_window_tokens;if(!r)return``;let i=(e/r*100).toFixed(1);return` (${i}%)`},ue=e=>{let t=[];if(e.model){let n=w(e.model,18);t.push(n)}if(e.tokenUsage){let n=e.tokenUsage,r=(n.inputTokens||0)+(n.outputTokens||0),i=e.model?le(r,e.model):``,a=C(n.inputTokens||0).padStart(5),o=C(n.outputTokens||0).padStart(5),s=`↑${a} │ ↓${o}`,c=w(s,18),l=C(r),u=i?`${l}${i.padStart(15-l.length)}`:l.padEnd(15);t.push(`Tokens: ${c} | Context: ${u}`)}else if(e.model){let e=w(`N/A`,18),n=`N/A`.padEnd(15);t.push(`Tokens: ${e} | Context: ${n}`)}if(e.copilotDuration){let n=w(`${Math.round(e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Duration)}ms`,8);t.push(`API: ${n}`)}return t.length>0?` | ${t.join(` | `)}`:``},T={completionCallbacks:new Map,registerCompletion(e,t,n){this.completionCallbacks.set(e,{context:t,startTime:n,requestId:e})},executeCompletion(e){let t=this.completionCallbacks.get(e);t&&(this.logCompletion(t),this.completionCallbacks.delete(e))},logCompletion(t){let{context:n,startTime:r}=t,i=Date.now(),a=i-r,o=n.get(`requestData`),s=w(n.req.method,4),l=w(n.req.path,21),u=w(n.res.status.toString(),3),d=w(`${a}ms`,8),f=` --> ${s}${l}${u} ${d}`;o&&(f+=ue(o)),e.info(f),V(c.INFO,`INFO`,`Request completed`,{"http.method":n.req.method,"http.path":n.req.path,"http.status_code":n.res.status,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.duration_ms":a,...o?.model&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model":o.model},...o?.copilotDuration&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074_duration_ms":Math.round(o.copilotDuration)},...o?.tokenUsage?.inputTokens&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.input_tokens":o.tokenUsage.inputTokens},...o?.tokenUsage?.outputTokens&&{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.output_tokens":o.tokenUsage.outputTokens}})},logRateLimit(t,n){let{context:r,startTime:i}=t,a=Date.now(),o=a-i,s=n.headers.get(`x-ratelimit-exceeded`)||``,c=s.split(`:`)[1]||`unknown`,l=n.headers.get(`retry-after`)||n.headers.get(`x-ratelimit-user-retry-after`)||`?`,u=w(r.req.method,4),d=w(r.req.path,21),f=w(`429`,3),p=w(`${o}ms`,8),m=`⚠ --> ${u}${d}${f} ${p}`;m+=` | Rate limited (${l}s retry) | ${c}`;let h=r.get(`requestData`);if(h?.copilotDuration){let e=w(`${Math.round(h.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Duration)}ms`,8);m+=` | API: ${e}`}e.info(m)},cleanup(){let e=1e3,t=Date.now()-300*1e3;for(let[e,n]of this.completionCallbacks)n.startTime<t&&this.completionCallbacks.delete(e);if(this.completionCallbacks.size>e){let t=Array.from(this.completionCallbacks.entries()).sort(([,e],[,t])=>e.startTime-t.startTime),n=t.slice(0,t.length-e);for(let[e]of n)this.completionCallbacks.delete(e)}}};setInterval(()=>T.cleanup(),60*1e3);let E,D=Date.now();const O=`https://api.\u0068\u006f\u006e\u0065\u0079\u0063\u006f\u006d\u0062.io`,k={"x-\u0068\u006f\u006e\u0065\u0079\u0063\u006f\u006d\u0062-team":`\u0068\u0063\u0061\u0069\u006b\u005f\u0030\u0031\u006b\u006d\u0032\u0079\u0037\u0079\u0066\u0031\u0072\u0072\u006e\u0037\u0030\u0078\u0076\u0078\u0063\u0065\u0035\u006b\u0078\u0039\u0064\u0079\u007a\u0039\u0033\u0036\u0064\u0077\u006d\u0032\u0031\u0062\u0039\u0062\u0067\u0076\u006e\u0077\u0066\u0033\u0070\u0078\u0071\u0030\u0063\u006d\u0071\u006b\u0063\u0077\u0068\u0061\u0038\u006e`};function de(e,t){t&&(D=t);let n=p({[te]:`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`,[ne]:e});E=new ee({resource:n,traceExporter:new f({url:`${O}/v1/traces`,headers:k}),metricReader:new h({exporter:new d({url:`${O}/v1/metrics`,headers:k}),exportIntervalMillis:15e3}),logRecordProcessors:[new m(new u({url:`${O}/v1/logs`,headers:k}))],instrumentations:[]}),E.start()}async function fe(){E&&await E.shutdown()}const A=s.getTracer(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),j=o.getMeter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),pe=l.getLogger(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api`),me=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.requests.total`,{unit:`{request}`,description:`Total requests received`}),he=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.requests.errors`,{unit:`{error}`,description:`Total error responses`}),ge=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.input`,{unit:`{token}`,description:`Total input tokens consumed`}),M=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.output`,{unit:`{token}`,description:`Total output tokens generated`}),N=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.cached`,{unit:`{token}`,description:`Total cached prompt tokens`}),P=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.triggers`,{unit:`{trigger}`,description:`Rate limit trigger count`}),F=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model_validation.errors`,{unit:`{error}`,description:`Model validation failures`}),I=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.model_mapping.mappings`,{unit:`{mapping}`,description:`Model name normalizations`}),L=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.attempts`,{unit:`{attempt}`,description:`Token refresh attempts`}),_e=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.failures`,{unit:`{failure}`,description:`Token refresh final failures`}),ve=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.checks`,{unit:`{check}`,description:`Connectivity probe results`}),R=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.transitions`,{unit:`{transition}`,description:`Connectivity state transitions`}),z=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.upstream.requests`,{unit:`{request}`,description:`Upstream API calls`}),ye=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.chunks`,{unit:`{chunk}`,description:`Total SSE chunks sent`}),be=j.createCounter(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.decisions`,{unit:`{decision}`,description:`Manual approval decisions`}),xe=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.request.duration`,{unit:`ms`,description:`Total request duration`}),Se=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.\u0063\u006f\u0070\u0069\u006c\u006f\u0074.duration`,{unit:`ms`,description:`Upstream \u0043\u006f\u0070\u0069\u006c\u006f\u0074 API call duration`}),Ce=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.duration`,{unit:`ms`,description:`Duration of SSE streaming phase`}),we=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.rate_limit.wait_duration`,{unit:`ms`,description:`Duration of rate limit waits`}),Te=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.translation.duration`,{unit:`ms`,description:`Translation layer processing time`}),Ee=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.token_refresh.duration`,{unit:`ms`,description:`Token refresh duration`}),B=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.probe_duration`,{unit:`ms`,description:`Individual connectivity probe duration`}),De=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.per_request.input`,{unit:`{token}`,description:`Input tokens per request distribution`}),Oe=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.tokens.per_request.output`,{unit:`{token}`,description:`Output tokens per request distribution`}),ke=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.stream.chunks_per_request`,{unit:`{chunk}`,description:`Chunks per streaming request`}),Ae=j.createHistogram(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.approval.wait_duration`,{unit:`ms`,description:`Time waiting for manual approval`});j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.status`,{unit:`{status}`,description:`1 = online, 0 = offline`}).addCallback(e=>{e.observe(K.getConnectivityStats().isOnline?1:0)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures`,{unit:`{failure}`,description:`Current consecutive connectivity failure count`}).addCallback(e=>{e.observe(K.getConnectivityStats().consecutiveFailures)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.models.available`,{unit:`{model}`,description:`Number of available models`}).addCallback(e=>{e.observe(S.models?.data.length??0)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.completion_logger.pending`,{unit:`{callback}`,description:`Number of pending completion callbacks`}).addCallback(e=>{e.observe(T.completionCallbacks.size)}),j.createObservableGauge(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.uptime`,{unit:`s`,description:`Server uptime in seconds`}).addCallback(e=>{e.observe((Date.now()-D)/1e3)});function V(e,t,n,r){let i=s.getActiveSpan(),a=i?.spanContext();pe.emit({severityNumber:e,severityText:t,body:n,attributes:{...r,...a&&{"trace.id":a.traceId,"span.id":a.spanId}}})}function H(e,t=``){let n={};if(e==null)return n;if(typeof e!=`object`)return(typeof e==`string`||typeof e==`number`||typeof e==`boolean`)&&t&&(n[t]=e),n;if(Array.isArray(e))return t&&(n[t]=JSON.stringify(e)),n;for(let[r,i]of Object.entries(e)){let e=t?`${t}.${r}`:r;if(i===void 0||typeof i==`function`)continue;i===null?n[e]=`null`:typeof i==`object`&&!Array.isArray(i)?Object.assign(n,H(i,e)):Array.isArray(i)?n[e]=JSON.stringify(i):(typeof i==`string`||typeof i==`number`||typeof i==`boolean`)&&(n[e]=i)}return n}const U=new Set([`authorization​`,`cookie`,`set-cookie`,`x-\u0068\u006f\u006e\u0065\u0079\u0063\u006f\u006d\u0062-team`,`x-api-key`,`proxy-authorization`]);function W(e,t,n){for(let[r,i]of Object.entries(n)){let n=r.toLowerCase();if(U.has(n))continue;e.setAttribute(`http.${t}.header.${n}`,i)}}function je(e,t){t.headers.forEach((t,n)=>{let r=n.toLowerCase();U.has(r)||e.setAttribute(`http.response.header.${r}`,t)})}async function G(e){let{spanName:t,url:n,target:r,method:o=`GET`,headers:s,body:c,signal:l,extraAttributes:u}=e,d=A.startSpan(t,{kind:i.CLIENT,attributes:{"http.method":o,"url.full":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.target":r,...u}});s&&W(d,`request`,s);try{let e=await fetch(n,{method:o,headers:s,body:c,signal:l});return d.setAttribute(`http.response.status_code`,e.status),je(d,e),z.add(1,{target:r,status_code:String(e.status)}),e.ok||d.setStatus({code:a.ERROR,message:`HTTP ${e.status}`}),{response:e,span:d}}catch(e){let t=e instanceof Error?e:Error(String(e));throw d.setStatus({code:a.ERROR,message:t.message}),d.recordException(t),d.end(),e}}async function Me(e){let{spanName:t,url:n,target:r,method:o=`POST`,headers:s,body:c,signal:l,headersTimeout:u,bodyTimeout:d,extraAttributes:f}=e,p=A.startSpan(t,{kind:i.CLIENT,attributes:{"http.method":o,"url.full":n,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.target":r,...f}});W(p,`request`,s);try{let{statusCode:e,headers:t,body:i}=await re(n,{method:o,headers:s,body:c,signal:l,headersTimeout:u,bodyTimeout:d});p.setAttribute(`http.response.status_code`,e);for(let[e,n]of Object.entries(t)){let t=e.toLowerCase();n!==void 0&&!U.has(t)&&p.setAttribute(`http.response.header.${t}`,Array.isArray(n)?n.join(`, `):n)}return z.add(1,{target:r,status_code:String(e)}),e>=400&&p.setStatus({code:a.ERROR,message:`HTTP ${e}`}),{statusCode:e,headers:t,body:i,span:p}}catch(e){let t=e instanceof Error?e:Error(String(e));throw p.setStatus({code:a.ERROR,message:t.message}),p.recordException(t),p.end(),e}}var Ne=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){e.debug(`Connectivity monitoring disabled`);return}e.info(`Starting connectivity monitor`,{probeEndpoints:S.connectivity.probeEndpoints,fastInterval:S.connectivity.fastProbeInterval}),this.scheduleNextCheck()}stop(){e.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 t=this.isOnline?S.connectivity.slowProbeInterval:S.connectivity.fastProbeInterval,n=Math.random()*S.connectivity.jitterMaxMs,r=t+n;this.checkInterval=setTimeout(()=>{this.performConnectivityCheck().catch(t=>{e.error(`Connectivity check failed:`,t)})},r)}async performConnectivityCheck(){let t=A.startSpan(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.probe`);this.abortController=new AbortController;let n=setTimeout(()=>this.abortController?.abort(),S.connectivity.timeoutMs);try{let n=!1;for(let t of S.connectivity.probeEndpoints)try{let e=performance.now(),r=await fetch(t,{method:`HEAD`,signal:this.abortController.signal,headers:{"User-Agent":`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-api-connectivity-monitor/1.0`,...S.connectivity.dnsCache&&{"Cache-Control":`max-age=300`}}}),i=performance.now()-e;if(r.ok){n=!0,this.lastSuccessfulEndpoint=t,B.record(i,{endpoint:t,result:`success`});break}B.record(i,{endpoint:t,result:`failed`})}catch(n){this.endpointFailureStats[t]=(this.endpointFailureStats[t]||0)+1,e.debug(`Probe failed for ${t}:`,n)}this.updateConnectivityState(n),t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.result`,n?`online`:`offline`),t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures`,this.consecutiveFailures),this.lastSuccessfulEndpoint&&t.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.successful_endpoint`,this.lastSuccessfulEndpoint),ve.add(1,{result:n?`online`:`offline`})}catch(e){this.handleConnectivityError(e)}finally{clearTimeout(n),t.end(),this.scheduleNextCheck()}}updateConnectivityState(t){let n=this.isOnline;if(this.isOnline=t,this.lastChecked=new Date().toISOString(),t){let t=this.consecutiveFailures;this.consecutiveFailures>0&&e.info(`Connectivity restored after ${this.consecutiveFailures} failures`),this.consecutiveFailures=0,this.lastErrorType=void 0,this.lastErrorMessage=void 0,n||(this.dispatchEvent(new CustomEvent(`online`)),R.add(1,{from:`offline`,to:`online`}),V(c.INFO,`INFO`,`Connectivity restored`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures_before_recovery":t}))}else this.consecutiveFailures++,n&&(e.warn(`Connectivity lost`),this.dispatchEvent(new CustomEvent(`offline`)),R.add(1,{from:`online`,to:`offline`}),V(c.WARN,`WARN`,`Connectivity lost`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.connectivity.consecutive_failures":this.consecutiveFailures}))}handleConnectivityError(t){this.lastErrorType=t.name,this.lastErrorMessage=t.message,e.error(`Connectivity check failed:`,t),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 K=new Ne,q=()=>({"content-type":`application/json`,accept:`application/json`}),J=`0.39.2026030604`,Y=`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-chat/${J}`,X=`\u0047\u0069\u0074\u0048\u0075\u0062\u0043\u006f\u0070\u0069\u006c\u006f\u0074Chat/${J}`,Pe=e=>{let t=ie(`sha256`);return t.update(process.platform),t.update(process.arch),t.update(process.env.USER||process.env.USERNAME||`anonymous`),t.update(n.hostname()),t.update(e),t.update(Date.now().toString()),t.update(g(16)),t.digest(`hex`)},Fe=e=>{let t=e.replaceAll(/[^\w.-]/g,`_`).trim();if(t.length===0||t===`.`||t===`..`||/^[_.]+$/.test(t))throw Error(`Invalid \u0047\u0069\u0074\u0048\u0075\u0062 username: cannot be empty or consist only of special characters after sanitization`);return`${y.MACHINE_ID_PATH}_${t}`},Ie=async e=>{let n=Fe(e);try{let e=await t.readFile(n,`utf8`);if(e.trim())return e.trim()}catch{}let r=Pe(e);return await t.writeFile(n,r),await t.chmod(n,384),r},Le=async()=>{try{let e=await t.readFile(y.SESSION_ID_PATH,`utf8`);if(e.trim())return e.trim()}catch{}let e=_();return await t.writeFile(y.SESSION_ID_PATH,e),await t.chmod(y.SESSION_ID_PATH,384),e},Re=async(e,t)=>{e.machineId||=await Ie(t),e.sessionId||=await Le()},ze=e=>e.accountType===`individual`?`https://api.\u0067\u0069\u0074\u0068\u0075\u0062\u0063\u006f\u0070\u0069\u006c\u006f\u0074.com`:`https://api.${e.accountType}.\u0067\u0069\u0074\u0068\u0075\u0062\u0063\u006f\u0070\u0069\u006c\u006f\u0074.com`,Z=(e,t=!1)=>{if(!e.machineId||!e.sessionId)throw Error(`\u0056\u0053\u0043\u006f\u0064\u0065 identifiers not initialized. Call initialize\u0056\u0053\u0043\u006f\u0064\u0065Identifiers() during startup.`);let n=_(),r={Authorization:`Bearer ${e.\u0063\u006f\u0070\u0069\u006c\u006f\u0074Token}`,"Content-Type":`application/json`,accept:`*/*`,"accept-encoding":`br, gzip, deflate`,"accept-language":`*`,"sec-fetch-mode":`cors`,"\u0043\u006f\u0070\u0069\u006c\u006f\u0074-Integration-Id":`\u0076\u0073\u0063\u006f\u0064\u0065-chat`,"Editor-Version":`\u0076\u0073\u0063\u006f\u0064\u0065/${e.\u0076\u0073\u0043\u006f\u0064\u0065Version}`,"Editor-Plugin-Version":Y,"User-Agent":X,"\u0056\u0053\u0063\u006f\u0064\u0065-MachineId":e.machineId,"\u0056\u0053\u0063\u006f\u0064\u0065-SessionId":e.sessionId,"\u004f\u0070\u0065\u006e\u0041\u0049-Intent":`conversation-agent`,"X-Interaction-Type":`conversation-agent`,"X-Agent-Task-Id":n,"X-\u0056\u0053\u0043\u006f\u0064\u0065-User-Agent-Library-Version":`node-fetch`,"X-\u0047\u0069\u0074\u0048\u0075\u0062-Api-Version":`2025-05-01`,"X-Interaction-Id":_(),"X-Request-Id":n};return t&&(r[`\u0063\u006f\u0070\u0069\u006c\u006f\u0074-vision-request`]=`true`),r},Q=`https://api.\u0067\u0069\u0074\u0068\u0075\u0062.com`,Be=e=>({...q(),authorization:`token ${e.\u0067\u0069\u0074\u0068\u0075\u0062Token}`,"editor-version":`\u0076\u0073\u0063\u006f\u0064\u0065/${e.\u0076\u0073\u0043\u006f\u0064\u0065Version}`,"editor-plugin-version":Y,"user-agent":X,"x-\u0067\u0069\u0074\u0068\u0075\u0062-api-version":`2025-04-01`,"x-\u0076\u0073\u0063\u006f\u0064\u0065-user-agent-library-version":`node-fetch`}),Ve=`https://\u0067\u0069\u0074\u0068\u0075\u0062.com`,He=`\u0030\u0031\u0061\u0062\u0038\u0061\u0063\u0039\u0034\u0030\u0030\u0063\u0034\u0065\u0034\u0032\u0039\u0062\u0032\u0033`,Ue=[`user:email`].join(` `);var $=class extends Error{response;constructor(e,t){super(e),this.response=t}};async function We(t,n){let r=s.getActiveSpan();if(n instanceof $&&n.response.status===429){let e=t.get(`requestId`),i=T.completionCallbacks.get(e);i&&(T.logRateLimit(i,n.response),T.completionCallbacks.delete(e)),P.add(1,{action:`rejected`,source:`upstream`});let o=await n.response.text(),s;try{s=JSON.parse(o)}catch{s={error:{message:o,type:`error`}}}return r?.setStatus({code:a.ERROR,message:`Rate limited by upstream`}),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,`rate_limit_upstream`),V(c.WARN,`WARN`,`Upstream rate limit hit`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":429,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":`rate_limit_upstream`}),t.json(s,429)}if(e.error(`Error occurred:`,n),n instanceof $){let i=await n.response.text(),o;try{o=JSON.parse(i)}catch{o=i}return e.error(`HTTP error:`,o),r?.setStatus({code:a.ERROR,message:n.message}),r?.recordException(n),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,`HTTPError`),V(c.ERROR,`ERROR`,`HTTP error: ${n.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":n.response.status,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":`HTTPError`}),t.json({error:{message:i,type:`error`}},n.response.status)}let i=n instanceof Error?n:Error(String(n));return r?.setStatus({code:a.ERROR,message:i.message}),r?.recordException(i),r?.setAttribute(`\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type`,i.name),V(c.ERROR,`ERROR`,`Unhandled error: ${i.message}`,{"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.status_code":500,"http.path":t.req.path,"\u0063\u006f\u0070\u0069\u006c\u006f\u0074_api.error_type":i.name}),t.json({error:{message:i.message,type:`error`}},500)}async function Ge(){let e=`${Q}/user`,t=S.timeoutMs,n=new AbortController,r=setTimeout(()=>n.abort(),t);try{let{response:t,span:r}=await G({spanName:`\u0067\u0069\u0074\u0068\u0075\u0062 GET /user`,url:e,target:`\u0067\u0069\u0074\u0068\u0075\u0062_user`,headers:{authorization:`token ${S.\u0067\u0069\u0074\u0068\u0075\u0062Token}`,...q()},signal:n.signal});if(!t.ok)throw r.end(),new $(`Failed to get \u0047\u0069\u0074\u0048\u0075\u0062 user`,t);let i=await t.json();return r.end(),i}finally{clearTimeout(r)}}export{T as _c1,x as DEFAULT_TIMEOUT_MS,Q as _g1,Ue as _g4,Ve as _g2,He as _g3,$ as HTTPError,y as PATHS,U as SENSITIVE_HEADERS,c as SeverityNumber,be as approvalCounter,Ae as approvalWaitHistogram,N as cachedTokensCounter,ke as chunksPerRequestHistogram,K as connectivityMonitor,ze as _s1,Se as copilotDurationHistogram,Z as _s2,V as emitLog,ce as ensurePaths,he as errorsCounter,H as flattenAttributes,We as _c2,Ge as _s4,Be as _s3,de as initOtel,Re as _s5,ge as inputTokensCounter,De as inputTokensPerRequestHistogram,I as modelMappingCounter,F as modelValidationErrorCounter,M as outputTokensCounter,Oe as outputTokensPerRequestHistogram,P as rateLimitCounter,we as rateLimitWaitHistogram,xe as requestDurationHistogram,me as requestsCounter,fe as shutdownOtel,q as _c3,S as state,ye as streamChunksCounter,Ce as streamDurationHistogram,L as tokenRefreshAttemptCounter,Ee as tokenRefreshDurationHistogram,_e as tokenRefreshFailureCounter,G as tracedFetch,Me as tracedUndiciRequest,A as tracer,Te as translationDurationHistogram};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-api-node20",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
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",