ghc-tunnel 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/dist/index.js +68 -67
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var dt=Object.create;var Ie=Object.defineProperty;var gt=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var ft=Object.getPrototypeOf,_t=Object.prototype.hasOwnProperty;var ht=(t,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of mt(e))!_t.call(t,s)&&s!==o&&Ie(t,s,{get:()=>e[s],enumerable:!(n=gt(e,s))||n.enumerable});return t};var A=(t,e,o)=>(o=t!=null?dt(ft(t)):{},ht(e||!t||!t.__esModule?Ie(o,"default",{value:t,enumerable:!0}):o,t));var lt=A(require("fs")),pt=A(require("path")),he=A(require("express"));var te=A(require("fs")),ce=A(require("path")),ye=A(require("os")),Ne=A(require("js-yaml")),je=parseInt(process.env.PORT||"8314",10),He=process.env.HOST||"localhost",Le="https://api.github.com",ne="0.26.7",oe="2025-04-01",se="1.93.0",Re={exact:{opus:"claude-opus-4.6-1m",sonnet:"claude-opus-4.6-1m",haiku:"claude-haiku-4.5"},prefix:{"claude-sonnet-4-":"claude-opus-4.6-1m","claude-opus-4.5-":"claude-opus-4.6-1m","claude-opus-4.6-":"claude-opus-4.6-1m","claude-opus-4-5-":"claude-opus-4.6-1m","claude-opus-4-6-":"claude-opus-4.6-1m","claude-opus-4.5":"claude-opus-4.6-1m","claude-opus-4.6":"claude-opus-4.6-1m","claude-opus-4-6":"claude-opus-4.6-1m","claude-opus-4-6[1m]":"claude-opus-4.6-1m","claude-sonnet-4-6":"claude-opus-4.6-1m","claude-sonnet-4-5":"claude-opus-4.6-1m","claude-haiku-4.5-":"claude-haiku-4.5","claude-haiku-4-5-":"claude-haiku-4.5"}},be="01ab8ac9400c4e429b23",ke=class{exactMappings={};prefixMappings={};translate(e){if(e in this.exactMappings)return this.exactMappings[e];for(let[o,n]of Object.entries(this.prefixMappings))if(e.startsWith(o))return n;return e}loadFromConfig(e){let o=e.model_mappings;this.exactMappings=o?.exact??{},this.prefixMappings=o?.prefix??{}}},M=new ke;function P(){return process.platform==="win32"?ce.default.join(process.env.APPDATA||ye.default.homedir(),"ghc-tunnel"):ce.default.join(ye.default.homedir(),".ghc-tunnel")}function Me(t){let e=te.default.readFileSync(t,"utf-8");return Ne.default.load(e)||{}}function we(){let t=P();te.default.mkdirSync(t,{recursive:!0});let e=ce.default.join(t,"config.yaml");if(te.default.existsSync(e)){console.log(`Configuration file already exists at: ${e}`);return}let o=`# GitHub Copilot API Proxy Configuration
2
+ "use strict";var gt=Object.create;var je=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var ft=Object.getOwnPropertyNames;var _t=Object.getPrototypeOf,ht=Object.prototype.hasOwnProperty;var yt=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ft(e))!ht.call(t,s)&&s!==n&&je(t,s,{get:()=>e[s],enumerable:!(o=mt(e,s))||o.enumerable});return t};var A=(t,e,n)=>(n=t!=null?gt(_t(t)):{},yt(e||!t||!t.__esModule?je(n,"default",{value:t,enumerable:!0}):n,t));var ae=A(require("fs")),ke=A(require("path")),ye=A(require("express"));var te=A(require("fs")),ue=A(require("path")),Re=A(require("os")),Le=A(require("js-yaml")),He=parseInt(process.env.PORT||"8314",10),Me=process.env.HOST||"localhost",Ue="https://api.github.com",ne="0.26.7",oe="2025-04-01",se="1.93.0",we={exact:{opus:"claude-opus-4.6-1m",sonnet:"claude-opus-4.6-1m",haiku:"claude-haiku-4.5"},prefix:{"claude-sonnet-4-":"claude-opus-4.6-1m","claude-opus-4.5-":"claude-opus-4.6-1m","claude-opus-4.6-":"claude-opus-4.6-1m","claude-opus-4-5-":"claude-opus-4.6-1m","claude-opus-4-6-":"claude-opus-4.6-1m","claude-opus-4.5":"claude-opus-4.6-1m","claude-opus-4.6":"claude-opus-4.6-1m","claude-opus-4-6":"claude-opus-4.6-1m","claude-opus-4-6[1m]":"claude-opus-4.6-1m","claude-sonnet-4-6":"claude-opus-4.6-1m","claude-sonnet-4-5":"claude-opus-4.6-1m","claude-haiku-4.5-":"claude-haiku-4.5","claude-haiku-4-5-":"claude-haiku-4.5"}},Se="01ab8ac9400c4e429b23",be=class{exactMappings={};prefixMappings={};translate(e){if(e in this.exactMappings)return this.exactMappings[e];for(let[n,o]of Object.entries(this.prefixMappings))if(e.startsWith(n))return o;return e}loadFromConfig(e){let n=e.model_mappings;this.exactMappings=n?.exact??{},this.prefixMappings=n?.prefix??{}}},M=new be;function T(){return process.platform==="win32"?ue.default.join(process.env.APPDATA||Re.default.homedir(),"ghc-tunnel"):ue.default.join(Re.default.homedir(),".ghc-tunnel")}function Fe(t){let e=te.default.readFileSync(t,"utf-8");return Le.default.load(e)||{}}function ve(){let t=T();te.default.mkdirSync(t,{recursive:!0});let e=ue.default.join(t,"config.yaml");if(te.default.existsSync(e)){console.log(`Configuration file already exists at: ${e}`);return}let n=`# GitHub Copilot API Proxy Configuration
3
3
  # ========================================
4
4
 
5
5
  # Server Settings
@@ -49,85 +49,85 @@ tool_result_suffix_remove: []
49
49
  # Retry Settings
50
50
  # Max retries for upstream connection errors (0 = no retries)
51
51
  max_connection_retries: 3
52
- `;te.default.writeFileSync(e,o,"utf-8"),console.log(`Configuration file generated at: ${e}`)}var ve=class{githubToken="";copilotToken=null;models=null;accountType="individual";tokenExpiresAt=0;vscodeVersion=se;copilotVersion=ne;apiVersion=oe;systemPromptRemove=[];systemPromptAdd=[];toolResultSuffixRemove=[];redirectAnthropic=!1;maxConnectionRetries=3;get editorPluginVersion(){return`copilot-chat/${this.copilotVersion}`}get userAgent(){return`GitHubCopilotChat/${this.copilotVersion}`}},g=new ve;var re=A(require("fs")),Ue=require("child_process"),Fe=A(require("path"));function ze(){let t=P();return re.default.mkdirSync(t,{recursive:!0}),Fe.default.join(t,"github_token.txt")}function yt(){let t=ze();if(!re.default.existsSync(t))return null;try{let e=re.default.readFileSync(t,"utf-8").trim();if(e)return console.log(`Loaded GitHub token from ${t}`),e}catch(e){console.log(`Failed to read token file: ${e}`)}return null}function kt(t){try{let e=ze();re.default.writeFileSync(e,t,"utf-8"),console.log(`Saved GitHub token to ${e}`)}catch(e){console.log(`Failed to save token file: ${e}`)}}function Rt(t){let e=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";(0,Ue.exec)(`${e} ${t}`,()=>{})}function bt(t){return new Promise(e=>setTimeout(e,t))}async function wt(){console.log(`
53
- `+"=".repeat(60)),console.log("GitHub Device Flow Authentication"),console.log("=".repeat(60));let t=await fetch("https://github.com/login/device/code",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:be,scope:"read:user copilot"})});if(!t.ok)return console.log(`Failed to get device code: ${t.status} ${await t.text()}`),null;let e=await t.json(),{device_code:o,user_code:n,verification_uri:s,expires_in:r=900}=e,i=e.interval??5;console.log(`
54
- Please visit: ${s}`),console.log(`And enter the code: ${n}`),console.log(`
55
- Waiting for authorization (expires in ${r} seconds)...`),Rt(s),console.log("(Browser opened automatically)");let c=Date.now()+r*1e3;for(;Date.now()<c;){await bt(i*1e3);let a=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:be,device_code:o,grant_type:"urn:ietf:params:oauth:grant-type:device_code"})});if(!a.ok)continue;let u=await a.json();if(u.error==="authorization_pending"){process.stdout.write(".");continue}if(u.error==="slow_down"){i+=5;continue}if(u.error==="expired_token")return console.log(`
52
+ `;te.default.writeFileSync(e,n,"utf-8"),console.log(`Configuration file generated at: ${e}`)}var xe=class{githubToken="";copilotToken=null;models=null;accountType="individual";tokenExpiresAt=0;vscodeVersion=se;copilotVersion=ne;apiVersion=oe;systemPromptRemove=[];systemPromptAdd=[];toolResultSuffixRemove=[];redirectAnthropic=!1;maxConnectionRetries=3;get editorPluginVersion(){return`copilot-chat/${this.copilotVersion}`}get userAgent(){return`GitHubCopilotChat/${this.copilotVersion}`}},g=new xe;var re=A(require("fs")),Be=require("child_process"),ze=A(require("path"));function Ve(){let t=T();return re.default.mkdirSync(t,{recursive:!0}),ze.default.join(t,"github_token.txt")}function kt(){let t=Ve();if(!re.default.existsSync(t))return null;try{let e=re.default.readFileSync(t,"utf-8").trim();if(e)return console.log(`Loaded GitHub token from ${t}`),e}catch(e){console.log(`Failed to read token file: ${e}`)}return null}function Rt(t){try{let e=Ve();re.default.writeFileSync(e,t,"utf-8"),console.log(`Saved GitHub token to ${e}`)}catch(e){console.log(`Failed to save token file: ${e}`)}}function bt(t){let e=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";(0,Be.exec)(`${e} ${t}`,()=>{})}function wt(t){return new Promise(e=>setTimeout(e,t))}async function St(){console.log(`
53
+ `+"=".repeat(60)),console.log("GitHub Device Flow Authentication"),console.log("=".repeat(60));let t=await fetch("https://github.com/login/device/code",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:Se,scope:"read:user copilot"})});if(!t.ok)return console.log(`Failed to get device code: ${t.status} ${await t.text()}`),null;let e=await t.json(),{device_code:n,user_code:o,verification_uri:s,expires_in:r=900}=e,i=e.interval??5;console.log(`
54
+ Please visit: ${s}`),console.log(`And enter the code: ${o}`),console.log(`
55
+ Waiting for authorization (expires in ${r} seconds)...`),bt(s),console.log("(Browser opened automatically)");let c=Date.now()+r*1e3;for(;Date.now()<c;){await wt(i*1e3);let a=await fetch("https://github.com/login/oauth/access_token",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:Se,device_code:n,grant_type:"urn:ietf:params:oauth:grant-type:device_code"})});if(!a.ok)continue;let u=await a.json();if(u.error==="authorization_pending"){process.stdout.write(".");continue}if(u.error==="slow_down"){i+=5;continue}if(u.error==="expired_token")return console.log(`
56
56
  Authorization expired. Please try again.`),null;if(u.error==="access_denied")return console.log(`
57
57
  Authorization denied by user.`),null;if(u.error)return console.log(`
58
58
  Error: ${u.error_description||u.error}`),null;if(u.access_token)return console.log(`
59
59
 
60
60
  Authorization successful!`),u.access_token}return console.log(`
61
- Authorization timed out. Please try again.`),null}async function ae(){let t=(process.env.GITHUB_TOKEN||"").trim();if(t)return console.log("Using GitHub token from GITHUB_TOKEN environment variable"),t;let e=yt();if(e)return e;console.log(`
62
- No GitHub token found. Starting GitHub Device Flow authentication...`);let o=await wt();return o?(kt(o),o):null}function D(){return g.accountType==="individual"?"https://api.githubcopilot.com":`https://api.${g.accountType}.githubcopilot.com`}function vt(){return{"Content-Type":"application/json",Accept:"application/json",Authorization:`token ${g.githubToken}`,"Editor-Version":`vscode/${g.vscodeVersion}`,"Editor-Plugin-Version":g.editorPluginVersion,"User-Agent":g.userAgent,"X-GitHub-Api-Version":g.apiVersion,"X-VSCode-User-Agent-Library-Version":"electron-fetch"}}function V(t=!1){let e={Authorization:`Bearer ${g.copilotToken}`,"Content-Type":"application/json","Copilot-Integration-Id":"vscode-chat","Editor-Version":`vscode/${g.vscodeVersion}`,"Editor-Plugin-Version":g.editorPluginVersion,"User-Agent":g.userAgent,"OpenAI-Intent":"conversation-panel","X-GitHub-Api-Version":g.apiVersion,"X-Request-Id":crypto.randomUUID(),"X-VSCode-User-Agent-Library-Version":"electron-fetch"};return t&&(e["Copilot-Vision-Request"]="true"),e}async function ie(){if(g.copilotToken&&Date.now()/1e3<g.tokenExpiresAt-60)return;console.log("Refreshing Copilot token...");let t=await fetch(`${Le}/copilot_internal/v2/token`,{headers:vt()});if(!t.ok)throw new Error(`Failed to get Copilot token: ${t.status} ${await t.text()}`);let e=await t.json();g.copilotToken=e.token,g.tokenExpiresAt=Date.now()/1e3+(e.refresh_in??1800),console.log("Copilot token refreshed successfully")}async function N(){(!g.copilotToken||Date.now()/1e3>=g.tokenExpiresAt-60)&&await ie()}async function W(){await N();let t=await fetch(`${D()}/models`,{headers:V()});t.ok?(g.models=await t.json(),console.log(`Loaded ${g.models.data?.length??0} models`)):console.log(`Failed to fetch models: ${t.status}`)}function Be(t){return g.redirectAnthropic?!1:g.models?.data?.find(o=>o.id===t)?.supported_endpoints?.includes("/v1/messages")??!1}function Ve(t){return g.models?.data?.find(o=>o.id===t)?.supported_endpoints?.includes("/responses")??!1}function j(t){return Math.ceil(t.length/4)}var J=A(require("fs")),ue=A(require("path"));function K(t,e,o,n){let s=P();J.default.mkdirSync(s,{recursive:!0});let r=ue.default.join(s,"error.log"),i={timestamp:new Date().toISOString(),endpoint:t,status_code:n,request:e,response:o};J.default.appendFileSync(r,JSON.stringify(i)+`
63
- `,"utf-8")}function le(t,e,o,n,s){try{let r=P();J.default.mkdirSync(r,{recursive:!0});let i=ue.default.join(r,"connection_retry.jl"),c={timestamp:new Date().toISOString(),request_id:t,endpoint:e,attempt:o+1,max_attempts:n+1,error_type:s.constructor.name,error_message:s.message};J.default.appendFileSync(i,JSON.stringify(c)+`
64
- `,"utf-8")}catch{}}function pe(t){try{let e=P();J.default.mkdirSync(e,{recursive:!0});let o=ue.default.join(e,"tool_result_cleanup.jl");t.timestamp=new Date().toISOString(),J.default.appendFileSync(o,JSON.stringify(t)+`
65
- `,"utf-8")}catch{}}function xe(t){let e=[],o="unexpected `tool_use_id` found in `tool_result` blocks: ",n=t.indexOf(o);if(n!==-1){let s=n+o.length,r=s;for(;r<t.length&&!/[. "'\\\n]/.test(t[r]);)r++;let i=t.slice(s,r).trim();i&&e.push(i)}if(e.length===0){let s=t;for(;s.includes("toolu_");){let r=s.indexOf("toolu_"),i=r+6;for(;i<s.length&&/[\w-]/.test(s[i]);)i++;let c=s.slice(r,i);c&&!e.includes(c)&&e.push(c),s=s.slice(i)}}return e}function $e(t,e){if(!e.length)return t;let o=new Set(e),n=[];for(let s of t){if(s.role!=="user"){n.push(s);continue}let r=s.content;if(!Array.isArray(r)){n.push(s);continue}let i=r.filter(c=>c.type==="tool_result"&&o.has(c.tool_use_id)?(console.log(`[Tool Result Cleanup] Removing orphaned tool_result: ${c.tool_use_id}`),!1):!0);i.length>0&&n.push({...s,content:i})}return n}function Se(t,e){return t===400&&e.includes("tool_use_id")&&e.includes("tool_result")}function Ae(){console.log(`
61
+ Authorization timed out. Please try again.`),null}async function le(){let t=(process.env.GITHUB_TOKEN||"").trim();if(t)return console.log("Using GitHub token from GITHUB_TOKEN environment variable"),t;let e=kt();if(e)return e;console.log(`
62
+ No GitHub token found. Starting GitHub Device Flow authentication...`);let n=await St();return n?(Rt(n),n):null}function D(){return g.accountType==="individual"?"https://api.githubcopilot.com":`https://api.${g.accountType}.githubcopilot.com`}function vt(){return{"Content-Type":"application/json",Accept:"application/json",Authorization:`token ${g.githubToken}`,"Editor-Version":`vscode/${g.vscodeVersion}`,"Editor-Plugin-Version":g.editorPluginVersion,"User-Agent":g.userAgent,"X-GitHub-Api-Version":g.apiVersion,"X-VSCode-User-Agent-Library-Version":"electron-fetch"}}function V(t=!1){let e={Authorization:`Bearer ${g.copilotToken}`,"Content-Type":"application/json","Copilot-Integration-Id":"vscode-chat","Editor-Version":`vscode/${g.vscodeVersion}`,"Editor-Plugin-Version":g.editorPluginVersion,"User-Agent":g.userAgent,"OpenAI-Intent":"conversation-panel","X-GitHub-Api-Version":g.apiVersion,"X-Request-Id":crypto.randomUUID(),"X-VSCode-User-Agent-Library-Version":"electron-fetch"};return t&&(e["Copilot-Vision-Request"]="true"),e}async function ie(){if(g.copilotToken&&Date.now()/1e3<g.tokenExpiresAt-60)return;console.log("Refreshing Copilot token...");let t=await fetch(`${Ue}/copilot_internal/v2/token`,{headers:vt()});if(!t.ok)throw new Error(`Failed to get Copilot token: ${t.status} ${await t.text()}`);let e=await t.json();g.copilotToken=e.token,g.tokenExpiresAt=Date.now()/1e3+(e.refresh_in??1800),console.log("Copilot token refreshed successfully")}async function N(){(!g.copilotToken||Date.now()/1e3>=g.tokenExpiresAt-60)&&await ie()}async function W(){await N();let t=await fetch(`${D()}/models`,{headers:V()});t.ok?(g.models=await t.json(),console.log(`Loaded ${g.models.data?.length??0} models`)):console.log(`Failed to fetch models: ${t.status}`)}function Je(t){return g.redirectAnthropic?!1:g.models?.data?.find(n=>n.id===t)?.supported_endpoints?.includes("/v1/messages")??!1}function Ge(t){return g.models?.data?.find(n=>n.id===t)?.supported_endpoints?.includes("/responses")??!1}function j(t){return Math.ceil(t.length/4)}var J=A(require("fs")),pe=A(require("path"));function K(t,e,n,o){let s=T();J.default.mkdirSync(s,{recursive:!0});let r=pe.default.join(s,"error.log"),i={timestamp:new Date().toISOString(),endpoint:t,status_code:o,request:e,response:n};J.default.appendFileSync(r,JSON.stringify(i)+`
63
+ `,"utf-8")}function de(t,e,n,o,s){try{let r=T();J.default.mkdirSync(r,{recursive:!0});let i=pe.default.join(r,"connection_retry.jl"),c={timestamp:new Date().toISOString(),request_id:t,endpoint:e,attempt:n+1,max_attempts:o+1,error_type:s.constructor.name,error_message:s.message};J.default.appendFileSync(i,JSON.stringify(c)+`
64
+ `,"utf-8")}catch{}}function ge(t){try{let e=T();J.default.mkdirSync(e,{recursive:!0});let n=pe.default.join(e,"tool_result_cleanup.jl");t.timestamp=new Date().toISOString(),J.default.appendFileSync(n,JSON.stringify(t)+`
65
+ `,"utf-8")}catch{}}function $e(t){let e=[],n="unexpected `tool_use_id` found in `tool_result` blocks: ",o=t.indexOf(n);if(o!==-1){let s=o+n.length,r=s;for(;r<t.length&&!/[. "'\\\n]/.test(t[r]);)r++;let i=t.slice(s,r).trim();i&&e.push(i)}if(e.length===0){let s=t;for(;s.includes("toolu_");){let r=s.indexOf("toolu_"),i=r+6;for(;i<s.length&&/[\w-]/.test(s[i]);)i++;let c=s.slice(r,i);c&&!e.includes(c)&&e.push(c),s=s.slice(i)}}return e}function Ae(t,e){if(!e.length)return t;let n=new Set(e),o=[];for(let s of t){if(s.role!=="user"){o.push(s);continue}let r=s.content;if(!Array.isArray(r)){o.push(s);continue}let i=r.filter(c=>c.type==="tool_result"&&n.has(c.tool_use_id)?(console.log(`[Tool Result Cleanup] Removing orphaned tool_result: ${c.tool_use_id}`),!1):!0);i.length>0&&o.push({...s,content:i})}return o}function Ce(t,e){return t===400&&e.includes("tool_use_id")&&e.includes("tool_result")}function Oe(){console.log(`
66
66
  `+"=".repeat(60)),console.log("Model Name Mappings"),console.log("=".repeat(60));let t=Object.entries(M.exactMappings);if(t.length){console.log(`
67
- Exact Mappings:`);for(let[o,n]of t)console.log(` ${o} -> ${n}`)}else console.log(`
67
+ Exact Mappings:`);for(let[n,o]of t)console.log(` ${n} -> ${o}`)}else console.log(`
68
68
  Exact Mappings: (none)`);let e=Object.entries(M.prefixMappings);if(e.length){console.log(`
69
- Prefix Mappings:`);for(let[o,n]of e)console.log(` ${o}* -> ${n}`)}else console.log(`
69
+ Prefix Mappings:`);for(let[n,o]of e)console.log(` ${n}* -> ${o}`)}else console.log(`
70
70
  Prefix Mappings: (none)`);console.log("=".repeat(60)+`
71
- `)}function Ce(){if(!g.models?.data?.length){console.log("No models available yet.");return}console.log(`
72
- `+"=".repeat(60)),console.log("Available Models"),console.log("=".repeat(60));for(let t of g.models.data){let e=t.capabilities,o=c=>c&&c>=1e3?`${Math.floor(c/1e3)}K`:String(c??"N/A"),n=o(e?.limits?.max_context_window_tokens),s=o(e?.limits?.max_prompt_tokens),r=o(e?.limits?.max_output_tokens),i=[];e?.supports?.vision&&i.push("Vision"),e?.supports?.tool_calls&&i.push("Tool"),t.supported_endpoints?.includes("/v1/messages")&&i.push("Anthropic"),t.preview&&i.push("Preview"),console.log(`${t.id.padEnd(30)} ctx: ${n} in: ${s} out: ${r} [${t.vendor??"unknown"}] (${i.join(",")})`)}console.log(`
71
+ `)}function Te(){if(!g.models?.data?.length){console.log("No models available yet.");return}console.log(`
72
+ `+"=".repeat(60)),console.log("Available Models"),console.log("=".repeat(60));for(let t of g.models.data){let e=t.capabilities,n=c=>c&&c>=1e3?`${Math.floor(c/1e3)}K`:String(c??"N/A"),o=n(e?.limits?.max_context_window_tokens),s=n(e?.limits?.max_prompt_tokens),r=n(e?.limits?.max_output_tokens),i=[];e?.supports?.vision&&i.push("Vision"),e?.supports?.tool_calls&&i.push("Tool"),t.supported_endpoints?.includes("/v1/messages")&&i.push("Anthropic"),t.preview&&i.push("Preview"),console.log(`${t.id.padEnd(30)} ctx: ${o} in: ${s} out: ${r} [${t.vendor??"unknown"}] (${i.join(",")})`)}console.log(`
73
73
  `+"=".repeat(60)+`
74
- `)}var We=require("express");var Oe=class{cache=new Map;maxEntries;requestCount=0;bytesSent=0;bytesReceived=0;modelStats={};endpointStats={};constructor(e=1e3){this.maxEntries=e}startRequest(e,o){this.evictIfFull(),this.cache.set(e,{id:e,timestamp:new Date().toISOString(),original_request_body:o.original_request_body??null,request_body:o.request_body??null,response_body:null,model:o.model??"unknown",translated_model:o.translated_model??null,endpoint:o.endpoint??"unknown",status_code:null,request_size:o.request_size??0,response_size:0,input_tokens:0,output_tokens:0,duration:0,state:"pending"})}updateRequestState(e,o,n){let s=this.cache.get(e);s&&(s.state=o,n&&Object.assign(s,n))}completeRequest(e,o){let n=this.cache.get(e);n?Object.assign(n,{response_body:o.response_body,status_code:o.status_code??200,response_size:o.response_size??0,input_tokens:o.input_tokens??0,output_tokens:o.output_tokens??0,duration:o.duration??0,state:(o.status_code??200)<400?"completed":"error"}):(this.evictIfFull(),n={id:e,timestamp:new Date().toISOString(),original_request_body:o.original_request_body??null,request_body:o.request_body??null,response_body:o.response_body??null,model:o.model??"unknown",translated_model:o.translated_model??null,endpoint:o.endpoint??"unknown",status_code:o.status_code??200,request_size:o.request_size??0,response_size:o.response_size??0,input_tokens:o.input_tokens??0,output_tokens:o.output_tokens??0,duration:o.duration??0,state:(o.status_code??200)<400?"completed":"error"},this.cache.set(e,n)),this.requestCount++,this.bytesSent+=o.request_size??0,this.bytesReceived+=o.response_size??0,this.updateModelStats(o),this.updateEndpointStats(o)}addRequest(e,o){this.cache.has(e)?this.completeRequest(e,o):(this.startRequest(e,o),this.completeRequest(e,o))}getRequest(e){return this.cache.get(e)}getRecentRequests(e=50,o=0){return[...this.cache.values()].reverse().slice(o,o+e)}getTotalCount(){return this.cache.size}getStats(){return{total_requests:this.requestCount,cached_requests:this.cache.size,bytes_sent:this.bytesSent,bytes_received:this.bytesReceived,model_stats:{...this.modelStats},endpoint_stats:{...this.endpointStats}}}searchRequests(e,o=50,n=0){let s=e.toLowerCase(),r=[];for(let i of[...this.cache.values()].reverse())(i.model.toLowerCase().includes(s)||i.endpoint.toLowerCase().includes(s)||JSON.stringify(i.request_body).toLowerCase().includes(s))&&r.push(i);return r.slice(n,n+o)}fulltextSearch(e,o=50,n=0){let s=e.toLowerCase(),r=[];for(let i of[...this.cache.values()].reverse()){let c=JSON.stringify(i.request_body).toLowerCase(),a=JSON.stringify(i.response_body).toLowerCase();(c.includes(s)||a.includes(s))&&r.push(i)}return[r.slice(n,n+o),r.length]}getAllRequests(){return[...this.cache.values()]}importRequest(e){let o=e.id||crypto.randomUUID();this.evictIfFull();let n={id:o,timestamp:e.timestamp||new Date().toISOString(),original_request_body:e.original_request_body??null,request_body:e.request_body??null,response_body:e.response_body??null,model:e.model||"unknown",translated_model:e.translated_model||null,endpoint:e.endpoint||"unknown",status_code:e.status_code??200,request_size:e.request_size??0,response_size:e.response_size??0,input_tokens:e.input_tokens??0,output_tokens:e.output_tokens??0,duration:e.duration??0,state:e.state||"completed"};this.cache.set(o,n),this.requestCount++,this.bytesSent+=n.request_size,this.bytesReceived+=n.response_size,this.updateModelStats(n),this.updateEndpointStats(n)}evictIfFull(){if(this.cache.size>=this.maxEntries){let e=this.cache.keys().next().value;this.cache.delete(e)}}updateModelStats(e){let o=e.model??"unknown";this.modelStats[o]||(this.modelStats[o]={request_count:0,input_tokens:0,output_tokens:0,bytes_sent:0,bytes_received:0});let n=this.modelStats[o];n.request_count++,n.input_tokens+=e.input_tokens??0,n.output_tokens+=e.output_tokens??0,n.bytes_sent+=e.request_size??0,n.bytes_received+=e.response_size??0}updateEndpointStats(e){let o=e.endpoint??"unknown";this.endpointStats[o]||(this.endpointStats[o]={request_count:0,bytes_sent:0,bytes_received:0});let n=this.endpointStats[o];n.request_count++,n.bytes_sent+=e.request_size??0,n.bytes_received+=e.response_size??0}},y=new Oe;function X(t){return M.translate(t)}function de(t){for(let e of g.systemPromptRemove)t.includes(e)&&(t=t.replaceAll(e,""),console.log(`[Content Filter] Removed from system prompt: ${e.slice(0,50)}${e.length>50?"...":""}`));return t}function Te(t){for(let e of g.toolResultSuffixRemove)t.endsWith(e)&&(t=t.slice(0,-e.length),console.log(`[Content Filter] Removed suffix from tool result: ${e.slice(0,50)}${e.length>50?"...":""}`));return t}function Je(t){let e=[],o=t.system;if(o){if(typeof o=="string")e.push({role:"system",content:de(o)});else if(Array.isArray(o)){let r=o.filter(i=>i.type==="text"&&!(i.text||"").includes("x-anthropic-billing-header")).map(i=>i.text);r.length&&e.push({role:"system",content:de(r.join(`
74
+ `)}var Xe=require("express");var Ee=class{cache=new Map;maxEntries;requestCount=0;bytesSent=0;bytesReceived=0;modelStats={};endpointStats={};constructor(e=1e3){this.maxEntries=e}startRequest(e,n){this.evictIfFull(),this.cache.set(e,{id:e,timestamp:new Date().toISOString(),original_request_body:n.original_request_body??null,request_body:n.request_body??null,response_body:null,model:n.model??"unknown",translated_model:n.translated_model??null,endpoint:n.endpoint??"unknown",status_code:null,request_size:n.request_size??0,response_size:0,input_tokens:0,output_tokens:0,duration:0,state:"pending"})}updateRequestState(e,n,o){let s=this.cache.get(e);s&&(s.state=n,o&&Object.assign(s,o))}completeRequest(e,n){let o=this.cache.get(e);o?Object.assign(o,{response_body:n.response_body,status_code:n.status_code??200,response_size:n.response_size??0,input_tokens:n.input_tokens??0,output_tokens:n.output_tokens??0,duration:n.duration??0,state:(n.status_code??200)<400?"completed":"error"}):(this.evictIfFull(),o={id:e,timestamp:new Date().toISOString(),original_request_body:n.original_request_body??null,request_body:n.request_body??null,response_body:n.response_body??null,model:n.model??"unknown",translated_model:n.translated_model??null,endpoint:n.endpoint??"unknown",status_code:n.status_code??200,request_size:n.request_size??0,response_size:n.response_size??0,input_tokens:n.input_tokens??0,output_tokens:n.output_tokens??0,duration:n.duration??0,state:(n.status_code??200)<400?"completed":"error"},this.cache.set(e,o)),this.requestCount++,this.bytesSent+=n.request_size??0,this.bytesReceived+=n.response_size??0,this.updateModelStats(n),this.updateEndpointStats(n)}addRequest(e,n){this.cache.has(e)?this.completeRequest(e,n):(this.startRequest(e,n),this.completeRequest(e,n))}getRequest(e){return this.cache.get(e)}getRecentRequests(e=50,n=0){return[...this.cache.values()].reverse().slice(n,n+e)}getTotalCount(){return this.cache.size}getStats(){return{total_requests:this.requestCount,cached_requests:this.cache.size,bytes_sent:this.bytesSent,bytes_received:this.bytesReceived,model_stats:{...this.modelStats},endpoint_stats:{...this.endpointStats}}}searchRequests(e,n=50,o=0){let s=e.toLowerCase(),r=[];for(let i of[...this.cache.values()].reverse())(i.model.toLowerCase().includes(s)||i.endpoint.toLowerCase().includes(s)||JSON.stringify(i.request_body).toLowerCase().includes(s))&&r.push(i);return r.slice(o,o+n)}fulltextSearch(e,n=50,o=0){let s=e.toLowerCase(),r=[];for(let i of[...this.cache.values()].reverse()){let c=JSON.stringify(i.request_body).toLowerCase(),a=JSON.stringify(i.response_body).toLowerCase();(c.includes(s)||a.includes(s))&&r.push(i)}return[r.slice(o,o+n),r.length]}getAllRequests(){return[...this.cache.values()]}importRequest(e){let n=e.id||crypto.randomUUID();this.evictIfFull();let o={id:n,timestamp:e.timestamp||new Date().toISOString(),original_request_body:e.original_request_body??null,request_body:e.request_body??null,response_body:e.response_body??null,model:e.model||"unknown",translated_model:e.translated_model||null,endpoint:e.endpoint||"unknown",status_code:e.status_code??200,request_size:e.request_size??0,response_size:e.response_size??0,input_tokens:e.input_tokens??0,output_tokens:e.output_tokens??0,duration:e.duration??0,state:e.state||"completed"};this.cache.set(n,o),this.requestCount++,this.bytesSent+=o.request_size,this.bytesReceived+=o.response_size,this.updateModelStats(o),this.updateEndpointStats(o)}evictIfFull(){if(this.cache.size>=this.maxEntries){let e=this.cache.keys().next().value;this.cache.delete(e)}}updateModelStats(e){let n=e.model??"unknown";this.modelStats[n]||(this.modelStats[n]={request_count:0,input_tokens:0,output_tokens:0,bytes_sent:0,bytes_received:0});let o=this.modelStats[n];o.request_count++,o.input_tokens+=e.input_tokens??0,o.output_tokens+=e.output_tokens??0,o.bytes_sent+=e.request_size??0,o.bytes_received+=e.response_size??0}updateEndpointStats(e){let n=e.endpoint??"unknown";this.endpointStats[n]||(this.endpointStats[n]={request_count:0,bytes_sent:0,bytes_received:0});let o=this.endpointStats[n];o.request_count++,o.bytes_sent+=e.request_size??0,o.bytes_received+=e.response_size??0}},y=new Ee;function X(t){return M.translate(t)}function me(t){for(let e of g.systemPromptRemove)t.includes(e)&&(t=t.replaceAll(e,""),console.log(`[Content Filter] Removed from system prompt: ${e.slice(0,50)}${e.length>50?"...":""}`));return t}function Pe(t){for(let e of g.toolResultSuffixRemove)t.endsWith(e)&&(t=t.slice(0,-e.length),console.log(`[Content Filter] Removed suffix from tool result: ${e.slice(0,50)}${e.length>50?"...":""}`));return t}function We(t){let e=[],n=t.system;if(n){if(typeof n=="string")e.push({role:"system",content:me(n)});else if(Array.isArray(n)){let r=n.filter(i=>i.type==="text"&&!(i.text||"").includes("x-anthropic-billing-header")).map(i=>i.text);r.length&&e.push({role:"system",content:me(r.join(`
75
75
 
76
- `))})}}for(let r of t.messages||[]){let i=r.role,c=r.content;if(i==="user")if(Array.isArray(c)){let a=c.filter(p=>p.type==="tool_result"),u=c.filter(p=>p.type!=="tool_result");for(let p of a){let l=p.content??"";typeof l=="string"&&(l=Te(l)),e.push({role:"tool",tool_call_id:p.tool_use_id,content:l})}if(u.length){let p=xt(u);p!=null&&e.push({role:"user",content:p})}}else e.push({role:"user",content:c});else if(i==="assistant")if(Array.isArray(c)){let a=c.filter(l=>l.type==="tool_use"),p=c.filter(l=>l.type==="text"||l.type==="thinking").map(l=>(l.type==="text"?l.text:l.thinking)??"").join(`
76
+ `))})}}for(let r of t.messages||[]){let i=r.role,c=r.content;if(i==="user")if(Array.isArray(c)){let a=c.filter(p=>p.type==="tool_result"),u=c.filter(p=>p.type!=="tool_result");for(let p of a){let l=p.content??"";typeof l=="string"&&(l=Pe(l)),e.push({role:"tool",tool_call_id:p.tool_use_id,content:l})}if(u.length){let p=xt(u);p!=null&&e.push({role:"user",content:p})}}else e.push({role:"user",content:c});else if(i==="assistant")if(Array.isArray(c)){let a=c.filter(l=>l.type==="tool_use"),p=c.filter(l=>l.type==="text"||l.type==="thinking").map(l=>(l.type==="text"?l.text:l.thinking)??"").join(`
77
77
 
78
- `);a.length?e.push({role:"assistant",content:p||null,tool_calls:a.map(l=>({id:l.id,type:"function",function:{name:l.name,arguments:JSON.stringify(l.input??{})}}))}):e.push({role:"assistant",content:p})}else e.push({role:"assistant",content:c})}let n={model:X(t.model??""),messages:e,max_tokens:t.max_tokens,stream:t.stream??!1};t.temperature!=null&&(n.temperature=t.temperature),t.top_p!=null&&(n.top_p=t.top_p),t.stop_sequences&&(n.stop=t.stop_sequences),Array.isArray(t.tools)&&(n.tools=t.tools.map(r=>({type:"function",function:{name:r.name,description:r.description,parameters:r.input_schema??{}}})));let s=t.tool_choice;if(s){let r=s.type;r==="auto"?n.tool_choice="auto":r==="any"?n.tool_choice="required":r==="none"?n.tool_choice="none":r==="tool"&&s.name&&(n.tool_choice={type:"function",function:{name:s.name}})}return n}function xt(t){if(!t.some(n=>n.type==="image")){let n=[];for(let s of t)s.type==="text"?n.push(s.text??""):s.type==="thinking"&&n.push(s.thinking??"");return n.length?n.join(`
78
+ `);a.length?e.push({role:"assistant",content:p||null,tool_calls:a.map(l=>({id:l.id,type:"function",function:{name:l.name,arguments:JSON.stringify(l.input??{})}}))}):e.push({role:"assistant",content:p})}else e.push({role:"assistant",content:c})}let o={model:X(t.model??""),messages:e,max_tokens:t.max_tokens,stream:t.stream??!1};t.temperature!=null&&(o.temperature=t.temperature),t.top_p!=null&&(o.top_p=t.top_p),t.stop_sequences&&(o.stop=t.stop_sequences),Array.isArray(t.tools)&&(o.tools=t.tools.map(r=>({type:"function",function:{name:r.name,description:r.description,parameters:r.input_schema??{}}})));let s=t.tool_choice;if(s){let r=s.type;r==="auto"?o.tool_choice="auto":r==="any"?o.tool_choice="required":r==="none"?o.tool_choice="none":r==="tool"&&s.name&&(o.tool_choice={type:"function",function:{name:s.name}})}return o}function xt(t){if(!t.some(o=>o.type==="image")){let o=[];for(let s of t)s.type==="text"?o.push(s.text??""):s.type==="thinking"&&o.push(s.thinking??"");return o.length?o.join(`
79
79
 
80
- `):null}let o=[];for(let n of t)if(n.type==="text")o.push({type:"text",text:n.text});else if(n.type==="thinking")o.push({type:"text",text:n.thinking});else if(n.type==="image"){let s=n.source;o.push({type:"image_url",image_url:{url:`data:${s?.media_type};base64,${s?.data}`}})}return o.length?o:null}var $t={stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"refusal"};function Pe(t){return t?$t[t]??null:null}function Ee(t){let e=[],o=null;for(let i of t.choices||[]){let c=i.message;if(c){if(c.content&&e.push({type:"text",text:c.content}),Array.isArray(c.tool_calls))for(let a of c.tool_calls){let u=a.function,p;try{p=JSON.parse(u.arguments||"{}")}catch{p={_raw_arguments:u.arguments}}e.push({type:"tool_use",id:a.id,name:u.name,input:p})}i.finish_reason&&(o=i.finish_reason)}}let n=t.usage??{},s=n.prompt_tokens_details?.cached_tokens??0,r=(n.prompt_tokens??0)-s;return{id:t.id??crypto.randomUUID(),type:"message",role:"assistant",content:e,model:t.model??"",stop_reason:Pe(o),stop_sequence:null,usage:{input_tokens:r,output_tokens:n.completion_tokens??0,...s?{cache_read_input_tokens:s}:{}}}}var ge=class{messageStartSent=!1;contentBlockIndex=0;contentBlockOpen=!1;toolCalls={}};function Ge(t,e){let o=[];if(!t.choices?.length)return o;let n=t.choices[0],s=n.delta??{};if(!e.messageStartSent){let r=t.usage??{},i=r.prompt_tokens_details?.cached_tokens??0;o.push({type:"message_start",message:{id:t.id??crypto.randomUUID(),type:"message",role:"assistant",content:[],model:t.model??"",stop_reason:null,stop_sequence:null,usage:{input_tokens:(r.prompt_tokens??0)-i,output_tokens:0,...i?{cache_read_input_tokens:i}:{}}}}),e.messageStartSent=!0}if(s.content&&(e.contentBlockOpen&&Object.values(e.toolCalls).some(r=>r.anthropicBlockIndex===e.contentBlockIndex)&&(o.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockIndex++,e.contentBlockOpen=!1),e.contentBlockOpen||(o.push({type:"content_block_start",index:e.contentBlockIndex,content_block:{type:"text",text:""}}),e.contentBlockOpen=!0),o.push({type:"content_block_delta",index:e.contentBlockIndex,delta:{type:"text_delta",text:s.content}})),s.tool_calls)for(let r of s.tool_calls){let i=r.index??0;if(r.id&&r.function?.name){e.contentBlockOpen&&(o.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockIndex++,e.contentBlockOpen=!1);let c=e.contentBlockIndex;e.toolCalls[i]={id:r.id,name:r.function.name,anthropicBlockIndex:c},o.push({type:"content_block_start",index:c,content_block:{type:"tool_use",id:r.id,name:r.function.name,input:{}}}),e.contentBlockOpen=!0}if(r.function?.arguments){let c=e.toolCalls[i];c&&o.push({type:"content_block_delta",index:c.anthropicBlockIndex,delta:{type:"input_json_delta",partial_json:r.function.arguments}})}}if(n.finish_reason){e.contentBlockOpen&&(o.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockOpen=!1);let r=t.usage??{},i=r.prompt_tokens_details?.cached_tokens??0;o.push({type:"message_delta",delta:{stop_reason:Pe(n.finish_reason),stop_sequence:null},usage:{input_tokens:(r.prompt_tokens??0)-i,output_tokens:r.completion_tokens??0,...i?{cache_read_input_tokens:i}:{}}}),o.push({type:"message_stop"})}return o}function me(t){if(!t.length)return{};let e=t[0],o=[],n={},s=null,r={};for(let a of t){a.usage&&(r=a.usage);for(let u of a.choices??[]){let p=u.delta;if(p?.content&&o.push(p.content),p?.tool_calls)for(let l of p.tool_calls){let f=l.index??0;n[f]||(n[f]={id:"",type:"function",function:{name:"",arguments:""}}),l.id&&(n[f].id=l.id),l.function?.name&&(n[f].function.name=l.function.name),l.function?.arguments&&(n[f].function.arguments+=l.function.arguments)}u.finish_reason&&(s=u.finish_reason)}}let i={role:"assistant",content:o.length?o.join(""):null},c=Object.keys(n).map(Number).sort((a,u)=>a-u);return c.length&&(i.tool_calls=c.map(a=>n[a])),{id:e.id??"",object:"chat.completion",created:e.created??0,model:e.model??"",choices:[{index:0,message:i,finish_reason:s}],usage:r}}var Y=(0,We.Router)();Y.get(["/v1/models","/models"],async(t,e)=>{try{await N(),g.models||await W();let o=(g.models?.data??[]).map(n=>({id:n.id,object:"model",type:"model",created:0,created_at:new Date(0).toISOString(),owned_by:n.vendor??"unknown",display_name:n.name??n.id}));e.json({object:"list",data:o,has_more:!1})}catch(o){e.status(500).json({error:String(o)})}});Y.get(["/v1/models/full/","/models/full/"],(t,e)=>{e.json(g.models)});Y.post(["/v1/chat/completions","/chat/completions"],async(t,e)=>{try{let o=Date.now();await N();let n=t.body,s=crypto.randomUUID(),r=n.model??"unknown",i=X(r);i!==r&&(n={...n,model:i});let c=(n.messages??[]).some(d=>Array.isArray(d.content)&&d.content.some(w=>w.type==="image_url")),a=(n.messages??[]).some(d=>d.role==="assistant"||d.role==="tool"),u=V(c);u["X-Initiator"]=a?"agent":"user";let p=JSON.stringify(n).length;if(n.stream)return St(e,n,u,s,p,o,r,i);let l=await Ke(`${D()}/chat/completions`,{method:"POST",headers:u,body:JSON.stringify(n)},s,"/v1/chat/completions"),f=Math.round((Date.now()-o)/1e3*100)/100;if(!l)return e.status(504).json({error:`Upstream connection error after ${g.maxConnectionRetries+1} attempts`});let _=await l.text(),k=_.length;if(l.ok){let d=JSON.parse(_),w=d.usage??{};y.addRequest(s,{request_body:n,response_body:d,model:r,translated_model:i!==r?i:null,endpoint:"/v1/chat/completions",status_code:l.status,request_size:p,response_size:k,input_tokens:w.prompt_tokens??0,output_tokens:w.completion_tokens??0,duration:f}),e.json(d)}else K("/v1/chat/completions",n,_,l.status),e.status(l.status).type("json").send(_)}catch(o){e.status(500).json({error:String(o)})}});async function St(t,e,o,n,s,r,i,c){y.startRequest(n,{request_body:e,model:i,translated_model:c!==i?c:null,endpoint:"/v1/chat/completions",request_size:s}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let a=[],u=0,p=0,l=200,f=!1;t.on("close",()=>{f=!0});try{y.updateRequestState(n,"sending");let d=await fetch(`${D()}/chat/completions`,{method:"POST",headers:o,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});l=d.status;let w=d.body.getReader(),b=new TextDecoder,h="";for(y.updateRequestState(n,"receiving");;){let{done:R,value:v}=await w.read();if(R)break;if(f){w.cancel();break}h+=b.decode(v,{stream:!0});let $=h.split(`
81
- `);h=$.pop();for(let S of $)if(S.trim()&&S.startsWith("data: ")){let C=S.slice(6);if(C==="[DONE]"){f||t.write(`data: [DONE]
80
+ `):null}let n=[];for(let o of t)if(o.type==="text")n.push({type:"text",text:o.text});else if(o.type==="thinking")n.push({type:"text",text:o.thinking});else if(o.type==="image"){let s=o.source;n.push({type:"image_url",image_url:{url:`data:${s?.media_type};base64,${s?.data}`}})}return n.length?n:null}var $t={stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"refusal"};function qe(t){return t?$t[t]??null:null}function De(t){let e=[],n=null;for(let i of t.choices||[]){let c=i.message;if(c){if(c.content&&e.push({type:"text",text:c.content}),Array.isArray(c.tool_calls))for(let a of c.tool_calls){let u=a.function,p;try{p=JSON.parse(u.arguments||"{}")}catch{p={_raw_arguments:u.arguments}}e.push({type:"tool_use",id:a.id,name:u.name,input:p})}i.finish_reason&&(n=i.finish_reason)}}let o=t.usage??{},s=o.prompt_tokens_details?.cached_tokens??0,r=(o.prompt_tokens??0)-s;return{id:t.id??crypto.randomUUID(),type:"message",role:"assistant",content:e,model:t.model??"",stop_reason:qe(n),stop_sequence:null,usage:{input_tokens:r,output_tokens:o.completion_tokens??0,...s?{cache_read_input_tokens:s}:{}}}}var fe=class{messageStartSent=!1;contentBlockIndex=0;contentBlockOpen=!1;toolCalls={}};function Ke(t,e){let n=[];if(!t.choices?.length)return n;let o=t.choices[0],s=o.delta??{};if(!e.messageStartSent){let r=t.usage??{},i=r.prompt_tokens_details?.cached_tokens??0;n.push({type:"message_start",message:{id:t.id??crypto.randomUUID(),type:"message",role:"assistant",content:[],model:t.model??"",stop_reason:null,stop_sequence:null,usage:{input_tokens:(r.prompt_tokens??0)-i,output_tokens:0,...i?{cache_read_input_tokens:i}:{}}}}),e.messageStartSent=!0}if(s.content&&(e.contentBlockOpen&&Object.values(e.toolCalls).some(r=>r.anthropicBlockIndex===e.contentBlockIndex)&&(n.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockIndex++,e.contentBlockOpen=!1),e.contentBlockOpen||(n.push({type:"content_block_start",index:e.contentBlockIndex,content_block:{type:"text",text:""}}),e.contentBlockOpen=!0),n.push({type:"content_block_delta",index:e.contentBlockIndex,delta:{type:"text_delta",text:s.content}})),s.tool_calls)for(let r of s.tool_calls){let i=r.index??0;if(r.id&&r.function?.name){e.contentBlockOpen&&(n.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockIndex++,e.contentBlockOpen=!1);let c=e.contentBlockIndex;e.toolCalls[i]={id:r.id,name:r.function.name,anthropicBlockIndex:c},n.push({type:"content_block_start",index:c,content_block:{type:"tool_use",id:r.id,name:r.function.name,input:{}}}),e.contentBlockOpen=!0}if(r.function?.arguments){let c=e.toolCalls[i];c&&n.push({type:"content_block_delta",index:c.anthropicBlockIndex,delta:{type:"input_json_delta",partial_json:r.function.arguments}})}}if(o.finish_reason){e.contentBlockOpen&&(n.push({type:"content_block_stop",index:e.contentBlockIndex}),e.contentBlockOpen=!1);let r=t.usage??{},i=r.prompt_tokens_details?.cached_tokens??0;n.push({type:"message_delta",delta:{stop_reason:qe(o.finish_reason),stop_sequence:null},usage:{input_tokens:(r.prompt_tokens??0)-i,output_tokens:r.completion_tokens??0,...i?{cache_read_input_tokens:i}:{}}}),n.push({type:"message_stop"})}return n}function _e(t){if(!t.length)return{};let e=t[0],n=[],o={},s=null,r={};for(let a of t){a.usage&&(r=a.usage);for(let u of a.choices??[]){let p=u.delta;if(p?.content&&n.push(p.content),p?.tool_calls)for(let l of p.tool_calls){let f=l.index??0;o[f]||(o[f]={id:"",type:"function",function:{name:"",arguments:""}}),l.id&&(o[f].id=l.id),l.function?.name&&(o[f].function.name=l.function.name),l.function?.arguments&&(o[f].function.arguments+=l.function.arguments)}u.finish_reason&&(s=u.finish_reason)}}let i={role:"assistant",content:n.length?n.join(""):null},c=Object.keys(o).map(Number).sort((a,u)=>a-u);return c.length&&(i.tool_calls=c.map(a=>o[a])),{id:e.id??"",object:"chat.completion",created:e.created??0,model:e.model??"",choices:[{index:0,message:i,finish_reason:s}],usage:r}}var Y=(0,Xe.Router)();Y.get(["/v1/models","/models"],async(t,e)=>{try{await N(),g.models||await W();let n=(g.models?.data??[]).map(o=>({id:o.id,object:"model",type:"model",created:0,created_at:new Date(0).toISOString(),owned_by:o.vendor??"unknown",display_name:o.name??o.id}));e.json({object:"list",data:n,has_more:!1})}catch(n){e.status(500).json({error:String(n)})}});Y.get(["/v1/models/full/","/models/full/"],(t,e)=>{e.json(g.models)});Y.post(["/v1/chat/completions","/chat/completions"],async(t,e)=>{try{let n=Date.now();await N();let o=t.body,s=crypto.randomUUID(),r=o.model??"unknown",i=X(r);i!==r&&(o={...o,model:i});let c=(o.messages??[]).some(d=>Array.isArray(d.content)&&d.content.some(w=>w.type==="image_url")),a=(o.messages??[]).some(d=>d.role==="assistant"||d.role==="tool"),u=V(c);u["X-Initiator"]=a?"agent":"user";let p=JSON.stringify(o).length;if(o.stream)return At(e,o,u,s,p,n,r,i);let l=await Ye(`${D()}/chat/completions`,{method:"POST",headers:u,body:JSON.stringify(o)},s,"/v1/chat/completions"),f=Math.round((Date.now()-n)/1e3*100)/100;if(!l)return e.status(504).json({error:`Upstream connection error after ${g.maxConnectionRetries+1} attempts`});let _=await l.text(),k=_.length;if(l.ok){let d=JSON.parse(_),w=d.usage??{};y.addRequest(s,{request_body:o,response_body:d,model:r,translated_model:i!==r?i:null,endpoint:"/v1/chat/completions",status_code:l.status,request_size:p,response_size:k,input_tokens:w.prompt_tokens??0,output_tokens:w.completion_tokens??0,duration:f}),e.json(d)}else K("/v1/chat/completions",o,_,l.status),e.status(l.status).type("json").send(_)}catch(n){e.status(500).json({error:String(n)})}});async function At(t,e,n,o,s,r,i,c){y.startRequest(o,{request_body:e,model:i,translated_model:c!==i?c:null,endpoint:"/v1/chat/completions",request_size:s}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let a=[],u=0,p=0,l=200,f=!1;t.on("close",()=>{f=!0});try{y.updateRequestState(o,"sending");let d=await fetch(`${D()}/chat/completions`,{method:"POST",headers:n,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});l=d.status;let w=d.body.getReader(),b=new TextDecoder,h="";for(y.updateRequestState(o,"receiving");;){let{done:R,value:S}=await w.read();if(R)break;if(f){w.cancel();break}h+=b.decode(S,{stream:!0});let x=h.split(`
81
+ `);h=x.pop();for(let $ of x)if($.trim()&&$.startsWith("data: ")){let C=$.slice(6);if(C==="[DONE]"){f||t.write(`data: [DONE]
82
82
 
83
83
  `);continue}try{let O=JSON.parse(C);a.push(O),O.usage&&(u=O.usage.prompt_tokens??0,p=O.usage.completion_tokens??0),f||t.write(`data: ${C}
84
84
 
85
- `)}catch{}}}}catch(d){l=504,console.log(`[Stream] Error for ${n}: ${d}`)}f?y.updateRequestState(n,"error",{status_code:499}):t.end();let _=Math.round((Date.now()-r)/1e3*100)/100,k=me(a);y.completeRequest(n,{request_body:e,response_body:k,model:i,translated_model:c!==i?c:null,endpoint:"/v1/chat/completions",status_code:f?499:l,request_size:s,response_size:a.reduce((d,w)=>d+JSON.stringify(w).length,0),input_tokens:u,output_tokens:p,duration:_})}Y.post(["/v1/responses","/responses"],async(t,e)=>{try{let o=Date.now();await N();let n=t.body,s=crypto.randomUUID(),r=n.model??"unknown",i=X(r);if(i!==r&&(n={...n,model:i}),!Ve(i))return e.status(400).json({error:{message:`Model '${r}' does not support the /v1/responses endpoint.`,type:"invalid_request_error",code:"unsupported_model"}});Array.isArray(n.tools)&&(n={...n,tools:n.tools.filter(_=>_.type==="web_search"?(console.log(`Removed unsupported tool 'web_search' from request ${s}`),!1):!0)});let c=Ct(n.input),a=V(c),u=JSON.stringify(n).length;if(n.stream)return At(e,n,a,s,u,o,r,i);let p=await Ke(`${D()}/v1/responses`,{method:"POST",headers:a,body:JSON.stringify(n)},s,"/v1/responses"),l=Math.round((Date.now()-o)/1e3*100)/100;if(!p)return e.status(504).json({error:`Upstream connection error after ${g.maxConnectionRetries+1} attempts`});let f=await p.text();if(p.ok){let _=JSON.parse(f),k=_.usage??{};y.addRequest(s,{request_body:n,response_body:_,model:r,translated_model:i!==r?i:null,endpoint:"/v1/responses",status_code:p.status,request_size:u,response_size:f.length,input_tokens:k.input_tokens??0,output_tokens:k.output_tokens??0,duration:l}),e.json(_)}else K("/v1/responses",n,f,p.status),e.status(p.status).type("json").send(f)}catch(o){e.status(500).json({error:String(o)})}});async function At(t,e,o,n,s,r,i,c){y.startRequest(n,{request_body:e,model:i,translated_model:c!==i?c:null,endpoint:"/v1/responses",request_size:s}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let a=0,u=0,p=200,l={},f=[],_=!1;t.on("close",()=>{_=!0});try{y.updateRequestState(n,"sending");let w=await fetch(`${D()}/v1/responses`,{method:"POST",headers:o,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});p=w.status;let b=w.body.getReader(),h=new TextDecoder,R="";for(y.updateRequestState(n,"receiving");;){let{done:v,value:$}=await b.read();if(v)break;if(_){b.cancel();break}R+=h.decode($,{stream:!0});let S=R.split(`
86
- `);R=S.pop();for(let C of S)if(C.trim()){if(C.startsWith("event: ")){_||t.write(`${C}
85
+ `)}catch{}}}}catch(d){l=504,console.log(`[Stream] Error for ${o}: ${d}`)}f?y.updateRequestState(o,"error",{status_code:499}):t.end();let _=Math.round((Date.now()-r)/1e3*100)/100,k=_e(a);y.completeRequest(o,{request_body:e,response_body:k,model:i,translated_model:c!==i?c:null,endpoint:"/v1/chat/completions",status_code:f?499:l,request_size:s,response_size:a.reduce((d,w)=>d+JSON.stringify(w).length,0),input_tokens:u,output_tokens:p,duration:_})}Y.post(["/v1/responses","/responses"],async(t,e)=>{try{let n=Date.now();await N();let o=t.body,s=crypto.randomUUID(),r=o.model??"unknown",i=X(r);if(i!==r&&(o={...o,model:i}),!Ge(i))return e.status(400).json({error:{message:`Model '${r}' does not support the /v1/responses endpoint.`,type:"invalid_request_error",code:"unsupported_model"}});Array.isArray(o.tools)&&(o={...o,tools:o.tools.filter(_=>_.type==="web_search"?(console.log(`Removed unsupported tool 'web_search' from request ${s}`),!1):!0)});let c=Ot(o.input),a=V(c),u=JSON.stringify(o).length;if(o.stream)return Ct(e,o,a,s,u,n,r,i);let p=await Ye(`${D()}/v1/responses`,{method:"POST",headers:a,body:JSON.stringify(o)},s,"/v1/responses"),l=Math.round((Date.now()-n)/1e3*100)/100;if(!p)return e.status(504).json({error:`Upstream connection error after ${g.maxConnectionRetries+1} attempts`});let f=await p.text();if(p.ok){let _=JSON.parse(f),k=_.usage??{};y.addRequest(s,{request_body:o,response_body:_,model:r,translated_model:i!==r?i:null,endpoint:"/v1/responses",status_code:p.status,request_size:u,response_size:f.length,input_tokens:k.input_tokens??0,output_tokens:k.output_tokens??0,duration:l}),e.json(_)}else K("/v1/responses",o,f,p.status),e.status(p.status).type("json").send(f)}catch(n){e.status(500).json({error:String(n)})}});async function Ct(t,e,n,o,s,r,i,c){y.startRequest(o,{request_body:e,model:i,translated_model:c!==i?c:null,endpoint:"/v1/responses",request_size:s}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let a=0,u=0,p=200,l={},f=[],_=!1;t.on("close",()=>{_=!0});try{y.updateRequestState(o,"sending");let w=await fetch(`${D()}/v1/responses`,{method:"POST",headers:n,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});p=w.status;let b=w.body.getReader(),h=new TextDecoder,R="";for(y.updateRequestState(o,"receiving");;){let{done:S,value:x}=await b.read();if(S)break;if(_){b.cancel();break}R+=h.decode(x,{stream:!0});let $=R.split(`
86
+ `);R=$.pop();for(let C of $)if(C.trim()){if(C.startsWith("event: ")){_||t.write(`${C}
87
87
  `);continue}if(C.startsWith("data: ")){let O=C.slice(6);if(O==="[DONE]"){_||t.write(`data: [DONE]
88
88
 
89
- `);continue}try{let I=JSON.parse(O);if(I.type==="response.completed"){let T=I.response??{};l=T;let L=T.usage??{};a=L.input_tokens??0,u=L.output_tokens??0}else I.type==="response.output_text.delta"&&f.push(I.delta??"");_||t.write(`data: ${O}
89
+ `);continue}try{let I=JSON.parse(O);if(I.type==="response.completed"){let E=I.response??{};l=E;let H=E.usage??{};a=H.input_tokens??0,u=H.output_tokens??0}else I.type==="response.output_text.delta"&&f.push(I.delta??"");_||t.write(`data: ${O}
90
90
 
91
91
  `)}catch{_||t.write(`data: ${O}
92
92
 
93
- `)}}}}}catch(w){p=504,console.log(`[Stream Responses] Error for ${n}: ${w}`)}_?y.updateRequestState(n,"error",{status_code:499}):t.end();let k=Math.round((Date.now()-r)/1e3*100)/100,d=Object.keys(l).length?l:null;!d&&f.length&&(d={output:[{type:"message",content:[{type:"output_text",text:f.join("")}]}]}),y.completeRequest(n,{request_body:e,response_body:d??{error:"Stream interrupted"},model:i,translated_model:c!==i?c:null,endpoint:"/v1/responses",status_code:_?499:p,request_size:s,response_size:JSON.stringify(d??{}).length,input_tokens:a,output_tokens:u,duration:k})}function Ct(t){if(!Array.isArray(t))return!1;for(let e of t){if(typeof e!="object"||!e)continue;let o=e.content;if(Array.isArray(o)&&o.some(n=>n.type==="input_image")||e.type==="input_image")return!0}return!1}async function Ke(t,e,o,n){let s=g.maxConnectionRetries;for(let r=0;r<=s;r++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(12e5)})}catch(i){let c=i;if(le(o,n,r,s,c),await N(),r<s){let a=Math.min(2**r,8)*1e3;console.log(`[${n}] Connection error (attempt ${r+1}/${s+1}): ${c.message}`),await new Promise(u=>setTimeout(u,a))}else console.log(`[${n}] Connection error (final attempt): ${c.message}`)}return null}var Xe=require("express");var fe=(0,Xe.Router)(),Ot=new Set(["model","messages","max_tokens","system","metadata","stop_sequences","stream","temperature","top_p","top_k","tools","tool_choice","thinking","service_tier"]);function Tt(t){let e=o=>{let n=o?.cache_control;n?.type==="ephemeral"&&"scope"in n&&delete n.scope};for(let o of t.tools??[])e(o);if(Array.isArray(t.system))for(let o of t.system)e(o);for(let o of t.messages??[])if(Array.isArray(o.content))for(let n of o.content)e(n)}function Pt(t){let e={};for(let[o,n]of Object.entries(t))Ot.has(o)&&(e[o]=n);return Tt(e),e}function Et(t){let e=t.thinking;if(!e?.budget_tokens)return t;let o=e.budget_tokens,n=t.max_tokens??0;if(n<=o){let s=o+Math.min(16384,o);return console.log(`[DirectAnthropic] Adjusted max_tokens: ${n} \u2192 ${s} (thinking.budget_tokens=${o})`),{...t,max_tokens:s}}return t}function qt(t){let e=t.system;if(!e)return g.systemPromptAdd.length?{...t,system:g.systemPromptAdd.map(o=>({type:"text",text:o}))}:t;if(typeof e=="string"){let o=de(e);for(let n of g.systemPromptAdd)o.includes(n)||(o+=`
93
+ `)}}}}}catch(w){p=504,console.log(`[Stream Responses] Error for ${o}: ${w}`)}_?y.updateRequestState(o,"error",{status_code:499}):t.end();let k=Math.round((Date.now()-r)/1e3*100)/100,d=Object.keys(l).length?l:null;!d&&f.length&&(d={output:[{type:"message",content:[{type:"output_text",text:f.join("")}]}]}),y.completeRequest(o,{request_body:e,response_body:d??{error:"Stream interrupted"},model:i,translated_model:c!==i?c:null,endpoint:"/v1/responses",status_code:_?499:p,request_size:s,response_size:JSON.stringify(d??{}).length,input_tokens:a,output_tokens:u,duration:k})}function Ot(t){if(!Array.isArray(t))return!1;for(let e of t){if(typeof e!="object"||!e)continue;let n=e.content;if(Array.isArray(n)&&n.some(o=>o.type==="input_image")||e.type==="input_image")return!0}return!1}async function Ye(t,e,n,o){let s=g.maxConnectionRetries;for(let r=0;r<=s;r++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(12e5)})}catch(i){let c=i;if(de(n,o,r,s,c),await N(),r<s){let a=Math.min(2**r,8)*1e3;console.log(`[${o}] Connection error (attempt ${r+1}/${s+1}): ${c.message}`),await new Promise(u=>setTimeout(u,a))}else console.log(`[${o}] Connection error (final attempt): ${c.message}`)}return null}var Qe=require("express");var he=(0,Qe.Router)(),Tt=new Set(["model","messages","max_tokens","system","metadata","stop_sequences","stream","temperature","top_p","top_k","tools","tool_choice","thinking","service_tier"]);function Et(t){let e=n=>{let o=n?.cache_control;o?.type==="ephemeral"&&"scope"in o&&delete o.scope};for(let n of t.tools??[])e(n);if(Array.isArray(t.system))for(let n of t.system)e(n);for(let n of t.messages??[])if(Array.isArray(n.content))for(let o of n.content)e(o)}function Pt(t){let e={};for(let[n,o]of Object.entries(t))Tt.has(n)&&(e[n]=o);return Et(e),e}function qt(t){let e=t.thinking;if(!e?.budget_tokens)return t;let n=e.budget_tokens,o=t.max_tokens??0;if(o<=n){let s=n+Math.min(16384,n);return console.log(`[DirectAnthropic] Adjusted max_tokens: ${o} \u2192 ${s} (thinking.budget_tokens=${n})`),{...t,max_tokens:s}}return t}function Dt(t){let e=t.system;if(!e)return g.systemPromptAdd.length?{...t,system:g.systemPromptAdd.map(n=>({type:"text",text:n}))}:t;if(typeof e=="string"){let n=me(e);for(let o of g.systemPromptAdd)n.includes(o)||(n+=`
94
94
 
95
- `+n);return{...t,system:o}}if(Array.isArray(e)){let o=e,n=o.filter(i=>i.type==="text").map(i=>i.text).join(`
96
- `),s=!1,r=[];for(let i of o)if(i.type==="text"){let c=i.text;if(c.startsWith("x-anthropic-billing-header:")){s=!0;continue}let a=c;for(let u of g.systemPromptRemove)a.includes(u)&&(a=a.replaceAll(u,""),s=!0);r.push(a!==c?{...i,text:a}:i)}else r.push(i);for(let i of g.systemPromptAdd)n.includes(i)||(r.push({type:"text",text:i}),s=!0);return s?{...t,system:r}:t}return t}function Dt(t){let e=t.messages;if(!e?.length)return t;let o=!1,n=e.map(s=>{if(!Array.isArray(s.content))return s;let r=!1,i=s.content.map(c=>{if(c.type!=="tool_result"||typeof c.content!="string")return c;let a=Te(c.content);return a!==c.content?(r=!0,{...c,content:a}):c});return r?(o=!0,{...s,content:i}):s});return o?{...t,messages:n}:t}fe.post("/v1/messages/count_tokens",async(t,e)=>{try{await N();let o=t.body,n=o.model??"",s=g.models?.data?.find(c=>c.id===n);if(!s)return e.json({input_tokens:1});let r=0,i=o.system;if(typeof i=="string")r+=j(i);else if(Array.isArray(i))for(let c of i)c.type==="text"&&(r+=j(c.text??""));for(let c of o.messages??[]){let a=c.content;if(typeof a=="string")r+=j(a);else if(Array.isArray(a))for(let u of a)u.type==="text"?r+=j(u.text??""):u.type==="tool_result"&&typeof u.content=="string"?r+=j(u.content):u.type==="tool_use"&&(r+=j(JSON.stringify(u.input??{})))}if(o.tools?.length){r+=n.startsWith("claude")?346:n.startsWith("grok")?480:346;for(let c of o.tools)r+=j(c.name??""),r+=j(c.description??""),r+=j(JSON.stringify(c.input_schema??{}))}s.vendor!=="Anthropic"&&(r=Math.ceil(r*(n.startsWith("grok")?1.03:1.05))),e.json({input_tokens:r})}catch(o){console.log(`[count_tokens] Error: ${o}`),e.json({input_tokens:1})}});fe.post("/v1/messages",async(t,e)=>{let o=Date.now();await N();let n=t.body,s=crypto.randomUUID(),r=n,i=n.model??"unknown",c=X(i);return c!==i&&(console.log(`[Anthropic API] Model name translated: ${i} -> ${c}`),n={...n,model:c}),n=qt(n),n=Dt(n),Be(c)?(console.log(`[Anthropic API] Using direct Anthropic API path for: ${c}`),It(e,n,s,o,i,c,r)):(console.log(`[Anthropic API] Using OpenAI translation path for: ${c}`),jt(e,n,s,o,i,c,r))});async function It(t,e,o,n,s,r,i){let c=JSON.stringify(e).length,a=Ye(e),u=(e.messages??[]).some(_=>_.role==="assistant"),p=V(a);p["anthropic-version"]="2023-06-01",p["X-Initiator"]=u?"agent":"user";let l=e,f=null;for(let _=0;_<=3;_++){let k=Pt(l);if(k=Et(k),k.stream)return Nt(t,k,p,o,l,c,n,s,r,i);let d=await Qe(`${D()}/v1/messages`,{method:"POST",headers:p,body:JSON.stringify(k)},o,"/v1/messages");if(!d)return void t.status(504).json({type:"error",error:{type:"api_error",message:"Upstream connection error"}});let w=Math.round((Date.now()-n)/1e3*100)/100;if(d.ok){let h=await d.json(),R=h.usage;return y.addRequest(o,{original_request_body:i,request_body:l,response_body:h,model:s,translated_model:r!==s?r:null,endpoint:"/v1/messages",status_code:d.status,request_size:c,response_size:JSON.stringify(h).length,input_tokens:R?.input_tokens??0,output_tokens:R?.output_tokens??0,duration:w}),f&&pe({...f,modified_request:l,final_status_code:d.status,final_response:h}),void t.json(h)}let b=await d.text();if(K("/v1/messages",l,b,d.status),Se(d.status,b)){let h=xe(b);if(h.length){console.log(`[Direct Anthropic] Attempt ${_+1}: orphaned IDs: ${h}`),f?f.orphaned_ids.push(...h):f={request_id:o,original_request:e,error_response:b,error_status_code:d.status,orphaned_ids:h},l={...l,messages:$e(l.messages,h)};continue}}return f&&pe({...f,modified_request:l,final_status_code:d.status,final_response:b}),void t.status(d.status).type("json").send(b)}}async function Nt(t,e,o,n,s,r,i,c,a,u){y.startRequest(n,{original_request_body:u,request_body:s,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",request_size:r}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let p=0,l=0,f=200,_=c,k=[],d=!1;t.on("close",()=>{d=!0});try{y.updateRequestState(n,"sending");let h=await fetch(`${D()}/v1/messages`,{method:"POST",headers:o,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});f=h.status,y.updateRequestState(n,"receiving");let R=h.body.getReader(),v=new TextDecoder,$="",S="";for(;;){let{done:C,value:O}=await R.read();if(C)break;if(d){R.cancel();break}$+=v.decode(O,{stream:!0});let I=$.split(`
97
- `);$=I.pop();for(let T of I){if(!T.trim())continue;if(T.startsWith("event: ")){S=T.slice(7);continue}if(!T.startsWith("data: "))continue;let L=T.slice(6);if(L==="[DONE]")break;try{let q=JSON.parse(L),G=S||q.type||"";if(S="",G==="message_start"){let ee=q.message??{};_=ee.model??c,p=ee.usage?.input_tokens??0}else G==="message_delta"?l=q.usage?.output_tokens??0:G==="content_block_delta"&&q.delta?.type==="text_delta"&&k.push(q.delta.text??"");d||t.write(`event: ${G}
98
- data: ${L}
95
+ `+o);return{...t,system:n}}if(Array.isArray(e)){let n=e,o=n.filter(i=>i.type==="text").map(i=>i.text).join(`
96
+ `),s=!1,r=[];for(let i of n)if(i.type==="text"){let c=i.text;if(c.startsWith("x-anthropic-billing-header:")){s=!0;continue}let a=c;for(let u of g.systemPromptRemove)a.includes(u)&&(a=a.replaceAll(u,""),s=!0);r.push(a!==c?{...i,text:a}:i)}else r.push(i);for(let i of g.systemPromptAdd)o.includes(i)||(r.push({type:"text",text:i}),s=!0);return s?{...t,system:r}:t}return t}function It(t){let e=t.messages;if(!e?.length)return t;let n=!1,o=e.map(s=>{if(!Array.isArray(s.content))return s;let r=!1,i=s.content.map(c=>{if(c.type!=="tool_result"||typeof c.content!="string")return c;let a=Pe(c.content);return a!==c.content?(r=!0,{...c,content:a}):c});return r?(n=!0,{...s,content:i}):s});return n?{...t,messages:o}:t}he.post("/v1/messages/count_tokens",async(t,e)=>{try{await N();let n=t.body,o=n.model??"",s=g.models?.data?.find(c=>c.id===o);if(!s)return e.json({input_tokens:1});let r=0,i=n.system;if(typeof i=="string")r+=j(i);else if(Array.isArray(i))for(let c of i)c.type==="text"&&(r+=j(c.text??""));for(let c of n.messages??[]){let a=c.content;if(typeof a=="string")r+=j(a);else if(Array.isArray(a))for(let u of a)u.type==="text"?r+=j(u.text??""):u.type==="tool_result"&&typeof u.content=="string"?r+=j(u.content):u.type==="tool_use"&&(r+=j(JSON.stringify(u.input??{})))}if(n.tools?.length){r+=o.startsWith("claude")?346:o.startsWith("grok")?480:346;for(let c of n.tools)r+=j(c.name??""),r+=j(c.description??""),r+=j(JSON.stringify(c.input_schema??{}))}s.vendor!=="Anthropic"&&(r=Math.ceil(r*(o.startsWith("grok")?1.03:1.05))),e.json({input_tokens:r})}catch(n){console.log(`[count_tokens] Error: ${n}`),e.json({input_tokens:1})}});he.post("/v1/messages",async(t,e)=>{let n=Date.now();await N();let o=t.body,s=crypto.randomUUID(),r=o,i=o.model??"unknown",c=X(i);return c!==i&&(console.log(`[Anthropic API] Model name translated: ${i} -> ${c}`),o={...o,model:c}),o=Dt(o),o=It(o),Je(c)?(console.log(`[Anthropic API] Using direct Anthropic API path for: ${c}`),Nt(e,o,s,n,i,c,r)):(console.log(`[Anthropic API] Using OpenAI translation path for: ${c}`),Lt(e,o,s,n,i,c,r))});async function Nt(t,e,n,o,s,r,i){let c=JSON.stringify(e).length,a=Ze(e),u=(e.messages??[]).some(_=>_.role==="assistant"),p=V(a);p["anthropic-version"]="2023-06-01",p["X-Initiator"]=u?"agent":"user";let l=e,f=null;for(let _=0;_<=3;_++){let k=Pt(l);if(k=qt(k),k.stream)return jt(t,k,p,n,l,c,o,s,r,i);let d=await et(`${D()}/v1/messages`,{method:"POST",headers:p,body:JSON.stringify(k)},n,"/v1/messages");if(!d)return void t.status(504).json({type:"error",error:{type:"api_error",message:"Upstream connection error"}});let w=Math.round((Date.now()-o)/1e3*100)/100;if(d.ok){let h=await d.json(),R=h.usage;return y.addRequest(n,{original_request_body:i,request_body:l,response_body:h,model:s,translated_model:r!==s?r:null,endpoint:"/v1/messages",status_code:d.status,request_size:c,response_size:JSON.stringify(h).length,input_tokens:R?.input_tokens??0,output_tokens:R?.output_tokens??0,duration:w}),f&&ge({...f,modified_request:l,final_status_code:d.status,final_response:h}),void t.json(h)}let b=await d.text();if(K("/v1/messages",l,b,d.status),Ce(d.status,b)){let h=$e(b);if(h.length){console.log(`[Direct Anthropic] Attempt ${_+1}: orphaned IDs: ${h}`),f?f.orphaned_ids.push(...h):f={request_id:n,original_request:e,error_response:b,error_status_code:d.status,orphaned_ids:h},l={...l,messages:Ae(l.messages,h)};continue}}return f&&ge({...f,modified_request:l,final_status_code:d.status,final_response:b}),void t.status(d.status).type("json").send(b)}}async function jt(t,e,n,o,s,r,i,c,a,u){y.startRequest(o,{original_request_body:u,request_body:s,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",request_size:r}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let p=0,l=0,f=200,_=c,k=[],d=!1;t.on("close",()=>{d=!0});try{y.updateRequestState(o,"sending");let h=await fetch(`${D()}/v1/messages`,{method:"POST",headers:n,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});f=h.status,y.updateRequestState(o,"receiving");let R=h.body.getReader(),S=new TextDecoder,x="",$="";for(;;){let{done:C,value:O}=await R.read();if(C)break;if(d){R.cancel();break}x+=S.decode(O,{stream:!0});let I=x.split(`
97
+ `);x=I.pop();for(let E of I){if(!E.trim())continue;if(E.startsWith("event: ")){$=E.slice(7);continue}if(!E.startsWith("data: "))continue;let H=E.slice(6);if(H==="[DONE]")break;try{let q=JSON.parse(H),G=$||q.type||"";if($="",G==="message_start"){let ee=q.message??{};_=ee.model??c,p=ee.usage?.input_tokens??0}else G==="message_delta"?l=q.usage?.output_tokens??0:G==="content_block_delta"&&q.delta?.type==="text_delta"&&k.push(q.delta.text??"");d||t.write(`event: ${G}
98
+ data: ${H}
99
99
 
100
- `)}catch{}}}}catch(h){f=504,console.log(`[Stream Direct Anthropic] Error for ${n}: ${h}`)}d?y.updateRequestState(n,"error",{status_code:499}):t.end();let w=Math.round((Date.now()-i)/1e3*100)/100,b=k.length?{id:n,type:"message",role:"assistant",content:[{type:"text",text:k.join("")}],model:_,usage:{input_tokens:p,output_tokens:l}}:{error:{type:"api_error",message:"Stream interrupted"}};y.completeRequest(n,{request_body:s,response_body:b,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",status_code:d?499:f,request_size:r,response_size:JSON.stringify(b).length,input_tokens:p,output_tokens:l,duration:w})}async function jt(t,e,o,n,s,r,i){let c=Ye(e),a=JSON.stringify(e).length,u=e,p=null;for(let l=0;l<=3;l++){let f=Je(u),_=(f.messages??[]).some(h=>h.role==="assistant"||h.role==="tool"),k=V(c);if(k["X-Initiator"]=_?"agent":"user",e.stream)return Ht(t,f,k,o,u,a,n,s,r,i);let d=await Qe(`${D()}/chat/completions`,{method:"POST",headers:k,body:JSON.stringify(f)},o,"/v1/messages (translated)");if(!d)return void t.status(504).json({type:"error",error:{type:"api_error",message:"Upstream connection error"}});let w=Math.round((Date.now()-n)/1e3*100)/100;if(d.ok){let h=await d.json(),R=Ee(h),v=h.usage;return y.addRequest(o,{original_request_body:i,request_body:u,response_body:R,model:s,translated_model:r!==s?r:null,endpoint:"/v1/messages",status_code:d.status,request_size:a,response_size:JSON.stringify(R).length,input_tokens:v?.prompt_tokens??0,output_tokens:v?.completion_tokens??0,duration:w}),void t.json(R)}let b=await d.text();if(K("/v1/messages",u,b,d.status),Se(d.status,b)){let h=xe(b);if(h.length){p?p.orphaned_ids.push(...h):p={request_id:o,original_request:e,error_response:b,error_status_code:d.status,orphaned_ids:h},u={...u,messages:$e(u.messages,h)};continue}}return p&&pe({...p,modified_request:u,final_status_code:d.status,final_response:b}),void t.status(d.status).type("json").send(b)}}async function Ht(t,e,o,n,s,r,i,c,a,u){y.startRequest(n,{original_request_body:u,request_body:s,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",request_size:r}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let p=new ge,l=[],f=0,_=0,k=200,d=!1;t.on("close",()=>{d=!0});try{y.updateRequestState(n,"sending");let R=await fetch(`${D()}/chat/completions`,{method:"POST",headers:o,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});k=R.status,y.updateRequestState(n,"receiving");let v=R.body.getReader(),$=new TextDecoder,S="";for(;;){let{done:C,value:O}=await v.read();if(C)break;if(d){v.cancel();break}S+=$.decode(O,{stream:!0});let I=S.split(`
101
- `);S=I.pop();for(let T of I){if(!T.trim()||!T.startsWith("data: "))continue;let L=T.slice(6);if(L==="[DONE]")break;try{let q=JSON.parse(L);l.push(q),q.usage&&(f=q.usage.prompt_tokens??0,_=q.usage.completion_tokens??0);let G=Ge(q,p);for(let ee of G)d||t.write(`event: ${ee.type}
100
+ `)}catch{}}}}catch(h){f=504,console.log(`[Stream Direct Anthropic] Error for ${o}: ${h}`)}d?y.updateRequestState(o,"error",{status_code:499}):t.end();let w=Math.round((Date.now()-i)/1e3*100)/100,b=k.length?{id:o,type:"message",role:"assistant",content:[{type:"text",text:k.join("")}],model:_,usage:{input_tokens:p,output_tokens:l}}:{error:{type:"api_error",message:"Stream interrupted"}};y.completeRequest(o,{request_body:s,response_body:b,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",status_code:d?499:f,request_size:r,response_size:JSON.stringify(b).length,input_tokens:p,output_tokens:l,duration:w})}async function Lt(t,e,n,o,s,r,i){let c=Ze(e),a=JSON.stringify(e).length,u=e,p=null;for(let l=0;l<=3;l++){let f=We(u),_=(f.messages??[]).some(h=>h.role==="assistant"||h.role==="tool"),k=V(c);if(k["X-Initiator"]=_?"agent":"user",e.stream)return Ht(t,f,k,n,u,a,o,s,r,i);let d=await et(`${D()}/chat/completions`,{method:"POST",headers:k,body:JSON.stringify(f)},n,"/v1/messages (translated)");if(!d)return void t.status(504).json({type:"error",error:{type:"api_error",message:"Upstream connection error"}});let w=Math.round((Date.now()-o)/1e3*100)/100;if(d.ok){let h=await d.json(),R=De(h),S=h.usage;return y.addRequest(n,{original_request_body:i,request_body:u,response_body:R,model:s,translated_model:r!==s?r:null,endpoint:"/v1/messages",status_code:d.status,request_size:a,response_size:JSON.stringify(R).length,input_tokens:S?.prompt_tokens??0,output_tokens:S?.completion_tokens??0,duration:w}),void t.json(R)}let b=await d.text();if(K("/v1/messages",u,b,d.status),Ce(d.status,b)){let h=$e(b);if(h.length){p?p.orphaned_ids.push(...h):p={request_id:n,original_request:e,error_response:b,error_status_code:d.status,orphaned_ids:h},u={...u,messages:Ae(u.messages,h)};continue}}return p&&ge({...p,modified_request:u,final_status_code:d.status,final_response:b}),void t.status(d.status).type("json").send(b)}}async function Ht(t,e,n,o,s,r,i,c,a,u){y.startRequest(o,{original_request_body:u,request_body:s,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",request_size:r}),t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"});let p=new fe,l=[],f=0,_=0,k=200,d=!1;t.on("close",()=>{d=!0});try{y.updateRequestState(o,"sending");let R=await fetch(`${D()}/chat/completions`,{method:"POST",headers:n,body:JSON.stringify(e),signal:AbortSignal.timeout(12e5)});k=R.status,y.updateRequestState(o,"receiving");let S=R.body.getReader(),x=new TextDecoder,$="";for(;;){let{done:C,value:O}=await S.read();if(C)break;if(d){S.cancel();break}$+=x.decode(O,{stream:!0});let I=$.split(`
101
+ `);$=I.pop();for(let E of I){if(!E.trim()||!E.startsWith("data: "))continue;let H=E.slice(6);if(H==="[DONE]")break;try{let q=JSON.parse(H);l.push(q),q.usage&&(f=q.usage.prompt_tokens??0,_=q.usage.completion_tokens??0);let G=Ke(q,p);for(let ee of G)d||t.write(`event: ${ee.type}
102
102
  data: ${JSON.stringify(ee)}
103
103
 
104
- `)}catch{}}}}catch(R){k=504,console.log(`[Stream Anthropic] Error for ${n}: ${R}`)}d?y.updateRequestState(n,"error",{status_code:499}):t.end();let w=Math.round((Date.now()-i)/1e3*100)/100,b=me(l),h=Object.keys(b).length?Ee(b):{error:{type:"api_error",message:"Stream interrupted"}};y.completeRequest(n,{request_body:s,response_body:h,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",status_code:d?499:k,request_size:r,response_size:l.reduce((R,v)=>R+JSON.stringify(v).length,0),input_tokens:f,output_tokens:_,duration:w})}function Ye(t){return(t.messages??[]).some(e=>Array.isArray(e.content)&&e.content.some(o=>o.type==="image"))}async function Qe(t,e,o,n){let s=g.maxConnectionRetries;for(let r=0;r<=s;r++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(12e5)})}catch(i){let c=i;le(o,n,r,s,c),await N(),r<s&&(console.log(`[${n}] Connection error (attempt ${r+1}/${s+1}): ${c.message}`),await new Promise(a=>setTimeout(a,Math.min(2**r,8)*1e3)))}return null}var Ze=require("express"),_e=A(require("path"));var E=(0,Ze.Router)();function et(){return _e.default.join(__dirname,"..","..","public")}E.get("/",(t,e)=>{e.sendFile(_e.default.join(et(),"dashboard.html"))});E.get("/requests",(t,e)=>{e.sendFile(_e.default.join(et(),"requests.html"))});E.get("/api/stats",(t,e)=>{e.json(y.getStats())});E.get("/api/requests",(t,e)=>{let o=parseInt(t.query.page)||1,n=parseInt(t.query.per_page)||50,s=t.query.search||"",r=(o-1)*n,i,c;s?(i=y.searchRequests(s,n,r),c=y.searchRequests(s,1e4,0).length):(i=y.getRecentRequests(n,r),c=y.getTotalCount());let a=i.map(u=>({...u,request_body:null,response_body:null}));e.json({items:a,total:c,page:o,per_page:n,total_pages:Math.ceil(c/n)})});E.get("/api/request/:id",(t,e)=>{let o=y.getRequest(t.params.id);if(!o)return e.status(404).json({error:"Request not found"});e.json(o)});E.get("/api/request/:id/request-body",(t,e)=>{let o=y.getRequest(t.params.id);if(!o)return e.status(404).json({error:"Request not found"});e.json(o.request_body)});E.get("/api/request/:id/response-body",(t,e)=>{let o=y.getRequest(t.params.id);if(!o)return e.status(404).json({error:"Request not found"});e.json(o.response_body)});E.get("/api/requests/search",(t,e)=>{let o=parseInt(t.query.page)||1,n=parseInt(t.query.per_page)||50,s=t.query.q||"",r=(o-1)*n;if(!s)return e.json({items:[],total:0,page:o,per_page:n,total_pages:0});let[i,c]=y.fulltextSearch(s,n,r),a=i.map(u=>({...u,request_body:null,response_body:null}));e.json({items:a,total:c,page:o,per_page:n,total_pages:c>0?Math.ceil(c/n):0})});E.get("/api/requests/export",(t,e)=>{let o=new Date().toISOString().replace(/[:.]/g,"").slice(0,15);e.setHeader("Content-Type","application/x-jsonlines"),e.setHeader("Content-Disposition",`attachment; filename=requests_${o}.jl`);for(let n of y.getAllRequests())e.write(JSON.stringify(n)+`
105
- `);e.end()});E.post("/api/requests/import",(t,e)=>{let n=(typeof t.body=="string"?t.body:JSON.stringify(t.body)).split(`
106
- `).filter(i=>i.trim()),s=0,r=[];for(let i=0;i<n.length;i++)try{let c=JSON.parse(n[i]);y.importRequest(c),s++}catch(c){r.push(`Line ${i+1}: ${c}`)}e.json({imported:s,errors:r.slice(0,10),total_errors:r.length})});var U=A(require("fs")),Z=A(require("path")),nt=A(require("readline"));var H="\x1B[1m",x="\x1B[2m",m="\x1B[0m",Q="\x1B[36m",z="\x1B[32m",De="\x1B[33m",B="\x1B[35m";function Lt(){console.log(`
107
- ${B}\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557${m}
108
- ${B}\u2551${m} ${H}ghc-tunnel Setup Wizard${m} ${B}\u2551${m}
109
- ${B}\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${m}
110
- `)}function ot(){return nt.default.createInterface({input:process.stdin,output:process.stdout})}function F(t,e){return new Promise(o=>t.question(e,o))}async function st(){Lt(),console.log(`${H}Step 1: GitHub Authentication${m}`),console.log(`${x}Checking for GitHub token...${m}
111
- `);let t=await ae();t||(console.error("Failed to get GitHub token. Cannot continue setup."),process.exit(1)),g.githubToken=t,await ie(),await W();let e=g.models?.data??[];e.length||(console.error("No models available. Check your Copilot subscription."),process.exit(1)),console.log(`
112
- ${H}Step 2: Configure Models${m}
113
- `),console.log(`${x}Available Copilot models:${m}
114
- `);for(let R=0;R<e.length;R++){let v=e[R],$=[];v.capabilities?.supports?.vision&&$.push("Vision"),v.capabilities?.supports?.tool_calls&&$.push("Tools"),v.supported_endpoints?.includes("/v1/messages")&&$.push("Anthropic"),v.preview&&$.push("Preview");let S=$.length?` ${x}(${$.join(", ")})${m}`:"";console.log(` ${Q}${String(R+1).padStart(2)}.${m} ${v.id}${S}`)}let o=ot();console.log(`
115
- ${De}Pick models by number. Press Enter to accept the default.${m}
116
- `);let n=qe(e,"claude-opus-4.6-1m")??qe(e,"claude-opus-4.6")??0,s=await tt(o,e,'Primary model (mapped to "opus", "sonnet" aliases)',n),r=e[s],i=qe(e,"claude-haiku-4.5")??0,c=await tt(o,e,'Small/fast model (mapped to "haiku" alias)',i),a=e[c];console.log(`
117
- ${z}Primary: ${r.id}${m}`),console.log(`${z}Small: ${a.id}${m}
118
- `),console.log(`${H}Step 3: Server Settings${m}
119
- `);let u=await F(o,` Port ${x}[8314]${m}: `),p=u.trim()?parseInt(u.trim(),10):8314,f=(await F(o,` Host ${x}[localhost]${m}: `)).trim()||"localhost";console.log(`
120
- ${H}Step 4: Claude Code Model Settings${m}`),console.log(`${x}These are the model identifiers written to ~/.claude/settings.json.${m}`),console.log(`${x}The proxy's model_mappings translate them to actual Copilot models.${m}
121
- `);let _="claude-opus-4-6[1m]",k="claude-sonnet-4-6",w=(await F(o,` ANTHROPIC_MODEL ${x}[${_}]${m}: `)).trim()||_,h=(await F(o,` ANTHROPIC_DEFAULT_HAIKU_MODEL ${x}[${k}]${m}: `)).trim()||k;return console.log(`
122
- ${z}ANTHROPIC_MODEL: ${w}${m}`),console.log(`${z}ANTHROPIC_DEFAULT_HAIKU_MODEL: ${h}${m}
123
- `),o.close(),console.log(`${H}Step 5: Saving Configuration${m}
124
- `),Mt(r.id,a.id,p,f),rt(p,f,w,h),console.log(`
125
- ${z}${H}Setup complete!${m}
126
- `),{port:p,host:f}}async function tt(t,e,o,n){let s=e[n]?.id??"?";for(;;){let r=await F(t,` ${o} ${x}[${n+1}: ${s}]${m}: `);if(!r.trim())return n;let i=parseInt(r.trim(),10);if(i>=1&&i<=e.length)return i-1;let c=e.findIndex(a=>a.id===r.trim());if(c!==-1)return c;console.log(` ${De}Invalid choice. Enter a number 1-${e.length} or a model name.${m}`)}}function qe(t,e){let o=t.findIndex(n=>n.id===e);return o>=0?o:void 0}function Mt(t,e,o,n){let s=P();U.default.mkdirSync(s,{recursive:!0});let r=Z.default.join(s,"config.yaml"),i=`# ghc-tunnel Configuration (generated by --setup)
104
+ `)}catch{}}}}catch(R){k=504,console.log(`[Stream Anthropic] Error for ${o}: ${R}`)}d?y.updateRequestState(o,"error",{status_code:499}):t.end();let w=Math.round((Date.now()-i)/1e3*100)/100,b=_e(l),h=Object.keys(b).length?De(b):{error:{type:"api_error",message:"Stream interrupted"}};y.completeRequest(o,{request_body:s,response_body:h,model:c,translated_model:a!==c?a:null,endpoint:"/v1/messages",status_code:d?499:k,request_size:r,response_size:l.reduce((R,S)=>R+JSON.stringify(S).length,0),input_tokens:f,output_tokens:_,duration:w})}function Ze(t){return(t.messages??[]).some(e=>Array.isArray(e.content)&&e.content.some(n=>n.type==="image"))}async function et(t,e,n,o){let s=g.maxConnectionRetries;for(let r=0;r<=s;r++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(12e5)})}catch(i){let c=i;de(n,o,r,s,c),await N(),r<s&&(console.log(`[${o}] Connection error (attempt ${r+1}/${s+1}): ${c.message}`),await new Promise(a=>setTimeout(a,Math.min(2**r,8)*1e3)))}return null}var tt=require("express"),ce=A(require("path")),nt=A(require("fs"));var P=(0,tt.Router)();function ot(){let t=ce.default.join(__dirname,"..","public");return nt.default.existsSync(t)?t:ce.default.join(__dirname,"..","..","public")}P.get("/",(t,e)=>{e.sendFile(ce.default.join(ot(),"dashboard.html"))});P.get("/requests",(t,e)=>{e.sendFile(ce.default.join(ot(),"requests.html"))});P.get("/api/stats",(t,e)=>{e.json(y.getStats())});P.get("/api/requests",(t,e)=>{let n=parseInt(t.query.page)||1,o=parseInt(t.query.per_page)||50,s=t.query.search||"",r=(n-1)*o,i,c;s?(i=y.searchRequests(s,o,r),c=y.searchRequests(s,1e4,0).length):(i=y.getRecentRequests(o,r),c=y.getTotalCount());let a=i.map(u=>({...u,request_body:null,response_body:null}));e.json({items:a,total:c,page:n,per_page:o,total_pages:Math.ceil(c/o)})});P.get("/api/request/:id",(t,e)=>{let n=y.getRequest(t.params.id);if(!n)return e.status(404).json({error:"Request not found"});e.json(n)});P.get("/api/request/:id/request-body",(t,e)=>{let n=y.getRequest(t.params.id);if(!n)return e.status(404).json({error:"Request not found"});e.json(n.request_body)});P.get("/api/request/:id/response-body",(t,e)=>{let n=y.getRequest(t.params.id);if(!n)return e.status(404).json({error:"Request not found"});e.json(n.response_body)});P.get("/api/requests/search",(t,e)=>{let n=parseInt(t.query.page)||1,o=parseInt(t.query.per_page)||50,s=t.query.q||"",r=(n-1)*o;if(!s)return e.json({items:[],total:0,page:n,per_page:o,total_pages:0});let[i,c]=y.fulltextSearch(s,o,r),a=i.map(u=>({...u,request_body:null,response_body:null}));e.json({items:a,total:c,page:n,per_page:o,total_pages:c>0?Math.ceil(c/o):0})});P.get("/api/requests/export",(t,e)=>{let n=new Date().toISOString().replace(/[:.]/g,"").slice(0,15);e.setHeader("Content-Type","application/x-jsonlines"),e.setHeader("Content-Disposition",`attachment; filename=requests_${n}.jl`);for(let o of y.getAllRequests())e.write(JSON.stringify(o)+`
105
+ `);e.end()});P.post("/api/requests/import",(t,e)=>{let o=(typeof t.body=="string"?t.body:JSON.stringify(t.body)).split(`
106
+ `).filter(i=>i.trim()),s=0,r=[];for(let i=0;i<o.length;i++)try{let c=JSON.parse(o[i]);y.importRequest(c),s++}catch(c){r.push(`Line ${i+1}: ${c}`)}e.json({imported:s,errors:r.slice(0,10),total_errors:r.length})});var U=A(require("fs")),Z=A(require("path")),rt=A(require("readline"));var L="\x1B[1m",v="\x1B[2m",m="\x1B[0m",Q="\x1B[36m",B="\x1B[32m",Ne="\x1B[33m",z="\x1B[35m";function Mt(){console.log(`
107
+ ${z}\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557${m}
108
+ ${z}\u2551${m} ${L}ghc-tunnel Setup Wizard${m} ${z}\u2551${m}
109
+ ${z}\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${m}
110
+ `)}function it(){return rt.default.createInterface({input:process.stdin,output:process.stdout})}function F(t,e){return new Promise(n=>t.question(e,n))}async function ct(){Mt(),console.log(`${L}Step 1: GitHub Authentication${m}`),console.log(`${v}Checking for GitHub token...${m}
111
+ `);let t=await le();t||(console.error("Failed to get GitHub token. Cannot continue setup."),process.exit(1)),g.githubToken=t,await ie(),await W();let e=g.models?.data??[];e.length||(console.error("No models available. Check your Copilot subscription."),process.exit(1)),console.log(`
112
+ ${L}Step 2: Configure Models${m}
113
+ `),console.log(`${v}Available Copilot models:${m}
114
+ `);for(let R=0;R<e.length;R++){let S=e[R],x=[];S.capabilities?.supports?.vision&&x.push("Vision"),S.capabilities?.supports?.tool_calls&&x.push("Tools"),S.supported_endpoints?.includes("/v1/messages")&&x.push("Anthropic"),S.preview&&x.push("Preview");let $=x.length?` ${v}(${x.join(", ")})${m}`:"";console.log(` ${Q}${String(R+1).padStart(2)}.${m} ${S.id}${$}`)}let n=it();console.log(`
115
+ ${Ne}Pick models by number. Press Enter to accept the default.${m}
116
+ `);let o=Ie(e,"claude-opus-4.6-1m")??Ie(e,"claude-opus-4.6")??0,s=await st(n,e,'Primary model (mapped to "opus", "sonnet" aliases)',o),r=e[s],i=Ie(e,"claude-haiku-4.5")??0,c=await st(n,e,'Small/fast model (mapped to "haiku" alias)',i),a=e[c];console.log(`
117
+ ${B}Primary: ${r.id}${m}`),console.log(`${B}Small: ${a.id}${m}
118
+ `),console.log(`${L}Step 3: Server Settings${m}
119
+ `);let u=await F(n,` Port ${v}[8314]${m}: `),p=u.trim()?parseInt(u.trim(),10):8314,f=(await F(n,` Host ${v}[localhost]${m}: `)).trim()||"localhost";console.log(`
120
+ ${L}Step 4: Claude Code Model Settings${m}`),console.log(`${v}These are the model identifiers written to ~/.claude/settings.json.${m}`),console.log(`${v}The proxy's model_mappings translate them to actual Copilot models.${m}
121
+ `);let _="claude-opus-4-6[1m]",k="claude-sonnet-4-6",w=(await F(n,` ANTHROPIC_MODEL ${v}[${_}]${m}: `)).trim()||_,h=(await F(n,` ANTHROPIC_DEFAULT_HAIKU_MODEL ${v}[${k}]${m}: `)).trim()||k;return console.log(`
122
+ ${B}ANTHROPIC_MODEL: ${w}${m}`),console.log(`${B}ANTHROPIC_DEFAULT_HAIKU_MODEL: ${h}${m}
123
+ `),n.close(),console.log(`${L}Step 5: Saving Configuration${m}
124
+ `),Ut(r.id,a.id,p,f),at(p,f,w,h),console.log(`
125
+ ${B}${L}Setup complete!${m}
126
+ `),{port:p,host:f}}async function st(t,e,n,o){let s=e[o]?.id??"?";for(;;){let r=await F(t,` ${n} ${v}[${o+1}: ${s}]${m}: `);if(!r.trim())return o;let i=parseInt(r.trim(),10);if(i>=1&&i<=e.length)return i-1;let c=e.findIndex(a=>a.id===r.trim());if(c!==-1)return c;console.log(` ${Ne}Invalid choice. Enter a number 1-${e.length} or a model name.${m}`)}}function Ie(t,e){let n=t.findIndex(o=>o.id===e);return n>=0?n:void 0}function Ut(t,e,n,o){let s=T();U.default.mkdirSync(s,{recursive:!0});let r=Z.default.join(s,"config.yaml"),i=`# ghc-tunnel Configuration (generated by --setup)
127
127
  # ================================================
128
128
 
129
- address: ${n}
130
- port: ${o}
129
+ address: ${o}
130
+ port: ${n}
131
131
  debug: false
132
132
 
133
133
  account_type: individual
@@ -161,17 +161,17 @@ system_prompt_add: []
161
161
  tool_result_suffix_remove: []
162
162
 
163
163
  max_connection_retries: 3
164
- `;U.default.writeFileSync(r,i,"utf-8"),console.log(` ${z}\u2713${m} Config saved to ${Q}${r}${m}`)}function rt(t,e,o,n){let s=Z.default.join(process.env.HOME||"~",".claude"),r=Z.default.join(s,"settings.json"),i={};if(U.default.existsSync(r))try{i=JSON.parse(U.default.readFileSync(r,"utf-8"))}catch{console.log(` ${De}\u26A0${m} Could not parse existing settings.json, creating new one`)}let c=`http://${e}:${t}/`,a=i.env??{};a.ANTHROPIC_BASE_URL=c,a.ANTHROPIC_AUTH_TOKEN="dummy",a.ANTHROPIC_MODEL=o,a.ANTHROPIC_DEFAULT_HAIKU_MODEL=n,delete a.ANTHROPIC_SMALL_FAST_MODEL,i.env=a,U.default.mkdirSync(s,{recursive:!0}),U.default.writeFileSync(r,JSON.stringify(i,null,2)+`
165
- `,"utf-8"),console.log(` ${z}\u2713${m} Claude Code settings updated at ${Q}${r}${m}`),console.log(` ${x}ANTHROPIC_BASE_URL = ${c}${m}`),console.log(` ${x}ANTHROPIC_MODEL = ${o}${m}`),console.log(` ${x}ANTHROPIC_DEFAULT_HAIKU_MODEL = ${n}${m}`)}async function it(){console.log(`
166
- ${B}\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557${m}
167
- ${B}\u2551${m} ${H}Claude Code Settings${m} ${B}\u2551${m}
168
- ${B}\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${m}
169
- `);let t=Z.default.join(process.env.HOME||"~",".claude"),e=Z.default.join(t,"settings.json"),o={},n={};if(U.default.existsSync(e))try{o=JSON.parse(U.default.readFileSync(e,"utf-8")),n=o.env??{}}catch{}(n.ANTHROPIC_BASE_URL||n.ANTHROPIC_MODEL||n.ANTHROPIC_DEFAULT_HAIKU_MODEL)&&(console.log(`${H}Current configuration:${m}`),n.ANTHROPIC_BASE_URL&&console.log(` ANTHROPIC_BASE_URL: ${Q}${n.ANTHROPIC_BASE_URL}${m}`),n.ANTHROPIC_MODEL&&console.log(` ANTHROPIC_MODEL: ${Q}${n.ANTHROPIC_MODEL}${m}`),n.ANTHROPIC_DEFAULT_HAIKU_MODEL&&console.log(` ANTHROPIC_DEFAULT_HAIKU_MODEL: ${Q}${n.ANTHROPIC_DEFAULT_HAIKU_MODEL}${m}`),console.log(`
170
- ${x}Press Enter to keep current values.${m}
171
- `));let r=8314,i="localhost",c=n.ANTHROPIC_MODEL||"claude-opus-4-6[1m]",a=n.ANTHROPIC_DEFAULT_HAIKU_MODEL||"claude-sonnet-4-6",u=r,p=i;if(n.ANTHROPIC_BASE_URL)try{let v=new URL(n.ANTHROPIC_BASE_URL);p=v.hostname,u=parseInt(v.port,10)||r}catch{}let l=ot(),f=await F(l,` Port ${x}[${u}]${m}: `),_=f.trim()?parseInt(f.trim(),10):u,d=(await F(l,` Host ${x}[${p}]${m}: `)).trim()||p,b=(await F(l,` ANTHROPIC_MODEL ${x}[${c}]${m}: `)).trim()||c,R=(await F(l,` ANTHROPIC_DEFAULT_HAIKU_MODEL ${x}[${a}]${m}: `)).trim()||a;l.close(),rt(_,d,b,R),console.log(`
172
- ${z}${H}Claude Code settings updated!${m}
173
- `)}var ct="1.0.0";function Ut(){let t=process.argv.slice(2),e={};for(let o=0;o<t.length;o++){let n=t[o];n==="-p"||n==="--port"?e.port=parseInt(t[++o],10):n==="-a"||n==="--address"?e.address=t[++o]:n==="-c"||n==="--config"?e.config=!0:n==="-s"||n==="--setup"?e.setup=!0:n==="--claudecode"?e.claudecode=!0:n==="-v"||n==="--version"?e.version=!0:(n==="-h"||n==="--help")&&(e.help=!0)}return e}function at(t,e){let o=(0,he.default)();o.use(he.default.json({limit:"50mb"})),o.use(he.default.text({limit:"50mb"})),o.use(fe),o.use(Y),o.use(E),o.use((n,s)=>s.status(404).json({error:"Not found"})),o.listen(e,t,()=>{console.log(`
174
- Starting GitHub Copilot API Proxy on ${t}:${e}`),console.log(`Dashboard: http://${t}:${e}/`),console.log(`OpenAI API: http://${t}:${e}/v1/chat/completions`),console.log(`Responses API: http://${t}:${e}/v1/responses`),console.log(`Anthropic API: http://${t}:${e}/v1/messages`)})}function ut(t,e){let o=P(),n=pt.default.join(o,"config.yaml");lt.default.existsSync(n)||(console.log(`No config file found at ${n}, generating one.`),we());try{let s=Me(n);t=s.address??t,e=s.port??e,s.account_type&&(g.accountType=s.account_type),s.vscode_version&&(g.vscodeVersion=s.vscode_version),s.api_version&&(g.apiVersion=s.api_version),s.copilot_version&&(g.copilotVersion=s.copilot_version),s.system_prompt_remove&&(g.systemPromptRemove=s.system_prompt_remove),s.system_prompt_add&&(g.systemPromptAdd=s.system_prompt_add),s.tool_result_suffix_remove&&(g.toolResultSuffixRemove=s.tool_result_suffix_remove),s.max_connection_retries!=null&&(g.maxConnectionRetries=s.max_connection_retries),s.model_mappings?M.loadFromConfig(s):M.loadFromConfig({model_mappings:Re}),console.log(`Loaded configuration from: ${n}`)}catch(s){console.log(`Error loading config: ${s}`),M.loadFromConfig({model_mappings:Re})}return{host:t,port:e}}async function Ft(){let t=Ut();if(t.help&&(console.log(`ghc-tunnel v${ct} \u2013 GitHub Copilot API Proxy
164
+ `;U.default.writeFileSync(r,i,"utf-8"),console.log(` ${B}\u2713${m} Config saved to ${Q}${r}${m}`)}function at(t,e,n,o){let s=Z.default.join(process.env.HOME||"~",".claude"),r=Z.default.join(s,"settings.json"),i={};if(U.default.existsSync(r))try{i=JSON.parse(U.default.readFileSync(r,"utf-8"))}catch{console.log(` ${Ne}\u26A0${m} Could not parse existing settings.json, creating new one`)}let c=`http://${e}:${t}/`,a=i.env??{};a.ANTHROPIC_BASE_URL=c,a.ANTHROPIC_AUTH_TOKEN="dummy",a.ANTHROPIC_MODEL=n,a.ANTHROPIC_DEFAULT_HAIKU_MODEL=o,a.DISABLE_NON_ESSENTIAL_MODEL_CALLS="1",a.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1",delete a.ANTHROPIC_SMALL_FAST_MODEL,i.env=a,U.default.mkdirSync(s,{recursive:!0}),U.default.writeFileSync(r,JSON.stringify(i,null,2)+`
165
+ `,"utf-8"),console.log(` ${B}\u2713${m} Claude Code settings updated at ${Q}${r}${m}`),console.log(` ${v}ANTHROPIC_BASE_URL = ${c}${m}`),console.log(` ${v}ANTHROPIC_MODEL = ${n}${m}`),console.log(` ${v}ANTHROPIC_DEFAULT_HAIKU_MODEL = ${o}${m}`)}async function ut(){console.log(`
166
+ ${z}\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557${m}
167
+ ${z}\u2551${m} ${L}Claude Code Settings${m} ${z}\u2551${m}
168
+ ${z}\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D${m}
169
+ `);let t=Z.default.join(process.env.HOME||"~",".claude"),e=Z.default.join(t,"settings.json"),n={},o={};if(U.default.existsSync(e))try{n=JSON.parse(U.default.readFileSync(e,"utf-8")),o=n.env??{}}catch{}(o.ANTHROPIC_BASE_URL||o.ANTHROPIC_MODEL||o.ANTHROPIC_DEFAULT_HAIKU_MODEL)&&(console.log(`${L}Current configuration:${m}`),o.ANTHROPIC_BASE_URL&&console.log(` ANTHROPIC_BASE_URL: ${Q}${o.ANTHROPIC_BASE_URL}${m}`),o.ANTHROPIC_MODEL&&console.log(` ANTHROPIC_MODEL: ${Q}${o.ANTHROPIC_MODEL}${m}`),o.ANTHROPIC_DEFAULT_HAIKU_MODEL&&console.log(` ANTHROPIC_DEFAULT_HAIKU_MODEL: ${Q}${o.ANTHROPIC_DEFAULT_HAIKU_MODEL}${m}`),console.log(`
170
+ ${v}Press Enter to keep current values.${m}
171
+ `));let r=8314,i="localhost",c=o.ANTHROPIC_MODEL||"claude-opus-4-6[1m]",a=o.ANTHROPIC_DEFAULT_HAIKU_MODEL||"claude-sonnet-4-6",u=r,p=i;if(o.ANTHROPIC_BASE_URL)try{let S=new URL(o.ANTHROPIC_BASE_URL);p=S.hostname,u=parseInt(S.port,10)||r}catch{}let l=it(),f=await F(l,` Port ${v}[${u}]${m}: `),_=f.trim()?parseInt(f.trim(),10):u,d=(await F(l,` Host ${v}[${p}]${m}: `)).trim()||p,b=(await F(l,` ANTHROPIC_MODEL ${v}[${c}]${m}: `)).trim()||c,R=(await F(l,` ANTHROPIC_DEFAULT_HAIKU_MODEL ${v}[${a}]${m}: `)).trim()||a;l.close(),at(_,d,b,R),console.log(`
172
+ ${B}${L}Claude Code settings updated!${m}
173
+ `)}var lt="1.0.2";function Ft(){let t=process.argv.slice(2),e={};for(let n=0;n<t.length;n++){let o=t[n];o==="-p"||o==="--port"?e.port=parseInt(t[++n],10):o==="-a"||o==="--address"?e.address=t[++n]:o==="-c"||o==="--config"?e.config=!0:o==="-s"||o==="--setup"?e.setup=!0:o==="--claudecode"?e.claudecode=!0:o==="-v"||o==="--version"?e.version=!0:(o==="-h"||o==="--help")&&(e.help=!0)}return e}function pt(t,e){let n=(0,ye.default)();n.use(ye.default.json({limit:"50mb"})),n.use(ye.default.text({limit:"50mb"})),n.use(he),n.use(Y),n.use(P),n.use((o,s)=>s.status(404).json({error:"Not found"})),n.listen(e,t,()=>{console.log(`
174
+ Starting GitHub Copilot API Proxy on ${t}:${e}`),console.log(`Dashboard: http://${t}:${e}/`),console.log(`OpenAI API: http://${t}:${e}/v1/chat/completions`),console.log(`Responses API: http://${t}:${e}/v1/responses`),console.log(`Anthropic API: http://${t}:${e}/v1/messages`)})}function dt(t,e){let n=T(),o=ke.default.join(n,"config.yaml");ae.default.existsSync(o)||(console.log(`No config file found at ${o}, generating one.`),ve());try{let s=Fe(o);t=s.address??t,e=s.port??e,s.account_type&&(g.accountType=s.account_type),s.vscode_version&&(g.vscodeVersion=s.vscode_version),s.api_version&&(g.apiVersion=s.api_version),s.copilot_version&&(g.copilotVersion=s.copilot_version),s.system_prompt_remove&&(g.systemPromptRemove=s.system_prompt_remove),s.system_prompt_add&&(g.systemPromptAdd=s.system_prompt_add),s.tool_result_suffix_remove&&(g.toolResultSuffixRemove=s.tool_result_suffix_remove),s.max_connection_retries!=null&&(g.maxConnectionRetries=s.max_connection_retries),s.model_mappings?M.loadFromConfig(s):M.loadFromConfig({model_mappings:we}),console.log(`Loaded configuration from: ${o}`)}catch(s){console.log(`Error loading config: ${s}`),M.loadFromConfig({model_mappings:we})}return{host:t,port:e}}function Bt(){let t=T(),e=ke.default.join(t,"config.yaml");if(!ae.default.existsSync(e))return!0;let n=ke.default.join(process.env.HOME||"~",".claude","settings.json");if(!ae.default.existsSync(n))return!0;try{let s=JSON.parse(ae.default.readFileSync(n,"utf-8"))?.env;if(!s?.ANTHROPIC_BASE_URL||!s.ANTHROPIC_BASE_URL.includes("localhost"))return!0}catch{return!0}return!1}async function zt(){let t=Ft();if(t.help&&(console.log(`ghc-tunnel v${lt} \u2013 GitHub Copilot API Proxy
175
175
 
176
176
  Usage: ghc-tunnel [options]
177
177
 
@@ -182,5 +182,6 @@ Options:
182
182
  -a, --address <addr> Address to listen on (default: localhost)
183
183
  -c, --config Generate default config file
184
184
  -v, --version Show version
185
- -h, --help Show this help`),process.exit(0)),t.version&&(console.log(`ghc-tunnel ${ct}`),process.exit(0)),t.config&&(we(),process.exit(0)),t.setup&&t.claudecode&&(await it(),process.exit(0)),t.setup){let{port:s,host:r}=await st(),{host:i,port:c}=ut(r,s);Ce(),Ae(),at(i,c);return}let{host:e,port:o}=ut(He,je);t.address!=null&&(e=t.address),t.port!=null&&(o=t.port);let n=await ae();n||(console.error(`
186
- `+"=".repeat(60)),console.error("ERROR: No GitHub token available!"),console.error("Options:"),console.error(" 1. Set GITHUB_TOKEN environment variable"),console.error(" 2. Create github_token.txt in "+P()),console.error(" 3. Run again for interactive Device Flow auth"),console.error("=".repeat(60)),process.exit(1)),g.githubToken=n,await ie(),await W(),Ce(),Ae(),at(e,o)}Ft().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
185
+ -h, --help Show this help`),process.exit(0)),t.version&&(console.log(`ghc-tunnel ${lt}`),process.exit(0)),t.config&&(ve(),process.exit(0)),t.setup&&t.claudecode&&(await ut(),process.exit(0)),t.setup||Bt()){t.setup||console.log(`First run detected \u2014 launching setup wizard.
186
+ `);let{port:r,host:i}=await ct(),{host:c,port:a}=dt(i,r);Te(),Oe(),pt(c,a);return}let{host:n,port:o}=dt(Me,He);t.address!=null&&(n=t.address),t.port!=null&&(o=t.port);let s=await le();s||(console.error(`
187
+ `+"=".repeat(60)),console.error("ERROR: No GitHub token available!"),console.error("Options:"),console.error(" 1. Set GITHUB_TOKEN environment variable"),console.error(" 2. Create github_token.txt in "+T()),console.error(" 3. Run again for interactive Device Flow auth"),console.error("=".repeat(60)),process.exit(1)),g.githubToken=s,await ie(),await W(),Te(),Oe(),pt(n,o)}zt().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ghc-tunnel",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "GitHub Copilot API Proxy - Provides OpenAI and Anthropic compatible endpoints via GitHub Copilot",
5
5
  "main": "dist/index.js",
6
6
  "bin": {