ghc-tunnel 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +53 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var
|
|
2
|
+
"use strict";var gt=Object.create;var Ie=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var ft=Object.getOwnPropertyNames;var _t=Object.getPrototypeOf,ht=Object.prototype.hasOwnProperty;var yt=(t,e,o,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ft(e))!ht.call(t,s)&&s!==o&&Ie(t,s,{get:()=>e[s],enumerable:!(n=mt(e,s))||n.enumerable});return t};var A=(t,e,o)=>(o=t!=null?gt(_t(t)):{},yt(e||!t||!t.__esModule?Ie(o,"default",{value:t,enumerable:!0}):o,t));var pt=A(require("fs")),dt=A(require("path")),he=A(require("express"));var te=A(require("fs")),ae=A(require("path")),ye=A(require("os")),Ne=A(require("js-yaml")),Le=parseInt(process.env.PORT||"8314",10),je=process.env.HOST||"localhost",He="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 E(){return process.platform==="win32"?ae.default.join(process.env.APPDATA||ye.default.homedir(),"ghc-tunnel"):ae.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=E();te.default.mkdirSync(t,{recursive:!0});let e=ae.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
|
|
3
3
|
# ========================================
|
|
4
4
|
|
|
5
5
|
# Server Settings
|
|
@@ -49,20 +49,20 @@ 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
|
|
52
|
+
`;te.default.writeFileSync(e,o,"utf-8"),console.log(`Configuration file generated at: ${e}`)}var Se=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 Se;var re=A(require("fs")),Ue=require("child_process"),Fe=A(require("path"));function Be(){let t=E();return re.default.mkdirSync(t,{recursive:!0}),Fe.default.join(t,"github_token.txt")}function kt(){let t=Be();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=Be();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,Ue.exec)(`${e} ${t}`,()=>{})}function wt(t){return new Promise(e=>setTimeout(e,t))}async function St(){console.log(`
|
|
53
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
54
|
Please visit: ${s}`),console.log(`And enter the code: ${n}`),console.log(`
|
|
55
|
-
Waiting for authorization (expires in ${r} seconds)...`),
|
|
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: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(`
|
|
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
|
|
62
|
-
No GitHub token found. Starting GitHub Device Flow authentication...`);let o=await
|
|
63
|
-
`,"utf-8")}function
|
|
64
|
-
`,"utf-8")}catch{}}function
|
|
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
|
|
61
|
+
Authorization timed out. Please try again.`),null}async function ue(){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 o=await St();return o?(Rt(o),o):null}function D(){return g.accountType==="individual"?"https://api.githubcopilot.com":`https://api.${g.accountType}.githubcopilot.com`}function xt(){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(`${He}/copilot_internal/v2/token`,{headers:xt()});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 ze(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 L(t){return Math.ceil(t.length/4)}var J=A(require("fs")),le=A(require("path"));function K(t,e,o,n){let s=E();J.default.mkdirSync(s,{recursive:!0});let r=le.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 pe(t,e,o,n,s){try{let r=E();J.default.mkdirSync(r,{recursive:!0});let i=le.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 de(t){try{let e=E();J.default.mkdirSync(e,{recursive:!0});let o=le.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 ve(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 $e(t,e){return t===400&&e.includes("tool_use_id")&&e.includes("tool_result")}function Ae(){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
67
|
Exact Mappings:`);for(let[o,n]of t)console.log(` ${o} -> ${n}`)}else console.log(`
|
|
68
68
|
Exact Mappings: (none)`);let e=Object.entries(M.prefixMappings);if(e.length){console.log(`
|
|
@@ -71,59 +71,59 @@ Prefix Mappings: (none)`);console.log("=".repeat(60)+`
|
|
|
71
71
|
`)}function Ce(){if(!g.models?.data?.length){console.log("No models available yet.");return}console.log(`
|
|
72
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(`
|
|
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
|
|
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 ge(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:ge(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:ge(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=
|
|
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=vt(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
|
|
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 vt(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(`
|
|
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
|
|
81
|
-
`);h
|
|
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 Ee(t){return t?$t[t]??null:null}function Pe(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:Ee(o),stop_sequence:null,usage:{input_tokens:r,output_tokens:n.completion_tokens??0,...s?{cache_read_input_tokens:s}:{}}}}var me=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:Ee(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 fe(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 At(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 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/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:S}=await w.read();if(R)break;if(f){w.cancel();break}h+=b.decode(S,{stream:!0});let v=h.split(`
|
|
81
|
+
`);h=v.pop();for(let $ of v)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=
|
|
86
|
-
`);R
|
|
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=fe(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=Ot(n.input),a=V(c),u=JSON.stringify(n).length;if(n.stream)return Ct(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 Ct(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:S,value:v}=await b.read();if(S)break;if(_){b.cancel();break}R+=h.decode(v,{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
|
|
89
|
+
`);continue}try{let I=JSON.parse(O);if(I.type==="response.completed"){let T=I.response??{};l=T;let H=T.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
|
|
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 Ot(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(pe(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 _e=(0,Xe.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=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))Tt.has(o)&&(e[o]=n);return Et(e),e}function qt(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 Dt(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=ge(e);for(let n of g.systemPromptAdd)o.includes(n)||(o+=`
|
|
94
94
|
|
|
95
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
|
|
97
|
-
`)
|
|
98
|
-
data: ${
|
|
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 It(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}_e.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+=L(i);else if(Array.isArray(i))for(let c of i)c.type==="text"&&(r+=L(c.text??""));for(let c of o.messages??[]){let a=c.content;if(typeof a=="string")r+=L(a);else if(Array.isArray(a))for(let u of a)u.type==="text"?r+=L(u.text??""):u.type==="tool_result"&&typeof u.content=="string"?r+=L(u.content):u.type==="tool_use"&&(r+=L(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+=L(c.name??""),r+=L(c.description??""),r+=L(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})}});_e.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=Dt(n),n=It(n),ze(c)?(console.log(`[Anthropic API] Using direct Anthropic API path for: ${c}`),Nt(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 Nt(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=qt(k),k.stream)return Lt(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&&de({...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),$e(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:ve(l.messages,h)};continue}}return f&&de({...f,modified_request:l,final_status_code:d.status,final_response:b}),void t.status(d.status).type("json").send(b)}}async function Lt(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(),S=new TextDecoder,v="",$="";for(;;){let{done:C,value:O}=await R.read();if(C)break;if(d){R.cancel();break}v+=S.decode(O,{stream:!0});let I=v.split(`
|
|
97
|
+
`);v=I.pop();for(let T of I){if(!T.trim())continue;if(T.startsWith("event: ")){$=T.slice(7);continue}if(!T.startsWith("data: "))continue;let H=T.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=
|
|
101
|
-
`)
|
|
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=Pe(h),S=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: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),$e(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:ve(u.messages,h)};continue}}return p&&de({...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 me,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 S=R.body.getReader(),v=new TextDecoder,$="";for(;;){let{done:C,value:O}=await S.read();if(C)break;if(d){S.cancel();break}$+=v.decode(O,{stream:!0});let I=$.split(`
|
|
101
|
+
`);$=I.pop();for(let T of I){if(!T.trim()||!T.startsWith("data: "))continue;let H=T.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=Ge(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=
|
|
105
|
-
`);e.end()});
|
|
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")),
|
|
107
|
-
${
|
|
108
|
-
${
|
|
109
|
-
${
|
|
110
|
-
`)}function
|
|
111
|
-
`);let t=await
|
|
112
|
-
${
|
|
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=fe(l),h=Object.keys(b).length?Pe(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,S)=>R+JSON.stringify(S).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;pe(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"),ce=A(require("path")),et=A(require("fs"));var P=(0,Ze.Router)();function tt(){let t=ce.default.join(__dirname,"..","public");return et.default.existsSync(t)?t:ce.default.join(__dirname,"..","..","public")}P.get("/",(t,e)=>{e.sendFile(ce.default.join(tt(),"dashboard.html"))});P.get("/requests",(t,e)=>{e.sendFile(ce.default.join(tt(),"requests.html"))});P.get("/api/stats",(t,e)=>{e.json(y.getStats())});P.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)})});P.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)});P.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)});P.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)});P.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})});P.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()});P.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")),ot=A(require("readline"));var j="\x1B[1m",x="\x1B[2m",m="\x1B[0m",Q="\x1B[36m",B="\x1B[32m",De="\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} ${j}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 st(){return ot.default.createInterface({input:process.stdin,output:process.stdout})}function F(t,e){return new Promise(o=>t.question(e,o))}async function rt(){Mt(),console.log(`${j}Step 1: GitHub Authentication${m}`),console.log(`${x}Checking for GitHub token...${m}
|
|
111
|
+
`);let t=await ue();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
|
+
${j}Step 2: Configure Models${m}
|
|
113
113
|
`),console.log(`${x}Available Copilot models:${m}
|
|
114
|
-
`);for(let R=0;R<e.length;R++){let
|
|
114
|
+
`);for(let R=0;R<e.length;R++){let S=e[R],v=[];S.capabilities?.supports?.vision&&v.push("Vision"),S.capabilities?.supports?.tool_calls&&v.push("Tools"),S.supported_endpoints?.includes("/v1/messages")&&v.push("Anthropic"),S.preview&&v.push("Preview");let $=v.length?` ${x}(${v.join(", ")})${m}`:"";console.log(` ${Q}${String(R+1).padStart(2)}.${m} ${S.id}${$}`)}let o=st();console.log(`
|
|
115
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
|
|
117
|
-
${
|
|
118
|
-
`),console.log(`${
|
|
116
|
+
`);let n=qe(e,"claude-opus-4.6-1m")??qe(e,"claude-opus-4.6")??0,s=await nt(o,e,'Primary model (mapped to "opus", "sonnet" aliases)',n),r=e[s],i=qe(e,"claude-haiku-4.5")??0,c=await nt(o,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(`${j}Step 3: Server Settings${m}
|
|
119
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
|
-
${
|
|
120
|
+
${j}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
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
|
-
${
|
|
123
|
-
`),o.close(),console.log(`${
|
|
124
|
-
`),
|
|
125
|
-
${
|
|
126
|
-
`),{port:p,host:f}}async function
|
|
122
|
+
${B}ANTHROPIC_MODEL: ${w}${m}`),console.log(`${B}ANTHROPIC_DEFAULT_HAIKU_MODEL: ${h}${m}
|
|
123
|
+
`),o.close(),console.log(`${j}Step 5: Saving Configuration${m}
|
|
124
|
+
`),Ut(r.id,a.id,p,f),it(p,f,w,h),console.log(`
|
|
125
|
+
${B}${j}Setup complete!${m}
|
|
126
|
+
`),{port:p,host:f}}async function nt(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 Ut(t,e,o,n){let s=E();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
129
|
address: ${n}
|
|
@@ -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(` ${
|
|
165
|
-
`,"utf-8"),console.log(` ${
|
|
166
|
-
${
|
|
167
|
-
${
|
|
168
|
-
${
|
|
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(`${
|
|
164
|
+
`;U.default.writeFileSync(r,i,"utf-8"),console.log(` ${B}\u2713${m} Config saved to ${Q}${r}${m}`)}function it(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,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(` ${x}ANTHROPIC_BASE_URL = ${c}${m}`),console.log(` ${x}ANTHROPIC_MODEL = ${o}${m}`),console.log(` ${x}ANTHROPIC_DEFAULT_HAIKU_MODEL = ${n}${m}`)}async function ct(){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} ${j}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"),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(`${j}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
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
|
|
172
|
-
${
|
|
173
|
-
`)}var
|
|
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
|
|
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 S=new URL(n.ANTHROPIC_BASE_URL);p=S.hostname,u=parseInt(S.port,10)||r}catch{}let l=st(),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(),it(_,d,b,R),console.log(`
|
|
172
|
+
${B}${j}Claude Code settings updated!${m}
|
|
173
|
+
`)}var at="1.0.0";function Ft(){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 ut(t,e){let o=(0,he.default)();o.use(he.default.json({limit:"50mb"})),o.use(he.default.text({limit:"50mb"})),o.use(_e),o.use(Y),o.use(P),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 lt(t,e){let o=E(),n=dt.default.join(o,"config.yaml");pt.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 Bt(){let t=Ft();if(t.help&&(console.log(`ghc-tunnel v${at} \u2013 GitHub Copilot API Proxy
|
|
175
175
|
|
|
176
176
|
Usage: ghc-tunnel [options]
|
|
177
177
|
|
|
@@ -182,5 +182,5 @@ 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 ${
|
|
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 "+
|
|
185
|
+
-h, --help Show this help`),process.exit(0)),t.version&&(console.log(`ghc-tunnel ${at}`),process.exit(0)),t.config&&(we(),process.exit(0)),t.setup&&t.claudecode&&(await ct(),process.exit(0)),t.setup){let{port:s,host:r}=await rt(),{host:i,port:c}=lt(r,s);Ce(),Ae(),ut(i,c);return}let{host:e,port:o}=lt(je,Le);t.address!=null&&(e=t.address),t.port!=null&&(o=t.port);let n=await ue();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 "+E()),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(),ut(e,o)}Bt().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
|