@wengine-ai/llms 2.0.65 → 2.0.66

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.
@@ -69,7 +69,7 @@ https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys`};var dd
69
69
  ${this.toMarkdown(s,r+1)}`:`${n}- ${s}`).join(`
70
70
  `):typeof e=="object"&&e!==null?Object.entries(e).map(([s,o])=>typeof o=="object"&&o!==null?`${n}${s}:
71
71
  ${this.toMarkdown(o,r+1)}`:`${n}${s}: ${o}`).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 wo,Yd=Be(()=>{"use strict";wo=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:o,metadata:a}=r||{},c={data:e};return s&&(c.timestamp=new Date().toISOString()),o&&(c.prefix=o),a&&Object.keys(a).length>0&&(c.metadata=a),c}async sendRequest(e,r,n,s,o){let a=new AbortController,c=setTimeout(()=>a.abort(),o);try{let l=await fetch(e,{method:r,headers:n,body:JSON.stringify(s),signal:a.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,o,a){let c=null;for(let l=1;l<=a.maxAttempts;l++)try{return await this.sendRequest(e,r,n,s,o)}catch(f){if(c=f,l===a.maxAttempts)break;let d=a.backoffMs*Math.pow(2,l-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${l}/${a.maxAttempts}), retrying in ${d}ms...`,f.message),await this.delay(d)}throw c}async output(e,r={}){let n=r.timeout||this.defaultTimeout;try{let s=this.buildHeaders(),o=this.buildBody(e,r),a=await this.sendWithRetry(this.config.url,this.config.method,s,o,n,this.config.retry);return!0}catch(s){let o=s instanceof Error?s.message:String(s);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${o}`),!1;throw new Error(`Webhook output failed: ${o}`)}}}});var ys,Qd,R0,Eo,Xd=Be(()=>{"use strict";ys=require("fs"),Qd=require("path"),R0=require("os"),Eo=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let r=(0,R0.tmpdir)();this.baseDir=(0,Qd.join)(r,this.config.subdirectory),this.ensureDir()}ensureDir(){try{(0,ys.existsSync)(this.baseDir)||(0,ys.mkdirSync)(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 o=Date.now();s=`${r}-${e}-${o}${n}`}else s=`${r}-${e}${n}`;return(0,Qd.join)(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},o=this.getFilePath(n);return(0,ys.writeFileSync)(o,JSON.stringify(s,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var Zd,_s,x0=Be(()=>{"use strict";Kd();Yd();Xd();Zd=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 Co(e.config);case"webhook":return new wo(e.config);case"temp-file":return new Eo(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:[]},o=Array.from(this.handlers.entries()).map(async([a,c])=>{try{await c.output(e,n)?s.success.push(a):s.failed.push(a)}catch(l){console.error(`[OutputManager] Handler ${a} failed:`,l),s.failed.push(a)}});return await Promise.all(o),s}async outputTo(e,r,n){let s={...this.defaultOptions,...n},o={success:[],failed:[]},a=e.map(async c=>{let l=this.handlers.get(c);if(!l){console.warn(`[OutputManager] Handler ${c} not found`),o.failed.push(c);return}try{await l.output(r,s)?o.success.push(c):o.failed.push(c)}catch(f){console.error(`[OutputManager] Handler ${c} failed:`,f),o.failed.push(c)}});return await Promise.all(a),o}async outputToType(e,r,n){let s=Array.from(this.handlers.entries()).filter(([o,a])=>a.type===e).map(([o])=>o);return this.outputTo(s,r,n)}},_s=new Zd});var QT={};Bu(QT,{ActiveProbeService:()=>_o,ConfigService:()=>un,ProviderHealthStore:()=>xs,ProviderService:()=>cn,SSEParserTransform:()=>An,SSESerializerTransform:()=>bo,TokenizerService:()=>En,TransformerService:()=>wn,calculateTokenCount:()=>Nd,default:()=>YT,getActiveProbeService:()=>zd,getAllQuotaResults:()=>E0,getAllRateLimitInfo:()=>Sh,getHealthStore:()=>lt,getQuotaAdapter:()=>su,getQuotaResult:()=>w0,getRateLimitInfo:()=>kh,pluginManager:()=>Wd,resetActiveProbeService:()=>A0,rewriteStream:()=>Vd,router:()=>nu,searchProjectBySession:()=>Bd,sessionUsageCache:()=>Xa,startActiveProbe:()=>iu,stopActiveProbe:()=>au,storeQuotaResult:()=>ou,tokenSpeedPlugin:()=>tf});module.exports=Eb(QT);var I0=je(require("fastify"),1),N0=je(require("@fastify/cors"),1);var Rs=require("fs"),Gu=require("path"),yh=require("dotenv"),_h=je(Wu(),1),un=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:(0,Gu.join)(process.cwd(),this.options.jsonPath);if((0,Rs.existsSync)(e))try{let r=(0,Rs.readFileSync)(e,"utf-8"),n=_h.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:(0,Gu.join)(process.cwd(),this.options.envPath);if((0,Rs.existsSync)(e))try{let r=(0,yh.config)({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")}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 nt(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 bh(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)}var Ch=require("undici");function wh(t,e,r,n,s){let o=new Headers({"Content-Type":"application/json"});r.headers&&Object.entries(r.headers).forEach(([f,d])=>{d&&o.set(f,d)});let a,c=AbortSignal.timeout(r.TIMEOUT??60*1e3*60);if(r.signal){let f=new AbortController,d=()=>f.abort();r.signal.addEventListener("abort",d),c.addEventListener("abort",d),a=f.signal}else a=c;let l={method:"POST",headers:o,body:JSON.stringify(e),signal:a};return r.httpsProxy&&(l.dispatcher=new Ch.ProxyAgent(new URL(r.httpsProxy).toString())),s?.debug({reqId:n.req.id,request:l,headers:Object.fromEntries(o.entries()),requestUrl:typeof t=="string"?t:t.toString(),useProxy:r.httpsProxy},"final request"),fetch(typeof t=="string"?t:t.toString(),l)}var Eh="2.0.65";var Ob={enabled:!0,failureThreshold:3,probeIntervalMinutes:5,halfOpenSuccessThreshold:2,rateLimitThreshold:1},xs=class{states=new Map;stickyFallbacks=new Map;config;probeTimer;constructor(e){this.config={...Ob,...e}}getKey(e,r){return`${e},${r}`}getStickyKey(e,r){return r?`${r}/${e}`:`default/${e}`}recordSuccess(e,r){if(!this.config.enabled)return;let n=this.getKey(e,r),s=this.states.get(n);s&&(s.successCount++,s.status==="half-open"?s.successCount>=this.config.halfOpenSuccessThreshold&&this.states.delete(n):s.status==="open"&&(s.status="half-open",s.successCount=1,s.failureCount=0))}isRateLimitError(e){if(!e)return!1;let r=e.toLowerCase();return r.includes("429")||r.includes("rate_limit")||r.includes("ratelimit")||r.includes("rate limit")||r.includes("overloaded")||r.includes("quota")}recordFailure(e,r,n){if(!this.config.enabled)return;let s=this.getKey(e,r),o=this.states.get(s);o||(o={provider:e,model:r,status:"closed",failureCount:0,successCount:0,lastFailureTime:0,lastProbeTime:0},this.states.set(s,o)),o.failureCount++,o.lastFailureTime=Date.now(),o.lastError=n;let c=this.isRateLimitError(n)?this.config.rateLimitThreshold:this.config.failureThreshold;o.status==="half-open"?(o.status="open",o.successCount=0,o.lastProbeTime=0):o.status==="closed"&&o.failureCount>=c&&(o.status="open",o.lastProbeTime=0)}getStickyFallback(e,r){let n=this.getStickyKey(e,r);return this.stickyFallbacks.get(n)||null}isStickyFallbackUsable(e){let r=this.getState(e.provider,e.model);if(!r||r.status==="closed"||r.status==="half-open")return!0;if(r.status==="open"){let n=Date.now()-r.lastProbeTime,s=this.config.probeIntervalMinutes*60*1e3;return n>=s}return!1}recordStickyFallbackSuccess(e,r,n,s){let o=this.getStickyKey(e,s),a=this.stickyFallbacks.get(o);this.stickyFallbacks.set(o,{provider:r,model:n,scenarioType:e,family:s||"",lastSuccessTime:Date.now(),failureCount:0}),this.recordSuccess(r,n)}recordStickyFallbackFailure(e,r){let n=this.getStickyKey(e,r),s=this.stickyFallbacks.get(n);if(!s)return;s.failureCount++,s.failureCount>=3&&this.stickyFallbacks.delete(n)}clearStickyFallback(e,r){let n=this.getStickyKey(e,r);this.stickyFallbacks.delete(n)}clearAllStickyFallbacks(){this.stickyFallbacks.clear()}getAllStickyFallbacks(){return Array.from(this.stickyFallbacks.values())}getState(e,r){return this.states.get(this.getKey(e,r))}isAvailable(e,r){if(!this.config.enabled)return!0;let n=this.getState(e,r);return n?n.status!=="open":!0}getPriority(e,r){if(!this.config.enabled)return 0;let n=this.getState(e,r);if(!n)return 0;switch(n.status){case"closed":return 0;case"half-open":return 1;case"open":return 2}}getHealthyModels(){return[]}getFailPoolModels(){let e=[];for(let[r,n]of this.states)n.status==="open"&&e.push(r);return e}getHalfOpenModels(){let e=[];for(let[r,n]of this.states)n.status==="half-open"&&e.push(r);return e}needsProbe(e){return Date.now()-e.lastProbeTime>=this.config.probeIntervalMinutes*60*1e3}markProbeAttempt(e,r){let n=this.getKey(e,r),s=this.states.get(n);s&&s.status==="open"&&(s.lastProbeTime=Date.now())}clear(){this.states.clear(),this.stickyFallbacks.clear()}getAllStates(){return Array.from(this.states.values())}stopProbeTimer(){this.probeTimer&&(clearInterval(this.probeTimer),this.probeTimer=void 0)}},Ju=null;function lt(t){return Ju||(Ju=new xs(t)),Ju}var Ku=new Map,Pb=["x-ratelimit-remaining","x-ratelimit-remaining-requests","x-ratelimit-remaining-tokens"],Ib=["x-ratelimit-limit","x-ratelimit-limit-requests","x-ratelimit-limit-tokens"],Nb=["x-ratelimit-reset","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];function Fs(t,e,r){let n=c=>{if(r instanceof Headers)return r.get(c);let l=Object.keys(r).find(f=>f.toLowerCase()===c);return l?r[l]:null},s=Vu(n,Pb),o=Vu(n,Ib),a=Vu(n,Nb);(s||o||a)&&Ku.set(t,{provider:t,remaining:Ah(s),limit:Ah(o),reset:Bb(a),capturedAt:Date.now()})}function kh(t){return Ku.get(t)}function Sh(){return Array.from(Ku.values())}function Vu(t,e){for(let r of e){let n=t(r);if(n)return n}return null}function Ah(t){if(!t)return null;let e=Number(t.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function Bb(t){if(!t)return null;let e=t.trim();if(!e)return null;let r=Number(e);if(Number.isFinite(r))return r>1e12?Math.floor(r/1e3):r>1e9?Math.floor(r):Math.floor(Date.now()/1e3+r);let n=Date.parse(e);if(Number.isFinite(n))return Math.floor(n/1e3);let s=jb(e);return s===null?null:Math.floor((Date.now()+s)/1e3)}function jb(t){let e=/(\d+(?:\.\d+)?)(ms|s|m|h|d)/gi,r=0,n=!1;for(let s of t.matchAll(e)){n=!0;let o=Number(s[1]),a=s[2].toLowerCase();if(Number.isFinite(o))switch(a){case"ms":r+=o;break;case"s":r+=o*1e3;break;case"m":r+=o*60*1e3;break;case"h":r+=o*60*60*1e3;break;case"d":r+=o*24*60*60*1e3;break}}return n?r:null}async function Lb(t,e,r,n){let s=t.body,o=t.provider,a=r.providerService.getProvider(o);if(!a)throw nt(`Provider '${o}' not found`,404,"provider_not_found");try{let{requestBody:c,config:l,bypass:f}=await vh(s,a,n,t.headers,{req:t}),d=await Th(c,l,a,r,f,n,{req:t});try{a?.baseUrl&&d?.headers&&Fs(o,a.baseUrl,d.headers)}catch{}let p=await Dh(c,d,a,n,f,{req:t});return Rh(p,e,s)}catch(c){let l=await Mb(t,e,r,n,c);if(l)return l;throw c}}async function Mb(t,e,r,n,s){let o=t.scenarioType||"default",a=t.familyFallback,c=t.modelFamily,l=r.configService.get("fallback"),f=lt(),d=g=>{let[m,...S]=g.split(","),y=m?.trim(),A=S.join(",").trim();return!y||!A?null:{provider:y,model:A,key:`${y},${A}`}},p=[];if(c){let g=a?.[o];Array.isArray(g)&&g.length>0?p.push({name:`${c}/${o}`,models:g}):t.log.warn(`No ${c} fallback configured for ${o}; will try global ${o} fallback`)}if(Array.isArray(l?.[o])&&l[o].length>0&&p.push({name:`global/${o}`,models:l[o]}),p.length===0)return null;let w=t.provider||"",T=t.body.model||"",E=new Set;w&&T&&(f.recordFailure(w,T,s?.message),E.add(`${w},${T}`));let b=p.reduce((g,m)=>g+m.models.length,0);t.log.warn(`Request failed for ${o}, trying ${b} fallback models across ${p.length} fallback stage(s)`);for(let g of p){t.log.info(`Trying ${g.name} fallback stage with ${g.models.length} models`);for(let m of g.models){let S=d(m);if(!S){t.log.warn(`Fallback model '${m}' is invalid, skipping`);continue}if(E.has(S.key))continue;E.add(S.key);let y=S.provider,A=S.model;try{if(!f.isAvailable(y,A)){t.log.warn(`Fallback model ${m} unavailable (fail pool), skipping`);continue}t.log.info(`Trying fallback model: ${m}`);let D={...t.body};D.model=A;let O={...t,provider:y,body:D},$=r.providerService.getProvider(y);if(!$){t.log.warn(`Fallback provider '${y}' not found, skipping`);continue}let{requestBody:V,config:B,bypass:K}=await vh(D,$,n,t.headers,{req:O}),re=await Th(V,B,$,r,K,n,{req:O});try{$?.baseUrl&&re?.headers&&Fs(y,$.baseUrl,re.headers)}catch{}let ee=await Dh(V,re,$,n,K,{req:O});return t.log.info(`Fallback model ${m} succeeded`),f.recordSuccess(y,A),Rh(ee,e,D)}catch(D){f.recordFailure(y,A,D.message),t.log.warn(`Fallback model ${S.key} failed: ${D.message}`);continue}}}return t.log.error(`All fallback models failed for ${o}`),null}async function vh(t,e,r,n,s){let o=JSON.parse(JSON.stringify(t)),a={},c=!1;if(c=Ub(e,r,t),c&&(n instanceof Headers?n.delete("content-length"):delete n["content-length"],a.headers=n),!c&&typeof r.transformRequestOut=="function"){let l=await r.transformRequestOut(o);l.body?(o=l.body,a=l.config||{}):o=l}if(!c&&e.transformer?.use?.length)for(let l of e.transformer.use){if(!l||typeof l.transformRequestIn!="function")continue;let f=await l.transformRequestIn(o,e,s);f.body?(o=f.body,a={...a,...f.config}):o=f}if(!c&&e.transformer?.[t.model]?.use?.length)for(let l of e.transformer[t.model].use)!l||typeof l.transformRequestIn!="function"||(o=await l.transformRequestIn(o,e,s));return{requestBody:o,config:a,bypass:c}}function Ub(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 Th(t,e,r,n,s,o,a){let c=e.url||new URL(r.baseUrl);if(!e.TIMEOUT){let d=n.configService.get("API_TIMEOUT_MS");d&&(e.TIMEOUT=typeof d=="string"?parseInt(d,10):d)}if(s&&typeof o.auth=="function"){let d=await o.auth(t,r);if(d.body){t=d.body;let p=e.headers||{};d.config?.headers&&(p={...p,...d.config.headers},delete p.host,delete d.config.headers),e={...e,...d.config,headers:p}}else t=d}let l={Authorization:`Bearer ${r.apiKey}`,...e?.headers||{}};for(let d in l)(l[d]==="undefined"||["authorization","Authorization"].includes(d)&&l[d]?.includes("undefined"))&&delete l[d];let f=await wh(c,t,{httpsProxy:n.configService.getHttpsProxy(),...e,headers:JSON.parse(JSON.stringify(l))},a,n.log);if(!f.ok){let d=await f.text();throw n.log.error(`[provider_response_error] Error from provider(${r.name},${t.model}: ${f.status}): ${d}`),nt(`Error from provider(${r.name},${t.model}: ${f.status}): ${d}`,f.status,"provider_response_error")}return f}async function Dh(t,e,r,n,s,o){let a=e;if(!s&&r.transformer?.use?.length)for(let c of Array.from(r.transformer.use).reverse())!c||typeof c.transformResponseOut!="function"||(a=await c.transformResponseOut(a,o));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"||(a=await c.transformResponseOut(a,o));return!s&&n.transformResponseIn&&(a=await n.transformResponseIn(a,o)),a}function Rh(t,e,r){return t.ok||e.code(t.status),r.stream===!0?(e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),e.send(t.body)):t.json()}var Yu=async t=>{t.get("/",async()=>({message:"LLMs API",version:Eh})),t.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()})),t.get("/providers/health",async()=>({states:lt().getAllStates().map(s=>({provider:s.provider,model:s.model,status:s.status,failureCount:s.failureCount,successCount:s.successCount,lastFailureTime:s.lastFailureTime,lastError:s.lastError})),timestamp:new Date().toISOString()}));let e=t.transformerService.getTransformersWithEndpoint();for(let{transformer:r}of e)r.endPoint&&t.post(r.endPoint,async(n,s)=>Lb(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"}}},required:["id","name","type","baseUrl","apiKey","models"]}}},async(r,n)=>{let{name:s,baseUrl:o,apiKey:a,models:c}=r.body;if(!s?.trim())throw nt("Provider name is required",400,"invalid_request");if(!o||!qb(o))throw nt("Valid base URL is required",400,"invalid_request");if(!a?.trim())throw nt("API key is required",400,"invalid_request");if(!c||!Array.isArray(c)||c.length===0)throw nt("At least one model is required",400,"invalid_request");if(t.providerService.getProvider(r.body.name))throw nt(`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 nt("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"}},enabled:{type:"boolean"}}}}},async(r,n)=>{let s=t.providerService.updateProvider(r.params.id,r.body);if(!s)throw nt("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 nt("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 nt("Provider not found",404,"provider_not_found");return{message:`Provider ${r.body.enabled?"enabled":"disabled"} successfully`}})};function qb(t){try{return new URL(t),!0}catch{return!1}}var cn=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(o=>{if(Array.isArray(o)&&typeof o[0]=="string"){let a=this.transformerService.getTransformer(o[0]);if(a)return new a(o[1])}if(typeof o=="string"){let a=this.transformerService.getTransformer(o);return typeof a=="function"?new a:a}}).filter(o=>typeof o<"u")):Array.isArray(r.transformer[s]?.use)&&(n[s]={use:r.transformer[s].use.map(o=>{if(Array.isArray(o)&&typeof o[0]=="string"){let a=this.transformerService.getTransformer(o[0]);if(a)return new a(o[1])}if(typeof o=="string"){let a=this.transformerService.getTransformer(o);return typeof a=="function"?new a:a}}).filter(o=>typeof o<"u")})}),this.registerProvider({name:r.name,baseUrl:r.api_base_url,apiKey:r.api_key,models:r.models||[],quotaToken:r.quota_token,transformer:r.transformer?n:void 0}),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}`,o={provider:r.name,model:n,fullModel:s};this.modelRoutes.set(s,o),this.modelRoutes.has(n)||this.modelRoutes.set(n,o)}),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(o=>{let a=`${n.name},${o}`;this.modelRoutes.delete(a),this.modelRoutes.delete(o)}),r.models.forEach(o=>{let a=`${n.name},${o}`,c={provider:n.name,model:o,fullModel:a};this.modelRoutes.set(a,c),this.modelRoutes.has(o)||this.modelRoutes.set(o,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,o={}]=n;r[s]=o}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 xh(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()}var Fh=require("crypto"),si=new Uint8Array(256),ni=si.length;function Qu(){return ni>si.length-16&&((0,Fh.randomFillSync)(si),ni=0),si.slice(ni,ni+=16)}var Oh=require("crypto"),Xu={randomUUID:Oh.randomUUID};function $b(t,e,r){if(Xu.randomUUID&&!e&&!t)return Xu.randomUUID();t=t||{};let n=t.random??t.rng?.()??Qu();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 xh(n)}var Qt=$b;var Ph=t=>t<=0?"none":t<=1024?"low":t<=8192?"medium":"high";var Ih=(t,e)=>(t.includes("base64")&&(t=t.split("base64").pop(),t.startsWith(",")&&(t=t.slice(1))),`data:${e};base64,${t}`);var oi=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 o=e.system.filter(a=>a.type==="text"&&a.text).map(a=>({type:"text",text:a.text,cache_control:a.cache_control}));r.push({role:"system",content:o})}}JSON.parse(JSON.stringify(e.messages||[]))?.forEach(o=>{if(o.role==="user"||o.role==="assistant"){if(typeof o.content=="string"){r.push({role:o.role,content:o.content});return}if(Array.isArray(o.content)){if(o.role==="user"){let a=o.content.filter(l=>l.type==="tool_result"&&l.tool_use_id);a.length&&a.forEach(l=>{let f={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(f)});let c=o.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"?Ih(l.source.data,l.source.media_type):l.source.url},media_type:l.source.media_type}:l)})}else if(o.role==="assistant"){let a={role:"assistant",content:""},c=o.content.filter(d=>d.type==="text"&&d.text);c.length&&(a.content=c.map(d=>d.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 wo,Yd=Be(()=>{"use strict";wo=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:o,metadata:a}=r||{},c={data:e};return s&&(c.timestamp=new Date().toISOString()),o&&(c.prefix=o),a&&Object.keys(a).length>0&&(c.metadata=a),c}async sendRequest(e,r,n,s,o){let a=new AbortController,c=setTimeout(()=>a.abort(),o);try{let l=await fetch(e,{method:r,headers:n,body:JSON.stringify(s),signal:a.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,o,a){let c=null;for(let l=1;l<=a.maxAttempts;l++)try{return await this.sendRequest(e,r,n,s,o)}catch(f){if(c=f,l===a.maxAttempts)break;let d=a.backoffMs*Math.pow(2,l-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${l}/${a.maxAttempts}), retrying in ${d}ms...`,f.message),await this.delay(d)}throw c}async output(e,r={}){let n=r.timeout||this.defaultTimeout;try{let s=this.buildHeaders(),o=this.buildBody(e,r),a=await this.sendWithRetry(this.config.url,this.config.method,s,o,n,this.config.retry);return!0}catch(s){let o=s instanceof Error?s.message:String(s);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${o}`),!1;throw new Error(`Webhook output failed: ${o}`)}}}});var ys,Qd,R0,Eo,Xd=Be(()=>{"use strict";ys=require("fs"),Qd=require("path"),R0=require("os"),Eo=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let r=(0,R0.tmpdir)();this.baseDir=(0,Qd.join)(r,this.config.subdirectory),this.ensureDir()}ensureDir(){try{(0,ys.existsSync)(this.baseDir)||(0,ys.mkdirSync)(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 o=Date.now();s=`${r}-${e}-${o}${n}`}else s=`${r}-${e}${n}`;return(0,Qd.join)(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},o=this.getFilePath(n);return(0,ys.writeFileSync)(o,JSON.stringify(s,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var Zd,_s,x0=Be(()=>{"use strict";Kd();Yd();Xd();Zd=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 Co(e.config);case"webhook":return new wo(e.config);case"temp-file":return new Eo(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:[]},o=Array.from(this.handlers.entries()).map(async([a,c])=>{try{await c.output(e,n)?s.success.push(a):s.failed.push(a)}catch(l){console.error(`[OutputManager] Handler ${a} failed:`,l),s.failed.push(a)}});return await Promise.all(o),s}async outputTo(e,r,n){let s={...this.defaultOptions,...n},o={success:[],failed:[]},a=e.map(async c=>{let l=this.handlers.get(c);if(!l){console.warn(`[OutputManager] Handler ${c} not found`),o.failed.push(c);return}try{await l.output(r,s)?o.success.push(c):o.failed.push(c)}catch(f){console.error(`[OutputManager] Handler ${c} failed:`,f),o.failed.push(c)}});return await Promise.all(a),o}async outputToType(e,r,n){let s=Array.from(this.handlers.entries()).filter(([o,a])=>a.type===e).map(([o])=>o);return this.outputTo(s,r,n)}},_s=new Zd});var QT={};Bu(QT,{ActiveProbeService:()=>_o,ConfigService:()=>un,ProviderHealthStore:()=>xs,ProviderService:()=>cn,SSEParserTransform:()=>An,SSESerializerTransform:()=>bo,TokenizerService:()=>En,TransformerService:()=>wn,calculateTokenCount:()=>Nd,default:()=>YT,getActiveProbeService:()=>zd,getAllQuotaResults:()=>E0,getAllRateLimitInfo:()=>Sh,getHealthStore:()=>lt,getQuotaAdapter:()=>su,getQuotaResult:()=>w0,getRateLimitInfo:()=>kh,pluginManager:()=>Wd,resetActiveProbeService:()=>A0,rewriteStream:()=>Vd,router:()=>nu,searchProjectBySession:()=>Bd,sessionUsageCache:()=>Xa,startActiveProbe:()=>iu,stopActiveProbe:()=>au,storeQuotaResult:()=>ou,tokenSpeedPlugin:()=>tf});module.exports=Eb(QT);var I0=je(require("fastify"),1),N0=je(require("@fastify/cors"),1);var Rs=require("fs"),Gu=require("path"),yh=require("dotenv"),_h=je(Wu(),1),un=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:(0,Gu.join)(process.cwd(),this.options.jsonPath);if((0,Rs.existsSync)(e))try{let r=(0,Rs.readFileSync)(e,"utf-8"),n=_h.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:(0,Gu.join)(process.cwd(),this.options.envPath);if((0,Rs.existsSync)(e))try{let r=(0,yh.config)({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")}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 nt(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 bh(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)}var Ch=require("undici");function wh(t,e,r,n,s){let o=new Headers({"Content-Type":"application/json"});r.headers&&Object.entries(r.headers).forEach(([f,d])=>{d&&o.set(f,d)});let a,c=AbortSignal.timeout(r.TIMEOUT??60*1e3*60);if(r.signal){let f=new AbortController,d=()=>f.abort();r.signal.addEventListener("abort",d),c.addEventListener("abort",d),a=f.signal}else a=c;let l={method:"POST",headers:o,body:JSON.stringify(e),signal:a};return r.httpsProxy&&(l.dispatcher=new Ch.ProxyAgent(new URL(r.httpsProxy).toString())),s?.debug({reqId:n.req.id,request:l,headers:Object.fromEntries(o.entries()),requestUrl:typeof t=="string"?t:t.toString(),useProxy:r.httpsProxy},"final request"),fetch(typeof t=="string"?t:t.toString(),l)}var Eh="2.0.66";var Ob={enabled:!0,failureThreshold:3,probeIntervalMinutes:5,halfOpenSuccessThreshold:2,rateLimitThreshold:1},xs=class{states=new Map;stickyFallbacks=new Map;config;probeTimer;constructor(e){this.config={...Ob,...e}}getKey(e,r){return`${e},${r}`}getStickyKey(e,r){return r?`${r}/${e}`:`default/${e}`}recordSuccess(e,r){if(!this.config.enabled)return;let n=this.getKey(e,r),s=this.states.get(n);s&&(s.successCount++,s.status==="half-open"?s.successCount>=this.config.halfOpenSuccessThreshold&&this.states.delete(n):s.status==="open"&&(s.status="half-open",s.successCount=1,s.failureCount=0))}isRateLimitError(e){if(!e)return!1;let r=e.toLowerCase();return r.includes("429")||r.includes("rate_limit")||r.includes("ratelimit")||r.includes("rate limit")||r.includes("overloaded")||r.includes("quota")}recordFailure(e,r,n){if(!this.config.enabled)return;let s=this.getKey(e,r),o=this.states.get(s);o||(o={provider:e,model:r,status:"closed",failureCount:0,successCount:0,lastFailureTime:0,lastProbeTime:0},this.states.set(s,o)),o.failureCount++,o.lastFailureTime=Date.now(),o.lastError=n;let c=this.isRateLimitError(n)?this.config.rateLimitThreshold:this.config.failureThreshold;o.status==="half-open"?(o.status="open",o.successCount=0,o.lastProbeTime=0):o.status==="closed"&&o.failureCount>=c&&(o.status="open",o.lastProbeTime=0)}getStickyFallback(e,r){let n=this.getStickyKey(e,r);return this.stickyFallbacks.get(n)||null}isStickyFallbackUsable(e){let r=this.getState(e.provider,e.model);if(!r||r.status==="closed"||r.status==="half-open")return!0;if(r.status==="open"){let n=Date.now()-r.lastProbeTime,s=this.config.probeIntervalMinutes*60*1e3;return n>=s}return!1}recordStickyFallbackSuccess(e,r,n,s){let o=this.getStickyKey(e,s),a=this.stickyFallbacks.get(o);this.stickyFallbacks.set(o,{provider:r,model:n,scenarioType:e,family:s||"",lastSuccessTime:Date.now(),failureCount:0}),this.recordSuccess(r,n)}recordStickyFallbackFailure(e,r){let n=this.getStickyKey(e,r),s=this.stickyFallbacks.get(n);if(!s)return;s.failureCount++,s.failureCount>=3&&this.stickyFallbacks.delete(n)}clearStickyFallback(e,r){let n=this.getStickyKey(e,r);this.stickyFallbacks.delete(n)}clearAllStickyFallbacks(){this.stickyFallbacks.clear()}getAllStickyFallbacks(){return Array.from(this.stickyFallbacks.values())}getState(e,r){return this.states.get(this.getKey(e,r))}isAvailable(e,r){if(!this.config.enabled)return!0;let n=this.getState(e,r);return n?n.status!=="open":!0}getPriority(e,r){if(!this.config.enabled)return 0;let n=this.getState(e,r);if(!n)return 0;switch(n.status){case"closed":return 0;case"half-open":return 1;case"open":return 2}}getHealthyModels(){return[]}getFailPoolModels(){let e=[];for(let[r,n]of this.states)n.status==="open"&&e.push(r);return e}getHalfOpenModels(){let e=[];for(let[r,n]of this.states)n.status==="half-open"&&e.push(r);return e}needsProbe(e){return Date.now()-e.lastProbeTime>=this.config.probeIntervalMinutes*60*1e3}markProbeAttempt(e,r){let n=this.getKey(e,r),s=this.states.get(n);s&&s.status==="open"&&(s.lastProbeTime=Date.now())}clear(){this.states.clear(),this.stickyFallbacks.clear()}getAllStates(){return Array.from(this.states.values())}stopProbeTimer(){this.probeTimer&&(clearInterval(this.probeTimer),this.probeTimer=void 0)}},Ju=null;function lt(t){return Ju||(Ju=new xs(t)),Ju}var Ku=new Map,Pb=["x-ratelimit-remaining","x-ratelimit-remaining-requests","x-ratelimit-remaining-tokens"],Ib=["x-ratelimit-limit","x-ratelimit-limit-requests","x-ratelimit-limit-tokens"],Nb=["x-ratelimit-reset","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];function Fs(t,e,r){let n=c=>{if(r instanceof Headers)return r.get(c);let l=Object.keys(r).find(f=>f.toLowerCase()===c);return l?r[l]:null},s=Vu(n,Pb),o=Vu(n,Ib),a=Vu(n,Nb);(s||o||a)&&Ku.set(t,{provider:t,remaining:Ah(s),limit:Ah(o),reset:Bb(a),capturedAt:Date.now()})}function kh(t){return Ku.get(t)}function Sh(){return Array.from(Ku.values())}function Vu(t,e){for(let r of e){let n=t(r);if(n)return n}return null}function Ah(t){if(!t)return null;let e=Number(t.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function Bb(t){if(!t)return null;let e=t.trim();if(!e)return null;let r=Number(e);if(Number.isFinite(r))return r>1e12?Math.floor(r/1e3):r>1e9?Math.floor(r):Math.floor(Date.now()/1e3+r);let n=Date.parse(e);if(Number.isFinite(n))return Math.floor(n/1e3);let s=jb(e);return s===null?null:Math.floor((Date.now()+s)/1e3)}function jb(t){let e=/(\d+(?:\.\d+)?)(ms|s|m|h|d)/gi,r=0,n=!1;for(let s of t.matchAll(e)){n=!0;let o=Number(s[1]),a=s[2].toLowerCase();if(Number.isFinite(o))switch(a){case"ms":r+=o;break;case"s":r+=o*1e3;break;case"m":r+=o*60*1e3;break;case"h":r+=o*60*60*1e3;break;case"d":r+=o*24*60*60*1e3;break}}return n?r:null}async function Lb(t,e,r,n){let s=t.body,o=t.provider,a=r.providerService.getProvider(o);if(!a)throw nt(`Provider '${o}' not found`,404,"provider_not_found");try{let{requestBody:c,config:l,bypass:f}=await vh(s,a,n,t.headers,{req:t}),d=await Th(c,l,a,r,f,n,{req:t});try{a?.baseUrl&&d?.headers&&Fs(o,a.baseUrl,d.headers)}catch{}let p=await Dh(c,d,a,n,f,{req:t});return Rh(p,e,s)}catch(c){let l=await Mb(t,e,r,n,c);if(l)return l;throw c}}async function Mb(t,e,r,n,s){let o=t.scenarioType||"default",a=t.familyFallback,c=t.modelFamily,l=r.configService.get("fallback"),f=lt(),d=g=>{let[m,...S]=g.split(","),y=m?.trim(),A=S.join(",").trim();return!y||!A?null:{provider:y,model:A,key:`${y},${A}`}},p=[];if(c){let g=a?.[o];Array.isArray(g)&&g.length>0?p.push({name:`${c}/${o}`,models:g}):t.log.warn(`No ${c} fallback configured for ${o}; will try global ${o} fallback`)}if(Array.isArray(l?.[o])&&l[o].length>0&&p.push({name:`global/${o}`,models:l[o]}),p.length===0)return null;let w=t.provider||"",T=t.body.model||"",E=new Set;w&&T&&(f.recordFailure(w,T,s?.message),E.add(`${w},${T}`));let b=p.reduce((g,m)=>g+m.models.length,0);t.log.warn(`Request failed for ${o}, trying ${b} fallback models across ${p.length} fallback stage(s)`);for(let g of p){t.log.info(`Trying ${g.name} fallback stage with ${g.models.length} models`);for(let m of g.models){let S=d(m);if(!S){t.log.warn(`Fallback model '${m}' is invalid, skipping`);continue}if(E.has(S.key))continue;E.add(S.key);let y=S.provider,A=S.model;try{if(!f.isAvailable(y,A)){t.log.warn(`Fallback model ${m} unavailable (fail pool), skipping`);continue}t.log.info(`Trying fallback model: ${m}`);let D={...t.body};D.model=A;let O={...t,provider:y,body:D},$=r.providerService.getProvider(y);if(!$){t.log.warn(`Fallback provider '${y}' not found, skipping`);continue}let{requestBody:V,config:B,bypass:K}=await vh(D,$,n,t.headers,{req:O}),re=await Th(V,B,$,r,K,n,{req:O});try{$?.baseUrl&&re?.headers&&Fs(y,$.baseUrl,re.headers)}catch{}let ee=await Dh(V,re,$,n,K,{req:O});return t.log.info(`Fallback model ${m} succeeded`),f.recordSuccess(y,A),Rh(ee,e,D)}catch(D){f.recordFailure(y,A,D.message),t.log.warn(`Fallback model ${S.key} failed: ${D.message}`);continue}}}return t.log.error(`All fallback models failed for ${o}`),null}async function vh(t,e,r,n,s){let o=JSON.parse(JSON.stringify(t)),a={},c=!1;if(c=Ub(e,r,t),c&&(n instanceof Headers?n.delete("content-length"):delete n["content-length"],a.headers=n),!c&&typeof r.transformRequestOut=="function"){let l=await r.transformRequestOut(o);l.body?(o=l.body,a=l.config||{}):o=l}if(!c&&e.transformer?.use?.length)for(let l of e.transformer.use){if(!l||typeof l.transformRequestIn!="function")continue;let f=await l.transformRequestIn(o,e,s);f.body?(o=f.body,a={...a,...f.config}):o=f}if(!c&&e.transformer?.[t.model]?.use?.length)for(let l of e.transformer[t.model].use)!l||typeof l.transformRequestIn!="function"||(o=await l.transformRequestIn(o,e,s));return{requestBody:o,config:a,bypass:c}}function Ub(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 Th(t,e,r,n,s,o,a){let c=e.url||new URL(r.baseUrl);if(!e.TIMEOUT){let d=n.configService.get("API_TIMEOUT_MS");d&&(e.TIMEOUT=typeof d=="string"?parseInt(d,10):d)}if(s&&typeof o.auth=="function"){let d=await o.auth(t,r);if(d.body){t=d.body;let p=e.headers||{};d.config?.headers&&(p={...p,...d.config.headers},delete p.host,delete d.config.headers),e={...e,...d.config,headers:p}}else t=d}let l={Authorization:`Bearer ${r.apiKey}`,...e?.headers||{}};for(let d in l)(l[d]==="undefined"||["authorization","Authorization"].includes(d)&&l[d]?.includes("undefined"))&&delete l[d];let f=await wh(c,t,{httpsProxy:n.configService.getHttpsProxy(),...e,headers:JSON.parse(JSON.stringify(l))},a,n.log);if(!f.ok){let d=await f.text();throw n.log.error(`[provider_response_error] Error from provider(${r.name},${t.model}: ${f.status}): ${d}`),nt(`Error from provider(${r.name},${t.model}: ${f.status}): ${d}`,f.status,"provider_response_error")}return f}async function Dh(t,e,r,n,s,o){let a=e;if(!s&&r.transformer?.use?.length)for(let c of Array.from(r.transformer.use).reverse())!c||typeof c.transformResponseOut!="function"||(a=await c.transformResponseOut(a,o));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"||(a=await c.transformResponseOut(a,o));return!s&&n.transformResponseIn&&(a=await n.transformResponseIn(a,o)),a}function Rh(t,e,r){return t.ok||e.code(t.status),r.stream===!0?(e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),e.send(t.body)):t.json()}var Yu=async t=>{t.get("/",async()=>({message:"LLMs API",version:Eh})),t.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()})),t.get("/providers/health",async()=>({states:lt().getAllStates().map(s=>({provider:s.provider,model:s.model,status:s.status,failureCount:s.failureCount,successCount:s.successCount,lastFailureTime:s.lastFailureTime,lastError:s.lastError})),timestamp:new Date().toISOString()}));let e=t.transformerService.getTransformersWithEndpoint();for(let{transformer:r}of e)r.endPoint&&t.post(r.endPoint,async(n,s)=>Lb(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"}}},required:["id","name","type","baseUrl","apiKey","models"]}}},async(r,n)=>{let{name:s,baseUrl:o,apiKey:a,models:c}=r.body;if(!s?.trim())throw nt("Provider name is required",400,"invalid_request");if(!o||!qb(o))throw nt("Valid base URL is required",400,"invalid_request");if(!a?.trim())throw nt("API key is required",400,"invalid_request");if(!c||!Array.isArray(c)||c.length===0)throw nt("At least one model is required",400,"invalid_request");if(t.providerService.getProvider(r.body.name))throw nt(`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 nt("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"}},enabled:{type:"boolean"}}}}},async(r,n)=>{let s=t.providerService.updateProvider(r.params.id,r.body);if(!s)throw nt("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 nt("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 nt("Provider not found",404,"provider_not_found");return{message:`Provider ${r.body.enabled?"enabled":"disabled"} successfully`}})};function qb(t){try{return new URL(t),!0}catch{return!1}}var cn=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(o=>{if(Array.isArray(o)&&typeof o[0]=="string"){let a=this.transformerService.getTransformer(o[0]);if(a)return new a(o[1])}if(typeof o=="string"){let a=this.transformerService.getTransformer(o);return typeof a=="function"?new a:a}}).filter(o=>typeof o<"u")):Array.isArray(r.transformer[s]?.use)&&(n[s]={use:r.transformer[s].use.map(o=>{if(Array.isArray(o)&&typeof o[0]=="string"){let a=this.transformerService.getTransformer(o[0]);if(a)return new a(o[1])}if(typeof o=="string"){let a=this.transformerService.getTransformer(o);return typeof a=="function"?new a:a}}).filter(o=>typeof o<"u")})}),this.registerProvider({name:r.name,baseUrl:r.api_base_url,apiKey:r.api_key,models:r.models||[],quotaToken:r.quota_token,transformer:r.transformer?n:void 0}),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}`,o={provider:r.name,model:n,fullModel:s};this.modelRoutes.set(s,o),this.modelRoutes.has(n)||this.modelRoutes.set(n,o)}),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(o=>{let a=`${n.name},${o}`;this.modelRoutes.delete(a),this.modelRoutes.delete(o)}),r.models.forEach(o=>{let a=`${n.name},${o}`,c={provider:n.name,model:o,fullModel:a};this.modelRoutes.set(a,c),this.modelRoutes.has(o)||this.modelRoutes.set(o,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,o={}]=n;r[s]=o}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 xh(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()}var Fh=require("crypto"),si=new Uint8Array(256),ni=si.length;function Qu(){return ni>si.length-16&&((0,Fh.randomFillSync)(si),ni=0),si.slice(ni,ni+=16)}var Oh=require("crypto"),Xu={randomUUID:Oh.randomUUID};function $b(t,e,r){if(Xu.randomUUID&&!e&&!t)return Xu.randomUUID();t=t||{};let n=t.random??t.rng?.()??Qu();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 xh(n)}var Qt=$b;var Ph=t=>t<=0?"none":t<=1024?"low":t<=8192?"medium":"high";var Ih=(t,e)=>(t.includes("base64")&&(t=t.split("base64").pop(),t.startsWith(",")&&(t=t.slice(1))),`data:${e};base64,${t}`);var oi=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 o=e.system.filter(a=>a.type==="text"&&a.text).map(a=>({type:"text",text:a.text,cache_control:a.cache_control}));r.push({role:"system",content:o})}}JSON.parse(JSON.stringify(e.messages||[]))?.forEach(o=>{if(o.role==="user"||o.role==="assistant"){if(typeof o.content=="string"){r.push({role:o.role,content:o.content});return}if(Array.isArray(o.content)){if(o.role==="user"){let a=o.content.filter(l=>l.type==="tool_result"&&l.tool_use_id);a.length&&a.forEach(l=>{let f={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(f)});let c=o.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"?Ih(l.source.data,l.source.media_type):l.source.url},media_type:l.source.media_type}:l)})}else if(o.role==="assistant"){let a={role:"assistant",content:""},c=o.content.filter(d=>d.type==="text"&&d.text);c.length&&(a.content=c.map(d=>d.text).join(`
73
73
  `));let l=o.content.filter(d=>d.type==="tool_use"&&d.id);l.length&&(a.tool_calls=l.map(d=>({id:d.id,type:"function",function:{name:d.name,arguments:JSON.stringify(d.input||{})}})));let f=o.content.find(d=>d.type==="thinking"&&d.signature);f&&(a.thinking={content:f.thinking,signature:f.signature}),r.push(a)}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:Ph(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(),o=this.convertOpenAIResponseToAnthropic(s,r);return new Response(JSON.stringify(o),{headers:{"Content-Type":"application/json"}})}}convertAnthropicToolsToUnified(e){return e.map(r=>({type:"function",function:{name:r.name,description:r.description||"",parameters:r.input_schema}}))}async convertOpenAIStreamToAnthropic(e,r){return new ReadableStream({start:async s=>{let o=new TextEncoder,a=`msg_${Date.now()}`,c=null,l="unknown",f=!1,d=!1,p=!1,w=new Map,T=new Map,E=0,b=0,g=0,m=!1,S=!1,y=0,A=-1,D=()=>{let B=y;return y++,B},O=B=>{if(!m)try{s.enqueue(B);let K=new TextDecoder().decode(B);this.logger.debug({reqId:r.req.id,data:K,type:"send data"})}catch(K){if(K instanceof TypeError&&K.message.includes("Controller is already closed"))m=!0;else throw this.logger.debug({reqId:r.req.id,error:K instanceof Error?K.message:String(K),type:"send data error"}),K}},$=()=>{if(!m)try{if(A>=0){let K={type:"content_block_stop",index:A};O(o.encode(`event: content_block_stop
74
74
  data: ${JSON.stringify(K)}
75
75