@thxp/llms 3.2.13 → 3.2.14
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/cjs/server.cjs +1 -1
- package/dist/cjs/server.cjs.map +1 -1
- package/dist/esm/server.mjs +1 -1
- package/dist/esm/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/esm/server.mjs
CHANGED
|
@@ -69,7 +69,7 @@ https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys`};var $l
|
|
|
69
69
|
${this.toMarkdown(s,r+1)}`:`${n}- ${s}`).join(`
|
|
70
70
|
`):typeof e=="object"&&e!==null?Object.entries(e).map(([s,i])=>typeof i=="object"&&i!==null?`${n}${s}:
|
|
71
71
|
${this.toMarkdown(i,r+1)}`:`${n}${s}: ${i}`).join(`
|
|
72
|
-
`):`${n}${e}`}async output(e,r={}){try{let n=this.formatData(e,r);switch(this.config.level||"log"){case"info":console.info(n);break;case"warn":console.warn(n);break;case"error":console.error(n);break;case"debug":console.debug(n);break;case"log":default:console.log(n);break}return!0}catch(n){return console.error("[ConsoleOutputHandler] Output failed:",n),!1}}}});var so,_d=je(()=>{"use strict";so=class{type="webhook";config;defaultTimeout=3e4;constructor(e){if(!e.url)throw new Error("Webhook URL is required");this.config={method:"POST",retry:{maxAttempts:3,backoffMs:1e3},silent:!1,...e}}buildHeaders(){let e={"Content-Type":"application/json",...this.config.headers||{}};if(this.config.auth)switch(this.config.auth.type){case"bearer":this.config.auth.token&&(e.Authorization=`Bearer ${this.config.auth.token}`);break;case"basic":if(this.config.auth.username&&this.config.auth.password){let r=Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString("base64");e.Authorization=`Basic ${r}`}break;case"custom":this.config.auth.custom&&(e[this.config.auth.custom.header]=this.config.auth.custom.value);break}return e}buildBody(e,r){let{format:n="json",timestamp:s=!0,prefix:i,metadata:u}=r||{},c={data:e};return s&&(c.timestamp=new Date().toISOString()),i&&(c.prefix=i),u&&Object.keys(u).length>0&&(c.metadata=u),c}async sendRequest(e,r,n,s,i){let u=new AbortController,c=setTimeout(()=>u.abort(),i);try{let l=await fetch(e,{method:r,headers:n,body:JSON.stringify(s),signal:u.signal});if(clearTimeout(c),!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);return l}catch(l){throw clearTimeout(c),l}}delay(e){return new Promise(r=>setTimeout(r,e))}async sendWithRetry(e,r,n,s,i,u){let c=null;for(let l=1;l<=u.maxAttempts;l++)try{return await this.sendRequest(e,r,n,s,i)}catch(d){if(c=d,l===u.maxAttempts)break;let h=u.backoffMs*Math.pow(2,l-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${l}/${u.maxAttempts}), retrying in ${h}ms...`,d.message),await this.delay(h)}throw c}async output(e,r={}){let n=r.timeout||this.defaultTimeout;try{let s=this.buildHeaders(),i=this.buildBody(e,r),u=await this.sendWithRetry(this.config.url,this.config.method,s,i,n,this.config.retry);return!0}catch(s){let i=s instanceof Error?s.message:String(s);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${i}`),!1;throw new Error(`Webhook output failed: ${i}`)}}}});import{writeFileSync as _T,existsSync as bT,mkdirSync as CT}from"fs";import{join as My}from"path";import{tmpdir as wT}from"os";var oo,bd=je(()=>{"use strict";oo=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let r=wT();this.baseDir=My(r,this.config.subdirectory),this.ensureDir()}ensureDir(){try{bT(this.baseDir)||CT(this.baseDir,{recursive:!0})}catch{}}extractSessionId(e){try{let r=e.match(/_session_([a-f0-9-]+)/i);return r?r[1]:null}catch{return null}}getFilePath(e){let r=this.config.prefix||"session",n=this.config.extension?`.${this.config.extension}`:"",s;if(this.config.includeTimestamp){let i=Date.now();s=`${r}-${e}-${i}${n}`}else s=`${r}-${e}${n}`;return My(this.baseDir,s)}async output(e,r={}){try{let n=r.metadata?.sessionId;if(!n)return!1;let s={...e,timestamp:Date.now(),sessionId:n},i=this.getFilePath(n);return _T(i,JSON.stringify(s,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var Cd,cs,Ly=je(()=>{"use strict";yd();_d();bd();Cd=class{handlers=new Map;defaultOptions={};registerHandler(e,r){this.handlers.set(e,r)}registerHandlers(e){for(let r of e)if(r.enabled!==!1)try{let n=this.createHandler(r),s=r.type+"_"+Date.now();this.registerHandler(s,n)}catch(n){console.error(`[OutputManager] Failed to register ${r.type} handler:`,n)}}createHandler(e){switch(e.type){case"console":return new no(e.config);case"webhook":return new so(e.config);case"temp-file":return new oo(e.config);default:throw new Error(`Unknown output handler type: ${e.type}`)}}unregisterHandler(e){return this.handlers.delete(e)}getHandler(e){return this.handlers.get(e)}getAllHandlers(){return new Map(this.handlers)}clearHandlers(){this.handlers.clear()}setDefaultOptions(e){this.defaultOptions={...this.defaultOptions,...e}}getDefaultOptions(){return{...this.defaultOptions}}async output(e,r){let n={...this.defaultOptions,...r},s={success:[],failed:[]},i=Array.from(this.handlers.entries()).map(async([u,c])=>{try{await c.output(e,n)?s.success.push(u):s.failed.push(u)}catch(l){console.error(`[OutputManager] Handler ${u} failed:`,l),s.failed.push(u)}});return await Promise.all(i),s}async outputTo(e,r,n){let s={...this.defaultOptions,...n},i={success:[],failed:[]},u=e.map(async c=>{let l=this.handlers.get(c);if(!l){console.warn(`[OutputManager] Handler ${c} not found`),i.failed.push(c);return}try{await l.output(r,s)?i.success.push(c):i.failed.push(c)}catch(d){console.error(`[OutputManager] Handler ${c} failed:`,d),i.failed.push(c)}});return await Promise.all(u),i}async outputToType(e,r,n){let s=Array.from(this.handlers.entries()).filter(([i,u])=>u.type===e).map(([i])=>i);return this.outputTo(s,r,n)}},cs=new Cd});import ET from"fastify";import AT from"@fastify/cors";var Lf=Fr(Su(),1);import{readFileSync as M_,existsSync as jf}from"fs";import{join as Mf}from"path";import{config as L_}from"dotenv";var Dn=class{config={};options;constructor(e={jsonPath:"./config.json"}){this.options={envPath:e.envPath||".env",jsonPath:e.jsonPath,useEnvFile:!1,useJsonFile:e.useJsonFile!==!1,useEnvironmentVariables:e.useEnvironmentVariables!==!1,...e},this.loadConfig()}loadConfig(){this.options.useJsonFile&&this.options.jsonPath&&this.loadJsonConfig(),this.options.initialConfig&&(this.config={...this.config,...this.options.initialConfig}),this.options.useEnvFile&&this.loadEnvConfig(),this.config.LOG_FILE&&(process.env.LOG_FILE=this.config.LOG_FILE),this.config.LOG&&(process.env.LOG=this.config.LOG)}loadJsonConfig(){if(!this.options.jsonPath)return;let e=this.isAbsolutePath(this.options.jsonPath)?this.options.jsonPath:Mf(process.cwd(),this.options.jsonPath);if(jf(e))try{let r=M_(e,"utf-8"),n=Lf.default.parse(r);this.config={...this.config,...n},console.log(`Loaded JSON config from: ${e}`)}catch(r){console.warn(`Failed to load JSON config from ${e}:`,r)}else console.warn(`JSON config file not found: ${e}`)}loadEnvConfig(){let e=this.isAbsolutePath(this.options.envPath)?this.options.envPath:Mf(process.cwd(),this.options.envPath);if(jf(e))try{let r=L_({path:e});r.parsed&&(this.config={...this.config,...this.parseEnvConfig(r.parsed)})}catch(r){console.warn(`Failed to load .env config from ${e}:`,r)}}loadEnvironmentVariables(){let e=this.parseEnvConfig(process.env);this.config={...this.config,...e}}parseEnvConfig(e){let r={};return Object.assign(r,e),r}isAbsolutePath(e){return e.startsWith("/")||e.includes(":")}get(e,r){let n=this.config[e];return n!==void 0?n:r}getAll(){return{...this.config}}getHttpsProxy(){return this.get("HTTPS_PROXY")||this.get("https_proxy")||this.get("httpsProxy")||this.get("PROXY_URL")||process.env.HTTPS_PROXY||process.env.https_proxy||process.env.HTTP_PROXY||process.env.http_proxy}has(e){return this.config[e]!==void 0}set(e,r){this.config[e]=r}reload(){this.config={},this.loadConfig()}getConfigSummary(){let e=[];return this.options.initialConfig&&e.push("Initial Config"),this.options.useJsonFile&&this.options.jsonPath&&e.push(`JSON: ${this.options.jsonPath}`),this.options.useEnvFile&&e.push(`ENV: ${this.options.envPath}`),this.options.useEnvironmentVariables&&e.push("Environment Variables"),`Config sources: ${e.join(", ")}`}};function Xe(t,e=500,r="internal_error",n="api_error"){let s=new Error(t);return s.statusCode=e,s.code=r,s.type=n,s}async function Uf(t,e,r){e.log.error(t);let n=t.statusCode||500,s={error:{message:t.message+t.stack||"Internal Server Error",type:t.type||"api_error",code:t.code||"internal_error"}};return r.code(n).send(s)}import{ProxyAgent as U_}from"undici";function qf(t,e,r,n,s){let i=new Headers({"Content-Type":"application/json"});r.headers&&Object.entries(r.headers).forEach(([d,h])=>{h&&i.set(d,h)});let u,c=AbortSignal.timeout(r.TIMEOUT??60*1e3*60);if(r.signal){let d=new AbortController,h=()=>d.abort();r.signal.addEventListener("abort",h),c.addEventListener("abort",h),u=d.signal}else u=c;let l={method:"POST",headers:i,body:JSON.stringify(e),signal:u};return r.httpsProxy&&(l.dispatcher=new U_(new URL(r.httpsProxy).toString())),s?.debug({reqId:n.req.id,request:l,headers:Object.fromEntries(i.entries()),requestUrl:typeof t=="string"?t:t.toString(),useProxy:r.httpsProxy},"final request"),fetch(typeof t=="string"?t:t.toString(),l)}import{existsSync as q_,writeFileSync as $_,readFileSync as z_}from"fs";import{join as H_}from"path";import{HOME_DIR as W_}from"@thxp/shared";var ku=H_(W_,"daily_usage.json"),tn=null;function G_(){let t=new Date;return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`}function $f(){let t=G_();if(tn&&tn.date===t)return tn;try{if(q_(ku)){let e=JSON.parse(z_(ku,"utf-8"));if(e?.date===t)return tn=e,e}}catch{}return tn={date:t,models:{}},zf(tn),tn}function zf(t){try{$_(ku,JSON.stringify(t,null,2),"utf-8")}catch{}}function J_(t,e,r){let n=$f(),s=`${t.toLowerCase()},${e.toLowerCase()}`;n.models[s]=(n.models[s]||0)+r,zf(n)}function Cs(t,e){return $f().models[`${t.toLowerCase()},${e.toLowerCase()}`]||0}var Hf="3.2.12";var Uo=class{capacity;cache;constructor(e){this.capacity=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;let r=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,r),r}put(e,r){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.capacity){let n=this.cache.keys().next().value;n!==void 0&&this.cache.delete(n)}this.cache.set(e,r)}has(e){return this.cache.has(e)}del(e){return this.cache.delete(e)}clear(){this.cache.clear()}values(){return Array.from(this.cache.values())}},K_=new Uo(100),Y_=300*1e3,Du=new Uo(1e3),Wf=t=>{Du.put(t,Date.now())},Tn=t=>{let e=Du.get(t);return e===void 0?!1:Date.now()-e>Y_?(Du.del(t),!1):!0};var vn=(t,e)=>`${t},${e}`;async function X_(t,e,r,n){let s=t.body,i=t.provider,u=r.providerService.getProvider(i);if(!u)throw Xe(`Provider '${i}' not found`,404,"provider_not_found");let c=s,l=u,d=n,h=0,m=15;for(;h<m;)try{t.provider=l.name,t.scenarioType=t.scenarioType||"default";let w=c.model;if(l.model_limits?.[w]!==void 0&&Cs(l.name,w)>=l.model_limits[w])throw Xe(`Model '${w}' daily token limit exceeded`,429,"daily_limit_exceeded");let{requestBody:k,config:E,bypass:g}=await eb(c,l,d,t.headers,{req:t},r),y=await rb(k,E,l,r,g,d,{req:t}),p=await nb(k,y,l,d,g,{req:t});return await sb(p,e,c)}catch(w){h++,t.log.warn(`[Fallback] Error on attempt ${h}: ${w.message?.substring(0,100)}`);let k=w.message||w.error?.message||"",E=k.match(/(?:max_tokens|should be\s*<=\s*|a value\s*<=\s*)(\d{2,})/i)||k.match(/(?:<=|<)\s*(\d{4,})/);if(E&&w.statusCode===400){let y=parseInt(E[1],10);if(y>0&&y<(c.max_tokens||1/0)){t.log.warn(`[AutoFix] max_tokens ${c.max_tokens} -> ${y} for ${l.name},${c.model}`),c={...c,max_tokens:y},s.max_tokens=y;try{let p=Q("os").homedir()+"/.claude-code-router/config.json",D=Q("fs"),_=JSON.parse(D.readFileSync(p,"utf-8")),v=(_.Providers||_.providers)?.find(x=>x.name===l.name);if(v){v.transformer||(v.transformer={}),v.transformer[c.model]?v.transformer[c.model].use||(v.transformer[c.model].use=[]):v.transformer[c.model]={use:[]};let x=v.transformer[c.model].use,q=x.find(V=>Array.isArray(V)&&V[0]==="maxtoken");q?q[1].max_tokens=y:x.push(["maxtoken",{max_tokens:y}]),D.writeFileSync(p,JSON.stringify(_,null,2)),t.log.info(`[AutoFix] Config updated: ${l.name} ${c.model} max_tokens=${y}`)}}catch(p){t.log.error(`[AutoFix] Failed to update config.json: ${p.message}`)}continue}}let g=await Z_(t,r,w);if(g){t.log.warn(`[Fallback] Rotating to ${g.provider.name},${g.modelName}`),l=g.provider,d=g.transformerConfig||d,c={...s,model:g.modelName},s.model=g.modelName;continue}throw w}}function Q_(t){return t?Array.isArray(t)?t:typeof t=="string"?t?[t]:[]:[]:[]}async function Z_(t,e,r){let n=!r.statusCode&&(r.code||r.name==="TypeError"||r.name==="SyntaxError"||r.message?.includes("fetch")||r.message?.includes("connect")||r.message?.includes("timeout")||r.message?.includes("JSON"));if(!(r.code==="provider_response_error"||r.statusCode>=400&&r.statusCode<600||n))return null;let i=vn(t.provider,t.body.model);Wf(i);let u=t.scenarioType||"default",c=e.configService,l=e.providerService,d=e.transformerService,m=c.getAll().Router||{},w=Q_(m[u]||m.default);if(!Array.isArray(w)||w.length===0)return null;let k=w.filter(D=>!Tn(D));if(k.length===0)return null;let E=k[0],[g,y]=E.split(","),p=l.getProvider(g);return p?{provider:p,modelName:y,transformerConfig:null}:null}async function eb(t,e,r,n,s,i){let u=t,c={},l=!1;if(l=tb(e,r,t),l&&(n instanceof Headers?n.delete("content-length"):delete n["content-length"],c.headers=n),!l&&typeof r.transformRequestOut=="function"){let d=await r.transformRequestOut(u);d.body?(u=d.body,c=d.config||{}):u=d}if(!l&&e.transformer?.use?.length)for(let d of e.transformer.use){let h=d;if(typeof d=="string"&&i?.transformerService&&(h=i.transformerService.getTransformer(d)),!h||typeof h.transformRequestIn!="function")continue;let m=await h.transformRequestIn(u,e,s);m.body?(u=m.body,c={...c,...m.config}):u=m}if(!l&&e.transformer?.[t.model]?.use?.length)for(let d of e.transformer[t.model].use){let h=d;typeof d=="string"&&i?.transformerService&&(h=i.transformerService.getTransformer(d)),!(!h||typeof h.transformRequestIn!="function")&&(u=await h.transformRequestIn(u,e,s))}return{requestBody:u,config:c,bypass:l}}function tb(t,e,r){return t.transformer?.use?.length===1&&t.transformer.use[0].name===e.name&&(!t.transformer?.[r.model]?.use.length||t.transformer?.[r.model]?.use.length===1&&t.transformer?.[r.model]?.use[0].name===e.name)}async function rb(t,e,r,n,s,i,u){let c=e.url||new URL(r.baseUrl);if(s&&typeof i.auth=="function"){let h=await i.auth(t,r);if(h.body){t=h.body;let m=e.headers||{};h.config?.headers&&(m={...m,...h.config.headers},delete m.host,delete h.config.headers),e={...e,...h.config,headers:m}}else t=h}t.stream&&r.baseUrl?.includes("/chat/completions")&&(t.stream_options={include_usage:!0});let l={Authorization:`Bearer ${r.apiKey}`,...e?.headers||{}};for(let h in l)(l[h]==="undefined"||["authorization","Authorization"].includes(h)&&l[h]?.includes("undefined"))&&delete l[h];let d=await qf(c,t,{httpsProxy:n.configService.getHttpsProxy(),...e,headers:JSON.parse(JSON.stringify(l))},u,n.log);if(!d.ok){let h;try{h=await d.text()}catch{h="(failed to read error body)"}throw n.log.error(`[provider_response_error] Error from provider(${r.name},${t.model}: ${d.status}): ${h}`),Xe(`Error from provider(${r.name},${t.model}: ${d.status}): ${h}`,d.status,"provider_response_error")}return d}async function nb(t,e,r,n,s,i){let u=e;if(!s&&r.transformer?.use?.length)for(let c of Array.from(r.transformer.use).reverse())!c||typeof c.transformResponseOut!="function"||(u=await c.transformResponseOut(u,i));if(!s&&r.transformer?.[t.model]?.use?.length)for(let c of Array.from(r.transformer[t.model].use).reverse())!c||typeof c.transformResponseOut!="function"||(u=await c.transformResponseOut(u,i));return!s&&n.transformResponseIn&&(u=await n.transformResponseIn(u,i)),u}async function sb(t,e,r){if(t.ok||e.code(t.status),r.stream===!0)return e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),e.send(t.body);{let s=t.headers.get("Content-Encoding"),i;if(s==="gzip"){let{gunzipSync:u}=await import("zlib"),c=await t.arrayBuffer();i=u(Buffer.from(c)).toString("utf-8")}else i=await t.text();try{return JSON.parse(i)}catch(u){throw Xe(`Failed to parse JSON response from provider: ${u.message}. Raw response: ${i.substring(0,500)}`,t.status||500,"provider_response_error")}}}var Tu=async t=>{t.get("/",async()=>({message:"LLMs API",version:Hf})),t.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()}));let e=t.transformerService.getTransformersWithEndpoint();for(let{transformer:r}of e)r.endPoint&&t.post(r.endPoint,async(n,s)=>X_(n,s,t,r));t.post("/providers",{schema:{body:{type:"object",properties:{id:{type:"string"},name:{type:"string"},type:{type:"string",enum:["openai","anthropic"]},baseUrl:{type:"string"},apiKey:{type:"string"},models:{type:"array",items:{type:"string"}},model_limits:{type:"object"}},required:["id","name","type","baseUrl","apiKey","models"]}}},async(r,n)=>{let{name:s,baseUrl:i,apiKey:u,models:c}=r.body;if(!s?.trim())throw Xe("Provider name is required",400,"invalid_request");if(!i||!ob(i))throw Xe("Valid base URL is required",400,"invalid_request");if(!u?.trim())throw Xe("API key is required",400,"invalid_request");if(!c||!Array.isArray(c)||c.length===0)throw Xe("At least one model is required",400,"invalid_request");if(t.providerService.getProvider(r.body.name))throw Xe(`Provider with name '${r.body.name}' already exists`,400,"provider_exists");return t.providerService.registerProvider(r.body)}),t.get("/providers",async()=>t.providerService.getProviders()),t.get("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async r=>{let n=t.providerService.getProvider(r.params.id);if(!n)throw Xe("Provider not found",404,"provider_not_found");return n}),t.put("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]},body:{type:"object",properties:{name:{type:"string"},type:{type:"string",enum:["openai","anthropic"]},baseUrl:{type:"string"},apiKey:{type:"string"},models:{type:"array",items:{type:"string"}},model_limits:{type:"object"},enabled:{type:"boolean"}}}}},async(r,n)=>{let s=t.providerService.updateProvider(r.params.id,r.body);if(!s)throw Xe("Provider not found",404,"provider_not_found");return s}),t.delete("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async r=>{if(!t.providerService.deleteProvider(r.params.id))throw Xe("Provider not found",404,"provider_not_found");return{message:"Provider deleted successfully"}}),t.patch("/providers/:id/toggle",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]},body:{type:"object",properties:{enabled:{type:"boolean"}},required:["enabled"]}}},async(r,n)=>{if(!t.providerService.toggleProvider(r.params.id,r.body.enabled))throw Xe("Provider not found",404,"provider_not_found");return{message:`Provider ${r.body.enabled?"enabled":"disabled"} successfully`}})};function ob(t){try{return new URL(t),!0}catch{return!1}}var Rn=class{constructor(e,r,n){this.configService=e;this.transformerService=r;this.logger=n;this.initializeCustomProviders()}providers=new Map;modelRoutes=new Map;initializeCustomProviders(){let e=this.configService.get("providers");if(e&&Array.isArray(e)){this.initializeFromProvidersArray(e);return}}initializeFromProvidersArray(e){e.forEach(r=>{try{if(!r.name||!r.api_base_url||!r.api_key)return;let n={};r.transformer&&Object.keys(r.transformer).forEach(s=>{s==="use"?Array.isArray(r.transformer.use)&&(n.use=r.transformer.use.map(i=>{if(Array.isArray(i)&&typeof i[0]=="string"){let u=this.transformerService.getTransformer(i[0]);if(u)return new u(i[1])}if(typeof i=="string"){let u=this.transformerService.getTransformer(i);return typeof u=="function"?new u:u}}).filter(i=>typeof i<"u")):Array.isArray(r.transformer[s]?.use)&&(n[s]={use:r.transformer[s].use.map(i=>{if(Array.isArray(i)&&typeof i[0]=="string"){let u=this.transformerService.getTransformer(i[0]);if(u)return new u(i[1])}if(typeof i=="string"){let u=this.transformerService.getTransformer(i);return typeof u=="function"?new u:u}}).filter(i=>typeof i<"u")})}),this.registerProvider({name:r.name,baseUrl:r.api_base_url,apiKey:r.api_key,models:r.models||[],transformer:r.transformer?n:void 0,model_limits:r.model_limits}),this.logger.info(`${r.name} provider registered`)}catch(n){this.logger.error(`${r.name} provider registered error: ${n}`)}})}registerProvider(e){let r={...e};return this.providers.set(r.name,r),e.models.forEach(n=>{let s=`${r.name},${n}`,i={provider:r.name,model:n,fullModel:s};this.modelRoutes.set(s,i),this.modelRoutes.has(n)||this.modelRoutes.set(n,i)}),r}getProviders(){return Array.from(this.providers.values())}getProvider(e){return this.providers.get(e)}updateProvider(e,r){let n=this.providers.get(e);if(!n)return null;let s={...n,...r,updatedAt:new Date};return this.providers.set(e,s),r.models&&(n.models.forEach(i=>{let u=`${n.name},${i}`;this.modelRoutes.delete(u),this.modelRoutes.delete(i)}),r.models.forEach(i=>{let u=`${n.name},${i}`,c={provider:n.name,model:i,fullModel:u};this.modelRoutes.set(u,c),this.modelRoutes.has(i)||this.modelRoutes.set(i,c)})),s}deleteProvider(e){let r=this.providers.get(e);return r?(r.models.forEach(n=>{let s=`${r.name},${n}`;this.modelRoutes.delete(s),this.modelRoutes.delete(n)}),this.providers.delete(e),!0):!1}toggleProvider(e,r){return!!this.providers.get(e)}resolveModelRoute(e){let r=this.modelRoutes.get(e);if(!r)return null;let n=this.providers.get(r.provider);return n?{provider:n,originalModel:e,targetModel:r.model}:null}getAvailableModelNames(){let e=[];return this.providers.forEach(r=>{r.models.forEach(n=>{e.push(n),e.push(`${r.name},${n}`)})}),e}getModelRoutes(){return Array.from(this.modelRoutes.values())}parseTransformerConfig(e){return e?Array.isArray(e)?e.reduce((r,n)=>{if(Array.isArray(n)){let[s,i={}]=n;r[s]=i}else r[n]={};return r},{}):e:{}}async getAvailableModels(){let e=[];return this.providers.forEach(r=>{r.models.forEach(n=>{e.push({id:n,object:"model",owned_by:r.name,provider:r.name}),e.push({id:`${r.name},${n}`,object:"model",owned_by:r.name,provider:r.name})})}),{object:"list",data:e}}};var Je=[];for(let t=0;t<256;++t)Je.push((t+256).toString(16).slice(1));function Gf(t,e=0){return(Je[t[e+0]]+Je[t[e+1]]+Je[t[e+2]]+Je[t[e+3]]+"-"+Je[t[e+4]]+Je[t[e+5]]+"-"+Je[t[e+6]]+Je[t[e+7]]+"-"+Je[t[e+8]]+Je[t[e+9]]+"-"+Je[t[e+10]]+Je[t[e+11]]+Je[t[e+12]]+Je[t[e+13]]+Je[t[e+14]]+Je[t[e+15]]).toLowerCase()}import{randomFillSync as ib}from"crypto";var $o=new Uint8Array(256),qo=$o.length;function vu(){return qo>$o.length-16&&(ib($o),qo=0),$o.slice(qo,qo+=16)}import{randomUUID as ab}from"crypto";var Ru={randomUUID:ab};function ub(t,e,r){if(Ru.randomUUID&&!e&&!t)return Ru.randomUUID();t=t||{};let n=t.random??t.rng?.()??vu();if(n.length<16)throw new Error("Random bytes length must be >= 16");if(n[6]=n[6]&15|64,n[8]=n[8]&63|128,e){if(r=r||0,r<0||r+16>e.length)throw new RangeError(`UUID byte range ${r}:${r+15} is out of buffer bounds`);for(let s=0;s<16;++s)e[r+s]=n[s];return e}return Gf(n)}var Gt=ub;var Jf=t=>t<=0?"none":t<=1024?"low":t<=8192?"medium":"high";var Vf=(t,e)=>(t.includes("base64")&&(t=t.split("base64").pop(),t.startsWith(",")&&(t=t.slice(1))),`data:${e};base64,${t}`);var zo=class{constructor(e){this.options=e;this.useBearer=this.options?.UseBearer??!1}name="Anthropic";endPoint="/v1/messages";useBearer;logger;async auth(e,r){let n={};return this.useBearer?(n.authorization=`Bearer ${r.apiKey}`,n["x-api-key"]=void 0):(n["x-api-key"]=r.apiKey,n.authorization=void 0),{body:e,config:{headers:n}}}async transformRequestOut(e){let r=[];if(e.system){if(typeof e.system=="string")r.push({role:"system",content:e.system});else if(Array.isArray(e.system)&&e.system.length){let i=e.system.filter(u=>u.type==="text"&&u.text).map(u=>({type:"text",text:u.text,cache_control:u.cache_control}));r.push({role:"system",content:i})}}JSON.parse(JSON.stringify(e.messages||[]))?.forEach(i=>{if(i.role==="user"||i.role==="assistant"){if(typeof i.content=="string"){r.push({role:i.role,content:i.content});return}if(Array.isArray(i.content)){if(i.role==="user"){let u=i.content.filter(l=>l.type==="tool_result"&&l.tool_use_id);u.length&&u.forEach(l=>{let d={role:"tool",content:typeof l.content=="string"?l.content:JSON.stringify(l.content),tool_call_id:l.tool_use_id,cache_control:l.cache_control};r.push(d)});let c=i.content.filter(l=>l.type==="text"&&l.text||l.type==="image"&&l.source);c.length&&r.push({role:"user",content:c.map(l=>l?.type==="image"?{type:"image_url",image_url:{url:l.source?.type==="base64"?Vf(l.source.data,l.source.media_type):l.source.url},media_type:l.source.media_type}:l)})}else if(i.role==="assistant"){let u={role:"assistant",content:""},c=i.content.filter(h=>h.type==="text"&&h.text);c.length&&(u.content=c.map(h=>h.text).join(`
|
|
72
|
+
`):`${n}${e}`}async output(e,r={}){try{let n=this.formatData(e,r);switch(this.config.level||"log"){case"info":console.info(n);break;case"warn":console.warn(n);break;case"error":console.error(n);break;case"debug":console.debug(n);break;case"log":default:console.log(n);break}return!0}catch(n){return console.error("[ConsoleOutputHandler] Output failed:",n),!1}}}});var so,_d=je(()=>{"use strict";so=class{type="webhook";config;defaultTimeout=3e4;constructor(e){if(!e.url)throw new Error("Webhook URL is required");this.config={method:"POST",retry:{maxAttempts:3,backoffMs:1e3},silent:!1,...e}}buildHeaders(){let e={"Content-Type":"application/json",...this.config.headers||{}};if(this.config.auth)switch(this.config.auth.type){case"bearer":this.config.auth.token&&(e.Authorization=`Bearer ${this.config.auth.token}`);break;case"basic":if(this.config.auth.username&&this.config.auth.password){let r=Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString("base64");e.Authorization=`Basic ${r}`}break;case"custom":this.config.auth.custom&&(e[this.config.auth.custom.header]=this.config.auth.custom.value);break}return e}buildBody(e,r){let{format:n="json",timestamp:s=!0,prefix:i,metadata:u}=r||{},c={data:e};return s&&(c.timestamp=new Date().toISOString()),i&&(c.prefix=i),u&&Object.keys(u).length>0&&(c.metadata=u),c}async sendRequest(e,r,n,s,i){let u=new AbortController,c=setTimeout(()=>u.abort(),i);try{let l=await fetch(e,{method:r,headers:n,body:JSON.stringify(s),signal:u.signal});if(clearTimeout(c),!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);return l}catch(l){throw clearTimeout(c),l}}delay(e){return new Promise(r=>setTimeout(r,e))}async sendWithRetry(e,r,n,s,i,u){let c=null;for(let l=1;l<=u.maxAttempts;l++)try{return await this.sendRequest(e,r,n,s,i)}catch(d){if(c=d,l===u.maxAttempts)break;let h=u.backoffMs*Math.pow(2,l-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${l}/${u.maxAttempts}), retrying in ${h}ms...`,d.message),await this.delay(h)}throw c}async output(e,r={}){let n=r.timeout||this.defaultTimeout;try{let s=this.buildHeaders(),i=this.buildBody(e,r),u=await this.sendWithRetry(this.config.url,this.config.method,s,i,n,this.config.retry);return!0}catch(s){let i=s instanceof Error?s.message:String(s);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${i}`),!1;throw new Error(`Webhook output failed: ${i}`)}}}});import{writeFileSync as _T,existsSync as bT,mkdirSync as CT}from"fs";import{join as My}from"path";import{tmpdir as wT}from"os";var oo,bd=je(()=>{"use strict";oo=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let r=wT();this.baseDir=My(r,this.config.subdirectory),this.ensureDir()}ensureDir(){try{bT(this.baseDir)||CT(this.baseDir,{recursive:!0})}catch{}}extractSessionId(e){try{let r=e.match(/_session_([a-f0-9-]+)/i);return r?r[1]:null}catch{return null}}getFilePath(e){let r=this.config.prefix||"session",n=this.config.extension?`.${this.config.extension}`:"",s;if(this.config.includeTimestamp){let i=Date.now();s=`${r}-${e}-${i}${n}`}else s=`${r}-${e}${n}`;return My(this.baseDir,s)}async output(e,r={}){try{let n=r.metadata?.sessionId;if(!n)return!1;let s={...e,timestamp:Date.now(),sessionId:n},i=this.getFilePath(n);return _T(i,JSON.stringify(s,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var Cd,cs,Ly=je(()=>{"use strict";yd();_d();bd();Cd=class{handlers=new Map;defaultOptions={};registerHandler(e,r){this.handlers.set(e,r)}registerHandlers(e){for(let r of e)if(r.enabled!==!1)try{let n=this.createHandler(r),s=r.type+"_"+Date.now();this.registerHandler(s,n)}catch(n){console.error(`[OutputManager] Failed to register ${r.type} handler:`,n)}}createHandler(e){switch(e.type){case"console":return new no(e.config);case"webhook":return new so(e.config);case"temp-file":return new oo(e.config);default:throw new Error(`Unknown output handler type: ${e.type}`)}}unregisterHandler(e){return this.handlers.delete(e)}getHandler(e){return this.handlers.get(e)}getAllHandlers(){return new Map(this.handlers)}clearHandlers(){this.handlers.clear()}setDefaultOptions(e){this.defaultOptions={...this.defaultOptions,...e}}getDefaultOptions(){return{...this.defaultOptions}}async output(e,r){let n={...this.defaultOptions,...r},s={success:[],failed:[]},i=Array.from(this.handlers.entries()).map(async([u,c])=>{try{await c.output(e,n)?s.success.push(u):s.failed.push(u)}catch(l){console.error(`[OutputManager] Handler ${u} failed:`,l),s.failed.push(u)}});return await Promise.all(i),s}async outputTo(e,r,n){let s={...this.defaultOptions,...n},i={success:[],failed:[]},u=e.map(async c=>{let l=this.handlers.get(c);if(!l){console.warn(`[OutputManager] Handler ${c} not found`),i.failed.push(c);return}try{await l.output(r,s)?i.success.push(c):i.failed.push(c)}catch(d){console.error(`[OutputManager] Handler ${c} failed:`,d),i.failed.push(c)}});return await Promise.all(u),i}async outputToType(e,r,n){let s=Array.from(this.handlers.entries()).filter(([i,u])=>u.type===e).map(([i])=>i);return this.outputTo(s,r,n)}},cs=new Cd});import ET from"fastify";import AT from"@fastify/cors";var Lf=Fr(Su(),1);import{readFileSync as M_,existsSync as jf}from"fs";import{join as Mf}from"path";import{config as L_}from"dotenv";var Dn=class{config={};options;constructor(e={jsonPath:"./config.json"}){this.options={envPath:e.envPath||".env",jsonPath:e.jsonPath,useEnvFile:!1,useJsonFile:e.useJsonFile!==!1,useEnvironmentVariables:e.useEnvironmentVariables!==!1,...e},this.loadConfig()}loadConfig(){this.options.useJsonFile&&this.options.jsonPath&&this.loadJsonConfig(),this.options.initialConfig&&(this.config={...this.config,...this.options.initialConfig}),this.options.useEnvFile&&this.loadEnvConfig(),this.config.LOG_FILE&&(process.env.LOG_FILE=this.config.LOG_FILE),this.config.LOG&&(process.env.LOG=this.config.LOG)}loadJsonConfig(){if(!this.options.jsonPath)return;let e=this.isAbsolutePath(this.options.jsonPath)?this.options.jsonPath:Mf(process.cwd(),this.options.jsonPath);if(jf(e))try{let r=M_(e,"utf-8"),n=Lf.default.parse(r);this.config={...this.config,...n},console.log(`Loaded JSON config from: ${e}`)}catch(r){console.warn(`Failed to load JSON config from ${e}:`,r)}else console.warn(`JSON config file not found: ${e}`)}loadEnvConfig(){let e=this.isAbsolutePath(this.options.envPath)?this.options.envPath:Mf(process.cwd(),this.options.envPath);if(jf(e))try{let r=L_({path:e});r.parsed&&(this.config={...this.config,...this.parseEnvConfig(r.parsed)})}catch(r){console.warn(`Failed to load .env config from ${e}:`,r)}}loadEnvironmentVariables(){let e=this.parseEnvConfig(process.env);this.config={...this.config,...e}}parseEnvConfig(e){let r={};return Object.assign(r,e),r}isAbsolutePath(e){return e.startsWith("/")||e.includes(":")}get(e,r){let n=this.config[e];return n!==void 0?n:r}getAll(){return{...this.config}}getHttpsProxy(){return this.get("HTTPS_PROXY")||this.get("https_proxy")||this.get("httpsProxy")||this.get("PROXY_URL")||process.env.HTTPS_PROXY||process.env.https_proxy||process.env.HTTP_PROXY||process.env.http_proxy}has(e){return this.config[e]!==void 0}set(e,r){this.config[e]=r}reload(){this.config={},this.loadConfig()}getConfigSummary(){let e=[];return this.options.initialConfig&&e.push("Initial Config"),this.options.useJsonFile&&this.options.jsonPath&&e.push(`JSON: ${this.options.jsonPath}`),this.options.useEnvFile&&e.push(`ENV: ${this.options.envPath}`),this.options.useEnvironmentVariables&&e.push("Environment Variables"),`Config sources: ${e.join(", ")}`}};function Xe(t,e=500,r="internal_error",n="api_error"){let s=new Error(t);return s.statusCode=e,s.code=r,s.type=n,s}async function Uf(t,e,r){e.log.error(t);let n=t.statusCode||500,s={error:{message:t.message+t.stack||"Internal Server Error",type:t.type||"api_error",code:t.code||"internal_error"}};return r.code(n).send(s)}import{ProxyAgent as U_}from"undici";function qf(t,e,r,n,s){let i=new Headers({"Content-Type":"application/json"});r.headers&&Object.entries(r.headers).forEach(([d,h])=>{h&&i.set(d,h)});let u,c=AbortSignal.timeout(r.TIMEOUT??60*1e3*60);if(r.signal){let d=new AbortController,h=()=>d.abort();r.signal.addEventListener("abort",h),c.addEventListener("abort",h),u=d.signal}else u=c;let l={method:"POST",headers:i,body:JSON.stringify(e),signal:u};return r.httpsProxy&&(l.dispatcher=new U_(new URL(r.httpsProxy).toString())),s?.debug({reqId:n.req.id,request:l,headers:Object.fromEntries(i.entries()),requestUrl:typeof t=="string"?t:t.toString(),useProxy:r.httpsProxy},"final request"),fetch(typeof t=="string"?t:t.toString(),l)}import{existsSync as q_,writeFileSync as $_,readFileSync as z_}from"fs";import{join as H_}from"path";import{HOME_DIR as W_}from"@thxp/shared";var ku=H_(W_,"daily_usage.json"),tn=null;function G_(){let t=new Date;return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`}function $f(){let t=G_();if(tn&&tn.date===t)return tn;try{if(q_(ku)){let e=JSON.parse(z_(ku,"utf-8"));if(e?.date===t)return tn=e,e}}catch{}return tn={date:t,models:{}},zf(tn),tn}function zf(t){try{$_(ku,JSON.stringify(t,null,2),"utf-8")}catch{}}function J_(t,e,r){let n=$f(),s=`${t.toLowerCase()},${e.toLowerCase()}`;n.models[s]=(n.models[s]||0)+r,zf(n)}function Cs(t,e){return $f().models[`${t.toLowerCase()},${e.toLowerCase()}`]||0}var Hf="3.2.14";var Uo=class{capacity;cache;constructor(e){this.capacity=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;let r=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,r),r}put(e,r){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.capacity){let n=this.cache.keys().next().value;n!==void 0&&this.cache.delete(n)}this.cache.set(e,r)}has(e){return this.cache.has(e)}del(e){return this.cache.delete(e)}clear(){this.cache.clear()}values(){return Array.from(this.cache.values())}},K_=new Uo(100),Y_=300*1e3,Du=new Uo(1e3),Wf=t=>{Du.put(t,Date.now())},Tn=t=>{let e=Du.get(t);return e===void 0?!1:Date.now()-e>Y_?(Du.del(t),!1):!0};var vn=(t,e)=>`${t},${e}`;async function X_(t,e,r,n){let s=t.body,i=t.provider,u=r.providerService.getProvider(i);if(!u)throw Xe(`Provider '${i}' not found`,404,"provider_not_found");let c=s,l=u,d=n,h=0,m=15;for(;h<m;)try{t.provider=l.name,t.scenarioType=t.scenarioType||"default";let w=c.model;if(l.model_limits?.[w]!==void 0&&Cs(l.name,w)>=l.model_limits[w])throw Xe(`Model '${w}' daily token limit exceeded`,429,"daily_limit_exceeded");let{requestBody:k,config:E,bypass:g}=await eb(c,l,d,t.headers,{req:t},r),y=await rb(k,E,l,r,g,d,{req:t}),p=await nb(k,y,l,d,g,{req:t});return await sb(p,e,c)}catch(w){h++,t.log.warn(`[Fallback] Error on attempt ${h}: ${w.message?.substring(0,100)}`);let k=w.message||w.error?.message||"",E=k.match(/(?:max_tokens|should be\s*<=\s*|a value\s*<=\s*)(\d{2,})/i)||k.match(/(?:<=|<)\s*(\d{4,})/);if(E&&w.statusCode===400){let y=parseInt(E[1],10);if(y>0&&y<(c.max_tokens||1/0)){t.log.warn(`[AutoFix] max_tokens ${c.max_tokens} -> ${y} for ${l.name},${c.model}`),c={...c,max_tokens:y},s.max_tokens=y;try{let p=Q("os").homedir()+"/.claude-code-router/config.json",D=Q("fs"),_=JSON.parse(D.readFileSync(p,"utf-8")),v=(_.Providers||_.providers)?.find(x=>x.name===l.name);if(v){v.transformer||(v.transformer={}),v.transformer[c.model]?v.transformer[c.model].use||(v.transformer[c.model].use=[]):v.transformer[c.model]={use:[]};let x=v.transformer[c.model].use,q=x.find(V=>Array.isArray(V)&&V[0]==="maxtoken");q?q[1].max_tokens=y:x.push(["maxtoken",{max_tokens:y}]),D.writeFileSync(p,JSON.stringify(_,null,2)),t.log.info(`[AutoFix] Config updated: ${l.name} ${c.model} max_tokens=${y}`)}}catch(p){t.log.error(`[AutoFix] Failed to update config.json: ${p.message}`)}continue}}let g=await Z_(t,r,w);if(g){t.log.warn(`[Fallback] Rotating to ${g.provider.name},${g.modelName}`),l=g.provider,d=g.transformerConfig||d,c={...s,model:g.modelName},s.model=g.modelName;continue}throw w}}function Q_(t){return t?Array.isArray(t)?t:typeof t=="string"?t?[t]:[]:[]:[]}async function Z_(t,e,r){let n=!r.statusCode&&(r.code||r.name==="TypeError"||r.name==="SyntaxError"||r.message?.includes("fetch")||r.message?.includes("connect")||r.message?.includes("timeout")||r.message?.includes("JSON"));if(!(r.code==="provider_response_error"||r.statusCode>=400&&r.statusCode<600||n))return null;let i=vn(t.provider,t.body.model);Wf(i);let u=t.scenarioType||"default",c=e.configService,l=e.providerService,d=e.transformerService,m=c.getAll().Router||{},w=Q_(m[u]||m.default);if(!Array.isArray(w)||w.length===0)return null;let k=w.filter(D=>!Tn(D));if(k.length===0)return null;let E=k[0],[g,y]=E.split(","),p=l.getProvider(g);return p?{provider:p,modelName:y,transformerConfig:null}:null}async function eb(t,e,r,n,s,i){let u=t,c={},l=!1;if(l=tb(e,r,t),l&&(n instanceof Headers?n.delete("content-length"):delete n["content-length"],c.headers=n),!l&&typeof r.transformRequestOut=="function"){let d=await r.transformRequestOut(u);d.body?(u=d.body,c=d.config||{}):u=d}if(!l&&e.transformer?.use?.length)for(let d of e.transformer.use){let h=d;if(typeof d=="string"&&i?.transformerService&&(h=i.transformerService.getTransformer(d)),!h||typeof h.transformRequestIn!="function")continue;let m=await h.transformRequestIn(u,e,s);m.body?(u=m.body,c={...c,...m.config}):u=m}if(!l&&e.transformer?.[t.model]?.use?.length)for(let d of e.transformer[t.model].use){let h=d;typeof d=="string"&&i?.transformerService&&(h=i.transformerService.getTransformer(d)),!(!h||typeof h.transformRequestIn!="function")&&(u=await h.transformRequestIn(u,e,s))}return{requestBody:u,config:c,bypass:l}}function tb(t,e,r){return t.transformer?.use?.length===1&&t.transformer.use[0].name===e.name&&(!t.transformer?.[r.model]?.use.length||t.transformer?.[r.model]?.use.length===1&&t.transformer?.[r.model]?.use[0].name===e.name)}async function rb(t,e,r,n,s,i,u){let c=e.url||new URL(r.baseUrl);if(s&&typeof i.auth=="function"){let h=await i.auth(t,r);if(h.body){t=h.body;let m=e.headers||{};h.config?.headers&&(m={...m,...h.config.headers},delete m.host,delete h.config.headers),e={...e,...h.config,headers:m}}else t=h}t.stream&&r.baseUrl?.includes("/chat/completions")&&(t.stream_options={include_usage:!0});let l={Authorization:`Bearer ${r.apiKey}`,...e?.headers||{}};for(let h in l)(l[h]==="undefined"||["authorization","Authorization"].includes(h)&&l[h]?.includes("undefined"))&&delete l[h];let d=await qf(c,t,{httpsProxy:n.configService.getHttpsProxy(),...e,headers:JSON.parse(JSON.stringify(l))},u,n.log);if(!d.ok){let h;try{h=await d.text()}catch{h="(failed to read error body)"}throw n.log.error(`[provider_response_error] Error from provider(${r.name},${t.model}: ${d.status}): ${h}`),Xe(`Error from provider(${r.name},${t.model}: ${d.status}): ${h}`,d.status,"provider_response_error")}return d}async function nb(t,e,r,n,s,i){let u=e;if(!s&&r.transformer?.use?.length)for(let c of Array.from(r.transformer.use).reverse())!c||typeof c.transformResponseOut!="function"||(u=await c.transformResponseOut(u,i));if(!s&&r.transformer?.[t.model]?.use?.length)for(let c of Array.from(r.transformer[t.model].use).reverse())!c||typeof c.transformResponseOut!="function"||(u=await c.transformResponseOut(u,i));return!s&&n.transformResponseIn&&(u=await n.transformResponseIn(u,i)),u}async function sb(t,e,r){if(t.ok||e.code(t.status),r.stream===!0)return e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),e.send(t.body);{let s=t.headers.get("Content-Encoding"),i;if(s==="gzip"){let{gunzipSync:u}=await import("zlib"),c=await t.arrayBuffer();i=u(Buffer.from(c)).toString("utf-8")}else i=await t.text();try{return JSON.parse(i)}catch(u){throw Xe(`Failed to parse JSON response from provider: ${u.message}. Raw response: ${i.substring(0,500)}`,t.status||500,"provider_response_error")}}}var Tu=async t=>{t.get("/",async()=>({message:"LLMs API",version:Hf})),t.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()}));let e=t.transformerService.getTransformersWithEndpoint();for(let{transformer:r}of e)r.endPoint&&t.post(r.endPoint,async(n,s)=>X_(n,s,t,r));t.post("/providers",{schema:{body:{type:"object",properties:{id:{type:"string"},name:{type:"string"},type:{type:"string",enum:["openai","anthropic"]},baseUrl:{type:"string"},apiKey:{type:"string"},models:{type:"array",items:{type:"string"}},model_limits:{type:"object"}},required:["id","name","type","baseUrl","apiKey","models"]}}},async(r,n)=>{let{name:s,baseUrl:i,apiKey:u,models:c}=r.body;if(!s?.trim())throw Xe("Provider name is required",400,"invalid_request");if(!i||!ob(i))throw Xe("Valid base URL is required",400,"invalid_request");if(!u?.trim())throw Xe("API key is required",400,"invalid_request");if(!c||!Array.isArray(c)||c.length===0)throw Xe("At least one model is required",400,"invalid_request");if(t.providerService.getProvider(r.body.name))throw Xe(`Provider with name '${r.body.name}' already exists`,400,"provider_exists");return t.providerService.registerProvider(r.body)}),t.get("/providers",async()=>t.providerService.getProviders()),t.get("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async r=>{let n=t.providerService.getProvider(r.params.id);if(!n)throw Xe("Provider not found",404,"provider_not_found");return n}),t.put("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]},body:{type:"object",properties:{name:{type:"string"},type:{type:"string",enum:["openai","anthropic"]},baseUrl:{type:"string"},apiKey:{type:"string"},models:{type:"array",items:{type:"string"}},model_limits:{type:"object"},enabled:{type:"boolean"}}}}},async(r,n)=>{let s=t.providerService.updateProvider(r.params.id,r.body);if(!s)throw Xe("Provider not found",404,"provider_not_found");return s}),t.delete("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async r=>{if(!t.providerService.deleteProvider(r.params.id))throw Xe("Provider not found",404,"provider_not_found");return{message:"Provider deleted successfully"}}),t.patch("/providers/:id/toggle",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]},body:{type:"object",properties:{enabled:{type:"boolean"}},required:["enabled"]}}},async(r,n)=>{if(!t.providerService.toggleProvider(r.params.id,r.body.enabled))throw Xe("Provider not found",404,"provider_not_found");return{message:`Provider ${r.body.enabled?"enabled":"disabled"} successfully`}})};function ob(t){try{return new URL(t),!0}catch{return!1}}var Rn=class{constructor(e,r,n){this.configService=e;this.transformerService=r;this.logger=n;this.initializeCustomProviders()}providers=new Map;modelRoutes=new Map;initializeCustomProviders(){let e=this.configService.get("providers");if(e&&Array.isArray(e)){this.initializeFromProvidersArray(e);return}}initializeFromProvidersArray(e){e.forEach(r=>{try{if(!r.name||!r.api_base_url||!r.api_key)return;let n={};r.transformer&&Object.keys(r.transformer).forEach(s=>{s==="use"?Array.isArray(r.transformer.use)&&(n.use=r.transformer.use.map(i=>{if(Array.isArray(i)&&typeof i[0]=="string"){let u=this.transformerService.getTransformer(i[0]);if(u)return new u(i[1])}if(typeof i=="string"){let u=this.transformerService.getTransformer(i);return typeof u=="function"?new u:u}}).filter(i=>typeof i<"u")):Array.isArray(r.transformer[s]?.use)&&(n[s]={use:r.transformer[s].use.map(i=>{if(Array.isArray(i)&&typeof i[0]=="string"){let u=this.transformerService.getTransformer(i[0]);if(u)return new u(i[1])}if(typeof i=="string"){let u=this.transformerService.getTransformer(i);return typeof u=="function"?new u:u}}).filter(i=>typeof i<"u")})}),this.registerProvider({name:r.name,baseUrl:r.api_base_url,apiKey:r.api_key,models:r.models||[],transformer:r.transformer?n:void 0,model_limits:r.model_limits}),this.logger.info(`${r.name} provider registered`)}catch(n){this.logger.error(`${r.name} provider registered error: ${n}`)}})}registerProvider(e){let r={...e};return this.providers.set(r.name,r),e.models.forEach(n=>{let s=`${r.name},${n}`,i={provider:r.name,model:n,fullModel:s};this.modelRoutes.set(s,i),this.modelRoutes.has(n)||this.modelRoutes.set(n,i)}),r}getProviders(){return Array.from(this.providers.values())}getProvider(e){return this.providers.get(e)}updateProvider(e,r){let n=this.providers.get(e);if(!n)return null;let s={...n,...r,updatedAt:new Date};return this.providers.set(e,s),r.models&&(n.models.forEach(i=>{let u=`${n.name},${i}`;this.modelRoutes.delete(u),this.modelRoutes.delete(i)}),r.models.forEach(i=>{let u=`${n.name},${i}`,c={provider:n.name,model:i,fullModel:u};this.modelRoutes.set(u,c),this.modelRoutes.has(i)||this.modelRoutes.set(i,c)})),s}deleteProvider(e){let r=this.providers.get(e);return r?(r.models.forEach(n=>{let s=`${r.name},${n}`;this.modelRoutes.delete(s),this.modelRoutes.delete(n)}),this.providers.delete(e),!0):!1}toggleProvider(e,r){return!!this.providers.get(e)}resolveModelRoute(e){let r=this.modelRoutes.get(e);if(!r)return null;let n=this.providers.get(r.provider);return n?{provider:n,originalModel:e,targetModel:r.model}:null}getAvailableModelNames(){let e=[];return this.providers.forEach(r=>{r.models.forEach(n=>{e.push(n),e.push(`${r.name},${n}`)})}),e}getModelRoutes(){return Array.from(this.modelRoutes.values())}parseTransformerConfig(e){return e?Array.isArray(e)?e.reduce((r,n)=>{if(Array.isArray(n)){let[s,i={}]=n;r[s]=i}else r[n]={};return r},{}):e:{}}async getAvailableModels(){let e=[];return this.providers.forEach(r=>{r.models.forEach(n=>{e.push({id:n,object:"model",owned_by:r.name,provider:r.name}),e.push({id:`${r.name},${n}`,object:"model",owned_by:r.name,provider:r.name})})}),{object:"list",data:e}}};var Je=[];for(let t=0;t<256;++t)Je.push((t+256).toString(16).slice(1));function Gf(t,e=0){return(Je[t[e+0]]+Je[t[e+1]]+Je[t[e+2]]+Je[t[e+3]]+"-"+Je[t[e+4]]+Je[t[e+5]]+"-"+Je[t[e+6]]+Je[t[e+7]]+"-"+Je[t[e+8]]+Je[t[e+9]]+"-"+Je[t[e+10]]+Je[t[e+11]]+Je[t[e+12]]+Je[t[e+13]]+Je[t[e+14]]+Je[t[e+15]]).toLowerCase()}import{randomFillSync as ib}from"crypto";var $o=new Uint8Array(256),qo=$o.length;function vu(){return qo>$o.length-16&&(ib($o),qo=0),$o.slice(qo,qo+=16)}import{randomUUID as ab}from"crypto";var Ru={randomUUID:ab};function ub(t,e,r){if(Ru.randomUUID&&!e&&!t)return Ru.randomUUID();t=t||{};let n=t.random??t.rng?.()??vu();if(n.length<16)throw new Error("Random bytes length must be >= 16");if(n[6]=n[6]&15|64,n[8]=n[8]&63|128,e){if(r=r||0,r<0||r+16>e.length)throw new RangeError(`UUID byte range ${r}:${r+15} is out of buffer bounds`);for(let s=0;s<16;++s)e[r+s]=n[s];return e}return Gf(n)}var Gt=ub;var Jf=t=>t<=0?"none":t<=1024?"low":t<=8192?"medium":"high";var Vf=(t,e)=>(t.includes("base64")&&(t=t.split("base64").pop(),t.startsWith(",")&&(t=t.slice(1))),`data:${e};base64,${t}`);var zo=class{constructor(e){this.options=e;this.useBearer=this.options?.UseBearer??!1}name="Anthropic";endPoint="/v1/messages";useBearer;logger;async auth(e,r){let n={};return this.useBearer?(n.authorization=`Bearer ${r.apiKey}`,n["x-api-key"]=void 0):(n["x-api-key"]=r.apiKey,n.authorization=void 0),{body:e,config:{headers:n}}}async transformRequestOut(e){let r=[];if(e.system){if(typeof e.system=="string")r.push({role:"system",content:e.system});else if(Array.isArray(e.system)&&e.system.length){let i=e.system.filter(u=>u.type==="text"&&u.text).map(u=>({type:"text",text:u.text,cache_control:u.cache_control}));r.push({role:"system",content:i})}}JSON.parse(JSON.stringify(e.messages||[]))?.forEach(i=>{if(i.role==="user"||i.role==="assistant"){if(typeof i.content=="string"){r.push({role:i.role,content:i.content});return}if(Array.isArray(i.content)){if(i.role==="user"){let u=i.content.filter(l=>l.type==="tool_result"&&l.tool_use_id);u.length&&u.forEach(l=>{let d={role:"tool",content:typeof l.content=="string"?l.content:JSON.stringify(l.content),tool_call_id:l.tool_use_id,cache_control:l.cache_control};r.push(d)});let c=i.content.filter(l=>l.type==="text"&&l.text||l.type==="image"&&l.source);c.length&&r.push({role:"user",content:c.map(l=>l?.type==="image"?{type:"image_url",image_url:{url:l.source?.type==="base64"?Vf(l.source.data,l.source.media_type):l.source.url},media_type:l.source.media_type}:l)})}else if(i.role==="assistant"){let u={role:"assistant",content:""},c=i.content.filter(h=>h.type==="text"&&h.text);c.length&&(u.content=c.map(h=>h.text).join(`
|
|
73
73
|
`));let l=i.content.filter(h=>h.type==="tool_use"&&h.id);l.length&&(u.tool_calls=l.map(h=>{let m=h.input;return(typeof m!="object"||m===null)&&(m=m?{text:String(m)}:{}),{id:h.id,type:"function",function:{name:h.name,arguments:JSON.stringify(m)}}}));let d=i.content.find(h=>h.type==="thinking"&&h.signature);d&&(u.thinking={content:d.thinking,signature:d.signature}),r.push(u)}return}}});let s={messages:r,model:e.model,max_tokens:e.max_tokens,temperature:e.temperature,stream:e.stream,tools:e.tools?.length?this.convertAnthropicToolsToUnified(e.tools):void 0,tool_choice:e.tool_choice};return e.thinking&&(s.reasoning={effort:Jf(e.thinking.budget_tokens),enabled:e.thinking.type==="enabled"}),e.tool_choice&&(e.tool_choice.type==="tool"?s.tool_choice={type:"function",function:{name:e.tool_choice.name}}:s.tool_choice=e.tool_choice.type),s}async transformResponseIn(e,r){if(e.headers.get("Content-Type")?.includes("text/event-stream")){if(!e.body)throw new Error("Stream response body is null");let s=await this.convertOpenAIStreamToAnthropic(e.body,r);return new Response(s,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}else{let s=await e.json(),i=this.convertOpenAIResponseToAnthropic(s,r);return new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}})}}async transformRequestIn(e,r){let n=[],s="";for(let u of e.messages)if(u.role==="system"){let c="";typeof u.content=="string"?c=u.content:Array.isArray(u.content)&&(c=u.content.filter(l=>l.type==="text"&&l.text).map(l=>l.text).join(`
|
|
74
74
|
`)),c&&(s=s?`${s}
|
|
75
75
|
|