@wengine-ai/llms 2.3.2391 → 2.3.2393
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
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
"use strict";var Pa=Object.create;var Wt=Object.defineProperty;var Ea=Object.getOwnPropertyDescriptor;var Oa=Object.getOwnPropertyNames;var Aa=Object.getPrototypeOf,Ia=Object.prototype.hasOwnProperty;var w=(n,e)=>()=>(n&&(e=n(n=0)),e);var Gt=(n,e)=>{for(var t in e)Wt(n,t,{get:e[t],enumerable:!0})},Mr=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Oa(e))!Ia.call(n,r)&&r!==t&&Wt(n,r,{get:()=>e[r],enumerable:!(o=Ea(e,r))||o.enumerable});return n};var Y=(n,e,t)=>(t=n!=null?Pa(Aa(n)):{},Mr(e||!n||!n.__esModule?Wt(t,"default",{value:n,enumerable:!0}):t,n)),$r=n=>Mr(Wt({},"__esModule",{value:!0}),n);function $a(n){if(n==null)return{ok:!0};let e=String(n).trim();if(!e)return{ok:!0};if(Ma.test(e))return{ok:!0};try{let t=new URL(e);return t.protocol!=="http:"&&t.protocol!=="https:"?{ok:!1,error:`Unsupported proxy protocol: ${t.protocol}. Only http:// and https:// are allowed.`}:{ok:!0}}catch{return{ok:!1,error:`Invalid proxy URL: ${e}`}}}function Dr(n){let e=[];for(let t of Lr){let o=n[t];if(o==null)continue;let r=$a(o);r.ok||e.push({key:t,error:r.error})}return e}function st(n){for(let e of Lr){let t=n.get(e);if(t==null)continue;let o=String(t).trim();if(o)return o}}function ao(n){if(n==null||n==="")return!0;if(typeof n=="string"){let e=n.trim().toLowerCase();return e==="false"||e==="0"?!1:e==="true"||e==="1"?!0:!!e}return n===!1||n===0?!1:n===!0||n===1?!0:!!n}function le(n,e){let t=st(n);if(t)return ao(n.get("PROXY_GLOBAL_ENABLED"))||e?.proxyEnabled===!0||e?.proxy_enabled===!0?t:void 0}function Q(n){let e=Na(n),t=Kt.get(e);if(t)return t;let o=new Nr.ProxyAgent(e);return Kt.set(e,o),o}async function Qt(){let n=Array.from(Kt.values());Kt.clear(),await Promise.allSettled(n.map(e=>e.close()))}function Na(n){let e=n.trim();if(!e)throw new TypeError("Proxy URL must not be empty");let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new TypeError(`Unsupported proxy protocol: ${t.protocol}`);return t.toString()}var Nr,Lr,Ma,Kt,se=w(()=>{"use strict";Nr=require("undici"),Lr=["HTTPS_PROXY","https_proxy","httpsProxy","PROXY_URL"],Ma=/\$\{[^}]+\}|\$[A-Z_][A-Z0-9_]*/;Kt=new Map});var it,co,Fr,Ur,ve,lo=w(()=>{"use strict";it=require("fs"),co=require("path"),Fr=require("dotenv"),Ur=Y(require("json5"),1);se();ve=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,co.join)(process.cwd(),this.options.jsonPath);if((0,it.existsSync)(e))try{let t=(0,it.readFileSync)(e,"utf-8"),o=Ur.default.parse(t);this.config={...this.config,...o},console.log(`Loaded JSON config from: ${e}`)}catch(t){console.warn(`Failed to load JSON config from ${e}:`,t)}else console.warn(`JSON config file not found: ${e}`)}loadEnvConfig(){let e=this.isAbsolutePath(this.options.envPath)?this.options.envPath:(0,co.join)(process.cwd(),this.options.envPath);if((0,it.existsSync)(e))try{let t=(0,Fr.config)({path:e});t.parsed&&(this.config={...this.config,...this.parseEnvConfig(t.parsed)})}catch(t){console.warn(`Failed to load .env config from ${e}:`,t)}}loadEnvironmentVariables(){let e=this.parseEnvConfig(process.env);this.config={...this.config,...e}}parseEnvConfig(e){let t={};return Object.assign(t,e),t}isAbsolutePath(e){return e.startsWith("/")||e.includes(":")}get(e,t){let o=this.config[e];return o!==void 0?o:t}getAll(){return{...this.config}}getHttpsProxy(){return st(this)}has(e){return this.config[e]!==void 0}set(e,t){this.config[e]=t}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 G(n,e=500,t="internal_error",o="api_error"){let r=new Error(n);return r.statusCode=e,r.code=t,r.type=o,r}async function jr(n,e,t){e.log.error(n);let o=n.statusCode||500;if(n.rawBody)try{let s=JSON.parse(n.rawBody);return t.code(o).send(s)}catch{return t.code(o).send(n.rawBody)}let r={error:{message:n.message||"Internal Server Error",type:n.type||"api_error",code:n.code||"internal_error"}};return t.code(o).send(r)}var Vt=w(()=>{"use strict"});function Yt(n){uo=n}function at(){return uo}function Xt(n){return uo||n.get("DEBUG_LOG")===!0}function Br(n){let e=n.get("DEBUG_LOG_OPTIONS");return!e||typeof e!="object"?Le:{maxBodyLength:e.maxBodyLength??Le.maxBodyLength,maxStreamChunks:e.maxStreamChunks??Le.maxStreamChunks}}function qt(n){let e={};for(let[t,o]of Object.entries(n))La.has(t.toLowerCase())?e[t]="***MASKED***":e[t]=o;return e}function Zt(n,e){return n.length<=e?n:n.slice(0,e)+`...[truncated, total ${n.length} bytes]`}function Jr(n,e,t){let o=typeof t.body=="string"?t.body:JSON.stringify(t.body);n.info({debug_log:!0,reqId:e,phase:"provider_request",url:t.url,headers:qt(t.headers),body:Zt(o,Le.maxBodyLength)})}function Wr(n,e,t){n.info({debug_log:!0,reqId:e,phase:"provider_response",status:t.status,headers:qt(t.headers),...t.body!==void 0?{body:Zt(t.body,Le.maxBodyLength)}:{}})}function Hr(n,e,t,o){let r=Da(o);n.info({debug_log:!0,reqId:e,phase:"provider_stream_chunk",chunkIndex:t,...r?{usage_monitor:r}:{},data:Zt(o,Le.maxBodyLength)})}function Da(n){let e=[];for(let t of n.split(/\r?\n/)){if(!t.startsWith("data:"))continue;let o=t.slice(5).trim();if(!(!o||o==="[DONE]"))try{let r=JSON.parse(o),s=r?.usage||r?.response?.usage;s&&e.push({path:r?.usage?"usage":"response.usage",usage:s,choicesLength:Array.isArray(r?.choices)?r.choices.length:void 0,finishReason:r?.choices?.[0]?.finish_reason})}catch{e.push({parseError:!0,data:Zt(o,512)})}}if(e.length)return e.length===1?e[0]:e}function zr(n,e,t){n.info({debug_log:!0,reqId:e,phase:"provider_stream_end",totalChunks:t})}function Gr(n,e,t,o){(async()=>{let r=n.pipeThrough(new TextDecoderStream).getReader(),s=0;try{let i="";for(;;){let{done:l,value:a}=await r.read();if(l)break;i+=a;let c=i.split(`
|
|
2
2
|
|
|
3
|
-
`);i=c.pop()||"";for(let u of c)u.trim()&&(s<o.maxStreamChunks?Hr(e,t,s,u):s===o.maxStreamChunks&&e.info({debug_log:!0,reqId:t,phase:"provider_stream_chunk_omitted",message:`[chunks after #${s} omitted, maxStreamChunks=${o.maxStreamChunks}]`}),s++)}i.trim()&&(s<o.maxStreamChunks&&Hr(e,t,s,i.trim()),s++),zr(e,t,s)}catch(i){console.error(`[debug_log] Error reading debug stream for reqId=${t}:`,i),zr(e,t,s)}finally{r.releaseLock()}})()}var La,Le,uo,ct=w(()=>{"use strict";La=new Set(["authorization","x-api-key","x-goog-api-key","cookie","set-cookie"]),Le={maxBodyLength:4096,maxStreamChunks:100},uo=!1});function Kr(n,e,t,o,r){let s=new Headers({"Content-Type":"application/json"});t.headers&&Object.entries(t.headers).forEach(([c,u])=>{u&&s.set(c,u)});let i,l=AbortSignal.timeout(t.TIMEOUT??60*1e3*60);if(t.signal){let c=new AbortController,u=()=>c.abort();t.signal.addEventListener("abort",u),l.addEventListener("abort",u),i=c.signal}else i=l;let a={method:"POST",headers:s,body:JSON.stringify(e),signal:i};return t.httpsProxy&&(a.dispatcher=Q(t.httpsProxy)),r?.debug({reqId:o.req.id,method:"POST",headers:qt(Object.fromEntries(s.entries())),requestUrl:typeof n=="string"?n:n.toString(),useProxy:Fa(t.httpsProxy)},"final request"),fetch(typeof n=="string"?n:n.toString(),a)}function Fa(n){if(!(typeof n!="string"||!n.trim()))try{let e=new URL(n);return e.username||e.password?(e.username="",e.password="",`${e.toString()} (credentials redacted)`):e.toString()}catch{return"[invalid proxy URL]"}}var Qr=w(()=>{se();ct()});var en,po=w(()=>{en="2.3.239"});var Vr={};Gt(Vr,{getFallbackPromotionStore:()=>De,resetFallbackPromotionStore:()=>Ha});function De(n){return xe||(xe=new fo,n&&xe.configure(n)),xe}function Ha(){xe&&(xe.clearAll(),xe=null)}var ja,fo,xe,tn=w(()=>{"use strict";ie();ja=600*1e3,fo=class{promotions=new Map;enabled=!0;ttlMs=ja;configure(e){e?.enabled!==void 0&&(this.enabled=e.enabled),e?.ttlMinutes!==void 0&&(this.ttlMs=e.ttlMinutes*60*1e3)}getKey(e,t,o){return`${e},${t}:${o}`}promote(e,t,o,r,s,i){if(!this.enabled)return;let l=this.getKey(e,t,o),a=`${r},${s}`;this.promotions.set(l,{promotedModel:a,timestamp:Date.now(),ttlMs:i??this.ttlMs})}getPromotion(e,t,o,r){if(!this.enabled)return null;let s=this.getKey(e,t,o),i=this.promotions.get(s);if(!i)return null;if(Date.now()-i.timestamp>=i.ttlMs)return this.promotions.delete(s),null;let[a,...c]=i.promotedModel.split(","),u=c.join(",");if(!U().isAvailable(a,u))return this.promotions.delete(s),null;let g=r.find(y=>y.name.toLowerCase()===a.toLowerCase()),m=g?.models?.find(y=>String(y).toLowerCase()===u.toLowerCase());return!g||!m||g.enabled===!1?(this.promotions.delete(s),null):`${g.name},${m}`}clear(e,t,o){let r=this.getKey(e,t,o);this.promotions.delete(r)}clearByPrimary(e,t){let o=`${e},${t}:`,r=0;for(let s of this.promotions.keys())s.startsWith(o)&&(this.promotions.delete(s),r++);return r}clearAll(){this.promotions.clear()}clearExpired(){let e=Date.now();for(let[t,o]of this.promotions)e-o.timestamp>=o.ttlMs&&this.promotions.delete(t)}getAllPromotions(){let e=Date.now(),t=[];for(let[o,r]of this.promotions){let s=r.ttlMs-(e-r.timestamp);s>0&&t.push({key:o,promotedModel:r.promotedModel,remainingMs:s})}return t}},xe=null});function Wa(n){try{if(!(0,pe.existsSync)(ho))return;let e=JSON.parse((0,pe.readFileSync)(ho,"utf-8"));if(!Array.isArray(e))return;let t=Date.now();for(let o of e){if(!o||!o.provider||!o.model)continue;let r=o.updatedAt||o.lastFailureTime||0;r&&t-r>1440*60*1e3||n.restore({provider:o.provider,model:o.model,status:o.status,failureCount:o.failureCount??0,successCount:o.successCount??0,lastFailureTime:o.lastFailureTime??0,lastProbeTime:o.lastProbeTime??0,lastError:o.lastError,rateLimitUntil:o.rateLimitUntil})}}catch{}}function Xr(n){try{let e=n.getAllStates();if(e.length===0)return;(0,pe.existsSync)(go)||(0,pe.mkdirSync)(go,{recursive:!0});let t=e.map(o=>({...o,updatedAt:Date.now()}));(0,pe.writeFileSync)(ho,JSON.stringify(t,null,2),"utf-8")}catch{}}function nn(){if(Yr)return;Yr=!0;let n=U();Wa(n),Ja=setInterval(()=>Xr(n),6e4),process.on("exit",()=>Xr(n))}function U(n){return mo||(mo=new lt(n)),mo}var pe,yo,qr,za,Ba,lt,go,ho,Yr,Ja,mo,ie=w(()=>{"use strict";pe=require("fs"),yo=require("path"),qr=require("@wengine-ai/claude-code-router-shared"),za=120,Ba={enabled:!0,failureThreshold:3,probeIntervalMinutes:5,halfOpenSuccessThreshold:2},lt=class{states=new Map;config;probeTimer;constructor(e){this.config={...Ba,...e}}getKey(e,t){return!e||!t?null:`${e},${t}`}recordSuccess(e,t){if(!this.config.enabled)return;let o=this.getKey(e,t);if(!o)return;let r=this.states.get(o);r&&(r.successCount++,!r.rateLimitUntil&&(r.status==="half-open"?r.successCount>=this.config.halfOpenSuccessThreshold&&(this.clearPromotionsForPrimary(e,t),this.states.delete(o)):r.status==="open"&&(r.status="half-open",r.successCount=1,r.failureCount=0)))}clearPromotionsForPrimary(e,t){try{let{getFallbackPromotionStore:o}=(tn(),$r(Vr));o().clearByPrimary(e,t)}catch{}}recordFailure(e,t,o){if(!this.config.enabled)return;let r=this.getKey(e,t);if(!r)return;let s=this.states.get(r);s||(s={provider:e,model:t,status:"closed",failureCount:0,successCount:0,lastFailureTime:0,lastProbeTime:0},this.states.set(r,s)),s.failureCount++,s.lastFailureTime=Date.now(),s.lastError=o,s.status==="half-open"?(s.status="open",s.successCount=0,s.lastProbeTime=0):s.status==="closed"&&s.failureCount>=this.config.failureThreshold&&(s.status="open",s.lastProbeTime=0)}getState(e,t){let o=this.getKey(e,t);if(o)return this.states.get(o)}isAvailable(e,t){if(!this.config.enabled)return!0;if(!this.getKey(e,t))return!1;let r=this.getState(e,t);return r?r.status==="open"&&r.rateLimitUntil?!(Date.now()<r.rateLimitUntil):r.status!=="open":!0}getPriority(e,t){if(!this.config.enabled)return 0;if(!this.getKey(e,t))return 2;let r=this.getState(e,t);if(!r)return 0;switch(r.status){case"closed":return 0;case"half-open":return 1;case"open":return 2}}getHealthyModels(){return[]}getFailPoolModels(){let e=[];for(let[t,o]of this.states)o.status==="open"&&e.push(t);return e}getHalfOpenModels(){let e=[];for(let[t,o]of this.states)o.status==="half-open"&&e.push(t);return e}forceOpen(e,t,o){if(!this.config.enabled)return;let r=this.getKey(e,t);if(!r)return;let s=this.states.get(r);s?(s.status="open",s.failureCount=Math.max(s.failureCount,this.config.failureThreshold),s.lastFailureTime=Date.now(),s.lastError=o,s.lastProbeTime=0):(s={provider:e,model:t,status:"open",failureCount:this.config.failureThreshold,successCount:0,lastFailureTime:Date.now(),lastProbeTime:0,lastError:o},this.states.set(r,s))}markRateLimited(e,t,o,r){if(!this.config.enabled)return;let s=this.getKey(e,t);if(!s)return;let i=this.states.get(s);i?(i.status="open",i.lastFailureTime=Date.now(),i.lastError=r||"rate-limited",i.lastProbeTime=0):(i={provider:e,model:t,status:"open",failureCount:0,successCount:0,lastFailureTime:Date.now(),lastProbeTime:0,lastError:r||"rate-limited"},this.states.set(s,i));let l=(o??za)*1e3;i.rateLimitUntil=Date.now()+l}getRateLimitedModels(){let e=[];for(let[t,o]of this.states)o.status==="open"&&o.rateLimitUntil&&e.push(t);return e}needsProbe(e){return Date.now()-e.lastProbeTime>=this.config.probeIntervalMinutes*60*1e3}markProbeAttempt(e,t){let o=this.getKey(e,t);if(!o)return;let r=this.states.get(o);r&&r.status==="open"&&(r.lastProbeTime=Date.now())}clear(){this.states.clear()}recover(e,t){let o=this.getKey(e,t);o&&this.states.delete(o)}getAllStates(){return Array.from(this.states.values())}restore(e){let t=this.getKey(e.provider,e.model);t&&this.states.set(t,{...e})}stopProbeTimer(){this.probeTimer&&(clearInterval(this.probeTimer),this.probeTimer=void 0)}},go=(0,yo.join)(qr.HOME_DIR,"runtime"),ho=(0,yo.join)(go,"provider-health.json"),Yr=!1,Ja=null;mo=null});function ut(n,e,t){let o=l=>{if(t instanceof Headers)return t.get(l);let a=Object.keys(t).find(c=>c.toLowerCase()===l);return a?t[a]:null},r=_o(o,Ga),s=_o(o,Ka),i=_o(o,Qa);(r||s||i)&&Fe.set(n,{provider:n,remaining:ts(r),limit:ts(s),reset:Va(i),capturedAt:Date.now()})}function rs(n){return Fe.get(n)}function on(){return Array.from(Fe.values())}function _o(n,e){for(let t of e){let o=n(t);if(o)return o}return null}function ts(n){if(!n)return null;let e=Number(n.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function Va(n){if(!n)return null;let e=n.trim();if(!e)return null;let t=Number(e);if(Number.isFinite(t))return t>1e12?Math.floor(t/1e3):t>1e9?Math.floor(t):Math.floor(Date.now()/1e3+t);let o=Date.parse(e);if(Number.isFinite(o))return Math.floor(o/1e3);let r=Ya(e);return r===null?null:Math.floor((Date.now()+r)/1e3)}function Ya(n){let e=/(\d+(?:\.\d+)?)(ms|s|m|h|d)/gi,t=0,o=!1;for(let r of n.matchAll(e)){o=!0;let s=Number(r[1]),i=r[2].toLowerCase();if(Number.isFinite(s))switch(i){case"ms":t+=s;break;case"s":t+=s*1e3;break;case"m":t+=s*60*1e3;break;case"h":t+=s*60*60*1e3;break;case"d":t+=s*24*60*60*1e3;break}}return o?t:null}function Xa(){try{if(!(0,fe.existsSync)(bo))return;let n=JSON.parse((0,fe.readFileSync)(bo,"utf-8"));if(!Array.isArray(n))return;let e=Date.now();for(let t of n)if(t&&t.provider){if(t.capturedAt&&e-t.capturedAt>3600*1e3)continue;Fe.set(t.provider,t)}}catch{}}function ns(){try{if(Fe.size===0)return;(0,fe.existsSync)(ko)||(0,fe.mkdirSync)(ko,{recursive:!0}),(0,fe.writeFileSync)(bo,JSON.stringify(Array.from(Fe.values()),null,2),"utf-8")}catch{}}function Ue(){Zr||(Zr=!0,Xa(),es=setInterval(ns,6e4),es.unref?.(),process.on("exit",ns))}var fe,To,os,ko,bo,Fe,Zr,es,Ga,Ka,Qa,je=w(()=>{"use strict";fe=require("fs"),To=require("path"),os=require("@wengine-ai/claude-code-router-shared"),ko=(0,To.join)(os.HOME_DIR,"runtime"),bo=(0,To.join)(ko,"rate-limit.json"),Fe=new Map,Zr=!1,es=null,Ga=["x-ratelimit-remaining-tokens","x-ratelimit-remaining-requests","x-ratelimit-remaining"],Ka=["x-ratelimit-limit-tokens","x-ratelimit-limit-requests","x-ratelimit-limit"],Qa=["x-ratelimit-reset-tokens","x-ratelimit-reset-requests","x-ratelimit-reset"]});var He,Co=w(()=>{"use strict";He=class{name="openai-responses";endPoint="/v1/responses";getCacheReadInputTokens(e){return e?.cache_read_input_tokens??e?.input_tokens_details?.cached_tokens??e?.prompt_tokens_details?.cached_tokens??0}getCacheCreationInputTokens(e){return e?.cache_creation_input_tokens??e?.input_tokens_details?.cache_creation_tokens??e?.input_tokens_details?.cache_write_tokens??e?.prompt_tokens_details?.cache_creation_tokens??e?.prompt_tokens_details?.cache_write_tokens??0}buildResponsesUsage(e){let t=e?.input_tokens??e?.prompt_tokens??0,o=e?.output_tokens??e?.completion_tokens??0,r=this.getCacheReadInputTokens(e),s=this.getCacheCreationInputTokens(e);return{input_tokens:t,output_tokens:o,total_tokens:e?.total_tokens??t+o,input_tokens_details:{cached_tokens:r,cache_creation_tokens:s},output_tokens_details:{reasoning_tokens:e?.output_tokens_details?.reasoning_tokens??0},cache_read_input_tokens:r,cache_creation_input_tokens:s}}async transformRequestIn(e){delete e.temperature,delete e.max_tokens,e.reasoning&&(e.reasoning={effort:e.reasoning.effort,summary:e.reasoning.summary||"auto"});let t=[],o=e.messages.filter(r=>r.role==="system");if(o.length>0){let r=o[0];Array.isArray(r.content)?r.content.forEach(s=>{let i="";typeof s=="string"?i=s:s&&typeof s=="object"&&"text"in s&&(i=s.text),t.push({role:"system",content:i})}):e.instructions=r.content}if(e.messages.forEach(r=>{if(r.role!=="system"){if(Array.isArray(r.content)){let s=r.content.map(i=>this.normalizeRequestContent(i,r.role)).filter(i=>i!==null);s.length>0?r.content=s:delete r.content}if(r.role==="tool"){let s={...r};s.type="function_call_output",s.call_id=r.tool_call_id,s.output=r.content,delete s.cache_control,delete s.role,delete s.tool_call_id,delete s.content,t.push(s);return}if(r.role==="assistant"&&Array.isArray(r.tool_calls)){r.tool_calls.forEach(s=>{t.push({type:"function_call",arguments:s.function.arguments,name:s.function.name,call_id:s.id})});return}t.push(r)}}),e.input=t,delete e.messages,Array.isArray(e.tools)){let r=e.tools.find(s=>s.function.name==="web_search");e.tools=e.tools.filter(s=>s.function.name!=="web_search").map(s=>(s.function.name==="WebSearch"&&delete s.function.parameters.properties.allowed_domains,s.function.name==="Edit"?{type:s.type,name:s.function.name,description:s.function.description,parameters:{...s.function.parameters,required:["file_path","old_string","new_string","replace_all"]},strict:!0}:{type:s.type,name:s.function.name,description:s.function.description,parameters:s.function.parameters})),r&&e.tools.push({type:"web_search"})}return e.parallel_tool_calls=!1,e}async transformResponseOut(e){let t=e.headers.get("Content-Type")||"";if(t.includes("application/json")){let o=await e.json();if(o.object==="response"&&o.output){let r=this.convertResponseToChat(o);return new Response(JSON.stringify(r),{status:e.status,statusText:e.statusText,headers:e.headers})}return o.type==="message"&&Array.isArray(o.content)?new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers}):new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers})}else if(t.includes("text/event-stream")){if(!e.body)return e;let[o,r]=e.body.tee(),s=o.getReader(),i="";try{let{value:f,done:_}=await s.read();!_&&f&&(i=new TextDecoder().decode(f))}finally{s.releaseLock()}if(o.cancel().catch(()=>{}),i.includes("message_start")||i.includes("content_block_start")){let f=this.prependToStream(i,r);return new Response(f,{status:e.status,statusText:e.statusText,headers:e.headers})}if(i.includes("response.created")||i.includes("response.output_text.delta")||i.includes("response.in_progress")||i.includes("response.output_item.added")){let f=this.prependToStream(i,r);return new Response(f,{status:e.status,statusText:e.statusText,headers:e.headers})}let c=this.prependToStream(i,r),u=new TextDecoder,d=new TextEncoder,g="",m=!1,y=this,p=new ReadableStream({async start(f){let _=c.getReader(),k=-1,h="",b=T=>(T!==h&&(k++,h=T),k);try{for(;;){let{done:T,value:x}=await _.read();if(T){m||f.enqueue(d.encode(`data: [DONE]
|
|
3
|
+
`);i=c.pop()||"";for(let u of c)u.trim()&&(s<o.maxStreamChunks?Hr(e,t,s,u):s===o.maxStreamChunks&&e.info({debug_log:!0,reqId:t,phase:"provider_stream_chunk_omitted",message:`[chunks after #${s} omitted, maxStreamChunks=${o.maxStreamChunks}]`}),s++)}i.trim()&&(s<o.maxStreamChunks&&Hr(e,t,s,i.trim()),s++),zr(e,t,s)}catch(i){console.error(`[debug_log] Error reading debug stream for reqId=${t}:`,i),zr(e,t,s)}finally{r.releaseLock()}})()}var La,Le,uo,ct=w(()=>{"use strict";La=new Set(["authorization","x-api-key","x-goog-api-key","cookie","set-cookie"]),Le={maxBodyLength:4096,maxStreamChunks:100},uo=!1});function Kr(n,e,t,o,r){let s=new Headers({"Content-Type":"application/json"});t.headers&&Object.entries(t.headers).forEach(([c,u])=>{u&&s.set(c,u)});let i,l=AbortSignal.timeout(t.TIMEOUT??60*1e3*60);if(t.signal){let c=new AbortController,u=()=>c.abort();t.signal.addEventListener("abort",u),l.addEventListener("abort",u),i=c.signal}else i=l;let a={method:"POST",headers:s,body:JSON.stringify(e),signal:i};return t.httpsProxy&&(a.dispatcher=Q(t.httpsProxy)),r?.debug({reqId:o.req.id,method:"POST",headers:qt(Object.fromEntries(s.entries())),requestUrl:typeof n=="string"?n:n.toString(),useProxy:Fa(t.httpsProxy)},"final request"),fetch(typeof n=="string"?n:n.toString(),a)}function Fa(n){if(!(typeof n!="string"||!n.trim()))try{let e=new URL(n);return e.username||e.password?(e.username="",e.password="",`${e.toString()} (credentials redacted)`):e.toString()}catch{return"[invalid proxy URL]"}}var Qr=w(()=>{se();ct()});var en,po=w(()=>{en="2.3.2393"});var Vr={};Gt(Vr,{getFallbackPromotionStore:()=>De,resetFallbackPromotionStore:()=>Ha});function De(n){return xe||(xe=new fo,n&&xe.configure(n)),xe}function Ha(){xe&&(xe.clearAll(),xe=null)}var ja,fo,xe,tn=w(()=>{"use strict";ie();ja=600*1e3,fo=class{promotions=new Map;enabled=!0;ttlMs=ja;configure(e){e?.enabled!==void 0&&(this.enabled=e.enabled),e?.ttlMinutes!==void 0&&(this.ttlMs=e.ttlMinutes*60*1e3)}getKey(e,t,o){return`${e},${t}:${o}`}promote(e,t,o,r,s,i){if(!this.enabled)return;let l=this.getKey(e,t,o),a=`${r},${s}`;this.promotions.set(l,{promotedModel:a,timestamp:Date.now(),ttlMs:i??this.ttlMs})}getPromotion(e,t,o,r){if(!this.enabled)return null;let s=this.getKey(e,t,o),i=this.promotions.get(s);if(!i)return null;if(Date.now()-i.timestamp>=i.ttlMs)return this.promotions.delete(s),null;let[a,...c]=i.promotedModel.split(","),u=c.join(",");if(!U().isAvailable(a,u))return this.promotions.delete(s),null;let g=r.find(y=>y.name.toLowerCase()===a.toLowerCase()),m=g?.models?.find(y=>String(y).toLowerCase()===u.toLowerCase());return!g||!m||g.enabled===!1?(this.promotions.delete(s),null):`${g.name},${m}`}clear(e,t,o){let r=this.getKey(e,t,o);this.promotions.delete(r)}clearByPrimary(e,t){let o=`${e},${t}:`,r=0;for(let s of this.promotions.keys())s.startsWith(o)&&(this.promotions.delete(s),r++);return r}clearAll(){this.promotions.clear()}clearExpired(){let e=Date.now();for(let[t,o]of this.promotions)e-o.timestamp>=o.ttlMs&&this.promotions.delete(t)}getAllPromotions(){let e=Date.now(),t=[];for(let[o,r]of this.promotions){let s=r.ttlMs-(e-r.timestamp);s>0&&t.push({key:o,promotedModel:r.promotedModel,remainingMs:s})}return t}},xe=null});function Wa(n){try{if(!(0,pe.existsSync)(ho))return;let e=JSON.parse((0,pe.readFileSync)(ho,"utf-8"));if(!Array.isArray(e))return;let t=Date.now();for(let o of e){if(!o||!o.provider||!o.model)continue;let r=o.updatedAt||o.lastFailureTime||0;r&&t-r>1440*60*1e3||n.restore({provider:o.provider,model:o.model,status:o.status,failureCount:o.failureCount??0,successCount:o.successCount??0,lastFailureTime:o.lastFailureTime??0,lastProbeTime:o.lastProbeTime??0,lastError:o.lastError,rateLimitUntil:o.rateLimitUntil})}}catch{}}function Xr(n){try{let e=n.getAllStates();if(e.length===0)return;(0,pe.existsSync)(go)||(0,pe.mkdirSync)(go,{recursive:!0});let t=e.map(o=>({...o,updatedAt:Date.now()}));(0,pe.writeFileSync)(ho,JSON.stringify(t,null,2),"utf-8")}catch{}}function nn(){if(Yr)return;Yr=!0;let n=U();Wa(n),Ja=setInterval(()=>Xr(n),6e4),process.on("exit",()=>Xr(n))}function U(n){return mo||(mo=new lt(n)),mo}var pe,yo,qr,za,Ba,lt,go,ho,Yr,Ja,mo,ie=w(()=>{"use strict";pe=require("fs"),yo=require("path"),qr=require("@wengine-ai/claude-code-router-shared"),za=120,Ba={enabled:!0,failureThreshold:3,probeIntervalMinutes:5,halfOpenSuccessThreshold:2},lt=class{states=new Map;config;probeTimer;constructor(e){this.config={...Ba,...e}}getKey(e,t){return!e||!t?null:`${e},${t}`}recordSuccess(e,t){if(!this.config.enabled)return;let o=this.getKey(e,t);if(!o)return;let r=this.states.get(o);r&&(r.successCount++,!r.rateLimitUntil&&(r.status==="half-open"?r.successCount>=this.config.halfOpenSuccessThreshold&&(this.clearPromotionsForPrimary(e,t),this.states.delete(o)):r.status==="open"&&(r.status="half-open",r.successCount=1,r.failureCount=0)))}clearPromotionsForPrimary(e,t){try{let{getFallbackPromotionStore:o}=(tn(),$r(Vr));o().clearByPrimary(e,t)}catch{}}recordFailure(e,t,o){if(!this.config.enabled)return;let r=this.getKey(e,t);if(!r)return;let s=this.states.get(r);s||(s={provider:e,model:t,status:"closed",failureCount:0,successCount:0,lastFailureTime:0,lastProbeTime:0},this.states.set(r,s)),s.failureCount++,s.lastFailureTime=Date.now(),s.lastError=o,s.status==="half-open"?(s.status="open",s.successCount=0,s.lastProbeTime=0):s.status==="closed"&&s.failureCount>=this.config.failureThreshold&&(s.status="open",s.lastProbeTime=0)}getState(e,t){let o=this.getKey(e,t);if(o)return this.states.get(o)}isAvailable(e,t){if(!this.config.enabled)return!0;if(!this.getKey(e,t))return!1;let r=this.getState(e,t);return r?r.status==="open"&&r.rateLimitUntil?!(Date.now()<r.rateLimitUntil):r.status!=="open":!0}getPriority(e,t){if(!this.config.enabled)return 0;if(!this.getKey(e,t))return 2;let r=this.getState(e,t);if(!r)return 0;switch(r.status){case"closed":return 0;case"half-open":return 1;case"open":return 2}}getHealthyModels(){return[]}getFailPoolModels(){let e=[];for(let[t,o]of this.states)o.status==="open"&&e.push(t);return e}getHalfOpenModels(){let e=[];for(let[t,o]of this.states)o.status==="half-open"&&e.push(t);return e}forceOpen(e,t,o){if(!this.config.enabled)return;let r=this.getKey(e,t);if(!r)return;let s=this.states.get(r);s?(s.status="open",s.failureCount=Math.max(s.failureCount,this.config.failureThreshold),s.lastFailureTime=Date.now(),s.lastError=o,s.lastProbeTime=0):(s={provider:e,model:t,status:"open",failureCount:this.config.failureThreshold,successCount:0,lastFailureTime:Date.now(),lastProbeTime:0,lastError:o},this.states.set(r,s))}markRateLimited(e,t,o,r){if(!this.config.enabled)return;let s=this.getKey(e,t);if(!s)return;let i=this.states.get(s);i?(i.status="open",i.lastFailureTime=Date.now(),i.lastError=r||"rate-limited",i.lastProbeTime=0):(i={provider:e,model:t,status:"open",failureCount:0,successCount:0,lastFailureTime:Date.now(),lastProbeTime:0,lastError:r||"rate-limited"},this.states.set(s,i));let l=(o??za)*1e3;i.rateLimitUntil=Date.now()+l}getRateLimitedModels(){let e=[];for(let[t,o]of this.states)o.status==="open"&&o.rateLimitUntil&&e.push(t);return e}needsProbe(e){return Date.now()-e.lastProbeTime>=this.config.probeIntervalMinutes*60*1e3}markProbeAttempt(e,t){let o=this.getKey(e,t);if(!o)return;let r=this.states.get(o);r&&r.status==="open"&&(r.lastProbeTime=Date.now())}clear(){this.states.clear()}recover(e,t){let o=this.getKey(e,t);o&&this.states.delete(o)}getAllStates(){return Array.from(this.states.values())}restore(e){let t=this.getKey(e.provider,e.model);t&&this.states.set(t,{...e})}stopProbeTimer(){this.probeTimer&&(clearInterval(this.probeTimer),this.probeTimer=void 0)}},go=(0,yo.join)(qr.HOME_DIR,"runtime"),ho=(0,yo.join)(go,"provider-health.json"),Yr=!1,Ja=null;mo=null});function ut(n,e,t){let o=l=>{if(t instanceof Headers)return t.get(l);let a=Object.keys(t).find(c=>c.toLowerCase()===l);return a?t[a]:null},r=_o(o,Ga),s=_o(o,Ka),i=_o(o,Qa);(r||s||i)&&Fe.set(n,{provider:n,remaining:ts(r),limit:ts(s),reset:Va(i),capturedAt:Date.now()})}function rs(n){return Fe.get(n)}function on(){return Array.from(Fe.values())}function _o(n,e){for(let t of e){let o=n(t);if(o)return o}return null}function ts(n){if(!n)return null;let e=Number(n.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function Va(n){if(!n)return null;let e=n.trim();if(!e)return null;let t=Number(e);if(Number.isFinite(t))return t>1e12?Math.floor(t/1e3):t>1e9?Math.floor(t):Math.floor(Date.now()/1e3+t);let o=Date.parse(e);if(Number.isFinite(o))return Math.floor(o/1e3);let r=Ya(e);return r===null?null:Math.floor((Date.now()+r)/1e3)}function Ya(n){let e=/(\d+(?:\.\d+)?)(ms|s|m|h|d)/gi,t=0,o=!1;for(let r of n.matchAll(e)){o=!0;let s=Number(r[1]),i=r[2].toLowerCase();if(Number.isFinite(s))switch(i){case"ms":t+=s;break;case"s":t+=s*1e3;break;case"m":t+=s*60*1e3;break;case"h":t+=s*60*60*1e3;break;case"d":t+=s*24*60*60*1e3;break}}return o?t:null}function Xa(){try{if(!(0,fe.existsSync)(bo))return;let n=JSON.parse((0,fe.readFileSync)(bo,"utf-8"));if(!Array.isArray(n))return;let e=Date.now();for(let t of n)if(t&&t.provider){if(t.capturedAt&&e-t.capturedAt>3600*1e3)continue;Fe.set(t.provider,t)}}catch{}}function ns(){try{if(Fe.size===0)return;(0,fe.existsSync)(ko)||(0,fe.mkdirSync)(ko,{recursive:!0}),(0,fe.writeFileSync)(bo,JSON.stringify(Array.from(Fe.values()),null,2),"utf-8")}catch{}}function Ue(){Zr||(Zr=!0,Xa(),es=setInterval(ns,6e4),es.unref?.(),process.on("exit",ns))}var fe,To,os,ko,bo,Fe,Zr,es,Ga,Ka,Qa,je=w(()=>{"use strict";fe=require("fs"),To=require("path"),os=require("@wengine-ai/claude-code-router-shared"),ko=(0,To.join)(os.HOME_DIR,"runtime"),bo=(0,To.join)(ko,"rate-limit.json"),Fe=new Map,Zr=!1,es=null,Ga=["x-ratelimit-remaining-tokens","x-ratelimit-remaining-requests","x-ratelimit-remaining"],Ka=["x-ratelimit-limit-tokens","x-ratelimit-limit-requests","x-ratelimit-limit"],Qa=["x-ratelimit-reset-tokens","x-ratelimit-reset-requests","x-ratelimit-reset"]});var He,Co=w(()=>{"use strict";He=class{name="openai-responses";endPoint="/v1/responses";getCacheReadInputTokens(e){return e?.cache_read_input_tokens??e?.input_tokens_details?.cached_tokens??e?.prompt_tokens_details?.cached_tokens??0}getCacheCreationInputTokens(e){return e?.cache_creation_input_tokens??e?.input_tokens_details?.cache_creation_tokens??e?.input_tokens_details?.cache_write_tokens??e?.prompt_tokens_details?.cache_creation_tokens??e?.prompt_tokens_details?.cache_write_tokens??0}buildResponsesUsage(e){let t=e?.input_tokens??e?.prompt_tokens??0,o=e?.output_tokens??e?.completion_tokens??0,r=this.getCacheReadInputTokens(e),s=this.getCacheCreationInputTokens(e);return{input_tokens:t,output_tokens:o,total_tokens:e?.total_tokens??t+o,input_tokens_details:{cached_tokens:r,cache_creation_tokens:s},output_tokens_details:{reasoning_tokens:e?.output_tokens_details?.reasoning_tokens??0},cache_read_input_tokens:r,cache_creation_input_tokens:s}}async transformRequestIn(e){delete e.temperature,delete e.max_tokens,e.reasoning&&(e.reasoning={effort:e.reasoning.effort,summary:e.reasoning.summary||"auto"});let t=[],o=e.messages.filter(r=>r.role==="system");if(o.length>0){let r=o[0];Array.isArray(r.content)?r.content.forEach(s=>{let i="";typeof s=="string"?i=s:s&&typeof s=="object"&&"text"in s&&(i=s.text),t.push({role:"system",content:i})}):e.instructions=r.content}if(e.messages.forEach(r=>{if(r.role!=="system"){if(Array.isArray(r.content)){let s=r.content.map(i=>this.normalizeRequestContent(i,r.role)).filter(i=>i!==null);s.length>0?r.content=s:delete r.content}if(r.role==="tool"){let s={...r};s.type="function_call_output",s.call_id=r.tool_call_id,s.output=r.content,delete s.cache_control,delete s.role,delete s.tool_call_id,delete s.content,t.push(s);return}if(r.role==="assistant"&&Array.isArray(r.tool_calls)){r.tool_calls.forEach(s=>{t.push({type:"function_call",arguments:s.function.arguments,name:s.function.name,call_id:s.id})});return}t.push(r)}}),e.input=t,delete e.messages,Array.isArray(e.tools)){let r=e.tools.find(s=>s.function.name==="web_search");e.tools=e.tools.filter(s=>s.function.name!=="web_search").map(s=>(s.function.name==="WebSearch"&&delete s.function.parameters.properties.allowed_domains,s.function.name==="Edit"?{type:s.type,name:s.function.name,description:s.function.description,parameters:{...s.function.parameters,required:["file_path","old_string","new_string","replace_all"]},strict:!0}:{type:s.type,name:s.function.name,description:s.function.description,parameters:s.function.parameters})),r&&e.tools.push({type:"web_search"})}return e.parallel_tool_calls=!1,e}async transformResponseOut(e){let t=e.headers.get("Content-Type")||"";if(t.includes("application/json")){let o=await e.json();if(o.object==="response"&&o.output){let r=this.convertResponseToChat(o);return new Response(JSON.stringify(r),{status:e.status,statusText:e.statusText,headers:e.headers})}return o.type==="message"&&Array.isArray(o.content)?new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers}):new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers})}else if(t.includes("text/event-stream")){if(!e.body)return e;let[o,r]=e.body.tee(),s=o.getReader(),i="";try{let{value:f,done:_}=await s.read();!_&&f&&(i=new TextDecoder().decode(f))}finally{s.releaseLock()}if(o.cancel().catch(()=>{}),i.includes("message_start")||i.includes("content_block_start")){let f=this.prependToStream(i,r);return new Response(f,{status:e.status,statusText:e.statusText,headers:e.headers})}if(i.includes("response.created")||i.includes("response.output_text.delta")||i.includes("response.in_progress")||i.includes("response.output_item.added")){let f=this.prependToStream(i,r);return new Response(f,{status:e.status,statusText:e.statusText,headers:e.headers})}let c=this.prependToStream(i,r),u=new TextDecoder,d=new TextEncoder,g="",m=!1,y=this,p=new ReadableStream({async start(f){let _=c.getReader(),k=-1,h="",b=T=>(T!==h&&(k++,h=T),k);try{for(;;){let{done:T,value:x}=await _.read();if(T){m||f.enqueue(d.encode(`data: [DONE]
|
|
4
4
|
|
|
5
|
-
`));break}let v=u.decode(x,{stream:!0});g+=v;let S=g.split(/\r?\n/);g=S.pop()||"";for(let C of S)if(C.trim())try{if(C.startsWith("event: "))continue;if(C.startsWith("data: ")){let
|
|
5
|
+
`));break}let v=u.decode(x,{stream:!0});g+=v;let S=g.split(/\r?\n/);g=S.pop()||"";for(let C of S)if(C.trim())try{if(C.startsWith("event: "))continue;if(C.startsWith("data: ")){let E=C.slice(5).trim();if(E==="[DONE]"){m=!0,f.enqueue(d.encode(`data: [DONE]
|
|
6
6
|
|
|
7
|
-
`));continue}try{let R=JSON.parse(
|
|
7
|
+
`));continue}try{let R=JSON.parse(E);if(R.type==="response.output_text.delta"){let A={id:R.item_id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model,choices:[{index:b(R.type),delta:{content:R.delta||""},finish_reason:null}]};f.enqueue(d.encode(`data: ${JSON.stringify(A)}
|
|
8
8
|
|
|
9
9
|
`))}else if(R.type==="response.output_item.added"&&R.item?.type==="function_call"){let A={id:R.item.call_id||R.item.id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model||"gpt-5-codex-",choices:[{index:b(R.type),delta:{role:"assistant",tool_calls:[{index:0,id:R.item.call_id||R.item.id,function:{name:R.item.name||"",arguments:""},type:"function"}]},finish_reason:null}]};f.enqueue(d.encode(`data: ${JSON.stringify(A)}
|
|
10
10
|
|
|
11
|
-
`))}else if(R.type==="response.output_item.added"&&R.item?.type==="message"){let A=[];(R.item.content||[]).forEach(I=>{I.type==="output_text"&&A.push({type:"text",text:I.text||""})});let
|
|
11
|
+
`))}else if(R.type==="response.output_item.added"&&R.item?.type==="message"){let A=[];(R.item.content||[]).forEach(I=>{I.type==="output_text"&&A.push({type:"text",text:I.text||""})});let O={role:"assistant"};if(A.length===1&&A[0].type==="text"?O.content=A[0].text:A.length>0&&(O.content=A),O.content){let I={id:R.item.id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model,choices:[{index:b(R.type),delta:O,finish_reason:null}]};f.enqueue(d.encode(`data: ${JSON.stringify(I)}
|
|
12
12
|
|
|
13
13
|
`))}}else if(R.type==="response.output_text.annotation.added"){let A={id:R.item_id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model||"gpt-5-codex",choices:[{index:b(R.type),delta:{annotations:[{type:"url_citation",url_citation:{url:R.annotation?.url||"",title:R.annotation?.title||"",content:"",start_index:R.annotation?.start_index||0,end_index:R.annotation?.end_index||0}}]},finish_reason:null}]};f.enqueue(d.encode(`data: ${JSON.stringify(A)}
|
|
14
14
|
|
|
15
15
|
`))}else if(R.type==="response.function_call_arguments.delta"){let A={id:R.item_id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model||"gpt-5-codex-",choices:[{index:b(R.type),delta:{tool_calls:[{index:0,function:{arguments:R.delta||""}}]},finish_reason:null}]};f.enqueue(d.encode(`data: ${JSON.stringify(A)}
|
|
16
16
|
|
|
17
|
-
`))}else if(R.type==="response.completed"){let A=R.response?.output?.some(I=>I.type==="function_call")?"tool_calls":"stop",
|
|
17
|
+
`))}else if(R.type==="response.completed"){let A=R.response?.output?.some(I=>I.type==="function_call")?"tool_calls":"stop",O={id:R.response?.id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model||"gpt-5-codex-",choices:[{index:0,delta:{},finish_reason:A}]};f.enqueue(d.encode(`data: ${JSON.stringify(O)}
|
|
18
18
|
|
|
19
19
|
`)),m=!0}else if(R.type==="response.reasoning_summary_text.delta"){let A={id:R.item_id||"chatcmpl-"+Date.now(),object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:R.response?.model,choices:[{index:b(R.type),delta:{thinking:{content:R.delta||""}},finish_reason:null}]};f.enqueue(d.encode(`data: ${JSON.stringify(A)}
|
|
20
20
|
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
`))}}catch{f.enqueue(d.encode(C+`
|
|
24
24
|
`))}}else f.enqueue(d.encode(C+`
|
|
25
|
-
`))}catch(
|
|
25
|
+
`))}catch(E){console.error("Error processing line:",C,E),f.enqueue(d.encode(C+`
|
|
26
26
|
`))}}g.trim()&&f.enqueue(d.encode(g+`
|
|
27
27
|
`)),m||f.enqueue(d.encode(`data: [DONE]
|
|
28
28
|
|
|
@@ -32,38 +32,38 @@ data: ${JSON.stringify(f)}
|
|
|
32
32
|
`),y=(p,f=[])=>({id:i,object:"response",created_at:Math.floor(Date.now()/1e3),status:p,model:s,output:f,usage:this.buildResponsesUsage()});return new ReadableStream({async start(p){try{let f=e.getReader(),_="",k=!1,h=b=>{if(!k){k=!0;for(let T of g)if(T.type==="function_call"){let x=g.indexOf(T);p.enqueue(m("response.function_call_arguments.done",{type:"response.function_call_arguments.done",item_id:T.call_id||T.id,output_index:x,arguments:T.arguments||""})),T.status="completed",p.enqueue(m("response.output_item.done",{type:"response.output_item.done",output_index:x,item:T}))}for(let T of g)if(T.type==="message"){let x=g.indexOf(T);T.status="completed",p.enqueue(m("response.output_item.done",{type:"response.output_item.done",output_index:x,item:T}))}p.enqueue(m("response.completed",{type:"response.completed",response:{id:i,object:"response",created_at:Math.floor(Date.now()/1e3),status:"completed",model:b?.model||s,output:g.slice(),usage:b?.usage?{...this.buildResponsesUsage(b.usage)}:this.buildResponsesUsage()}}))}};for(;;){let{done:b,value:T}=await f.read();if(b)break;_+=o.decode(T,{stream:!0});let x=_.split(`
|
|
33
33
|
`);_=x.pop()||"";for(let v of x){let S=v.trim();if(!S||S.startsWith("event:")||!S.startsWith("data:"))continue;let C=S.slice(5).trim();if(C==="[DONE]"){h({}),p.enqueue(r.encode(`data: [DONE]
|
|
34
34
|
|
|
35
|
-
`));continue}let
|
|
35
|
+
`));continue}let E;try{E=JSON.parse(C)}catch{continue}a||(a=!0,p.enqueue(m("response.created",{type:"response.created",response:y("in_progress")})),p.enqueue(m("response.in_progress",{type:"response.in_progress",response:y("in_progress")})));let R=E.choices?.[0];if(!R)continue;let A=R.delta;if(A?.content){if(!c){c=!0;let O=l++,I={id:`${i}_msg`,type:"message",status:"in_progress",role:"assistant",content:[]};g.push(I),p.enqueue(m("response.output_item.added",{type:"response.output_item.added",output_index:O,item:I}))}p.enqueue(m("response.output_text.delta",{type:"response.output_text.delta",item_id:`${i}_msg`,output_index:l-1,content_index:0,delta:A.content}))}if(Array.isArray(A?.tool_calls))for(let O of A.tool_calls){if(O.id){u=O.id,d=l++;let I={id:O.id,type:"function_call",status:"in_progress",call_id:O.id,name:O.function?.name||"",arguments:""};g.push(I),p.enqueue(m("response.output_item.added",{type:"response.output_item.added",output_index:d,item:I}))}if(O.function?.arguments){p.enqueue(m("response.function_call_arguments.delta",{type:"response.function_call_arguments.delta",item_id:u,output_index:d,delta:O.function.arguments}));let I=g.find(L=>L.call_id===u);I&&(I.arguments+=O.function.arguments)}}R.finish_reason&&h(E)}}k||h({}),p.close()}catch(f){p.error(f)}}})}convertAnthropicStreamToResponsesAPI(e,t){let o=new TextDecoder,r=new TextEncoder,s=t?.provider?.models?.[0]||"gpt-5.4",i=`resp_${Date.now()}`,l="",a="",c=-1,u="",d="",g="",m=-1,y="",p="",f=-1,_=0,k=!1,h=!1,b=!1,T=!1,x=null,v=[],S=(I,L)=>r.encode(`event: ${I}
|
|
36
36
|
data: ${JSON.stringify(L)}
|
|
37
37
|
|
|
38
|
-
`),C=(I,L=[])=>({id:i,object:"response",created_at:Math.floor(Date.now()/1e3),status:I,model:s,output:L,usage:this.buildResponsesUsage()}),
|
|
39
|
-
`);F=K.pop()||"";for(let Ce of K){let H=Ce.trim();if(!H||H.startsWith("event:")||!H.startsWith("data:"))continue;let te=H.slice(5).trim();if(te==="[DONE]")continue;let B;try{B=JSON.parse(te)}catch{continue}if(B.type==="message_start"&&(i=B.message?.id||i,
|
|
38
|
+
`),C=(I,L=[])=>({id:i,object:"response",created_at:Math.floor(Date.now()/1e3),status:I,model:s,output:L,usage:this.buildResponsesUsage()}),E=()=>{k||(k=!0,O.enqueue(S("response.created",{type:"response.created",response:C("in_progress")})),O.enqueue(S("response.in_progress",{type:"response.in_progress",response:C("in_progress")})))},R=(I,L)=>{O.enqueue(S("response.output_item.done",{type:"response.output_item.done",output_index:I,item:{...L,status:"completed"}}))},A=I=>{if(!T){if(T=!0,h){let L=v.find(F=>F.type==="message");L&&(L.content=[{type:"output_text",text:l}],L.status="completed")}for(let L of v)L.type==="function_call"&&(L.status="completed");return S("response.completed",{type:"response.completed",response:{id:i,object:"response",created_at:Math.floor(Date.now()/1e3),status:"completed",model:s,output:v,usage:I?{...this.buildResponsesUsage(I)}:this.buildResponsesUsage()}})}},O;return new ReadableStream({async start(I){O=I;try{let L=e.getReader(),F="";for(;;){let{done:N,value:D}=await L.read();if(N)break;F+=o.decode(D,{stream:!0});let K=F.split(`
|
|
39
|
+
`);F=K.pop()||"";for(let Ce of K){let H=Ce.trim();if(!H||H.startsWith("event:")||!H.startsWith("data:"))continue;let te=H.slice(5).trim();if(te==="[DONE]")continue;let B;try{B=JSON.parse(te)}catch{continue}if(B.type==="message_start"&&(i=B.message?.id||i,E()),B.type==="content_block_start"){let M=B.content_block;if(x=M?.type||null,M?.type==="tool_use"){u=M.id||"",d=M.name||"",g="",m=_++;let W={id:u,type:"function_call",status:"in_progress",call_id:u,name:d,arguments:""};v.push(W),O.enqueue(S("response.output_item.added",{type:"response.output_item.added",output_index:m,item:W}))}if(M?.type==="thinking"&&(y=M.thinking||"",!b)){b=!0,f=_++,p=`rs_${i}`;let W={id:p,type:"reasoning",status:"in_progress",summary:[]};v.push(W),O.enqueue(S("response.output_item.added",{type:"response.output_item.added",output_index:f,item:W}))}if(M?.type==="text"&&(l=M?.text||"",!h)){h=!0,c=_++,a=`${i}_msg`;let W={id:a,type:"message",status:"in_progress",role:"assistant",content:[]};v.push(W),O.enqueue(S("response.output_item.added",{type:"response.output_item.added",output_index:c,item:W}))}}if(B.type==="content_block_delta"){let M=B.delta;if(M?.type==="text_delta"){if(!h){h=!0,c=_++,a=`${i}_msg`;let W={id:a,type:"message",status:"in_progress",role:"assistant",content:[]};v.push(W),O.enqueue(S("response.output_item.added",{type:"response.output_item.added",output_index:c,item:W}))}l+=M.text||"",O.enqueue(S("response.output_text.delta",{type:"response.output_text.delta",item_id:a,output_index:c,content_index:0,delta:M.text||""}))}M?.type==="thinking_delta"&&(y+=M.thinking||"",O.enqueue(S("response.reasoning_summary_text.delta",{type:"response.reasoning_summary_text.delta",item_id:p||`rs_${i}`,output_index:f>=0?f:0,summary_index:0,delta:M.thinking||""}))),M?.type==="input_json_delta"&&(g+=M.partial_json||"",O.enqueue(S("response.function_call_arguments.delta",{type:"response.function_call_arguments.delta",item_id:u||"call_0",output_index:m>=0?m:0,delta:M.partial_json||""})))}if(B.type==="content_block_stop"){if(x==="tool_use"&&u){O.enqueue(S("response.function_call_arguments.done",{type:"response.function_call_arguments.done",item_id:u,output_index:m,arguments:g}));let M=v.find(W=>W.call_id===u);M&&(M.arguments=g,M.status="completed"),M&&R(m,M)}if(x==="text"&&h){O.enqueue(S("response.output_text.done",{type:"response.output_text.done",item_id:a,output_index:c,content_index:0,text:l}));let M=v.find(W=>W.type==="message");M&&(M.content=[{type:"output_text",text:l}],R(c,M))}if(x==="thinking"&&b){let M=v.find(W=>W.type==="reasoning");M&&(M.summary=[{type:"summary_text",text:y}],R(f,M))}x=null}if(B.type==="message_delta"){let M=A(B.usage);M&&O.enqueue(M)}if(B.type==="message_stop"){let M=A();M&&O.enqueue(M),O.enqueue(r.encode(`data: [DONE]
|
|
40
40
|
|
|
41
|
-
`))}}}P();let z=A();z&&E.enqueue(z),F="",E.close()}catch(L){E.error(L)}}})}wrapChatInResponses(e){let t=e?.choices?.[0],o=[],r=[];if(t?.message?.content&&r.push({type:"output_text",text:t.message.content}),o.push({type:"message",role:"assistant",content:r}),Array.isArray(t?.message?.tool_calls))for(let s of t.message.tool_calls)o.push({type:"function_call",id:s.id,call_id:s.id,name:s.function?.name||"",arguments:s.function?.arguments||"{}"});return{id:e.id||`resp_${Date.now()}`,object:"response",model:e.model,output:o,usage:e.usage?{...this.buildResponsesUsage(e.usage)}:void 0}}convertResponseToChat(e){let t=e.output?.find(c=>c.type==="message"),o=e.output?.find(c=>c.type==="function_call"),r;t?.content?.length&&t?.content[0].annotations&&(r=t.content[0].annotations.map(c=>({type:"url_citation",url_citation:{url:c.url||"",title:c.title||"",content:"",start_index:c.start_index||0,end_index:c.end_index||0}}))),this.logger.debug({data:r,type:"url_citation"});let s=null,i=null,l=null;if(t&&t.reasoning&&(l={content:t.reasoning}),t&&t.content){let c=[],u=[];if(t.content.forEach(d=>{if(d.type==="output_text")c.push(d.text||"");else if(d.type==="output_image"){let g=this.buildImageContent({url:d.image_url,mime_type:d.mime_type});g&&u.push(g)}else if(d.type==="output_image_base64"){let g=this.buildImageContent({b64_json:d.image_base64,mime_type:d.mime_type});g&&u.push(g)}}),u.length>0){let d=[];c.length>0&&d.push({type:"text",text:c.join("")}),d.push(...u),s=d}else s=c.join("")}return o&&(i=[{id:o.call_id||o.id,function:{name:o.name,arguments:o.arguments},type:"function"}]),{id:e.id||"chatcmpl-"+Date.now(),object:"chat.completion",created:e.created_at,model:e.model,choices:[{index:0,message:{role:"assistant",content:s||null,tool_calls:i,thinking:l,annotations:r},logprobs:null,finish_reason:i?"tool_calls":"stop"}],usage:e.usage?{prompt_tokens:e.usage.input_tokens||0,completion_tokens:e.usage.output_tokens||0,total_tokens:e.usage.total_tokens||0,prompt_tokens_details:{cached_tokens:this.getCacheReadInputTokens(e.usage),cache_creation_tokens:this.getCacheCreationInputTokens(e.usage)},cache_read_input_tokens:this.getCacheReadInputTokens(e.usage),cache_creation_input_tokens:this.getCacheCreationInputTokens(e.usage)}:null}}buildImageContent(e){return e&&(e.url||e.b64_json)?{type:"image_url",image_url:{url:e.url||"",b64_json:e.b64_json},media_type:e.mime_type}:null}}});var vo,q,rn=w(()=>{"use strict";vo=class{capacity;cache;constructor(e){this.capacity=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;let t=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,t),t}put(e,t){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.capacity){let o=this.cache.keys().next().value;o!==void 0&&this.cache.delete(o)}this.cache.set(e,t)}values(){return Array.from(this.cache.values())}delete(e){return this.cache.delete(e)}},q=new vo(100)});function sn(n,e){n&&ze.set(n,{...e,provider:n,capturedAt:Date.now()})}function dt(n){let e=ze.get(n);return e?{...e}:void 0}function an(){return Array.from(ze.values()).map(n=>({...n}))}function qa(){try{if(!(0,me.existsSync)(So))return;let n=JSON.parse((0,me.readFileSync)(So,"utf-8"));if(!Array.isArray(n))return;let e=Date.now();for(let t of n)if(t&&t.provider){if(t.capturedAt&&e-t.capturedAt>1440*60*1e3)continue;ze.set(t.provider,t)}}catch{}}function as(){try{if(ze.size===0)return;(0,me.existsSync)(xo)||(0,me.mkdirSync)(xo,{recursive:!0}),(0,me.writeFileSync)(So,JSON.stringify(Array.from(ze.values()),null,2),"utf-8")}catch{}}function Be(){ss||(ss=!0,qa(),is=setInterval(as,6e4),is.unref?.(),process.on("exit",as))}var me,Ro,cs,xo,So,ze,ss,is,Je=w(()=>{"use strict";me=require("fs"),Ro=require("path"),cs=require("@wengine-ai/claude-code-router-shared"),xo=(0,Ro.join)(cs.HOME_DIR,"runtime"),So=(0,Ro.join)(xo,"quota-store.json"),ze=new Map,ss=!1,is=null});function Se(n){if(typeof n!="string")return;let e=n.trim();if(!(!e||!Za.test(e)))return e}function We(n){if(!n)return;if(typeof n=="object")return Se(n.session_id??n.sessionId);if(typeof n!="string")return;let e=n.trim();if(!e)return;try{let r=JSON.parse(e),s=Se(r?.session_id??r?.sessionId);if(s)return s}catch{}let t="_session_",o=e.lastIndexOf(t);if(o!==-1)return Se(e.slice(o+t.length))}var Za,pt=w(()=>{"use strict";Za=/^[A-Za-z0-9_-]+$/});function tc(n){if(typeof n=="string")return n.slice(0,1e3);if(Array.isArray(n)){let e=n.find(t=>t&&typeof t.text=="string");return e?String(e.text).slice(0,1e3):""}return""}function nc(n){if(typeof n?.pathname=="string")return n.pathname;if(typeof n?.url!="string")return"";try{return new URL(n.url,"http://127.0.0.1").pathname}catch{return n.url}}function ft(n,e=!0){return{clientType:n,usageScope:"request",supportsExplicitExtendedContext:e}}function us(n,e,t=!0){let o=We(n?.body?.metadata?.user_id);return{clientType:e,usageScope:o?"session":"request",stableSessionId:o,supportsExplicitExtendedContext:t}}function Po(n){return typeof n=="string"&&ec.includes(n)}function Re(n){if(Po(n?.clientType))return n.clientType;let e=nc(n),t=n?.headers||{},o=typeof t["user-agent"]=="string"?t["user-agent"]:"",r=n?.body||{},s=tc(r.system);if(/\bYou are Qwen Code\b/i.test(s)||/Qwen Code, an interactive CLI agent/i.test(s))return"qwen-code";if(/operating inside pi\b/i.test(s)||/a coding agent harness/i.test(s))return"pi";if(/\bYou are opencode\b/i.test(s))return"opencode";let i=t["x-anthropic-billing-header"];if(typeof i=="string"&&i.includes("cc_version="))return"claude-code";if(o.includes("codex")||o.includes("Codex")||e.endsWith("/v1/responses"))return"codex";if(r.metadata&&typeof r.metadata=="object"&&typeof r.metadata.user_id=="string")return"claude-code";if(o.includes("opencode"))return"opencode";if(o.includes("pi-coding-agent"))return"pi";if(o.includes("QwenCode"))return"qwen-code";let l=n?.originalModel||r.model||"";return/^ccr-(opus|sonnet|haiku)(\[1m\])?$/i.test(l)?o.includes("Anthropic/")?"pi":o.includes("claude-cli")||o.includes("Claude-CLI")?"qwen-code":typeof t["x-stainless-package-version"]=="string"?"pi":"claude-code":o.includes("claude-cli")||o.includes("Claude-CLI")?"claude-code":String(l).toLowerCase()==="ccr-codex"?"codex":e.endsWith("/v1/messages")?"api":"unknown"}function Eo(n){return wo[n]}function uc(n){if(typeof n?.__ccrRequestScopeId=="string"&&n.__ccrRequestScopeId)return n.__ccrRequestScopeId;let e=typeof n?.id=="string"&&n.id||(0,ls.randomUUID)();return n.__ccrRequestScopeId=e,e}function he(n,e={}){let t=Re(n),o=Eo(t).createContext(n,e),r=o.stableSessionId||uc(n),s=o.usageScope==="session"?"session":"request";return n.clientType=t,n.clientContext=o,o.stableSessionId?n.sessionId=o.stableSessionId:delete n.sessionId,n.usageSessionId=r,n.usageCacheKey=`${t}:${s}:${r}`,o}function ds(){}var ls,ec,oc,rc,sc,ic,ac,cc,lc,wo,Ge=w(()=>{"use strict";ls=require("node:crypto");pt();ec=["claude-code","pi","qwen-code","opencode","codex","api","unknown"];oc={type:"claude-code",createContext(n){return us(n,"claude-code")}},rc={type:"pi",createContext(){return ft("pi",!1)}},sc={type:"qwen-code",createContext(n){return us(n,"qwen-code")}},ic={type:"opencode",createContext(){return ft("opencode")}},ac={type:"codex",createContext(){return ft("codex")}},cc={type:"api",createContext(){return ft("api")}},lc={type:"unknown",createContext(){return ft("unknown")}},wo={"claude-code":oc,pi:rc,"qwen-code":sc,opencode:ic,codex:ac,api:cc,unknown:lc}});function ne(n,e,t,o){let r=Oo(e,t),s=n.sessionId||n.clientContext?.stableSessionId,i=hs[r.code]||502;throw new ue(`Project routing error (${o}): ${r.reason}. Project-level Router target: "${e}". Session: "${s||"unknown"}".`,{sessionId:s,configuredTarget:e,code:r.code,statusCode:i})}function dn(n){let e=n||"";return e.includes(",")&&(e=e.split(",").pop()||e),e.includes("/")&&(e=e.split("/").pop()||e),e.includes(":")&&(e=e.split(":")[0]),e.trim().toLowerCase()}function ht(n){let e=dn(n),t=e.includes("[1m]")||e.endsWith("[1m"),o=e.replace(/\[1m\]|\[1m$/g,""),r=o.match(/^ccr-(opus|sonnet|haiku)$/i);if(r)return{family:r[1].toLowerCase(),extended:t,isCcrAlias:!0};let s=o.match(/claude-(?:\d+-\d+-|\d+-)?(sonnet|opus|haiku)(?:-|$)/i)||o.match(/claude-(sonnet|opus|haiku)(?:-|$)/i);return s?{family:s[1].toLowerCase(),extended:t,isCcrAlias:!1}:{family:null,extended:t,isCcrAlias:!1}}function pc(n,e){if(!e||!n)return null;let t=dn(n);if(e[n])return e[n];if(e[t])return e[t];let{family:o}=ht(n);if(o&&e[o])return e[o];for(let[r,s]of Object.entries(e)){let i=dn(r);if(i&&t.includes(i))return s}return null}function fc(n){return n?(n.input_tokens||0)+(n.cache_read_input_tokens||0)+(n.cache_creation_input_tokens||0):0}function cn(n){if(!n?.includes(","))return null;let[e,...t]=n.split(","),o=e.trim(),r=t.join(",").trim();return!o||!r?null:{providerName:o,routeModel:r}}function mt(n,e,t){let o=n.find(s=>s.name.toLowerCase()===e.toLowerCase());if(!o||o.enabled===!1)return null;let r=o.models?.find(s=>String(s).toLowerCase()===t.toLowerCase());return r?{provider:o,model:String(r)}:null}function Oo(n,e){let t=cn(n);if(!t)return{reason:`invalid model format "${n}" (expected "provider,model")`,code:"invalid_model_format"};let{providerName:o,routeModel:r}=t,s=e.find(c=>c.name?.toLowerCase()===o.toLowerCase());if(!s)return{reason:`provider "${o}" not found`,code:"provider_not_found"};if(s.enabled===!1)return{reason:`provider "${o}" is disabled`,code:"provider_disabled"};let i=s.models?.find(c=>String(c).toLowerCase()===r.toLowerCase());if(!i)return{reason:`model "${r}" not found in provider "${o}"`,code:"model_not_found"};if(!U().isAvailable(s.name,String(i)))return{reason:`model "${r}" in provider "${o}" is temporarily unavailable (health fail-pool)`,code:"model_unhealthy"};let a=dt(s.name);if(a){let c=a.limitDaily!==void 0&&a.usedDailyBalance!==void 0&&a.usedDailyBalance>=a.limitDaily,u=a.totalBalance!==void 0&&a.usedBalance!==void 0&&a.usedBalance>=a.totalBalance;if(c||u)return{reason:`provider "${o}" quota is exhausted`,code:"quota_exhausted"}}return{reason:`unable to resolve model "${n}"`,code:"resolution_failed"}}function X(n,e,t,o,r,s,i){let l=cn(n);if(!l)return i?null:n;let{providerName:a,routeModel:c}=l,u=mt(e,a,c);if(!u){if(r===!0&&o&&!t&&s!==!1){let g=De(),m=g.getPromotion(a,c,o,e);if(m){let y=cn(m);if(y){let p=mt(e,y.providerName,y.routeModel);if(p)return`${p.provider.name},${p.model}`}g.clear(a,c,o)}}return null}if(r===!0&&o&&!t&&s!==!1){let g=De(),m=g.getPromotion(a,c,o,e);if(m){let y=cn(m);if(y){let p=mt(e,y.providerName,y.routeModel);if(p)return`${p.provider.name},${p.model}`}g.clear(a,c,o)}}if(!t&&!U().isAvailable(u.provider.name,u.model))return null;let d=dt(u.provider.name);if(d){let g=d.limitDaily!==void 0&&d.usedDailyBalance!==void 0&&d.usedDailyBalance>=d.limitDaily,m=d.totalBalance!==void 0&&d.usedBalance!==void 0&&d.usedBalance>=d.totalBalance;if(g||m)return null}return`${u.provider.name},${u.model}`}function Z(n,e,t,o,r,s){let i=U(),l=[t?.[n],o?.[n]];for(let a of l)if(!(!Array.isArray(a)||a.length===0))for(let c of a){let u=X(c,e,!1,n,void 0,void 0,s);if(u)return u}return null}function mc(n){return n.body.messages?.some(e=>e.role==="user"&&Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"||Array.isArray(t?.content)&&t.content.some(o=>o.type==="image"||o.type==="image_url")))}function Ao(n){let e=dn(n);return[/claude/i,/gemini/i,/gpt-4o/i,/gpt-4\.1/i,/gpt-4-vision/i,/qwen.*vl/i,/glm-4v/i,/grok.*vision/i,/pixtral/i,/llava/i].some(o=>o.test(e))}function ys(n,e,t){return t?.usageScope!=="session"?n:Math.max(n,fc(e))}function _s(n,e,t){return n?.extendedContextThreshold??e?.extendedContextThreshold??t??2e5}function gc(n,e,t,o,r,s,i,l,a,c,u,d){let g=n.clientContext,m=g?.longContextThreshold??t.longContextThreshold??a??6e4,y=ys(e,r,g),p=n.modelFamily,f=_s(g,t,c),_=g?.supportsExplicitExtendedContext!==!1&&s===!0;if((_||y>f)&&t.extendedContext){let b=X(t.extendedContext,o,!1,"extendedContext",l,d,u);if(b)return n.log.info(`Family: using extended context model (1M+), tokens: ${y}, estimated: ${e}, explicit: ${_}, threshold: ${f}`),{model:b,scenarioType:"extendedContext",isFallback:!1};let T=l?Z("extendedContext",o,t.fallback,i,p,u):null;if(T)return n.log.info(`Family: using extended context fallback model (1M+), tokens: ${y}, estimated: ${e}, explicit: ${_}, threshold: ${f}`),{model:T,scenarioType:"extendedContext",isFallback:!0};u&&ne(n,t.extendedContext,o,"extendedContext"),n.log.warn("Family: extendedContext model unavailable (fail pool), skipping")}if(y>m&&(t.longContext||t.fallback?.longContext?.length||i?.longContext?.length)){let b=t.longContext?X(t.longContext,o,!1,"longContext",l,d,u):null;if(b)return n.log.info(`Family: using long context model, tokens: ${y}, estimated: ${e}`),{model:b,scenarioType:"longContext",isFallback:!1};let T=l?Z("longContext",o,t.fallback,i,p,u):null;if(T)return n.log.info(`Family: using long context fallback model, tokens: ${y}, estimated: ${e}`),{model:T,scenarioType:"longContext",isFallback:!0};u&&t.longContext&&ne(n,t.longContext,o,"longContext"),n.log.warn("Family: no healthy longContext model available, falling through to other scenarios")}if(Array.isArray(n.body.tools)&&n.body.tools.some(b=>b.type?.startsWith("web_search"))&&t.webSearch){let b=X(t.webSearch,o,!1,"webSearch",l,d,u);if(b)return{model:b,scenarioType:"webSearch",isFallback:!1};let T=l?Z("webSearch",o,t.fallback,i,p,u):null;if(T)return n.log.info("Family: using webSearch fallback model"),{model:T,scenarioType:"webSearch",isFallback:!0};u&&ne(n,t.webSearch,o,"webSearch"),n.log.warn("Family: webSearch model unavailable (fail pool), skipping")}if(n.body.thinking?.type==="enabled"&&t.think){let b=X(t.think,o,!1,"think",l,d,u);if(b)return{model:b,scenarioType:"think",isFallback:!1};let T=l?Z("think",o,t.fallback,i,p,u):null;if(T)return n.log.info("Family: using think fallback model"),{model:T,scenarioType:"think",isFallback:!0};u&&ne(n,t.think,o,"think"),n.log.warn("Family: think model unavailable (fail pool), skipping")}if(t.default){let b=X(t.default,o,!1,"default",l,d,u);if(b)return{model:b,scenarioType:"default",isFallback:!1};let T=l?Z("default",o,t.fallback,i,p,u):null;if(T)return n.log.info("Family: using default fallback model"),{model:T,scenarioType:"default",isFallback:!0};u&&ne(n,t.default,o,"default"),n.log.warn("Family: default model unavailable (fail pool), skipping")}return null}function bc(){if(we.size<=ps)return;let n=[...we.keys()].slice(0,we.size-ps);for(let e of n)we.delete(e)}function Tc(){if(Ke.size<=fs)return;let n=[...Ke].slice(0,Ke.size-fs);for(let e of n)Ke.delete(e)}var gs,ln,pn,un,Qe,hs,ue,ge,gt,dc,hc,yt,we,ps,Ke,fs,yc,_c,kc,ms,Io,Ve=w(()=>{"use strict";gs=require("tiktoken");rn();ln=require("fs/promises"),pn=require("fs/promises"),un=require("path"),Qe=require("@wengine-ai/claude-code-router-shared");ie();Je();tn();pt();Ge();hs={provider_not_found:404,model_not_found:404,invalid_model_format:400,provider_disabled:503,model_unhealthy:503,quota_exhausted:503,resolution_failed:502,project_config_error:500},ue=class extends Error{statusCode;code;type;sessionId;configuredTarget;constructor(e,t){super(e),this.name="ProjectRoutingError",this.statusCode=t?.statusCode||hs[t?.code||""]||502,this.code=t?.code||"project_routing_error",this.type="api_error",this.sessionId=t?.sessionId,this.configuredTarget=t?.configuredTarget}};ge=(0,gs.get_encoding)("cl100k_base"),gt=(n,e,t)=>{let o=0;return Array.isArray(n)&&n.forEach(r=>{typeof r.content=="string"?o+=ge.encode(r.content).length:Array.isArray(r.content)&&r.content.forEach(s=>{s.type==="text"?o+=ge.encode(s.text).length:s.type==="tool_use"?o+=ge.encode(JSON.stringify(s.input)).length:s.type==="tool_result"&&(o+=ge.encode(typeof s.content=="string"?s.content:JSON.stringify(s.content)).length)})}),typeof e=="string"?o+=ge.encode(e).length:Array.isArray(e)&&e.forEach(r=>{r.type==="text"&&(typeof r.text=="string"?o+=ge.encode(r.text).length:Array.isArray(r.text)&&r.text.forEach(s=>{o+=ge.encode(s||"").length}))}),t&&t.forEach(r=>{r.description&&(o+=ge.encode(r.name+r.description).length),r.input_schema&&(o+=ge.encode(JSON.stringify(r.input_schema)).length)}),o},dc=async(n,e)=>{if(n.sessionId){let t=await Io(n.sessionId);if(t){let o=(0,un.join)(Qe.HOME_DIR,t,"config.json"),r=(0,un.join)(Qe.HOME_DIR,t,`${n.sessionId}.json`);try{let s=JSON.parse(await(0,ln.readFile)(r,"utf8"));if(s&&s.Router&&Object.keys(s.Router).length>0)return s.Router}catch{}try{let s=JSON.parse(await(0,ln.readFile)(o,"utf8"));if(s&&s.Router&&Object.keys(s.Router).length>0)return s.Router}catch(s){if(s&&s.code!=="ENOENT"){let i=n.sessionId||n.clientContext?.stableSessionId;throw new ue(`Project routing error: project config.json is malformed or unreadable in project "${t}". ${s.message}. Session: "${i||"unknown"}".`,{sessionId:i,configuredTarget:o,code:"project_config_error",statusCode:500})}}}}};hc=async(n,e,t,o,r,s)=>{let i=t.get("providers")||[],l=r||t.get("Router"),a=l?.enableFallback===!0,c=a?l?.fallback:void 0,u=a&&!s?c||t.get("fallback"):c,d=!s,g=null;if(n.body?.system?.length>1&&n.body?.system[1]?.text?.includes("<CCR-SUBAGENT-MODEL>")){let v=n.body?.system[1].text.match(/<CCR-SUBAGENT-MODEL>(.*?)<\/CCR-SUBAGENT-MODEL>/s);v&&(n.body.system[1].text=n.body.system[1].text.replace(`<CCR-SUBAGENT-MODEL>${v[1]}</CCR-SUBAGENT-MODEL>`,""),g=v[1])}let{family:m,extended:y,isCcrAlias:p}=ht(n.body.model),f=l?.families?.[m||""];if(f&&l?.enableFamilyRouting){n.log.info(`Using model family routing for: ${m}${y?" (1M)":""}`),n.modelFamily=m,n.familyFallback=f.fallback;let v=gc(n,e,f,i,o,y,u,a,l?.longContextThreshold,l?.extendedContextThreshold,s,d);if(v)return{model:v.model,scenarioType:v.scenarioType}}if(n.body.model.includes(",")&&!s){let v=X(n.body.model,i,!1,"default",a,d,s);if(v)return{model:v,scenarioType:"default"};n.log.warn(`Explicit model ${n.body.model} unavailable (fail pool), trying fallback`);let S=a?Z("default",i,void 0,u,void 0,s):null;if(S)return n.log.info(`Using fallback for explicit model: ${S}`),{model:S,scenarioType:"default"};n.log.warn(`No fallback available for explicit model ${n.body.model}, continuing through routing logic`)}let _=p&&!l?.enableFamilyRouting?null:pc(n.body.model,l?.models);if(_){let v=X(_,i,!1,"modelMapping",a,d,s);if(v)return n.log.info(`Using mapped model for ${n.body.model}: ${_}`),{model:v,scenarioType:"modelMapping"};let S=a?Z("modelMapping",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"modelMapping"};s&&ne(n,_,i,"modelMapping"),n.log.warn(`Mapped model ${_} unavailable (fail pool), skipping`)}let k=n.clientContext,h=ys(e,o,k),b=_s(k,void 0,l?.extendedContextThreshold);if(h>b&&l?.extendedContext){n.log.info(`Using extended context (1M) model due to token count: ${h}, estimated: ${e}, threshold: ${b}`);let v=X(l.extendedContext,i,!1,"extendedContext",a,d,s);if(v)return{model:v,scenarioType:"extendedContext"};n.log.warn(`Extended context model ${l.extendedContext} unavailable (fail pool), trying fallback`);let S=a?Z("extendedContext",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"extendedContext"};s&&ne(n,l.extendedContext,i,"extendedContext")}let T=k?.longContextThreshold??l?.longContextThreshold??6e4;if(h>T&&l?.longContext){n.log.info(`Using long context model due to token count: ${h}, estimated: ${e}, threshold: ${T}`);let v=X(l.longContext,i,!1,"longContext",a,d,s);if(v)return{model:v,scenarioType:"longContext"};n.log.warn(`Long context model ${l.longContext} unavailable (fail pool), trying fallback`);let S=a?Z("longContext",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"longContext"};s&&ne(n,l.longContext,i,"longContext")}if(!s&&g)return{model:g,scenarioType:"default"};if(n.body.model?.includes("claude")&&n.body.model?.includes("haiku")&&l?.background){n.log.info(`Using background model for ${n.body.model}`);let v=X(l.background,i,!1,"background",a,d,s);if(v)return{model:v,scenarioType:"background"};let S=a?Z("background",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"background"};s&&ne(n,l.background,i,"background"),n.log.warn(`Background model ${l.background} unavailable (fail pool), falling through`)}if(Array.isArray(n.body.tools)&&n.body.tools.some(v=>v.type?.startsWith("web_search"))&&l?.webSearch){let v=X(l.webSearch,i,!1,"webSearch",a,d,s);if(v)return{model:v,scenarioType:"webSearch"};n.log.warn(`WebSearch model ${l.webSearch} unavailable (fail pool), trying fallback`);let S=a?Z("webSearch",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"webSearch"};s&&ne(n,l.webSearch,i,"webSearch")}if(n.body.thinking?.type==="enabled"&&l?.think){n.log.info(`Using think model for ${n.body.thinking}`);let v=X(l.think,i,!1,"think",a,d,s);if(v)return{model:v,scenarioType:"think"};n.log.warn(`Think model ${l.think} unavailable (fail pool), trying fallback`);let S=a?Z("think",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"think"};s&&ne(n,l.think,i,"think")}if(l?.default){let v=X(l.default,i,!1,"default",a,d,s);if(v)return{model:v,scenarioType:"default"};n.log.warn(`Default model ${l.default} unavailable (fail pool), trying fallback`);let S=a?Z("default",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"default"};if(!s){let C=X(l.default,i,!0,"default",a,d,s);if(C)return n.log.warn(`No fallback available; retrying default model ${l.default} despite fail-pool state`),{model:C,scenarioType:"default"}}}return s&&ne(n,l?.default||n.body.model,i,"default"),{model:void 0,scenarioType:"default"}},yt=async(n,e,t)=>{let{configService:o,event:r}=t;!n.originalModel&&n.body.model&&(n.originalModel=n.body.model),he(n,o.getAll());let s=await dc(n,o),i=s||o.get("Router"),l=i?.enableFallback===!0,a=o.get("providers")||[],c=!!s;n.enableFallback=l,n.strictProjectRouting=c,n.fallbackConfig=c?i?.fallback:i?.fallback||o.get("fallback");let u=n.clientContext?.usageScope==="session"?n.previousUsage??q.get(n.usageCacheKey):void 0,{messages:d,system:g=[],tools:m}=n.body,y=o.get("REWRITE_SYSTEM_PROMPT");if(y&&g.length>1&&g[1]?.text?.includes("<env>")){let p=await(0,ln.readFile)(y,"utf-8");g[1].text=`${p}<env>${g[1].text.split("<env>").pop()}`}try{let[p,f]=n.body.model.split(","),_=t.tokenizerService?.getTokenizerConfigForModel(p,f),k;t.tokenizerService?k=(await t.tokenizerService.countTokens({messages:d,system:g,tools:m},_,p)).tokenCount:k=gt(d,g,m),n.tokenCount=k;let h,b=c?void 0:o.get("CUSTOM_ROUTER_PATH");if(b)try{h=await require(b)(n,o.getAll(),{event:r})}catch(S){n.log.error(`failed to load custom router: ${S.message}`)}if(h)n.scenarioType="default";else{let S=await hc(n,k,o,u,s,!!s);h=S.model,n.scenarioType=S.scenarioType}let{family:T}=ht(n.originalModel||n.body.model),x=i?.enableFamilyRouting&&T?i.families?.[T]:void 0,v=[x?.image,i?.image].filter((S,C,P)=>!!S&&P.indexOf(S)===C);if(v.length>0&&mc(n)&&!Ao(h))if(v.includes(h))n.scenarioType="image";else{let S=v.map(C=>X(C,a,!1,"image",l,!c,c)).find(C=>!!C);if(S)n.log.info(`Using image model fallback for ${h}`),h=S,n.scenarioType="image";else{let C=l?Z("image",a,x?.fallback,n.fallbackConfig,T||void 0,c):null;C?(n.log.info(`Using image fallback model: ${C}`),h=C,n.scenarioType="image"):c?ne(n,v[0],a,"image"):(n.log.warn(`Image models ${v.join(", ")} unavailable (fail pool), keeping ${h}`),n.scenarioType="image")}}typeof h=="string"&&h.trim()?n.body.model=h:(n.log.warn(`Router could not resolve a valid model for ${n.originalModel||n.body.model}; keeping original request model`),n.scenarioType=n.scenarioType||"default")}catch(p){if(p instanceof ue)throw p;if(n.log.error(`Error in router middleware: ${p.message}`),c){let f=n.sessionId||n.clientContext?.stableSessionId;throw new ue(`Project routing error: router failure in project mode. ${p.message}. Session: "${f||"unknown"}".`,{sessionId:f,configuredTarget:i?.default,code:"project_router_failure",statusCode:502})}n.body.model=i?.default,n.scenarioType="default"}},we=new Map,ps=1e3,Ke=new Set,fs=1e3,yc=3,_c=50,kc=n=>new Promise(e=>setTimeout(e,n));ms=async n=>{let e=await(0,pn.opendir)(Qe.CLAUDE_PROJECTS_DIR),t=[];for await(let s of e)s.isDirectory()&&t.push(s.name);let o=t.map(async s=>{let i=(0,un.join)(Qe.CLAUDE_PROJECTS_DIR,s,`${n}.jsonl`);try{return(await(0,pn.stat)(i)).isFile()?s:null}catch{return null}}),r=await Promise.all(o);for(let s of r)if(s)return s;return null},Io=async n=>{let e=Se(n);if(!e)return null;if(we.has(e))return we.get(e)||null;try{let t=await ms(e);if(!t&&!Ke.has(e)){Ke.add(e),Tc();for(let o=0;o<yc&&!t;o++)await kc(_c),t=await ms(e)}return t?(we.set(e,t),bc(),t):null}catch(t){return console.error("Error searching for project by session:",t),null}}});function _t(n){let e=[],t=Array.isArray(n.input)?n.input:[n.input];for(let o of t)if(o.type==="function_call")e.push({role:"assistant",tool_calls:[{id:o.call_id,type:"function",function:{name:o.name,arguments:o.arguments||"{}"}}]});else if(o.type==="function_call_output")e.push({role:"tool",tool_call_id:o.call_id,content:typeof o.output=="string"?o.output:JSON.stringify(o.output)});else if(o.type==="reasoning"){let r=Array.isArray(o.summary)?o.summary.filter(s=>s.type==="summary_text"&&s.text).map(s=>s.text).join(`
|
|
41
|
+
`))}}}E();let z=A();z&&O.enqueue(z),F="",O.close()}catch(L){O.error(L)}}})}wrapChatInResponses(e){let t=e?.choices?.[0],o=[],r=[];if(t?.message?.content&&r.push({type:"output_text",text:t.message.content}),o.push({type:"message",role:"assistant",content:r}),Array.isArray(t?.message?.tool_calls))for(let s of t.message.tool_calls)o.push({type:"function_call",id:s.id,call_id:s.id,name:s.function?.name||"",arguments:s.function?.arguments||"{}"});return{id:e.id||`resp_${Date.now()}`,object:"response",model:e.model,output:o,usage:e.usage?{...this.buildResponsesUsage(e.usage)}:void 0}}convertResponseToChat(e){let t=e.output?.find(c=>c.type==="message"),o=e.output?.find(c=>c.type==="function_call"),r;t?.content?.length&&t?.content[0].annotations&&(r=t.content[0].annotations.map(c=>({type:"url_citation",url_citation:{url:c.url||"",title:c.title||"",content:"",start_index:c.start_index||0,end_index:c.end_index||0}}))),this.logger.debug({data:r,type:"url_citation"});let s=null,i=null,l=null;if(t&&t.reasoning&&(l={content:t.reasoning}),t&&t.content){let c=[],u=[];if(t.content.forEach(d=>{if(d.type==="output_text")c.push(d.text||"");else if(d.type==="output_image"){let g=this.buildImageContent({url:d.image_url,mime_type:d.mime_type});g&&u.push(g)}else if(d.type==="output_image_base64"){let g=this.buildImageContent({b64_json:d.image_base64,mime_type:d.mime_type});g&&u.push(g)}}),u.length>0){let d=[];c.length>0&&d.push({type:"text",text:c.join("")}),d.push(...u),s=d}else s=c.join("")}return o&&(i=[{id:o.call_id||o.id,function:{name:o.name,arguments:o.arguments},type:"function"}]),{id:e.id||"chatcmpl-"+Date.now(),object:"chat.completion",created:e.created_at,model:e.model,choices:[{index:0,message:{role:"assistant",content:s||null,tool_calls:i,thinking:l,annotations:r},logprobs:null,finish_reason:i?"tool_calls":"stop"}],usage:e.usage?{prompt_tokens:e.usage.input_tokens||0,completion_tokens:e.usage.output_tokens||0,total_tokens:e.usage.total_tokens||0,prompt_tokens_details:{cached_tokens:this.getCacheReadInputTokens(e.usage),cache_creation_tokens:this.getCacheCreationInputTokens(e.usage)},cache_read_input_tokens:this.getCacheReadInputTokens(e.usage),cache_creation_input_tokens:this.getCacheCreationInputTokens(e.usage)}:null}}buildImageContent(e){return e&&(e.url||e.b64_json)?{type:"image_url",image_url:{url:e.url||"",b64_json:e.b64_json},media_type:e.mime_type}:null}}});var vo,q,rn=w(()=>{"use strict";vo=class{capacity;cache;constructor(e){this.capacity=e,this.cache=new Map}get(e){if(!this.cache.has(e))return;let t=this.cache.get(e);return this.cache.delete(e),this.cache.set(e,t),t}put(e,t){if(this.cache.has(e))this.cache.delete(e);else if(this.cache.size>=this.capacity){let o=this.cache.keys().next().value;o!==void 0&&this.cache.delete(o)}this.cache.set(e,t)}values(){return Array.from(this.cache.values())}delete(e){return this.cache.delete(e)}},q=new vo(100)});function sn(n,e){n&&ze.set(n,{...e,provider:n,capturedAt:Date.now()})}function dt(n){let e=ze.get(n);return e?{...e}:void 0}function an(){return Array.from(ze.values()).map(n=>({...n}))}function qa(){try{if(!(0,me.existsSync)(So))return;let n=JSON.parse((0,me.readFileSync)(So,"utf-8"));if(!Array.isArray(n))return;let e=Date.now();for(let t of n)if(t&&t.provider){if(t.capturedAt&&e-t.capturedAt>1440*60*1e3)continue;ze.set(t.provider,t)}}catch{}}function as(){try{if(ze.size===0)return;(0,me.existsSync)(xo)||(0,me.mkdirSync)(xo,{recursive:!0}),(0,me.writeFileSync)(So,JSON.stringify(Array.from(ze.values()),null,2),"utf-8")}catch{}}function Be(){ss||(ss=!0,qa(),is=setInterval(as,6e4),is.unref?.(),process.on("exit",as))}var me,Ro,cs,xo,So,ze,ss,is,Je=w(()=>{"use strict";me=require("fs"),Ro=require("path"),cs=require("@wengine-ai/claude-code-router-shared"),xo=(0,Ro.join)(cs.HOME_DIR,"runtime"),So=(0,Ro.join)(xo,"quota-store.json"),ze=new Map,ss=!1,is=null});function Se(n){if(typeof n!="string")return;let e=n.trim();if(!(!e||!Za.test(e)))return e}function We(n){if(!n)return;if(typeof n=="object")return Se(n.session_id??n.sessionId);if(typeof n!="string")return;let e=n.trim();if(!e)return;try{let r=JSON.parse(e),s=Se(r?.session_id??r?.sessionId);if(s)return s}catch{}let t="_session_",o=e.lastIndexOf(t);if(o!==-1)return Se(e.slice(o+t.length))}var Za,pt=w(()=>{"use strict";Za=/^[A-Za-z0-9_-]+$/});function tc(n){if(typeof n=="string")return n.slice(0,1e3);if(Array.isArray(n)){let e=n.find(t=>t&&typeof t.text=="string");return e?String(e.text).slice(0,1e3):""}return""}function nc(n){if(typeof n?.pathname=="string")return n.pathname;if(typeof n?.url!="string")return"";try{return new URL(n.url,"http://127.0.0.1").pathname}catch{return n.url}}function ft(n,e=!0){return{clientType:n,usageScope:"request",supportsExplicitExtendedContext:e}}function us(n,e,t=!0){let o=We(n?.body?.metadata?.user_id);return{clientType:e,usageScope:o?"session":"request",stableSessionId:o,supportsExplicitExtendedContext:t}}function Po(n){return typeof n=="string"&&ec.includes(n)}function Re(n){if(Po(n?.clientType))return n.clientType;let e=nc(n),t=n?.headers||{},o=typeof t["user-agent"]=="string"?t["user-agent"]:"",r=n?.body||{},s=tc(r.system);if(/\bYou are Qwen Code\b/i.test(s)||/Qwen Code, an interactive CLI agent/i.test(s))return"qwen-code";if(/operating inside pi\b/i.test(s)||/a coding agent harness/i.test(s))return"pi";if(/\bYou are opencode\b/i.test(s))return"opencode";let i=t["x-anthropic-billing-header"];if(typeof i=="string"&&i.includes("cc_version="))return"claude-code";if(o.includes("codex")||o.includes("Codex")||e.endsWith("/v1/responses"))return"codex";if(r.metadata&&typeof r.metadata=="object"&&typeof r.metadata.user_id=="string")return"claude-code";if(o.includes("opencode"))return"opencode";if(o.includes("pi-coding-agent"))return"pi";if(o.includes("QwenCode"))return"qwen-code";let l=n?.originalModel||r.model||"";return/^ccr-(opus|sonnet|haiku)(\[1m\])?$/i.test(l)?o.includes("Anthropic/")?"pi":o.includes("claude-cli")||o.includes("Claude-CLI")?"qwen-code":typeof t["x-stainless-package-version"]=="string"?"pi":"claude-code":o.includes("claude-cli")||o.includes("Claude-CLI")?"claude-code":String(l).toLowerCase()==="ccr-codex"?"codex":e.endsWith("/v1/messages")?"api":"unknown"}function Eo(n){return wo[n]}function uc(n){if(typeof n?.__ccrRequestScopeId=="string"&&n.__ccrRequestScopeId)return n.__ccrRequestScopeId;let e=typeof n?.id=="string"&&n.id||(0,ls.randomUUID)();return n.__ccrRequestScopeId=e,e}function he(n,e={}){let t=Re(n),o=Eo(t).createContext(n,e),r=o.stableSessionId||uc(n),s=o.usageScope==="session"?"session":"request";return n.clientType=t,n.clientContext=o,o.stableSessionId?n.sessionId=o.stableSessionId:delete n.sessionId,n.usageSessionId=r,n.usageCacheKey=`${t}:${s}:${r}`,o}function ds(){}var ls,ec,oc,rc,sc,ic,ac,cc,lc,wo,Ge=w(()=>{"use strict";ls=require("node:crypto");pt();ec=["claude-code","pi","qwen-code","opencode","codex","api","unknown"];oc={type:"claude-code",createContext(n){return us(n,"claude-code")}},rc={type:"pi",createContext(){return ft("pi",!1)}},sc={type:"qwen-code",createContext(n){return us(n,"qwen-code")}},ic={type:"opencode",createContext(){return ft("opencode")}},ac={type:"codex",createContext(){return ft("codex")}},cc={type:"api",createContext(){return ft("api")}},lc={type:"unknown",createContext(){return ft("unknown")}},wo={"claude-code":oc,pi:rc,"qwen-code":sc,opencode:ic,codex:ac,api:cc,unknown:lc}});function ne(n,e,t,o){let r=Oo(e,t),s=n.sessionId||n.clientContext?.stableSessionId,i=hs[r.code]||502;throw new ue(`Project routing error (${o}): ${r.reason}. Project-level Router target: "${e}". Session: "${s||"unknown"}".`,{sessionId:s,configuredTarget:e,code:r.code,statusCode:i})}function dn(n){let e=n||"";return e.includes(",")&&(e=e.split(",").pop()||e),e.includes("/")&&(e=e.split("/").pop()||e),e.includes(":")&&(e=e.split(":")[0]),e.trim().toLowerCase()}function ht(n){let e=dn(n),t=e.includes("[1m]")||e.endsWith("[1m"),o=e.replace(/\[1m\]|\[1m$/g,""),r=o.match(/^ccr-(opus|sonnet|haiku)$/i);if(r)return{family:r[1].toLowerCase(),extended:t,isCcrAlias:!0};let s=o.match(/claude-(?:\d+-\d+-|\d+-)?(sonnet|opus|haiku)(?:-|$)/i)||o.match(/claude-(sonnet|opus|haiku)(?:-|$)/i);return s?{family:s[1].toLowerCase(),extended:t,isCcrAlias:!1}:{family:null,extended:t,isCcrAlias:!1}}function pc(n,e){if(!e||!n)return null;let t=dn(n);if(e[n])return e[n];if(e[t])return e[t];let{family:o}=ht(n);if(o&&e[o])return e[o];for(let[r,s]of Object.entries(e)){let i=dn(r);if(i&&t.includes(i))return s}return null}function fc(n){return n?(n.input_tokens||0)+(n.cache_read_input_tokens||0)+(n.cache_creation_input_tokens||0):0}function cn(n){if(!n?.includes(","))return null;let[e,...t]=n.split(","),o=e.trim(),r=t.join(",").trim();return!o||!r?null:{providerName:o,routeModel:r}}function mt(n,e,t){let o=n.find(s=>s.name.toLowerCase()===e.toLowerCase());if(!o||o.enabled===!1)return null;let r=o.models?.find(s=>String(s).toLowerCase()===t.toLowerCase());return r?{provider:o,model:String(r)}:null}function Oo(n,e){let t=cn(n);if(!t)return{reason:`invalid model format "${n}" (expected "provider,model")`,code:"invalid_model_format"};let{providerName:o,routeModel:r}=t,s=e.find(c=>c.name?.toLowerCase()===o.toLowerCase());if(!s)return{reason:`provider "${o}" not found`,code:"provider_not_found"};if(s.enabled===!1)return{reason:`provider "${o}" is disabled`,code:"provider_disabled"};let i=s.models?.find(c=>String(c).toLowerCase()===r.toLowerCase());if(!i)return{reason:`model "${r}" not found in provider "${o}"`,code:"model_not_found"};if(!U().isAvailable(s.name,String(i)))return{reason:`model "${r}" in provider "${o}" is temporarily unavailable (health fail-pool)`,code:"model_unhealthy"};let a=dt(s.name);if(a){let c=a.limitDaily!==void 0&&a.usedDailyBalance!==void 0&&a.usedDailyBalance>=a.limitDaily,u=a.totalBalance!==void 0&&a.usedBalance!==void 0&&a.usedBalance>=a.totalBalance;if(c||u)return{reason:`provider "${o}" quota is exhausted`,code:"quota_exhausted"}}return{reason:`unable to resolve model "${n}"`,code:"resolution_failed"}}function X(n,e,t,o,r,s,i){let l=cn(n);if(!l)return i?null:n;let{providerName:a,routeModel:c}=l,u=mt(e,a,c);if(!u){if(r===!0&&o&&!t&&s!==!1){let g=De(),m=g.getPromotion(a,c,o,e);if(m){let y=cn(m);if(y){let p=mt(e,y.providerName,y.routeModel);if(p)return`${p.provider.name},${p.model}`}g.clear(a,c,o)}}return null}if(r===!0&&o&&!t&&s!==!1){let g=De(),m=g.getPromotion(a,c,o,e);if(m){let y=cn(m);if(y){let p=mt(e,y.providerName,y.routeModel);if(p)return`${p.provider.name},${p.model}`}g.clear(a,c,o)}}if(!t&&!U().isAvailable(u.provider.name,u.model))return null;let d=dt(u.provider.name);if(d){let g=d.limitDaily!==void 0&&d.usedDailyBalance!==void 0&&d.usedDailyBalance>=d.limitDaily,m=d.totalBalance!==void 0&&d.usedBalance!==void 0&&d.usedBalance>=d.totalBalance;if(g||m)return null}return`${u.provider.name},${u.model}`}function Z(n,e,t,o,r,s){let i=U(),l=[t?.[n],o?.[n]];for(let a of l)if(!(!Array.isArray(a)||a.length===0))for(let c of a){let u=X(c,e,!1,n,void 0,void 0,s);if(u)return u}return null}function mc(n){return n.body.messages?.some(e=>e.role==="user"&&Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"||Array.isArray(t?.content)&&t.content.some(o=>o.type==="image"||o.type==="image_url")))}function Ao(n){let e=dn(n);return[/claude/i,/gemini/i,/gpt-4o/i,/gpt-4\.1/i,/gpt-4-vision/i,/qwen.*vl/i,/glm-4v/i,/grok.*vision/i,/pixtral/i,/llava/i].some(o=>o.test(e))}function ys(n,e,t){return t?.usageScope!=="session"?n:Math.max(n,fc(e))}function _s(n,e,t){return n?.extendedContextThreshold??e?.extendedContextThreshold??t??2e5}function gc(n,e,t,o,r,s,i,l,a,c,u,d){let g=n.clientContext,m=g?.longContextThreshold??t.longContextThreshold??a??6e4,y=ys(e,r,g),p=n.modelFamily,f=_s(g,t,c),_=g?.supportsExplicitExtendedContext!==!1&&s===!0;if((_||y>f)&&t.extendedContext){let b=X(t.extendedContext,o,!1,"extendedContext",l,d,u);if(b)return n.log.info(`Family: using extended context model (1M+), tokens: ${y}, estimated: ${e}, explicit: ${_}, threshold: ${f}`),{model:b,scenarioType:"extendedContext",isFallback:!1};let T=l?Z("extendedContext",o,t.fallback,i,p,u):null;if(T)return n.log.info(`Family: using extended context fallback model (1M+), tokens: ${y}, estimated: ${e}, explicit: ${_}, threshold: ${f}`),{model:T,scenarioType:"extendedContext",isFallback:!0};u&&ne(n,t.extendedContext,o,"extendedContext"),n.log.warn("Family: extendedContext model unavailable (fail pool), skipping")}if(y>m&&(t.longContext||t.fallback?.longContext?.length||i?.longContext?.length)){let b=t.longContext?X(t.longContext,o,!1,"longContext",l,d,u):null;if(b)return n.log.info(`Family: using long context model, tokens: ${y}, estimated: ${e}`),{model:b,scenarioType:"longContext",isFallback:!1};let T=l?Z("longContext",o,t.fallback,i,p,u):null;if(T)return n.log.info(`Family: using long context fallback model, tokens: ${y}, estimated: ${e}`),{model:T,scenarioType:"longContext",isFallback:!0};u&&t.longContext&&ne(n,t.longContext,o,"longContext"),n.log.warn("Family: no healthy longContext model available, falling through to other scenarios")}if(Array.isArray(n.body.tools)&&n.body.tools.some(b=>b.type?.startsWith("web_search"))&&t.webSearch){let b=X(t.webSearch,o,!1,"webSearch",l,d,u);if(b)return{model:b,scenarioType:"webSearch",isFallback:!1};let T=l?Z("webSearch",o,t.fallback,i,p,u):null;if(T)return n.log.info("Family: using webSearch fallback model"),{model:T,scenarioType:"webSearch",isFallback:!0};u&&ne(n,t.webSearch,o,"webSearch"),n.log.warn("Family: webSearch model unavailable (fail pool), skipping")}if(n.body.thinking?.type==="enabled"&&t.think){let b=X(t.think,o,!1,"think",l,d,u);if(b)return{model:b,scenarioType:"think",isFallback:!1};let T=l?Z("think",o,t.fallback,i,p,u):null;if(T)return n.log.info("Family: using think fallback model"),{model:T,scenarioType:"think",isFallback:!0};u&&ne(n,t.think,o,"think"),n.log.warn("Family: think model unavailable (fail pool), skipping")}if(t.default){let b=X(t.default,o,!1,"default",l,d,u);if(b)return{model:b,scenarioType:"default",isFallback:!1};let T=l?Z("default",o,t.fallback,i,p,u):null;if(T)return n.log.info("Family: using default fallback model"),{model:T,scenarioType:"default",isFallback:!0};u&&ne(n,t.default,o,"default"),n.log.warn("Family: default model unavailable (fail pool), skipping")}return null}function bc(){if(we.size<=ps)return;let n=[...we.keys()].slice(0,we.size-ps);for(let e of n)we.delete(e)}function Tc(){if(Ke.size<=fs)return;let n=[...Ke].slice(0,Ke.size-fs);for(let e of n)Ke.delete(e)}var gs,ln,pn,un,Qe,hs,ue,ge,gt,dc,hc,yt,we,ps,Ke,fs,yc,_c,kc,ms,Io,Ve=w(()=>{"use strict";gs=require("tiktoken");rn();ln=require("fs/promises"),pn=require("fs/promises"),un=require("path"),Qe=require("@wengine-ai/claude-code-router-shared");ie();Je();tn();pt();Ge();hs={provider_not_found:404,model_not_found:404,invalid_model_format:400,provider_disabled:503,model_unhealthy:503,quota_exhausted:503,resolution_failed:502,project_config_error:500},ue=class extends Error{statusCode;code;type;sessionId;configuredTarget;constructor(e,t){super(e),this.name="ProjectRoutingError",this.statusCode=t?.statusCode||hs[t?.code||""]||502,this.code=t?.code||"project_routing_error",this.type="api_error",this.sessionId=t?.sessionId,this.configuredTarget=t?.configuredTarget}};ge=(0,gs.get_encoding)("cl100k_base"),gt=(n,e,t)=>{let o=0;return Array.isArray(n)&&n.forEach(r=>{typeof r.content=="string"?o+=ge.encode(r.content).length:Array.isArray(r.content)&&r.content.forEach(s=>{s.type==="text"?o+=ge.encode(s.text).length:s.type==="tool_use"?o+=ge.encode(JSON.stringify(s.input)).length:s.type==="tool_result"&&(o+=ge.encode(typeof s.content=="string"?s.content:JSON.stringify(s.content)).length)})}),typeof e=="string"?o+=ge.encode(e).length:Array.isArray(e)&&e.forEach(r=>{r.type==="text"&&(typeof r.text=="string"?o+=ge.encode(r.text).length:Array.isArray(r.text)&&r.text.forEach(s=>{o+=ge.encode(s||"").length}))}),t&&t.forEach(r=>{r.description&&(o+=ge.encode(r.name+r.description).length),r.input_schema&&(o+=ge.encode(JSON.stringify(r.input_schema)).length)}),o},dc=async(n,e)=>{if(n.sessionId){let t=await Io(n.sessionId);if(t){let o=(0,un.join)(Qe.HOME_DIR,t,"config.json"),r=(0,un.join)(Qe.HOME_DIR,t,`${n.sessionId}.json`);try{let s=JSON.parse(await(0,ln.readFile)(r,"utf8"));if(s&&s.Router&&Object.keys(s.Router).length>0)return s.Router}catch{}try{let s=JSON.parse(await(0,ln.readFile)(o,"utf8"));if(s&&s.Router&&Object.keys(s.Router).length>0)return s.Router}catch(s){if(s&&s.code!=="ENOENT"){let i=n.sessionId||n.clientContext?.stableSessionId;throw new ue(`Project routing error: project config.json is malformed or unreadable in project "${t}". ${s.message}. Session: "${i||"unknown"}".`,{sessionId:i,configuredTarget:o,code:"project_config_error",statusCode:500})}}}}};hc=async(n,e,t,o,r,s)=>{let i=t.get("providers")||[],l=r||t.get("Router"),a=l?.enableFallback===!0,c=a?l?.fallback:void 0,u=a&&!s?c||t.get("fallback"):c,d=!s,g=null;if(n.body?.system?.length>1&&n.body?.system[1]?.text?.includes("<CCR-SUBAGENT-MODEL>")){let v=n.body?.system[1].text.match(/<CCR-SUBAGENT-MODEL>(.*?)<\/CCR-SUBAGENT-MODEL>/s);v&&(n.body.system[1].text=n.body.system[1].text.replace(`<CCR-SUBAGENT-MODEL>${v[1]}</CCR-SUBAGENT-MODEL>`,""),g=v[1])}let{family:m,extended:y,isCcrAlias:p}=ht(n.body.model),f=l?.families?.[m||""];if(f&&l?.enableFamilyRouting){n.log.info(`Using model family routing for: ${m}${y?" (1M)":""}`),n.modelFamily=m,n.familyFallback=f.fallback;let v=gc(n,e,f,i,o,y,u,a,l?.longContextThreshold,l?.extendedContextThreshold,s,d);if(v)return{model:v.model,scenarioType:v.scenarioType}}if(n.body.model.includes(",")&&!s){let v=X(n.body.model,i,!1,"default",a,d,s);if(v)return{model:v,scenarioType:"default"};n.log.warn(`Explicit model ${n.body.model} unavailable (fail pool), trying fallback`);let S=a?Z("default",i,void 0,u,void 0,s):null;if(S)return n.log.info(`Using fallback for explicit model: ${S}`),{model:S,scenarioType:"default"};n.log.warn(`No fallback available for explicit model ${n.body.model}, continuing through routing logic`)}let _=p&&!l?.enableFamilyRouting?null:pc(n.body.model,l?.models);if(_){let v=X(_,i,!1,"modelMapping",a,d,s);if(v)return n.log.info(`Using mapped model for ${n.body.model}: ${_}`),{model:v,scenarioType:"modelMapping"};let S=a?Z("modelMapping",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"modelMapping"};s&&ne(n,_,i,"modelMapping"),n.log.warn(`Mapped model ${_} unavailable (fail pool), skipping`)}let k=n.clientContext,h=ys(e,o,k),b=_s(k,void 0,l?.extendedContextThreshold);if(h>b&&l?.extendedContext){n.log.info(`Using extended context (1M) model due to token count: ${h}, estimated: ${e}, threshold: ${b}`);let v=X(l.extendedContext,i,!1,"extendedContext",a,d,s);if(v)return{model:v,scenarioType:"extendedContext"};n.log.warn(`Extended context model ${l.extendedContext} unavailable (fail pool), trying fallback`);let S=a?Z("extendedContext",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"extendedContext"};s&&ne(n,l.extendedContext,i,"extendedContext")}let T=k?.longContextThreshold??l?.longContextThreshold??6e4;if(h>T&&l?.longContext){n.log.info(`Using long context model due to token count: ${h}, estimated: ${e}, threshold: ${T}`);let v=X(l.longContext,i,!1,"longContext",a,d,s);if(v)return{model:v,scenarioType:"longContext"};n.log.warn(`Long context model ${l.longContext} unavailable (fail pool), trying fallback`);let S=a?Z("longContext",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"longContext"};s&&ne(n,l.longContext,i,"longContext")}if(!s&&g)return{model:g,scenarioType:"default"};if(n.body.model?.includes("claude")&&n.body.model?.includes("haiku")&&l?.background){n.log.info(`Using background model for ${n.body.model}`);let v=X(l.background,i,!1,"background",a,d,s);if(v)return{model:v,scenarioType:"background"};let S=a?Z("background",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"background"};s&&ne(n,l.background,i,"background"),n.log.warn(`Background model ${l.background} unavailable (fail pool), falling through`)}if(Array.isArray(n.body.tools)&&n.body.tools.some(v=>v.type?.startsWith("web_search"))&&l?.webSearch){let v=X(l.webSearch,i,!1,"webSearch",a,d,s);if(v)return{model:v,scenarioType:"webSearch"};n.log.warn(`WebSearch model ${l.webSearch} unavailable (fail pool), trying fallback`);let S=a?Z("webSearch",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"webSearch"};s&&ne(n,l.webSearch,i,"webSearch")}if(n.body.thinking?.type==="enabled"&&l?.think){n.log.info(`Using think model for ${n.body.thinking}`);let v=X(l.think,i,!1,"think",a,d,s);if(v)return{model:v,scenarioType:"think"};n.log.warn(`Think model ${l.think} unavailable (fail pool), trying fallback`);let S=a?Z("think",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"think"};s&&ne(n,l.think,i,"think")}if(l?.default){let v=X(l.default,i,!1,"default",a,d,s);if(v)return{model:v,scenarioType:"default"};n.log.warn(`Default model ${l.default} unavailable (fail pool), trying fallback`);let S=a?Z("default",i,void 0,u,void 0,s):null;if(S)return{model:S,scenarioType:"default"};if(!s){let C=X(l.default,i,!0,"default",a,d,s);if(C)return n.log.warn(`No fallback available; retrying default model ${l.default} despite fail-pool state`),{model:C,scenarioType:"default"}}}return s&&ne(n,l?.default||n.body.model,i,"default"),{model:void 0,scenarioType:"default"}},yt=async(n,e,t)=>{let{configService:o,event:r}=t;!n.originalModel&&n.body.model&&(n.originalModel=n.body.model),he(n,o.getAll());let s=await dc(n,o),i=s||o.get("Router"),l=i?.enableFallback===!0,a=o.get("providers")||[],c=!!s;n.enableFallback=l,n.strictProjectRouting=c,n.fallbackConfig=c?i?.fallback:i?.fallback||o.get("fallback");let u=n.clientContext?.usageScope==="session"?n.previousUsage??q.get(n.usageCacheKey):void 0,{messages:d,system:g=[],tools:m}=n.body,y=o.get("REWRITE_SYSTEM_PROMPT");if(y&&g.length>1&&g[1]?.text?.includes("<env>")){let p=await(0,ln.readFile)(y,"utf-8");g[1].text=`${p}<env>${g[1].text.split("<env>").pop()}`}try{let[p,f]=n.body.model.split(","),_=t.tokenizerService?.getTokenizerConfigForModel(p,f),k;t.tokenizerService?k=(await t.tokenizerService.countTokens({messages:d,system:g,tools:m},_,p)).tokenCount:k=gt(d,g,m),n.tokenCount=k;let h,b=c?void 0:o.get("CUSTOM_ROUTER_PATH");if(b)try{h=await require(b)(n,o.getAll(),{event:r})}catch(S){n.log.error(`failed to load custom router: ${S.message}`)}if(h)n.scenarioType="default";else{let S=await hc(n,k,o,u,s,!!s);h=S.model,n.scenarioType=S.scenarioType}let{family:T}=ht(n.originalModel||n.body.model),x=i?.enableFamilyRouting&&T?i.families?.[T]:void 0,v=[x?.image,i?.image].filter((S,C,E)=>!!S&&E.indexOf(S)===C);if(v.length>0&&mc(n)&&!Ao(h))if(v.includes(h))n.scenarioType="image";else{let S=v.map(C=>X(C,a,!1,"image",l,!c,c)).find(C=>!!C);if(S)n.log.info(`Using image model fallback for ${h}`),h=S,n.scenarioType="image";else{let C=l?Z("image",a,x?.fallback,n.fallbackConfig,T||void 0,c):null;C?(n.log.info(`Using image fallback model: ${C}`),h=C,n.scenarioType="image"):c?ne(n,v[0],a,"image"):(n.log.warn(`Image models ${v.join(", ")} unavailable (fail pool), keeping ${h}`),n.scenarioType="image")}}typeof h=="string"&&h.trim()?n.body.model=h:(n.log.warn(`Router could not resolve a valid model for ${n.originalModel||n.body.model}; keeping original request model`),n.scenarioType=n.scenarioType||"default")}catch(p){if(p instanceof ue)throw p;if(n.log.error(`Error in router middleware: ${p.message}`),c){let f=n.sessionId||n.clientContext?.stableSessionId;throw new ue(`Project routing error: router failure in project mode. ${p.message}. Session: "${f||"unknown"}".`,{sessionId:f,configuredTarget:i?.default,code:"project_router_failure",statusCode:502})}n.body.model=i?.default,n.scenarioType="default"}},we=new Map,ps=1e3,Ke=new Set,fs=1e3,yc=3,_c=50,kc=n=>new Promise(e=>setTimeout(e,n));ms=async n=>{let e=await(0,pn.opendir)(Qe.CLAUDE_PROJECTS_DIR),t=[];for await(let s of e)s.isDirectory()&&t.push(s.name);let o=t.map(async s=>{let i=(0,un.join)(Qe.CLAUDE_PROJECTS_DIR,s,`${n}.jsonl`);try{return(await(0,pn.stat)(i)).isFile()?s:null}catch{return null}}),r=await Promise.all(o);for(let s of r)if(s)return s;return null},Io=async n=>{let e=Se(n);if(!e)return null;if(we.has(e))return we.get(e)||null;try{let t=await ms(e);if(!t&&!Ke.has(e)){Ke.add(e),Tc();for(let o=0;o<yc&&!t;o++)await kc(_c),t=await ms(e)}return t?(we.set(e,t),bc(),t):null}catch(t){return console.error("Error searching for project by session:",t),null}}});function _t(n){let e=[],t=Array.isArray(n.input)?n.input:[n.input];for(let o of t)if(o.type==="function_call")e.push({role:"assistant",tool_calls:[{id:o.call_id,type:"function",function:{name:o.name,arguments:o.arguments||"{}"}}]});else if(o.type==="function_call_output")e.push({role:"tool",tool_call_id:o.call_id,content:typeof o.output=="string"?o.output:JSON.stringify(o.output)});else if(o.type==="reasoning"){let r=Array.isArray(o.summary)?o.summary.filter(s=>s.type==="summary_text"&&s.text).map(s=>s.text).join(`
|
|
42
42
|
`):"";r&&e.push({role:"assistant",content:[{type:"text",text:`[reasoning]
|
|
43
43
|
${r}`}],_reasoningItem:!0})}else if(o.role){let r=o.content;Array.isArray(r)&&(r=r.map(s=>s.type==="input_text"?{type:"text",text:s.text}:s.type==="output_text"?{type:"text",text:s.text}:s.type==="input_image"?{type:"image_url",image_url:{url:s.image_url},media_type:s.mime_type}:s)),e.push({role:o.role,content:r})}n.messages=e,delete n.input,n.instructions&&typeof n.instructions=="string"&&(n.system=n.instructions,delete n.instructions),Array.isArray(n.tools)&&(n.tools=n.tools.filter(o=>o&&typeof o=="object").map(o=>o.type==="function"&&o.name&&!o.function?{type:"function",function:{name:o.name,description:o.description||"",parameters:o.parameters||{type:"object",properties:{}}}}:o.function?.name?o:o.type==="web_search"?{type:"function",function:{name:"web_search",description:"Search the web",parameters:{type:"object",properties:{query:{type:"string"}}}}}:null).filter(Boolean)),n.reasoning&&typeof n.reasoning=="object"&&(n.reasoning={enabled:!0,effort:n.reasoning.effort}),delete n.store,delete n.previous_response_id,delete n.include}async function ks(n,e,t,o){let r=n.body;(n.ccrHookOrder||=[]).push("handler"),o.endPoint==="/v1/responses"&&r?.input&&!r?.messages&&_t(r),o.endPoint==="/v1/responses"&&!n.provider&&typeof r?.model=="string"&&Cc.test(r.model)&&await yt(n,e,{configService:t.configService,tokenizerService:t.tokenizerService});let s=n.provider;if(!s&&r?.model){let c=r.model.split(",");c.length>1&&(s=c[0],r.model=c.slice(1).join(","))}let i=s?t.providerService.getProvider(s):void 0;if(!i&&r?.model){let c=t.providerService.resolveModelRoute(r.model);c&&(i=c.provider,r.model=c.targetModel)}if(!i&&r?.model){let u=t.configService.get("Router")?.default;if(u&&u.includes(",")){let[d,...g]=u.split(","),m=t.providerService.getProvider(d);m&&(i=m,r.model=g.join(","))}}if(n.originalModel||(n.originalModel=r?.model),!i)throw G(`Provider '${s}' not found`,404,"provider_not_found");n.provider=i.name||s;let l=Sc(n),a=o.endPoint==="/v1/messages"&&l;l&&e.header("X-Codex-Detected","true"),a&&e.header("X-Codex-On-Messages","true"),n.isCodexOnMessagesEndpoint=a,n.codexDetected=l;try{o.endPoint==="/v1/responses"&&r.input&&!r.messages&&_t(r);let{requestBody:c,config:u,bypass:d}=await Ts(r,i,o,n.headers,{req:n});if(c?.messages&&!d&&!n.isTargetAnthropic){let p=c.messages,f=new Set,_=[],k=[];for(let h of p){if(h?.role!=="system"){k.push(h);continue}let b=JSON.stringify(h.content??"");f.has(b)||(f.add(b),_.push(h))}_.length>0&&k.length>0&&(c.messages=[..._,...k])}let g=await Cs(c,u,i,t,d,o,{req:n});try{i?.baseUrl&&g?.headers&&ut(s,i.baseUrl,g.headers)}catch{}let m=await vs(c,g,i,o,d,{req:n,isCodexOnMessagesEndpoint:a});m=await bs(r,m,i.name||s);let y=xs(m,e,r,t);try{let p=r.model||n.originalModel;s&&p&&U().recordSuccess(s,p)}catch{}return y}catch(c){if(c instanceof ue)throw c;if(!n.__retryAttempted){n.__retryAttempted=!0;try{return await ks(n,e,t,o)}catch(d){if(n.__fallbackExhausted)throw d;c=d}}let u=await vc(n,e,t,o,c);if(u)return u;throw n.__fallbackExhausted=!0,c}}async function bs(n,e,t){if(!n?.stream||!e?.body)return e;let o=e.body.getReader(),r=await o.read();if(r.done)throw o.releaseLock(),G(`Provider returned empty streaming response from ${t}`,400,"provider_response_error");let s=new TextDecoder().decode(r.value);if(s.includes("event: error")){o.releaseLock();let a=s.length<500?s:s.slice(0,500);throw G(`Provider ${t} returned error in SSE stream: ${a}`,400,"provider_response_error")}if(s.split(`
|
|
44
|
-
`).filter(a=>a.startsWith("data:")&&a.trim().length>5).length===0){o.releaseLock();let a=s.length<500?s:s.slice(0,500);throw G(`Provider ${t} returned streaming response with no SSE data lines: ${a}`,400,"provider_response_error")}let l=new ReadableStream({start:a=>{a.enqueue(r.value);let c=()=>{o.read().then(({done:u,value:d})=>{u?a.close():(a.enqueue(d),c())}).catch(u=>a.error(u))};c()},cancel:()=>{o.cancel()}});return new Response(l,{headers:e.headers,status:e.status,statusText:e.statusText})}async function vc(n,e,t,o,r){let s=n.scenarioType||"default",i=n.familyFallback,l=n.modelFamily,a=n.strictProjectRouting?n.fallbackConfig:n.fallbackConfig??t.configService.get("fallback"),c=U(),u=n.provider||"",d=n.body.model||"",g=new Set,m=r?.statusCode===429||r?.isRateLimit===!0||r?.rawBody&&fn(r.rawBody)||r?.message&&fn(r.message);if(u&&d&&(m?(c.markRateLimited(u,d,120,r?.message),n.log.warn(`Primary model ${u},${d} rate-limited, will try fallbacks`)):c.recordFailure(u,d,r?.message),g.add(`${u},${d}`),t.recordUsage?.({provider:u,model:d,originalModel:n.originalModel||d,scenarioType:s,modelFamily:n.modelFamily,errorMessage:r?.message||String(r),sessionId:n.usageSessionId||n.id,stream:n.body.stream,inputTokens:n.tokenCount||0,req:n})),!(n.enableFallback??t.configService.get("Router")?.enableFallback===!0))return n.log.info("Fallback disabled by configuration, skipping fallback attempts"),null;let p=k=>{let[h,...b]=k.split(","),T=h?.trim(),x=b.join(",").trim();return!T||!x?null:{provider:T,model:x,key:`${T},${x}`}},f=[];if(l){let k=i?.[s];if(Array.isArray(k)&&k.length>0)f.push({name:`${l}/${s}`,models:k});else{let h=n.strictProjectRouting;n.log.warn(`No ${l} fallback configured for ${s}; ${h?"no project fallback available":"will try global fallback"}`)}}if(Array.isArray(a?.[s])&&a[s].length>0&&f.push({name:`global/${s}`,models:a[s]}),f.length===0&&s!=="image"&&n.body?.messages?.some(b=>b.role==="user"&&Array.isArray(b.content)&&b.content.some(T=>T.type==="image"||T.type==="image_url"||Array.isArray(T?.content)&&T.content.some(x=>x.type==="image"||x.type==="image_url")))&&Array.isArray(a?.image)&&a.image.length>0&&(n.log.info(`No fallback for scenario '${s}', but request has images \u2014 trying fallback.image`),f.push({name:"global/image (auto-detected)",models:a.image})),f.length===0)return null;let _=f.reduce((k,h)=>k+h.models.length,0);n.log.warn(`Request failed for ${s}, trying ${_} fallback models across ${f.length} fallback stage(s)`);for(let k of f){n.log.info(`Trying ${k.name} fallback stage with ${k.models.length} models`);for(let h of k.models){let b=p(h);if(!b){n.log.warn(`Fallback model '${h}' is invalid, skipping`);continue}if(g.has(b.key))continue;g.add(b.key);let T=t.providerService.getProviders(),x=mt(T,b.provider,b.model);if(!x){n.log.warn(`Fallback model ${h} is not configured or provider is disabled, skipping`);continue}let v=x.provider.name,S=x.model;if(!c.isAvailable(v,S)){n.log.warn(`Fallback model ${h} unavailable (fail pool), skipping`);continue}let C;for(let P=1;P<=2;P++)try{n.log.info(`Trying fallback model: ${v},${S}${P>1?" (retry)":""}`);let R={...n.body};R.model=S;let A={...n,provider:v,body:R},E=x.provider,{requestBody:I,config:L,bypass:F}=await Ts(R,E,o,n.headers,{req:A}),z=await Cs(I,L,E,t,F,o,{req:A});try{E?.baseUrl&&z?.headers&&ut(v,E.baseUrl,z.headers)}catch{}let N=await vs(I,z,E,o,F,{req:A,isCodexOnMessagesEndpoint:n.isCodexOnMessagesEndpoint||!1});return N=await bs(R,N,v),n.log.info(`Fallback model ${v},${S} succeeded`),c.recordSuccess(v,S),u&&d&&!n.strictProjectRouting&&(De().promote(u,d,s,v,S),n.log.info(`Promoted fallback model ${v},${S} for ${u},${d}:${s}`),m?n.log.info(`Rate-limited original model ${u},${d} already marked unavailable with cooldown`):(c.forceOpen(u,d,r?.message),n.log.info(`Marked original model ${u},${d} as unavailable`))),n.provider=v,n.body=R,xs(N,e,R,t)}catch(R){if(C=R,P===1){n.log.warn(`Fallback model ${v},${S} failed, retrying once: ${R.message}`);continue}}c.recordFailure(v,S,C?.message),n.log.warn(`Fallback model ${v},${S} failed after retry: ${C?.message}`),t.recordUsage?.({provider:v,model:S,originalModel:n.originalModel||d||n.body.model,scenarioType:s,modelFamily:n.modelFamily,errorMessage:C?.message||String(C),sessionId:n.usageSessionId||n.id,stream:n.body.stream,inputTokens:n.tokenCount||0,req:n})}}return n.log.error(`All fallback models failed for ${s}`),null}async function Ts(n,e,t,o,r){let s=JSON.parse(JSON.stringify(n)),i=s?.system;if(typeof i=="string"&&i.includes("cch="))s.system=i.replace(/cch=[^;]+;?/g,"cch=ccr-stable;");else if(Array.isArray(i))for(let c=0;c<i.length;c++){let u=i[c],d=typeof u=="string"?u:u?.text??"";if(d.includes("cch=")){let g=d.replace(/cch=[^;]+;?/g,"cch=ccr-stable;");typeof u=="string"?i[c]=g:typeof u?.text=="string"&&(u.text=g)}}let l={},a=!1;if(a=xc(e,t,n),a&&(o instanceof Headers?o.delete("content-length"):delete o["content-length"],l.headers=o),!a&&typeof t.transformRequestOut=="function"){let c=await t.transformRequestOut(s);c.body?(s=c.body,l=c.config||{}):s=c}if(!a&&e.transformer?.use?.length)for(let c of e.transformer.use){if(!c||typeof c.transformRequestIn!="function")continue;let u=await c.transformRequestIn(s,e,r);u.body?(s=u.body,l={...l,...u.config}):s=u}if(!a&&e.transformer?.[n.model]?.use?.length)for(let c of e.transformer[n.model].use)!c||typeof c.transformRequestIn!="function"||(s=await c.transformRequestIn(s,e,r));return{requestBody:s,config:l,bypass:a}}function xc(n,e,t){return e.endPoint==="/v1/chat/completions"&&Array.isArray(t?.system)?!1:n.transformer?.use?.length===1&&n.transformer.use[0].name===e.name&&(!n.transformer?.[t.model]?.use.length||n.transformer?.[t.model]?.use.length===1&&n.transformer?.[t.model]?.use[0].name===e.name)}function Sc(n){if(n.clientType)return n.clientType==="codex";let e=n.headers||{},t=e["x-anthropic-billing-header"]||"";if(typeof t=="string"&&t.includes("cc_version="))return!1;let o=e["user-agent"]||"";if(typeof o=="string"&&/codex/i.test(o))return!0;let r=n.pathname||n.url||"";if(typeof r=="string"&&r.split("?",1)[0].endsWith("/v1/responses"))return!0;let s=n.originalModel||n.body?.model||"";return typeof s=="string"&&s.toLowerCase()==="ccr-codex"}async function Cs(n,e,t,o,r,s,i){let l=e.url||new URL(t.baseUrl);if(!e.TIMEOUT){let u=o.configService.get("API_TIMEOUT_MS");u&&(e.TIMEOUT=typeof u=="string"?parseInt(u,10):u)}if(r&&typeof s.auth=="function"){let u=await s.auth(n,t);if(u.body){n=u.body;let d=e.headers||{};u.config?.headers&&(d={...d,...u.config.headers},delete d.host,delete u.config.headers),e={...e,...u.config,headers:d}}else n=u}let a={Authorization:`Bearer ${t.apiKey}`,...e?.headers||{}};for(let u in a)(a[u]==="undefined"||["authorization","Authorization"].includes(u)&&a[u]?.includes("undefined"))&&delete a[u];Xt(o.configService)&&Jr(o.log,i.req.id,{url:String(l),headers:a,body:n});let c=await Kr(l,n,{...e,headers:JSON.parse(JSON.stringify(a)),httpsProxy:le(o.configService,t)},i,o.log);if(!c.ok){let u=await c.text();o.log.error(`[provider_response_error] Error from provider(${t.name},${n.model}: ${c.status}): ${u}`);let d=G(`Error from provider(${t.name},${n.model}: ${c.status}): ${u}`,c.status,"provider_response_error");throw d.isRateLimit=c.status===429||fn(u),d.rawBody=u,d}if(c.ok){let u=c.headers.get("content-type")||"",d=n.stream===!0;if(o.log.info(`[hidden-error-check] provider=${t.name} model=${n.model} stream=${n.stream} isStreamRequest=${d} contentType=${u} ok=${c.ok} status=${c.status} hasBody=${!!c.body}`),!d||u.includes("application/json")){let g=c.clone(),m="";try{if(m=await g.text(),!m||m.trim()==="")throw new SyntaxError("Empty JSON body");let y=JSON.parse(m);if(y&&typeof y=="object"&&y.error&&(typeof y.error=="string"||typeof y.error=="object"&&Object.keys(y.error).length>0)){o.log.error(`[provider_response_error] Hidden error from provider(${t.name},${n.model}: ${c.status}): ${m}`);let f=fn(m),_=G(`Error from provider(${t.name},${n.model}: ${c.status}): ${m}`,400,"provider_response_error");throw _.isRateLimit=f,_.rawBody=m,_}}catch(y){if(y instanceof SyntaxError){o.log.warn(`[provider_response_error] Empty or malformed JSON response from provider(${t.name},${n.model}: 200): "${m}"`);let p=G(`API returned an empty or malformed response (HTTP 200) from ${t.name} \u2014 check for a proxy or gateway intercepting the request`,400,"provider_response_error");throw p.rawBody=m,p}throw y}}}if(!n.stream&&Xt(o.configService)){let d=await c.clone().text();Wr(o.log,i.req.id,{status:c.status,headers:Object.fromEntries(c.headers.entries()),body:d})}return c}async function vs(n,e,t,o,r,s){let i=e;if(!r&&t.transformer?.use?.length)for(let l of Array.from(t.transformer.use).reverse())!l||typeof l.transformResponseOut!="function"||(i=await l.transformResponseOut(i,s));if(!r&&t.transformer?.[n.model]?.use?.length)for(let l of Array.from(t.transformer[n.model].use).reverse())!l||typeof l.transformResponseOut!="function"||(i=await l.transformResponseOut(i,s));if(!r&&o.transformResponseIn&&(s.provider||(s.provider=t),i=await o.transformResponseIn(i,s)),s?.isCodexOnMessagesEndpoint)try{i=await new He().transformResponseIn(i,{...s,provider:t})}catch(l){console.error("Failed to apply Responses API conversion for codex client:",l)}return i}function xs(n,e,t,o){if(n.ok||e.code(n.status),t.stream===!0){if(e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),o&&Xt(o.configService)){let[s,i]=n.body.tee(),l=Br(o.configService);return Gr(s,o.log,e.request.id,l),e.send(i)}return e.send(n.body)}else return n.json()}function fn(n){let e=n.toLowerCase();return e.includes("rate limit")||e.includes("rate_limit")||e.includes("rate_limit_error")||e.includes("too many requests")||e.includes("too many")||e.includes("quota exhausted")||e.includes("qps_limit")||e.includes("token_limit")||e.includes("\u9650\u6D41")||e.includes("\u9891\u7387\u9650\u5236")}function Rc(n){try{return new URL(n),!0}catch{return!1}}var Cc,Ss,mn=w(()=>{"use strict";Qr();Vt();ct();po();ie();je();tn();Co();Ve();se();Cc=/^ccr-(opus|sonnet|haiku)(\[1m\])?$/i;Ss=async n=>{n.get("/",async()=>({message:"LLMs API",version:en})),n.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()})),n.get("/providers/health",async()=>({states:U().getAllStates().map(r=>({provider:r.provider,model:r.model,status:r.status,failureCount:r.failureCount,successCount:r.successCount,lastFailureTime:r.lastFailureTime,lastError:r.lastError,rateLimitUntil:r.rateLimitUntil??null})),timestamp:new Date().toISOString()}));let e=n.transformerService.getTransformersWithEndpoint();for(let{transformer:t}of e)t.endPoint&&n.post(t.endPoint,async(o,r)=>ks(o,r,n,t));n.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"}},proxyEnabled:{type:"boolean"}},required:["id","name","type","baseUrl","apiKey","models"]}}},async(t,o)=>{let{name:r,baseUrl:s,apiKey:i,models:l}=t.body;if(!r?.trim())throw G("Provider name is required",400,"invalid_request");if(!s||!Rc(s))throw G("Valid base URL is required",400,"invalid_request");if(!i?.trim())throw G("API key is required",400,"invalid_request");if(!l||!Array.isArray(l)||l.length===0)throw G("At least one model is required",400,"invalid_request");if(n.providerService.getProvider(t.body.name))throw G(`Provider with name '${t.body.name}' already exists`,400,"provider_exists");return n.providerService.registerProvider(t.body)}),n.get("/providers",async()=>n.providerService.getProviders()),n.get("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async t=>{let o=n.providerService.getProvider(t.params.id);if(!o)throw G("Provider not found",404,"provider_not_found");return o}),n.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"}},proxyEnabled:{type:"boolean"},enabled:{type:"boolean"}}}}},async(t,o)=>{let r=n.providerService.updateProvider(t.params.id,t.body);if(!r)throw G("Provider not found",404,"provider_not_found");return r}),n.delete("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async t=>{if(!n.providerService.deleteProvider(t.params.id))throw G("Provider not found",404,"provider_not_found");return{message:"Provider deleted successfully"}}),n.patch("/providers/:id/toggle",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]},body:{type:"object",properties:{enabled:{type:"boolean"}},required:["enabled"]}}},async(t,o)=>{if(!n.providerService.toggleProvider(t.params.id,t.body.enabled))throw G("Provider not found",404,"provider_not_found");return{message:`Provider ${t.body.enabled?"enabled":"disabled"} successfully`}})}});var de,gn=w(()=>{"use strict";de=class{constructor(e,t,o){this.configService=e;this.transformerService=t;this.logger=o;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(t=>{try{if(!t.name||!t.api_base_url||!t.api_key)return;let o={};t.transformer&&Object.keys(t.transformer).forEach(r=>{r==="use"?Array.isArray(t.transformer.use)&&(o.use=t.transformer.use.map(s=>{if(Array.isArray(s)&&typeof s[0]=="string"){let i=this.transformerService.getTransformer(s[0]);if(i)return new i(s[1])}if(typeof s=="string"){let i=this.transformerService.getTransformer(s);return typeof i=="function"?new i:i}}).filter(s=>typeof s<"u")):Array.isArray(t.transformer[r]?.use)&&(o[r]={use:t.transformer[r].use.map(s=>{if(Array.isArray(s)&&typeof s[0]=="string"){let i=this.transformerService.getTransformer(s[0]);if(i)return new i(s[1])}if(typeof s=="string"){let i=this.transformerService.getTransformer(s);return typeof i=="function"?new i:i}}).filter(s=>typeof s<"u")})}),this.registerProvider({name:t.name,baseUrl:t.api_base_url,apiKey:t.api_key,models:t.models||[],quotaToken:t.quota_token,quotaSecToken:t.quota_sec_token,transformer:t.transformer?o:void 0,cacheMode:t.cache_mode||"exclusive",enabled:t.enabled!==!1,proxyEnabled:t.proxy_enabled===!0,wakeupEnabled:t.wakeup_enabled===!0,wakeupTime:t.wakeup_time||"06:00",wakeupModel:t.wakeup_model||""}),this.logger.info(`${t.name} provider registered`)}catch(o){this.logger.error(`${t.name} provider registered error: ${o}`)}})}registerProvider(e){let t={...e,enabled:e.enabled!==!1,proxyEnabled:e.proxyEnabled===!0,wakeupEnabled:e.wakeupEnabled===!0,wakeupTime:e.wakeupTime||"06:00",wakeupModel:e.wakeupModel||""};return this.providers.set(t.name,t),e.models.forEach(o=>{let r=`${t.name},${o}`,s={provider:t.name,model:o,fullModel:r};this.modelRoutes.set(r,s),this.modelRoutes.has(o)||this.modelRoutes.set(o,s)}),t}getProviders(){return Array.from(this.providers.values())}getProvider(e){return this.providers.get(e)}updateProvider(e,t){let o=this.providers.get(e);if(!o)return null;let r={...o,...t,updatedAt:new Date};return this.providers.set(e,r),t.models&&(o.models.forEach(s=>{let i=`${o.name},${s}`;this.modelRoutes.delete(i),this.modelRoutes.delete(s)}),t.models.forEach(s=>{let i=`${o.name},${s}`,l={provider:o.name,model:s,fullModel:i};this.modelRoutes.set(i,l),this.modelRoutes.has(s)||this.modelRoutes.set(s,l)})),r}deleteProvider(e){let t=this.providers.get(e);return t?(t.models.forEach(o=>{let r=`${t.name},${o}`;this.modelRoutes.delete(r),this.modelRoutes.delete(o)}),this.providers.delete(e),!0):!1}toggleProvider(e,t){let o=this.providers.get(e);if(!o)return!1;o.enabled=t;let r=this.configService.get("providers");if(r&&Array.isArray(r)){let s=r.find(i=>i.name===e);s&&(s.enabled=t)}return!0}resolveModelRoute(e){let t=this.modelRoutes.get(e);if(!t)return null;let o=this.providers.get(t.provider);return o?{provider:o,originalModel:e,targetModel:t.model}:null}getAvailableModelNames(){let e=[];return this.providers.forEach(t=>{t.enabled!==!1&&t.models.forEach(o=>{e.push(o),e.push(`${t.name},${o}`)})}),e}getModelRoutes(){return Array.from(this.modelRoutes.values())}parseTransformerConfig(e){return e?Array.isArray(e)?e.reduce((t,o)=>{if(Array.isArray(o)){let[r,s={}]=o;t[r]=s}else t[o]={};return t},{}):e:{}}async getAvailableModels(){let e=[];return this.providers.forEach(t=>{t.enabled!==!1&&t.models.forEach(o=>{e.push({id:o,object:"model",owned_by:t.name,provider:t.name}),e.push({id:`${t.name},${o}`,object:"model",owned_by:t.name,provider:t.name})})}),{object:"list",data:e}}}});var Rs,ws=w(()=>{Rs=n=>n<=0?"none":n<=1024?"low":n<=8192?"medium":"high"});var Ps,Es=w(()=>{Ps=(n,e)=>(n.includes("base64")&&(n=n.split("base64").pop(),n.startsWith(",")&&(n=n.slice(1))),`data:${e};base64,${n}`)});function wc(n){return n.filter(e=>!!e?.function?.name).map(e=>({name:e.function.name,description:e.function.description,input_schema:e.function.parameters}))}function Os(n){let e=[],t=[],o=g=>{if(typeof g=="string"){t.push({type:"text",text:g});return}Array.isArray(g)&&g.forEach(m=>{if(typeof m=="string"){t.push({type:"text",text:m});return}m&&typeof m=="object"&&m.type==="text"&&m.text&&t.push({...m})})},r=()=>{let g=new Map;for(let m=0;m<t.length;m++){let y=t[m],p=y?.text??JSON.stringify(y),f=g.get(p);if(f===void 0){g.set(p,m);continue}!t[f]?.cache_control&&y?.cache_control&&(t[f]=y),t.splice(m,1),m--}};n.messages.forEach(g=>{g.role==="system"?o(g.content):e.push(g)}),r();let s=[];for(let g=0;g<e.length;g++){let m=e[g];if(m.role==="tool"){let y=m.content;try{typeof m.content=="string"&&(y=JSON.parse(m.content))}catch{}y!=null&&typeof y!="object"&&typeof y!="string"&&(y=String(y));let p={type:"tool_result",tool_use_id:m.tool_call_id,content:y};m.cache_control&&(p.cache_control=m.cache_control);let f=s[s.length-1];f&&f.role==="user"&&Array.isArray(f.content)?f.content.push(p):s.push({role:"user",content:[p]})}else if(m.role==="user"){let y=[];typeof m.content=="string"?y.push({type:"text",text:m.content}):Array.isArray(m.content)&&m.content.forEach(f=>{f&&typeof f=="object"&&f.type==="image_url"&&f.image_url?.url?y.push({type:"image",source:{type:"base64",media_type:f.media_type||"image/jpeg",data:f.image_url.url.split(",")[1]||f.image_url.url}}):y.push(f)});let p=s[s.length-1];p&&p.role==="user"&&Array.isArray(p.content)?p.content.push(...y):s.push({role:"user",content:y.length>0?y:[{type:"text",text:" "}]})}else if(m.role==="assistant"){let y=[];m.content&&(typeof m.content=="string"?y.push({type:"text",text:m.content}):Array.isArray(m.content)&&y.push(...m.content)),m.tool_calls&&m.tool_calls.length>0&&m.tool_calls.forEach(f=>{let _={};try{_=JSON.parse(f.function.arguments)}catch{_=f.function.arguments}y.push({type:"tool_use",id:f.id,name:f.function.name,input:_})}),m.thinking&&y.unshift({type:"thinking",thinking:m.thinking.content,signature:m.thinking.signature});let p=s[s.length-1];p&&p.role==="assistant"&&Array.isArray(p.content)?p.content.push(...y):s.push({role:"assistant",content:y.length>0?y:[{type:"text",text:" "}]})}}let i=()=>{let g=t.filter(m=>m?.cache_control).length;for(let m of s)Array.isArray(m.content)&&(g+=m.content.filter(y=>y?.cache_control).length);return g},l=g=>g&&typeof g=="object"?{...g}:{type:"ephemeral"},a=()=>{for(let g=s.length-1;g>=0;g--){let m=s[g]?.content;if(!Array.isArray(m))continue;let y=m.find(p=>p?.cache_control);if(y?.cache_control)return y.cache_control}for(let g=t.length-1;g>=0;g--)if(t[g]?.cache_control)return t[g].cache_control;return{type:"ephemeral"}},c=(g,m)=>{if(!Array.isArray(g?.content)||g.content.some(p=>p?.cache_control))return!1;let y=g.content.find(p=>p&&typeof p=="object"&&!p.cache_control);return y?(y.cache_control=l(m),!0):!1};(()=>{let g=4-i();if(g<=0||s.length===0)return;let m=s,y=a(),p=[];for(let f=m.length-1;f>=0;f--)m[f]?.role!=="user"||!Array.isArray(m[f].content)||p.push(f);for(let f of p){if(g<=0)break;c(m[f],y)&&g--}})();let d={messages:s,model:n.model,max_tokens:n.max_tokens||4096,temperature:n.temperature,stream:n.stream};if(t.length>0){let g=t.some(m=>m?.cache_control);d.system=g?t:t.map(m=>m.text||"").join(`
|
|
44
|
+
`).filter(a=>a.startsWith("data:")&&a.trim().length>5).length===0){o.releaseLock();let a=s.length<500?s:s.slice(0,500);throw G(`Provider ${t} returned streaming response with no SSE data lines: ${a}`,400,"provider_response_error")}let l=new ReadableStream({start:a=>{a.enqueue(r.value);let c=()=>{o.read().then(({done:u,value:d})=>{u?a.close():(a.enqueue(d),c())}).catch(u=>a.error(u))};c()},cancel:()=>{o.cancel()}});return new Response(l,{headers:e.headers,status:e.status,statusText:e.statusText})}async function vc(n,e,t,o,r){let s=n.scenarioType||"default",i=n.familyFallback,l=n.modelFamily,a=n.strictProjectRouting?n.fallbackConfig:n.fallbackConfig??t.configService.get("fallback"),c=U(),u=n.provider||"",d=n.body.model||"",g=new Set,m=r?.statusCode===429||r?.isRateLimit===!0||r?.rawBody&&fn(r.rawBody)||r?.message&&fn(r.message);if(u&&d&&(m?(c.markRateLimited(u,d,120,r?.message),n.log.warn(`Primary model ${u},${d} rate-limited, will try fallbacks`)):c.recordFailure(u,d,r?.message),g.add(`${u},${d}`),t.recordUsage?.({provider:u,model:d,originalModel:n.originalModel||d,scenarioType:s,modelFamily:n.modelFamily,errorMessage:r?.message||String(r),sessionId:n.usageSessionId||n.id,stream:n.body.stream,inputTokens:n.tokenCount||0,req:n})),!(n.enableFallback??t.configService.get("Router")?.enableFallback===!0))return n.log.info("Fallback disabled by configuration, skipping fallback attempts"),null;let p=k=>{let[h,...b]=k.split(","),T=h?.trim(),x=b.join(",").trim();return!T||!x?null:{provider:T,model:x,key:`${T},${x}`}},f=[];if(l){let k=i?.[s];if(Array.isArray(k)&&k.length>0)f.push({name:`${l}/${s}`,models:k});else{let h=n.strictProjectRouting;n.log.warn(`No ${l} fallback configured for ${s}; ${h?"no project fallback available":"will try global fallback"}`)}}if(Array.isArray(a?.[s])&&a[s].length>0&&f.push({name:`global/${s}`,models:a[s]}),f.length===0&&s!=="image"&&n.body?.messages?.some(b=>b.role==="user"&&Array.isArray(b.content)&&b.content.some(T=>T.type==="image"||T.type==="image_url"||Array.isArray(T?.content)&&T.content.some(x=>x.type==="image"||x.type==="image_url")))&&Array.isArray(a?.image)&&a.image.length>0&&(n.log.info(`No fallback for scenario '${s}', but request has images \u2014 trying fallback.image`),f.push({name:"global/image (auto-detected)",models:a.image})),f.length===0)return null;let _=f.reduce((k,h)=>k+h.models.length,0);n.log.warn(`Request failed for ${s}, trying ${_} fallback models across ${f.length} fallback stage(s)`);for(let k of f){n.log.info(`Trying ${k.name} fallback stage with ${k.models.length} models`);for(let h of k.models){let b=p(h);if(!b){n.log.warn(`Fallback model '${h}' is invalid, skipping`);continue}if(g.has(b.key))continue;g.add(b.key);let T=t.providerService.getProviders(),x=mt(T,b.provider,b.model);if(!x){n.log.warn(`Fallback model ${h} is not configured or provider is disabled, skipping`);continue}let v=x.provider.name,S=x.model;if(!c.isAvailable(v,S)){n.log.warn(`Fallback model ${h} unavailable (fail pool), skipping`);continue}let C;for(let E=1;E<=2;E++)try{n.log.info(`Trying fallback model: ${v},${S}${E>1?" (retry)":""}`);let R={...n.body};R.model=S;let A={...n,provider:v,body:R},O=x.provider,{requestBody:I,config:L,bypass:F}=await Ts(R,O,o,n.headers,{req:A}),z=await Cs(I,L,O,t,F,o,{req:A});try{O?.baseUrl&&z?.headers&&ut(v,O.baseUrl,z.headers)}catch{}let N=await vs(I,z,O,o,F,{req:A,isCodexOnMessagesEndpoint:n.isCodexOnMessagesEndpoint||!1});return N=await bs(R,N,v),n.log.info(`Fallback model ${v},${S} succeeded`),c.recordSuccess(v,S),u&&d&&!n.strictProjectRouting&&(De().promote(u,d,s,v,S),n.log.info(`Promoted fallback model ${v},${S} for ${u},${d}:${s}`),m?n.log.info(`Rate-limited original model ${u},${d} already marked unavailable with cooldown`):(c.forceOpen(u,d,r?.message),n.log.info(`Marked original model ${u},${d} as unavailable`))),n.provider=v,n.body=R,xs(N,e,R,t)}catch(R){if(C=R,E===1){n.log.warn(`Fallback model ${v},${S} failed, retrying once: ${R.message}`);continue}}c.recordFailure(v,S,C?.message),n.log.warn(`Fallback model ${v},${S} failed after retry: ${C?.message}`),t.recordUsage?.({provider:v,model:S,originalModel:n.originalModel||d||n.body.model,scenarioType:s,modelFamily:n.modelFamily,errorMessage:C?.message||String(C),sessionId:n.usageSessionId||n.id,stream:n.body.stream,inputTokens:n.tokenCount||0,req:n})}}return n.log.error(`All fallback models failed for ${s}`),null}async function Ts(n,e,t,o,r){let s=JSON.parse(JSON.stringify(n)),i=s?.system;if(typeof i=="string"&&i.includes("cch="))s.system=i.replace(/cch=[^;]+;?/g,"cch=ccr-stable;");else if(Array.isArray(i))for(let c=0;c<i.length;c++){let u=i[c],d=typeof u=="string"?u:u?.text??"";if(d.includes("cch=")){let g=d.replace(/cch=[^;]+;?/g,"cch=ccr-stable;");typeof u=="string"?i[c]=g:typeof u?.text=="string"&&(u.text=g)}}let l={},a=!1;if(a=xc(e,t,n),a&&(o instanceof Headers?o.delete("content-length"):delete o["content-length"],l.headers=o),!a&&typeof t.transformRequestOut=="function"){let c=await t.transformRequestOut(s);c.body?(s=c.body,l=c.config||{}):s=c}if(!a&&e.transformer?.use?.length)for(let c of e.transformer.use){if(!c||typeof c.transformRequestIn!="function")continue;let u=await c.transformRequestIn(s,e,r);u.body?(s=u.body,l={...l,...u.config}):s=u}if(!a&&e.transformer?.[n.model]?.use?.length)for(let c of e.transformer[n.model].use)!c||typeof c.transformRequestIn!="function"||(s=await c.transformRequestIn(s,e,r));return{requestBody:s,config:l,bypass:a}}function xc(n,e,t){return e.endPoint==="/v1/chat/completions"&&Array.isArray(t?.system)?!1:n.transformer?.use?.length===1&&n.transformer.use[0].name===e.name&&(!n.transformer?.[t.model]?.use.length||n.transformer?.[t.model]?.use.length===1&&n.transformer?.[t.model]?.use[0].name===e.name)}function Sc(n){if(n.clientType)return n.clientType==="codex";let e=n.headers||{},t=e["x-anthropic-billing-header"]||"";if(typeof t=="string"&&t.includes("cc_version="))return!1;let o=e["user-agent"]||"";if(typeof o=="string"&&/codex/i.test(o))return!0;let r=n.pathname||n.url||"";if(typeof r=="string"&&r.split("?",1)[0].endsWith("/v1/responses"))return!0;let s=n.originalModel||n.body?.model||"";return typeof s=="string"&&s.toLowerCase()==="ccr-codex"}async function Cs(n,e,t,o,r,s,i){let l=e.url||new URL(t.baseUrl);if(!e.TIMEOUT){let u=o.configService.get("API_TIMEOUT_MS");u&&(e.TIMEOUT=typeof u=="string"?parseInt(u,10):u)}if(r&&typeof s.auth=="function"){let u=await s.auth(n,t);if(u.body){n=u.body;let d=e.headers||{};u.config?.headers&&(d={...d,...u.config.headers},delete d.host,delete u.config.headers),e={...e,...u.config,headers:d}}else n=u}let a={Authorization:`Bearer ${t.apiKey}`,...e?.headers||{}};for(let u in a)(a[u]==="undefined"||["authorization","Authorization"].includes(u)&&a[u]?.includes("undefined"))&&delete a[u];Xt(o.configService)&&Jr(o.log,i.req.id,{url:String(l),headers:a,body:n});let c=await Kr(l,n,{...e,headers:JSON.parse(JSON.stringify(a)),httpsProxy:le(o.configService,t)},i,o.log);if(!c.ok){let u=await c.text();o.log.error(`[provider_response_error] Error from provider(${t.name},${n.model}: ${c.status}): ${u}`);let d=G(`Error from provider(${t.name},${n.model}: ${c.status}): ${u}`,c.status,"provider_response_error");throw d.isRateLimit=c.status===429||fn(u),d.rawBody=u,d}if(c.ok){let u=c.headers.get("content-type")||"",d=n.stream===!0;if(o.log.info(`[hidden-error-check] provider=${t.name} model=${n.model} stream=${n.stream} isStreamRequest=${d} contentType=${u} ok=${c.ok} status=${c.status} hasBody=${!!c.body}`),!d||u.includes("application/json")){let g=c.clone(),m="";try{if(m=await g.text(),!m||m.trim()==="")throw new SyntaxError("Empty JSON body");let y=JSON.parse(m);if(y&&typeof y=="object"&&y.error&&(typeof y.error=="string"||typeof y.error=="object"&&Object.keys(y.error).length>0)){o.log.error(`[provider_response_error] Hidden error from provider(${t.name},${n.model}: ${c.status}): ${m}`);let f=fn(m),_=G(`Error from provider(${t.name},${n.model}: ${c.status}): ${m}`,400,"provider_response_error");throw _.isRateLimit=f,_.rawBody=m,_}}catch(y){if(y instanceof SyntaxError){o.log.warn(`[provider_response_error] Empty or malformed JSON response from provider(${t.name},${n.model}: 200): "${m}"`);let p=G(`API returned an empty or malformed response (HTTP 200) from ${t.name} \u2014 check for a proxy or gateway intercepting the request`,400,"provider_response_error");throw p.rawBody=m,p}throw y}}}if(!n.stream&&Xt(o.configService)){let d=await c.clone().text();Wr(o.log,i.req.id,{status:c.status,headers:Object.fromEntries(c.headers.entries()),body:d})}return c}async function vs(n,e,t,o,r,s){let i=e;if(!r&&t.transformer?.use?.length)for(let l of Array.from(t.transformer.use).reverse())!l||typeof l.transformResponseOut!="function"||(i=await l.transformResponseOut(i,s));if(!r&&t.transformer?.[n.model]?.use?.length)for(let l of Array.from(t.transformer[n.model].use).reverse())!l||typeof l.transformResponseOut!="function"||(i=await l.transformResponseOut(i,s));if(!r&&o.transformResponseIn&&(s.provider||(s.provider=t),i=await o.transformResponseIn(i,s)),s?.isCodexOnMessagesEndpoint)try{i=await new He().transformResponseIn(i,{...s,provider:t})}catch(l){console.error("Failed to apply Responses API conversion for codex client:",l)}return i}function xs(n,e,t,o){if(n.ok||e.code(n.status),t.stream===!0){if(e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),o&&Xt(o.configService)){let[s,i]=n.body.tee(),l=Br(o.configService);return Gr(s,o.log,e.request.id,l),e.send(i)}return e.send(n.body)}else return n.json()}function fn(n){let e=n.toLowerCase();return e.includes("rate limit")||e.includes("rate_limit")||e.includes("rate_limit_error")||e.includes("too many requests")||e.includes("too many")||e.includes("quota exhausted")||e.includes("qps_limit")||e.includes("token_limit")||e.includes("\u9650\u6D41")||e.includes("\u9891\u7387\u9650\u5236")}function Rc(n){try{return new URL(n),!0}catch{return!1}}var Cc,Ss,mn=w(()=>{"use strict";Qr();Vt();ct();po();ie();je();tn();Co();Ve();se();Cc=/^ccr-(opus|sonnet|haiku)(\[1m\])?$/i;Ss=async n=>{n.get("/",async()=>({message:"LLMs API",version:en})),n.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()})),n.get("/providers/health",async()=>({states:U().getAllStates().map(r=>({provider:r.provider,model:r.model,status:r.status,failureCount:r.failureCount,successCount:r.successCount,lastFailureTime:r.lastFailureTime,lastError:r.lastError,rateLimitUntil:r.rateLimitUntil??null})),timestamp:new Date().toISOString()}));let e=n.transformerService.getTransformersWithEndpoint();for(let{transformer:t}of e)t.endPoint&&n.post(t.endPoint,async(o,r)=>ks(o,r,n,t));n.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"}},proxyEnabled:{type:"boolean"}},required:["id","name","type","baseUrl","apiKey","models"]}}},async(t,o)=>{let{name:r,baseUrl:s,apiKey:i,models:l}=t.body;if(!r?.trim())throw G("Provider name is required",400,"invalid_request");if(!s||!Rc(s))throw G("Valid base URL is required",400,"invalid_request");if(!i?.trim())throw G("API key is required",400,"invalid_request");if(!l||!Array.isArray(l)||l.length===0)throw G("At least one model is required",400,"invalid_request");if(n.providerService.getProvider(t.body.name))throw G(`Provider with name '${t.body.name}' already exists`,400,"provider_exists");return n.providerService.registerProvider(t.body)}),n.get("/providers",async()=>n.providerService.getProviders()),n.get("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async t=>{let o=n.providerService.getProvider(t.params.id);if(!o)throw G("Provider not found",404,"provider_not_found");return o}),n.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"}},proxyEnabled:{type:"boolean"},enabled:{type:"boolean"}}}}},async(t,o)=>{let r=n.providerService.updateProvider(t.params.id,t.body);if(!r)throw G("Provider not found",404,"provider_not_found");return r}),n.delete("/providers/:id",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]}}},async t=>{if(!n.providerService.deleteProvider(t.params.id))throw G("Provider not found",404,"provider_not_found");return{message:"Provider deleted successfully"}}),n.patch("/providers/:id/toggle",{schema:{params:{type:"object",properties:{id:{type:"string"}},required:["id"]},body:{type:"object",properties:{enabled:{type:"boolean"}},required:["enabled"]}}},async(t,o)=>{if(!n.providerService.toggleProvider(t.params.id,t.body.enabled))throw G("Provider not found",404,"provider_not_found");return{message:`Provider ${t.body.enabled?"enabled":"disabled"} successfully`}})}});var de,gn=w(()=>{"use strict";de=class{constructor(e,t,o){this.configService=e;this.transformerService=t;this.logger=o;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(t=>{try{if(!t.name||!t.api_base_url||!t.api_key)return;let o={};t.transformer&&Object.keys(t.transformer).forEach(r=>{r==="use"?Array.isArray(t.transformer.use)&&(o.use=t.transformer.use.map(s=>{if(Array.isArray(s)&&typeof s[0]=="string"){let i=this.transformerService.getTransformer(s[0]);if(i)return new i(s[1])}if(typeof s=="string"){let i=this.transformerService.getTransformer(s);return typeof i=="function"?new i:i}}).filter(s=>typeof s<"u")):Array.isArray(t.transformer[r]?.use)&&(o[r]={use:t.transformer[r].use.map(s=>{if(Array.isArray(s)&&typeof s[0]=="string"){let i=this.transformerService.getTransformer(s[0]);if(i)return new i(s[1])}if(typeof s=="string"){let i=this.transformerService.getTransformer(s);return typeof i=="function"?new i:i}}).filter(s=>typeof s<"u")})}),this.registerProvider({name:t.name,baseUrl:t.api_base_url,apiKey:t.api_key,models:t.models||[],quotaToken:t.quota_token,quotaSecToken:t.quota_sec_token,transformer:t.transformer?o:void 0,cacheMode:t.cache_mode||"exclusive",enabled:t.enabled!==!1,proxyEnabled:t.proxy_enabled===!0,wakeupEnabled:t.wakeup_enabled===!0,wakeupTime:t.wakeup_time||"06:00",wakeupModel:t.wakeup_model||""}),this.logger.info(`${t.name} provider registered`)}catch(o){this.logger.error(`${t.name} provider registered error: ${o}`)}})}registerProvider(e){let t={...e,enabled:e.enabled!==!1,proxyEnabled:e.proxyEnabled===!0,wakeupEnabled:e.wakeupEnabled===!0,wakeupTime:e.wakeupTime||"06:00",wakeupModel:e.wakeupModel||""};return this.providers.set(t.name,t),e.models.forEach(o=>{let r=`${t.name},${o}`,s={provider:t.name,model:o,fullModel:r};this.modelRoutes.set(r,s),this.modelRoutes.has(o)||this.modelRoutes.set(o,s)}),t}getProviders(){return Array.from(this.providers.values())}getProvider(e){return this.providers.get(e)}updateProvider(e,t){let o=this.providers.get(e);if(!o)return null;let r={...o,...t,updatedAt:new Date};return this.providers.set(e,r),t.models&&(o.models.forEach(s=>{let i=`${o.name},${s}`;this.modelRoutes.delete(i),this.modelRoutes.delete(s)}),t.models.forEach(s=>{let i=`${o.name},${s}`,l={provider:o.name,model:s,fullModel:i};this.modelRoutes.set(i,l),this.modelRoutes.has(s)||this.modelRoutes.set(s,l)})),r}deleteProvider(e){let t=this.providers.get(e);return t?(t.models.forEach(o=>{let r=`${t.name},${o}`;this.modelRoutes.delete(r),this.modelRoutes.delete(o)}),this.providers.delete(e),!0):!1}toggleProvider(e,t){let o=this.providers.get(e);if(!o)return!1;o.enabled=t;let r=this.configService.get("providers");if(r&&Array.isArray(r)){let s=r.find(i=>i.name===e);s&&(s.enabled=t)}return!0}resolveModelRoute(e){let t=this.modelRoutes.get(e);if(!t)return null;let o=this.providers.get(t.provider);return o?{provider:o,originalModel:e,targetModel:t.model}:null}getAvailableModelNames(){let e=[];return this.providers.forEach(t=>{t.enabled!==!1&&t.models.forEach(o=>{e.push(o),e.push(`${t.name},${o}`)})}),e}getModelRoutes(){return Array.from(this.modelRoutes.values())}parseTransformerConfig(e){return e?Array.isArray(e)?e.reduce((t,o)=>{if(Array.isArray(o)){let[r,s={}]=o;t[r]=s}else t[o]={};return t},{}):e:{}}async getAvailableModels(){let e=[];return this.providers.forEach(t=>{t.enabled!==!1&&t.models.forEach(o=>{e.push({id:o,object:"model",owned_by:t.name,provider:t.name}),e.push({id:`${t.name},${o}`,object:"model",owned_by:t.name,provider:t.name})})}),{object:"list",data:e}}}});var Rs,ws=w(()=>{Rs=n=>n<=0?"none":n<=1024?"low":n<=8192?"medium":"high"});var Ps,Es=w(()=>{Ps=(n,e)=>(n.includes("base64")&&(n=n.split("base64").pop(),n.startsWith(",")&&(n=n.slice(1))),`data:${e};base64,${n}`)});function wc(n){return n.filter(e=>!!e?.function?.name).map(e=>({name:e.function.name,description:e.function.description,input_schema:e.function.parameters}))}function Os(n){let e=[],t=[],o=g=>{if(typeof g=="string"){t.push({type:"text",text:g});return}Array.isArray(g)&&g.forEach(m=>{if(typeof m=="string"){t.push({type:"text",text:m});return}m&&typeof m=="object"&&m.type==="text"&&m.text&&t.push({...m})})},r=()=>{let g=new Map;for(let m=0;m<t.length;m++){let y=t[m],p=y?.text??JSON.stringify(y),f=g.get(p);if(f===void 0){g.set(p,m);continue}!t[f]?.cache_control&&y?.cache_control&&(t[f]=y),t.splice(m,1),m--}};n.messages.forEach(g=>{g.role==="system"?o(g.content):e.push(g)}),r();let s=[];for(let g=0;g<e.length;g++){let m=e[g];if(m.role==="tool"){let y=m.content;try{typeof m.content=="string"&&(y=JSON.parse(m.content))}catch{}y!=null&&typeof y!="object"&&typeof y!="string"&&(y=String(y));let p={type:"tool_result",tool_use_id:m.tool_call_id,content:y};m.cache_control&&(p.cache_control=m.cache_control);let f=s[s.length-1];f&&f.role==="user"&&Array.isArray(f.content)?f.content.push(p):s.push({role:"user",content:[p]})}else if(m.role==="user"){let y=[];typeof m.content=="string"?y.push({type:"text",text:m.content}):Array.isArray(m.content)&&m.content.forEach(f=>{f&&typeof f=="object"&&f.type==="image_url"&&f.image_url?.url?y.push({type:"image",source:{type:"base64",media_type:f.media_type||"image/jpeg",data:f.image_url.url.split(",")[1]||f.image_url.url}}):y.push(f)});let p=s[s.length-1];p&&p.role==="user"&&Array.isArray(p.content)?p.content.push(...y):s.push({role:"user",content:y.length>0?y:[{type:"text",text:" "}]})}else if(m.role==="assistant"){let y=[];m.content&&(typeof m.content=="string"?y.push({type:"text",text:m.content}):Array.isArray(m.content)&&y.push(...m.content)),m.tool_calls&&m.tool_calls.length>0&&m.tool_calls.forEach(f=>{let _={};try{_=JSON.parse(f.function.arguments)}catch{_=f.function.arguments}y.push({type:"tool_use",id:f.id,name:f.function.name,input:_})}),m.thinking&&y.unshift({type:"thinking",thinking:m.thinking.content,signature:m.thinking.signature});let p=s[s.length-1];p&&p.role==="assistant"&&Array.isArray(p.content)?p.content.push(...y):s.push({role:"assistant",content:y.length>0?y:[{type:"text",text:" "}]})}}let i=()=>{let g=t.filter(m=>m?.cache_control).length;for(let m of s)Array.isArray(m.content)&&(g+=m.content.filter(y=>y?.cache_control).length);return g},l=g=>g&&typeof g=="object"?{...g}:{type:"ephemeral"},a=()=>{for(let g=s.length-1;g>=0;g--){let m=s[g]?.content;if(!Array.isArray(m))continue;let y=m.find(p=>p?.cache_control);if(y?.cache_control)return y.cache_control}for(let g=t.length-1;g>=0;g--)if(t[g]?.cache_control)return t[g].cache_control;return{type:"ephemeral"}},c=(g,m)=>{if(!Array.isArray(g?.content)||g.content.some(p=>p?.cache_control))return!1;let y=g.content.find(p=>p&&typeof p=="object"&&!p.cache_control);return y?(y.cache_control=l(m),!0):!1};(()=>{let g=4-i();if(g<=0||s.length===0)return;let m=s,y=a(),p=[];for(let f=m.length-1;f>=0;f--)m[f]?.role!=="user"||!Array.isArray(m[f].content)||p.push(f);for(let f of p){if(g<=0)break;c(m[f],y)&&g--}})();let d={messages:s,model:n.model,max_tokens:n.max_tokens||4096,temperature:n.temperature,stream:n.stream};if(t.length>0){let g=t.some(m=>m?.cache_control);d.system=g?t:t.map(m=>m.text||"").join(`
|
|
45
45
|
|
|
46
46
|
`)}return n.tools&&n.tools.length>0&&(d.tools=wc(n.tools),n.tool_choice&&(n.tool_choice==="auto"?d.tool_choice={type:"auto"}:n.tool_choice==="any"||n.tool_choice==="required"?d.tool_choice={type:"any"}:typeof n.tool_choice=="string"?d.tool_choice={type:"tool",name:n.tool_choice}:typeof n.tool_choice=="object"&&n.tool_choice.type==="function"&&(d.tool_choice={type:"tool",name:n.tool_choice.function.name}))),d}var As=w(()=>{});var hn,yn,Is=w(()=>{"use strict";hn=require("uuid");ws();Vt();Es();As();yn=class{constructor(e){this.options=e;this.useBearer=this.options?.UseBearer??!1}name="Anthropic";endPoint="/v1/messages";useBearer;logger;async auth(e,t){let o={};return this.useBearer?(o.authorization=`Bearer ${t.apiKey}`,o["x-api-key"]=void 0):(o["x-api-key"]=t.apiKey,o.authorization=void 0),{body:e,config:{headers:o}}}async transformRequestOut(e){let t=[];if(e.system){if(typeof e.system=="string")t.push({role:"system",content:e.system});else if(Array.isArray(e.system)&&e.system.length){let s=e.system.filter(i=>i.type==="text"&&i.text).map(i=>({type:"text",text:i.text,cache_control:i.cache_control}));t.push({role:"system",content:s})}}let o=JSON.parse(JSON.stringify(e.messages||[]));o?.forEach(s=>{s.role==="system"&&t.push({role:"system",content:s.content})}),o?.forEach(s=>{if(s.role!=="system"&&(s.role==="user"||s.role==="assistant")){if(typeof s.content=="string"){t.push({role:s.role,content:s.content});return}if(Array.isArray(s.content)){if(s.role==="user"){let i=s.content.filter(a=>a.type==="tool_result"&&a.tool_use_id);i.length&&i.forEach(a=>{let c={role:"tool",content:typeof a.content=="string"?a.content:JSON.stringify(a.content),tool_call_id:a.tool_use_id,cache_control:a.cache_control};t.push(c)});let l=s.content.filter(a=>a.type==="text"&&a.text||a.type==="image"&&a.source);l.length&&t.push({role:"user",content:l.map(a=>a?.type==="image"?{type:"image_url",image_url:{url:a.source?.type==="base64"?Ps(a.source.data,a.source.media_type):a.source.url},media_type:a.source.media_type}:a)})}else if(s.role==="assistant"){let i={role:"assistant",content:""},l=s.content.filter(u=>u.type==="text"&&u.text);l.length&&(i.content=l.map(u=>u.text).join(`
|
|
47
|
-
`));let a=s.content.filter(u=>u.type==="tool_use"&&u.id);a.length&&(i.tool_calls=a.map(u=>({id:u.id,type:"function",function:{name:u.name,arguments:JSON.stringify(u.input||{})}})));let c=s.content.find(u=>u.type==="thinking");c&&(i.thinking={content:c.thinking,signature:c.signature}),t.push(i)}return}}});let r={messages:t,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&&(r.reasoning={effort:Rs(e.thinking.budget_tokens),enabled:e.thinking.type==="enabled"}),e.tool_choice&&(e.tool_choice.type==="tool"?r.tool_choice={type:"function",function:{name:e.tool_choice.name}}:r.tool_choice=e.tool_choice.type),r}async transformRequestIn(e,t,o){if(!this.isAnthropicMessagesEndpoint(t.baseUrl))return e;o&&o.req&&(o.req.isTargetAnthropic=!0);let r=Os(e),s={};return this.useBearer?(s.authorization=`Bearer ${t.apiKey}`,s["x-api-key"]=void 0):(s["x-api-key"]=t.apiKey,s.authorization=void 0),s["anthropic-version"]="2023-06-01",s["content-type"]="application/json",{body:r,config:{headers:s}}}isAnthropicMessagesEndpoint(e){try{return new URL(e.trim()).pathname.replace(/\/+$/,"").endsWith("/messages")}catch{return!1}}async transformResponseIn(e,t){if(t?.req?.isTargetAnthropic)return e;if(e.headers.get("Content-Type")?.includes("text/event-stream")){if(!e.body)throw new Error("Stream response body is null");let r=await this.convertOpenAIStreamToAnthropic(e.body,t);return new Response(r,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}else{let r=await e.json(),s=this.convertOpenAIResponseToAnthropic(r,t);return new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json"}})}}convertAnthropicToolsToUnified(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description||"",parameters:t.input_schema}}))}async convertOpenAIStreamToAnthropic(e,t){return new ReadableStream({start:async r=>{let s=new TextEncoder,i=`msg_${Date.now()}`,l=null,a="unknown",c=!1,u=!1,d=!1,g=new Map,m=new Map,y=0,p=0,f=0,_=!1,k=!1,h=0,b=-1,T=()=>{let C=h;return h++,C},x=C=>{if(!_)try{r.enqueue(C);let
|
|
48
|
-
data: ${JSON.stringify(
|
|
47
|
+
`));let a=s.content.filter(u=>u.type==="tool_use"&&u.id);a.length&&(i.tool_calls=a.map(u=>({id:u.id,type:"function",function:{name:u.name,arguments:JSON.stringify(u.input||{})}})));let c=s.content.find(u=>u.type==="thinking");c&&(i.thinking={content:c.thinking,signature:c.signature}),t.push(i)}return}}});let r={messages:t,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&&(r.reasoning={effort:Rs(e.thinking.budget_tokens),enabled:e.thinking.type==="enabled"}),e.tool_choice&&(e.tool_choice.type==="tool"?r.tool_choice={type:"function",function:{name:e.tool_choice.name}}:r.tool_choice=e.tool_choice.type),r}async transformRequestIn(e,t,o){if(!this.isAnthropicMessagesEndpoint(t.baseUrl))return e;o&&o.req&&(o.req.isTargetAnthropic=!0);let r=Os(e),s={};return this.useBearer?(s.authorization=`Bearer ${t.apiKey}`,s["x-api-key"]=void 0):(s["x-api-key"]=t.apiKey,s.authorization=void 0),s["anthropic-version"]="2023-06-01",s["content-type"]="application/json",{body:r,config:{headers:s}}}isAnthropicMessagesEndpoint(e){try{return new URL(e.trim()).pathname.replace(/\/+$/,"").endsWith("/messages")}catch{return!1}}async transformResponseIn(e,t){if(t?.req?.isTargetAnthropic)return e;if(e.headers.get("Content-Type")?.includes("text/event-stream")){if(!e.body)throw new Error("Stream response body is null");let r=await this.convertOpenAIStreamToAnthropic(e.body,t);return new Response(r,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}else{let r=await e.json(),s=this.convertOpenAIResponseToAnthropic(r,t);return new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json"}})}}convertAnthropicToolsToUnified(e){return e.map(t=>({type:"function",function:{name:t.name,description:t.description||"",parameters:t.input_schema}}))}async convertOpenAIStreamToAnthropic(e,t){return new ReadableStream({start:async r=>{let s=new TextEncoder,i=`msg_${Date.now()}`,l=null,a="unknown",c=!1,u=!1,d=!1,g=new Map,m=new Map,y=0,p=0,f=0,_=!1,k=!1,h=0,b=-1,T=()=>{let C=h;return h++,C},x=C=>{if(!_)try{r.enqueue(C);let E=new TextDecoder().decode(C);this.logger.debug({reqId:t.req.id,data:E,type:"send data"})}catch(E){if(E instanceof TypeError&&E.message.includes("Controller is already closed"))_=!0;else throw this.logger.debug({reqId:t.req.id,error:E instanceof Error?E.message:String(E),type:"send data error"}),E}},v=()=>{if(!_)try{if(!c){this.logger?.warn("[empty_stream] Upstream produced no data, closing silently"),r.close(),_=!0;return}if(b>=0){let E={type:"content_block_stop",index:b};x(s.encode(`event: content_block_stop
|
|
48
|
+
data: ${JSON.stringify(E)}
|
|
49
49
|
|
|
50
50
|
`)),b=-1}if(l)x(s.encode(`event: message_delta
|
|
51
51
|
data: ${JSON.stringify(l)}
|
|
52
52
|
|
|
53
|
-
`)),l=null;else{let
|
|
54
|
-
data: ${JSON.stringify({type:"message_delta",delta:{stop_reason:"end_turn",stop_sequence:null},usage:{input_tokens:
|
|
53
|
+
`)),l=null;else{let E=t?.req?.tokenCount||0;x(s.encode(`event: message_delta
|
|
54
|
+
data: ${JSON.stringify({type:"message_delta",delta:{stop_reason:"end_turn",stop_sequence:null},usage:{input_tokens:E,output_tokens:0,cache_read_input_tokens:0}})}
|
|
55
55
|
|
|
56
56
|
`))}let C={type:"message_stop"};x(s.encode(`event: message_stop
|
|
57
57
|
data: ${JSON.stringify(C)}
|
|
58
58
|
|
|
59
|
-
`)),r.close(),_=!0}catch(C){if(C instanceof TypeError&&C.message.includes("Controller is already closed"))_=!0;else throw C}},S=null;try{S=e.getReader();let C=new TextDecoder,
|
|
60
|
-
`);
|
|
59
|
+
`)),r.close(),_=!0}catch(C){if(C instanceof TypeError&&C.message.includes("Controller is already closed"))_=!0;else throw C}},S=null;try{S=e.getReader();let C=new TextDecoder,E="";for(;!_;){let{done:R,value:A}=await S.read();if(R)break;E+=C.decode(A,{stream:!0});let O=E.split(`
|
|
60
|
+
`);E=O.pop()||"";for(let I of O){if(_)break;if(!I.startsWith("data:"))continue;let L=I.slice(5).trim();if(this.logger.debug({reqId:t.req.id,type:"recieved data",data:L}),L!=="[DONE]")try{let F=JSON.parse(L);if(y++,this.logger.debug({reqId:t.req.id,response:F,tppe:"Original Response"}),F.error){t?.req&&(t.req.sseError=F.error);let N={type:"error",message:{type:"api_error",message:JSON.stringify(F.error)}};x(s.encode(`event: error
|
|
61
61
|
data: ${JSON.stringify(N)}
|
|
62
62
|
|
|
63
63
|
`));continue}if(a=F.model||a,!c&&!_&&!d){c=!0;let N=t?.req?.tokenCount||0,D={type:"message_start",message:{id:i,type:"message",role:"assistant",content:[],model:a,stop_reason:null,stop_sequence:null,usage:{input_tokens:N,output_tokens:0}}};x(s.encode(`event: message_start
|
|
64
64
|
data: ${JSON.stringify(D)}
|
|
65
65
|
|
|
66
|
-
`))}let z=F.choices?.[0];if(F.usage){let N=F.usage?.prompt_tokens_details?.cached_tokens
|
|
66
|
+
`))}let z=F.choices?.[0];if(F.usage){let N=F.usage?.prompt_tokens_details?.cached_tokens??F.usage?.prompt_cache_hit_tokens??0,K=(F.usage?.prompt_tokens||0)-N,Ce=F.usage?.completion_tokens||0;this.logger?.info({debug_log:!0,reqId:t.req.id,phase:"anthropic_transformer_usage",providerUsage:F.usage,mappedUsage:{input_tokens:K,output_tokens:Ce,cache_read_input_tokens:N},choicesLength:Array.isArray(F.choices)?F.choices.length:void 0,finishReason:z?.finish_reason});let H={input_tokens:K,output_tokens:Ce,cache_read_input_tokens:N};if(!l)l={type:"message_delta",delta:{stop_reason:"end_turn",stop_sequence:null},usage:{...H}};else{let te=l.usage||{};l.usage={input_tokens:H.input_tokens||te.input_tokens||0,output_tokens:H.output_tokens||te.output_tokens||0,cache_read_input_tokens:H.cache_read_input_tokens||te.cache_read_input_tokens||0}}}if(!z)continue;if(z?.delta?.thinking&&!_&&!d&&!u){if(!k){let N=T(),D={type:"content_block_start",index:N,content_block:{type:"thinking",thinking:""}};x(s.encode(`event: content_block_start
|
|
67
67
|
data: ${JSON.stringify(D)}
|
|
68
68
|
|
|
69
69
|
`)),b=N,k=!0}if(z.delta.thinking.signature){let N={type:"content_block_delta",index:b,delta:{type:"signature_delta",signature:z.delta.thinking.signature}};x(s.encode(`event: content_block_delta
|
|
@@ -108,23 +108,23 @@ data: ${JSON.stringify(M)}
|
|
|
108
108
|
`))}catch(B){console.error(B)}}}}}if(z?.finish_reason&&!_&&!d){if(p===0&&f===0&&console.error("Warning: No content in the stream response!"),b>=0){let N={type:"content_block_stop",index:b};x(s.encode(`event: content_block_stop
|
|
109
109
|
data: ${JSON.stringify(N)}
|
|
110
110
|
|
|
111
|
-
`)),b=-1}if(!_){let D={stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"stop_sequence"}[z.finish_reason]||"end_turn";l?l.delta={...l.delta,stop_reason:D,stop_sequence:null}:l={type:"message_delta",delta:{stop_reason:D,stop_sequence:null},usage:{input_tokens:0,output_tokens:0,cache_read_input_tokens:0}}}d=!0}}catch(F){this.logger?.error(`parseError: ${F.name} message: ${F.message} stack: ${F.stack} data: ${L}`)}}}v()}catch(C){if(!_)try{r.error(C)}catch(
|
|
112
|
-
`)||"",u={id:o.responseId,choices:[{finish_reason:o.candidates[0].finishReason?.toLowerCase()||null,index:0,message:{content:c,role:"assistant",tool_calls:a.length>0?a:void 0,...s&&{thinking:{content:r||"(no content)",signature:s}}}}],created:parseInt(new Date().getTime()/1e3+"",10),model:o.modelVersion,object:"chat.completion",usage:{completion_tokens:o.usageMetadata?.candidatesTokenCount||0,prompt_tokens:o.usageMetadata?.promptTokenCount||0,prompt_tokens_details:{cached_tokens:o.usageMetadata?.cachedContentTokenCount||0},total_tokens:o.usageMetadata?.totalTokenCount||0,output_tokens_details:{reasoning_tokens:o.usageMetadata?.thoughtsTokenCount||0}}};return new Response(JSON.stringify(u),{status:n.status,statusText:n.statusText,headers:n.headers})}else if(n.headers.get("Content-Type")?.includes("stream")){if(!n.body)return n;let o=new TextDecoder,r=new TextEncoder,s=!1,i=!1,l=!1,a="",c=0,u=-1,d=new ReadableStream({async start(g){let m=async(f,_)=>{if(f.startsWith("data: ")){let k=f.slice(6).trim();if(k){t?.debug({chunkStr:k},`${e} chunk:`);try{let h=JSON.parse(k);if(!h.candidates||!h.candidates[0]){t?.debug({chunkStr:k},"Invalid chunk structure");return}let b=h.candidates[0],T=b.content?.parts||[];T.filter(C=>C.text&&C.thought===!0).forEach(C=>{l||(l=!0);let
|
|
111
|
+
`)),b=-1}if(!_){let D={stop:"end_turn",length:"max_tokens",tool_calls:"tool_use",content_filter:"stop_sequence"}[z.finish_reason]||"end_turn";l?l.delta={...l.delta,stop_reason:D,stop_sequence:null}:l={type:"message_delta",delta:{stop_reason:D,stop_sequence:null},usage:{input_tokens:0,output_tokens:0,cache_read_input_tokens:0}}}d=!0}}catch(F){this.logger?.error(`parseError: ${F.name} message: ${F.message} stack: ${F.stack} data: ${L}`)}}}v()}catch(C){if(!_)try{r.error(C)}catch(E){console.error(E)}}finally{if(S)try{S.releaseLock()}catch(C){console.error(C)}}},cancel:r=>{this.logger.debug({reqId:t.req.id},`cancle stream: ${r}`)}})}convertOpenAIResponseToAnthropic(e,t){this.logger.debug({reqId:t.req.id,response:e},"Original OpenAI response");try{let o=e.choices[0];if(!o)throw new Error("No choices found in OpenAI response");let r=[];if(o.message.annotations){let a=`srvtoolu_${(0,hn.v4)()}`;r.push({type:"server_tool_use",id:a,name:"web_search",input:{query:""}}),r.push({type:"web_search_tool_result",tool_use_id:a,content:o.message.annotations.map(c=>({type:"web_search_result",url:c.url_citation.url,title:c.url_citation.title}))})}o.message.content&&r.push({type:"text",text:o.message.content}),o.message.tool_calls&&o.message.tool_calls.length>0&&o.message.tool_calls.forEach(a=>{let c={};try{let u=a.function.arguments||"{}";typeof u=="object"?c=u:typeof u=="string"&&(c=JSON.parse(u))}catch{c={text:a.function.arguments||""}}r.push({type:"tool_use",id:a.id,name:a.function.name,input:c})}),o.message?.thinking?.content&&r.push({type:"thinking",thinking:o.message.thinking.content,signature:o.message.thinking.signature});let s=e.usage?.prompt_tokens_details?.cached_tokens??e.usage?.prompt_cache_hit_tokens??0,i=(e.usage?.prompt_tokens||0)-s,l={id:e.id?.startsWith("msg_")?e.id:`msg_${(0,hn.v4)().replace(/-/g,"")}`,type:"message",role:"assistant",model:e.model,content:r,stop_reason:o.finish_reason==="stop"?"end_turn":o.finish_reason==="length"?"max_tokens":o.finish_reason==="tool_calls"?"tool_use":o.finish_reason==="content_filter"?"stop_sequence":"end_turn",stop_sequence:null,usage:{input_tokens:i,cache_creation_input_tokens:0,cache_read_input_tokens:s,output_tokens:e.usage?.completion_tokens||0,server_tool_use:{web_search_requests:0,web_fetch_requests:0},service_tier:"standard",cache_creation:{ephemeral_1h_input_tokens:0,ephemeral_5m_input_tokens:0},inference_geo:"",iterations:[],speed:"standard"},stop_details:null,context_management:null};return this.logger.debug({reqId:t.req.id,result:l},"Conversion complete, final Anthropic response"),l}catch{throw G(`Provider error: ${JSON.stringify(e)}`,500,"provider_error")}}}});function Pc(n,e){n.includes("null")&&(e.nullable=!0);let t=n.filter(o=>o!=="null");if(t.length===1){let o=t[0].toUpperCase();e.type=Object.values(Ye).includes(o)?o:Ye.TYPE_UNSPECIFIED}else{e.anyOf=[];for(let o of t){let r=o.toUpperCase();e.anyOf.push({type:Object.values(Ye).includes(r)?r:Ye.TYPE_UNSPECIFIED})}}}function kt(n){let e={},t=["items"],o=["anyOf"],r=["properties"];if(n.type&&n.anyOf)throw new Error("type and anyOf cannot be both populated.");let s=n.anyOf;s!=null&&Array.isArray(s)&&s.length==2&&(s[0]&&s[0].type==="null"?(e.nullable=!0,n=s[1]):s[1]&&s[1].type==="null"&&(e.nullable=!0,n=s[0])),n.type&&Array.isArray(n.type)&&Pc(n.type,e);for(let[i,l]of Object.entries(n))if(l!=null)if(i=="type"){if(l==="null")throw new Error("type: null can not be the only possible type for the field.");if(Array.isArray(l))continue;let a=l.toUpperCase();e.type=Object.values(Ye).includes(a)?a:Ye.TYPE_UNSPECIFIED}else if(t.includes(i))e[i]=kt(l);else if(o.includes(i)){let a=[];for(let c of l){if(c.type=="null"){e.nullable=!0;continue}a.push(kt(c))}e[i]=a}else if(r.includes(i)){let a={};for(let[c,u]of Object.entries(l))a[c]=kt(u);e[i]=a}else{if(i==="additionalProperties")continue;e[i]=l}return e}function Ec(n){if(n.functionDeclarations)for(let e of n.functionDeclarations)e.parameters&&(Object.keys(e.parameters).includes("$schema")?e.parametersJsonSchema||(e.parametersJsonSchema=e.parameters,delete e.parameters):e.parameters=kt(e.parameters)),e.response&&(Object.keys(e.response).includes("$schema")?e.responseJsonSchema||(e.responseJsonSchema=e.response,delete e.response):e.response=kt(e.response));return n}function _n(n){let e=[],t=n.tools?.filter(a=>a.function.name!=="web_search")?.map(a=>({name:a.function.name,description:a.function.description,parametersJsonSchema:a.function.parameters}));t?.length&&e.push(Ec({functionDeclarations:t})),n.tools?.find(a=>a.function.name==="web_search")&&e.push({googleSearch:{}});let r=[],s=n.messages.filter(a=>a.role==="tool");n.messages.filter(a=>a.role!=="tool").forEach(a=>{let c;a.role==="assistant"?c="model":(["user","system"].includes(a.role),c="user");let u=[];if(typeof a.content=="string"){let d={text:a.content};a.thinking?.signature&&(d.thoughtSignature=a.thinking.signature),u.push(d)}else Array.isArray(a.content)?u.push(...a.content.map(d=>{if(d.type==="text")return{text:d.text||""};if(d.type==="image_url")return d.image_url.url.startsWith("http")?{file_data:{mime_type:d.media_type,file_uri:d.image_url.url}}:{inlineData:{mime_type:d.media_type,data:d.image_url.url?.split(",")?.pop()||d.image_url.url}}})):a.content&&typeof a.content=="object"&&(a.content.text?u.push({text:a.content.text}):u.push({text:JSON.stringify(a.content)}));if(Array.isArray(a.tool_calls)&&u.push(...a.tool_calls.map(d=>{let g={functionCall:{id:d.id||`tool_${Math.random().toString(36).substring(2,15)}`,name:d.function.name,args:JSON.parse(d.function.arguments||"{}")}};return a.thinking?.signature&&(g.thoughtSignature=a.thinking.signature),g})),u.length===0&&u.push({text:""}),r.push({role:c,parts:u}),c==="model"&&a.tool_calls){let d=a.tool_calls.map(g=>{let m=s.find(y=>y.tool_call_id===g.id);return{functionResponse:{name:g?.function?.name,response:{result:m?.content}}}});r.push({role:"user",parts:d})}});let i={};if(n.reasoning&&n.reasoning.effort&&n.reasoning.effort!=="none")if(i.thinkingConfig={includeThoughts:!0},n.model.includes("gemini-3"))i.thinkingConfig.thinkingLevel=n.reasoning.effort;else{let a=n.model.includes("pro")?[128,32768]:[0,24576],c,u=n.reasoning.max_tokens;typeof u<"u"&&(u>=a[0]&&u<=a[1]?c=u:u<a[0]?c=a[0]:u>a[1]&&(c=a[1]),i.thinkingConfig.thinkingBudget=c)}let l={contents:r,tools:e.length?e:void 0,generationConfig:i};if(n.tool_choice){let a={functionCallingConfig:{}};n.tool_choice==="auto"?a.functionCallingConfig.mode="auto":n.tool_choice==="none"?a.functionCallingConfig.mode="none":n.tool_choice==="required"?a.functionCallingConfig.mode="any":n.tool_choice?.function?.name&&(a.functionCallingConfig.mode="any",a.functionCallingConfig.allowedFunctionNames=[n.tool_choice?.function?.name]),l.toolConfig=a}return l}function kn(n){let e=n.contents,t=n.tools,o=n.model,r=n.max_tokens,s=n.temperature,i=n.stream,l=n.tool_choice,a={messages:[],model:o,max_tokens:r,temperature:s,stream:i,tool_choice:l};return Array.isArray(e)&&e.forEach(c=>{typeof c=="string"?a.messages.push({role:"user",content:c}):typeof c.text=="string"?a.messages.push({role:"user",content:c.text||null}):c.role==="user"?a.messages.push({role:"user",content:c?.parts?.map(u=>({type:"text",text:u.text||""}))||[]}):c.role==="model"&&a.messages.push({role:"assistant",content:c?.parts?.map(u=>({type:"text",text:u.text||""}))||[]})}),Array.isArray(t)&&(a.tools=[],t.forEach(c=>{Array.isArray(c.functionDeclarations)&&c.functionDeclarations.forEach(u=>{a.tools.push({type:"function",function:{name:u.name,description:u.description,parameters:u.parameters}})})})),a}async function bn(n,e,t){if(n.headers.get("Content-Type")?.includes("application/json")){let o=await n.json();t?.debug({response:o},`${e} response:`);let r="",s="",i=o.candidates[0]?.content?.parts||[],l=[];for(let d of i)d.text&&d.thought===!0?r+=d.text:l.push(d);s=i.find(d=>d.thoughtSignature)?.thoughtSignature;let a=l?.filter(d=>d.functionCall)?.map(d=>({id:d.functionCall?.id||`tool_${Math.random().toString(36).substring(2,15)}`,type:"function",function:{name:d.functionCall?.name,arguments:JSON.stringify(d.functionCall?.args||{})}}))||[],c=l?.filter(d=>d.text)?.map(d=>d.text)?.join(`
|
|
112
|
+
`)||"",u={id:o.responseId,choices:[{finish_reason:o.candidates[0].finishReason?.toLowerCase()||null,index:0,message:{content:c,role:"assistant",tool_calls:a.length>0?a:void 0,...s&&{thinking:{content:r||"(no content)",signature:s}}}}],created:parseInt(new Date().getTime()/1e3+"",10),model:o.modelVersion,object:"chat.completion",usage:{completion_tokens:o.usageMetadata?.candidatesTokenCount||0,prompt_tokens:o.usageMetadata?.promptTokenCount||0,prompt_tokens_details:{cached_tokens:o.usageMetadata?.cachedContentTokenCount||0},total_tokens:o.usageMetadata?.totalTokenCount||0,output_tokens_details:{reasoning_tokens:o.usageMetadata?.thoughtsTokenCount||0}}};return new Response(JSON.stringify(u),{status:n.status,statusText:n.statusText,headers:n.headers})}else if(n.headers.get("Content-Type")?.includes("stream")){if(!n.body)return n;let o=new TextDecoder,r=new TextEncoder,s=!1,i=!1,l=!1,a="",c=0,u=-1,d=new ReadableStream({async start(g){let m=async(f,_)=>{if(f.startsWith("data: ")){let k=f.slice(6).trim();if(k){t?.debug({chunkStr:k},`${e} chunk:`);try{let h=JSON.parse(k);if(!h.candidates||!h.candidates[0]){t?.debug({chunkStr:k},"Invalid chunk structure");return}let b=h.candidates[0],T=b.content?.parts||[];T.filter(C=>C.text&&C.thought===!0).forEach(C=>{l||(l=!0);let E={choices:[{delta:{role:"assistant",content:null,thinking:{content:C.text}},finish_reason:null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1"};_.enqueue(r.encode(`data: ${JSON.stringify(E)}
|
|
113
113
|
|
|
114
|
-
`))});let x=T.find(C=>C.thoughtSignature)?.thoughtSignature;if(x&&!s){if(!l){let
|
|
114
|
+
`))});let x=T.find(C=>C.thoughtSignature)?.thoughtSignature;if(x&&!s){if(!l){let E={choices:[{delta:{role:"assistant",content:null,thinking:{content:"(no content)"}},finish_reason:null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1"};_.enqueue(r.encode(`data: ${JSON.stringify(E)}
|
|
115
115
|
|
|
116
116
|
`))}let C={choices:[{delta:{role:"assistant",content:null,thinking:{signature:x}},finish_reason:null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1"};if(_.enqueue(r.encode(`data: ${JSON.stringify(C)}
|
|
117
117
|
|
|
118
|
-
`)),s=!0,c++,a){let
|
|
118
|
+
`)),s=!0,c++,a){let E={choices:[{delta:{role:"assistant",content:a},finish_reason:null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1"};_.enqueue(r.encode(`data: ${JSON.stringify(E)}
|
|
119
119
|
|
|
120
120
|
`)),a="",i||(i=!0)}}let v=T.filter(C=>C.functionCall).map(C=>({id:C.functionCall?.id||`ccr_tool_${Math.random().toString(36).substring(2,15)}`,type:"function",function:{name:C.functionCall?.name,arguments:JSON.stringify(C.functionCall?.args||{})}})),S=T.filter(C=>C.text&&C.thought!==!0).map(C=>C.text).join(`
|
|
121
121
|
`);if(!S&&s&&!i){let C={choices:[{delta:{role:"assistant",content:"(no content)"},index:c,finish_reason:null,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1"};_.enqueue(r.encode(`data: ${JSON.stringify(C)}
|
|
122
122
|
|
|
123
123
|
`)),i||(i=!0)}if(l&&S&&!s)if(h.modelVersion.includes("3")){a+=S;return}else{let C={choices:[{delta:{role:"assistant",content:null,thinking:{signature:`ccr_${+new Date}`}},finish_reason:null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1"};_.enqueue(r.encode(`data: ${JSON.stringify(C)}
|
|
124
124
|
|
|
125
|
-
`)),s=!0}if(S){a||c++;let C={choices:[{delta:{role:"assistant",content:S},finish_reason:b.finishReason?.toLowerCase()||null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1",usage:{completion_tokens:h.usageMetadata?.candidatesTokenCount||0,prompt_tokens:h.usageMetadata?.promptTokenCount||0,prompt_tokens_details:{cached_tokens:h.usageMetadata?.cachedContentTokenCount||0},total_tokens:h.usageMetadata?.totalTokenCount||0,output_tokens_details:{reasoning_tokens:h.usageMetadata?.thoughtsTokenCount||0}}};b?.groundingMetadata?.groundingChunks?.length&&(C.choices[0].delta.annotations=b.groundingMetadata.groundingChunks.map((
|
|
125
|
+
`)),s=!0}if(S){a||c++;let C={choices:[{delta:{role:"assistant",content:S},finish_reason:b.finishReason?.toLowerCase()||null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1",usage:{completion_tokens:h.usageMetadata?.candidatesTokenCount||0,prompt_tokens:h.usageMetadata?.promptTokenCount||0,prompt_tokens_details:{cached_tokens:h.usageMetadata?.cachedContentTokenCount||0},total_tokens:h.usageMetadata?.totalTokenCount||0,output_tokens_details:{reasoning_tokens:h.usageMetadata?.thoughtsTokenCount||0}}};b?.groundingMetadata?.groundingChunks?.length&&(C.choices[0].delta.annotations=b.groundingMetadata.groundingChunks.map((E,R)=>{let A=b?.groundingMetadata?.groundingSupports?.filter(O=>O.groundingChunkIndices?.includes(R));return{type:"url_citation",url_citation:{url:E?.web?.uri||"",title:E?.web?.title||"",content:A?.[0]?.segment?.text||"",start_index:A?.[0]?.segment?.startIndex||0,end_index:A?.[0]?.segment?.endIndex||0}}})),_.enqueue(r.encode(`data: ${JSON.stringify(C)}
|
|
126
126
|
|
|
127
|
-
`)),!i&&S&&(i=!0)}v.length>0&&(v.forEach(C=>{c++,u++;let
|
|
127
|
+
`)),!i&&S&&(i=!0)}v.length>0&&(v.forEach(C=>{c++,u++;let E={choices:[{delta:{role:"assistant",tool_calls:[{...C,index:u}]},finish_reason:b.finishReason?.toLowerCase()||null,index:c,logprobs:null}],created:parseInt(new Date().getTime()/1e3+"",10),id:h.responseId||"",model:h.modelVersion||"",object:"chat.completion.chunk",system_fingerprint:"fp_a49d71b8a1",usage:{completion_tokens:h.usageMetadata?.candidatesTokenCount||0,prompt_tokens:h.usageMetadata?.promptTokenCount||0,prompt_tokens_details:{cached_tokens:h.usageMetadata?.cachedContentTokenCount||0},total_tokens:h.usageMetadata?.totalTokenCount||0,output_tokens_details:{reasoning_tokens:h.usageMetadata?.thoughtsTokenCount||0}}};b?.groundingMetadata?.groundingChunks?.length&&(E.choices[0].delta.annotations=b.groundingMetadata.groundingChunks.map((R,A)=>{let O=b?.groundingMetadata?.groundingSupports?.filter(I=>I.groundingChunkIndices?.includes(A));return{type:"url_citation",url_citation:{url:R?.web?.uri||"",title:R?.web?.title||"",content:O?.[0]?.segment?.text||"",start_index:O?.[0]?.segment?.startIndex||0,end_index:O?.[0]?.segment?.endIndex||0}}})),_.enqueue(r.encode(`data: ${JSON.stringify(E)}
|
|
128
128
|
|
|
129
129
|
`))}),!i&&S&&(i=!0))}catch(h){t?.error(`Error parsing ${e} stream chunk`,k,h.message)}}}},y=n.body.getReader(),p="";try{for(;;){let{done:f,value:_}=await y.read();if(f){p&&await m(p,g);break}p+=o.decode(_,{stream:!0});let k=p.split(`
|
|
130
130
|
`);p=k.pop()||"";for(let h of k)await m(h,g)}}catch(f){g.error(f)}finally{g.close()}}});return new Response(d,{status:n.status,statusText:n.statusText,headers:n.headers})}}var Ye,Mo=w(()=>{"use strict";Ye={TYPE_UNSPECIFIED:"TYPE_UNSPECIFIED",STRING:"STRING",NUMBER:"NUMBER",INTEGER:"INTEGER",BOOLEAN:"BOOLEAN",ARRAY:"ARRAY",OBJECT:"OBJECT",NULL:"NULL"}});var Tn,Ms=w(()=>{"use strict";Mo();Tn=class{name="gemini";endPoint="/v1beta/models/:modelAndAction";async transformRequestIn(e,t){return{body:_n(e),config:{url:new URL(`./${e.model}:${e.stream?"streamGenerateContent?alt=sse":"generateContent"}`,t.baseUrl),headers:{"x-goog-api-key":t.apiKey,Authorization:void 0}}}}transformRequestOut=kn;async transformResponseOut(e){return bn(e,this.name,this.logger)}}});async function Oc(){try{let{GoogleAuth:n}=await import("google-auth-library");return(await(await new n({scopes:["https://www.googleapis.com/auth/cloud-platform"]}).getClient()).getAccessToken()).token||""}catch(n){throw console.error("Error getting access token:",n),new Error(`Failed to get access token for Vertex AI. Please ensure you have set up authentication using one of these methods:
|
|
@@ -162,11 +162,11 @@ Examples:
|
|
|
162
162
|
`);for(let k of _)k.trim()&&p.enqueue(f.encode(k+`
|
|
163
163
|
`))},m=(y,p)=>{let{controller:f,encoder:_}=p;if(y.startsWith("data: ")&&y.trim()!=="data: [DONE]"){let k=y.slice(6);try{let h=JSON.parse(k);if(h.usage&&(this.logger?.debug({usage:h.usage,hasToolCall:l},"usage"),h.choices[0].finish_reason=l?"tool_calls":"stop"),h.choices?.[0]?.finish_reason==="error"){f.enqueue(_.encode(`data: ${JSON.stringify({error:h.choices?.[0].error})}
|
|
164
164
|
|
|
165
|
-
`));return}h.choices?.[0]?.delta?.content&&!p.hasTextContent()&&p.setHasTextContent(!0);let b=h.choices?.[0]?.delta?.reasoning||h.choices?.[0]?.delta?.reasoning_content;if(b){p.appendReasoningContent(b);let C={...h,choices:[{...h.choices?.[0],delta:{...h.choices[0].delta,thinking:{content:b}}}]};C.choices?.[0]?.delta&&(delete C.choices[0].delta.reasoning,delete C.choices[0].delta.reasoning_content);let
|
|
165
|
+
`));return}h.choices?.[0]?.delta?.content&&!p.hasTextContent()&&p.setHasTextContent(!0);let b=h.choices?.[0]?.delta?.reasoning||h.choices?.[0]?.delta?.reasoning_content;if(b){p.appendReasoningContent(b);let C={...h,choices:[{...h.choices?.[0],delta:{...h.choices[0].delta,thinking:{content:b}}}]};C.choices?.[0]?.delta&&(delete C.choices[0].delta.reasoning,delete C.choices[0].delta.reasoning_content);let E=`data: ${JSON.stringify(C)}
|
|
166
166
|
|
|
167
|
-
`;f.enqueue(_.encode(
|
|
167
|
+
`;f.enqueue(_.encode(E));return}if(h.choices?.[0]?.delta?.content&&p.reasoningContent()&&!p.isReasoningComplete()){p.setReasoningComplete(!0);let C="ccr_think_signature",E=h.choices[0].delta.content,R={...h,choices:[{...h.choices?.[0],delta:{...h.choices[0].delta,content:null,thinking:{content:p.reasoningContent(),signature:C}}}]};R.choices?.[0]?.delta&&delete R.choices[0].delta.reasoning;let A=`data: ${JSON.stringify(R)}
|
|
168
168
|
|
|
169
|
-
`;f.enqueue(_.encode(A));let
|
|
169
|
+
`;f.enqueue(_.encode(A));let O={...h,choices:[{...h.choices?.[0],delta:{...h.choices[0].delta,content:E}}]};O.choices?.[0]?.delta&&(delete O.choices[0].delta.reasoning,delete O.choices[0].delta.reasoning_content);let I=`data: ${JSON.stringify(O)}
|
|
170
170
|
|
|
171
171
|
`;f.enqueue(_.encode(I));return}h.choices?.[0]?.delta?.reasoning&&delete h.choices[0].delta.reasoning,h.choices?.[0]?.delta?.reasoning_content&&delete h.choices[0].delta.reasoning_content,h.choices?.[0]?.delta?.tool_calls?.length&&!Number.isNaN(parseInt(h.choices?.[0]?.delta?.tool_calls[0].id,10))&&h.choices?.[0]?.delta?.tool_calls.forEach(C=>{C.id=`call_${(0,Ds.v4)()}`}),h.choices?.[0]?.delta?.tool_calls?.length&&!l&&(l=!0);let T=h.choices?.[0]?.delta,x=T&&Object.keys(T).length>0,v=h.choices?.[0]?.finish_reason,S=h.usage;if(x||v||S){let C=`data: ${JSON.stringify(h)}
|
|
172
172
|
|
|
@@ -278,13 +278,13 @@ ${r.content}`),delete r.thinking)});let o=e.messages[e.messages.length-1];return
|
|
|
278
278
|
|
|
279
279
|
`))}catch{a.enqueue(r.encode(y+`
|
|
280
280
|
`))}else a.enqueue(r.encode(y+`
|
|
281
|
-
`))}}catch(u){a.error(u)}finally{try{c.releaseLock()}catch{}a.close()}}});return new Response(l,{status:e.status,statusText:e.statusText,headers:{"Content-Type":t||"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}if(t?.includes("application/json")){let o=await e.json();return o.choices?.[0]?.message?.reasoning_content&&(o.choices[0].message.thinking={content:o.choices[0].message.reasoning_content},delete o.choices[0].message.reasoning_content),new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers})}return e}}});var li,Hn,ui=w(()=>{"use strict";li=require("uuid"),Hn=class{constructor(e){this.options=e}static TransformerName="opencode";endPoint="/v1/chat/completions";async transformRequestIn(e){return e.messages.forEach(t=>{Array.isArray(t.content)
|
|
281
|
+
`))}}catch(u){a.error(u)}finally{try{c.releaseLock()}catch{}a.close()}}});return new Response(l,{status:e.status,statusText:e.statusText,headers:{"Content-Type":t||"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}if(t?.includes("application/json")){let o=await e.json();return o.choices?.[0]?.message?.reasoning_content&&(o.choices[0].message.thinking={content:o.choices[0].message.reasoning_content},delete o.choices[0].message.reasoning_content),new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers})}return e}}});var li,Hn,ui=w(()=>{"use strict";li=require("uuid"),Hn=class{constructor(e){this.options=e}static TransformerName="opencode";endPoint="/v1/chat/completions";async transformRequestIn(e){return e.messages.forEach(t=>{Array.isArray(t.content)&&t.content.forEach(o=>{o.type==="image_url"&&(o.image_url.url.startsWith("http")||(o.image_url.url=`data:${o.media_type};base64,${o.image_url.url}`),delete o.media_type)})}),Object.assign(e,this.options||{}),e}async transformResponseOut(e){if(e.headers.get("Content-Type")?.includes("application/json")){let t=await e.json();return t.choices?.[0]?.message?.reasoning_content&&(t.choices[0].message.thinking={content:t.choices[0].message.reasoning_content},delete t.choices[0].message.reasoning_content),new Response(JSON.stringify(t),{status:e.status,statusText:e.statusText,headers:e.headers})}if(e.headers.get("Content-Type")?.includes("stream")){if(!e.body)return e;let t=new TextDecoder,o=new TextEncoder,r=!1,s="",i=!1,l=!1,a="",c=new ReadableStream({async start(u){let d=e.body.getReader(),g=(y,p,f)=>{let _=y.split(`
|
|
282
282
|
`);for(let k of _)k.trim()&&p.enqueue(f.encode(k+`
|
|
283
283
|
`))},m=(y,p)=>{let{controller:f,encoder:_}=p;if(y.startsWith("data: ")&&y.trim()!=="data: [DONE]")try{let k=JSON.parse(y.slice(6));if(k.usage&&(k.choices[0].finish_reason=l?"tool_calls":"stop"),k.choices?.[0]?.finish_reason==="error"){f.enqueue(_.encode(`data: ${JSON.stringify({error:k.choices?.[0]?.error})}
|
|
284
284
|
|
|
285
285
|
`));return}k.choices?.[0]?.delta?.content&&!p.hasTextContent()&&p.setHasTextContent(!0);let h=k.choices?.[0]?.delta?.reasoning||k.choices?.[0]?.delta?.reasoning_content;if(h){p.appendReasoningContent(h);let S={...k,choices:[{...k.choices?.[0],delta:{...k.choices[0].delta,thinking:{content:h}}}]};S.choices?.[0]?.delta&&(delete S.choices[0].delta.reasoning,delete S.choices[0].delta.reasoning_content),f.enqueue(_.encode(`data: ${JSON.stringify(S)}
|
|
286
286
|
|
|
287
|
-
`));return}if(k.choices?.[0]?.delta?.content&&p.reasoningContent()&&!p.isReasoningComplete()){p.setReasoningComplete(!0);let S="ccr_think_signature",C=k.choices[0].delta.content,
|
|
287
|
+
`));return}if(k.choices?.[0]?.delta?.content&&p.reasoningContent()&&!p.isReasoningComplete()){p.setReasoningComplete(!0);let S="ccr_think_signature",C=k.choices[0].delta.content,E={...k,choices:[{...k.choices?.[0],delta:{...k.choices[0].delta,content:null,thinking:{content:p.reasoningContent(),signature:S}}}]};E.choices?.[0]?.delta&&(delete E.choices[0].delta.reasoning,delete E.choices[0].delta.reasoning_content),f.enqueue(_.encode(`data: ${JSON.stringify(E)}
|
|
288
288
|
|
|
289
289
|
`));let R={...k,choices:[{...k.choices?.[0],delta:{...k.choices[0].delta,content:C}}]};R.choices?.[0]?.delta&&(delete R.choices[0].delta.reasoning,delete R.choices[0].delta.reasoning_content),f.enqueue(_.encode(`data: ${JSON.stringify(R)}
|
|
290
290
|
|
|
@@ -311,7 +311,7 @@ Stack: ${e.stack}`)}}async registerDefaultTransformersInternal(){try{Object.valu
|
|
|
311
311
|
${this.toMarkdown(r,t+1)}`:`${o}- ${r}`).join(`
|
|
312
312
|
`):typeof e=="object"&&e!==null?Object.entries(e).map(([r,s])=>typeof s=="object"&&s!==null?`${o}${r}:
|
|
313
313
|
${this.toMarkdown(s,t+1)}`:`${o}${r}: ${s}`).join(`
|
|
314
|
-
`):`${o}${e}`}async output(e,t={}){try{let o=this.formatData(e,t);switch(this.config.level||"log"){case"info":console.info(o);break;case"warn":console.warn(o);break;case"error":console.error(o);break;case"debug":console.debug(o);break;case"log":default:console.log(o);break}return!0}catch(o){return console.error("[ConsoleOutputHandler] Output failed:",o),!1}}}});var wt,sr=w(()=>{"use strict";wt=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 t=Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString("base64");e.Authorization=`Basic ${t}`}break;case"custom":this.config.auth.custom&&(e[this.config.auth.custom.header]=this.config.auth.custom.value);break}return e}buildBody(e,t){let{format:o="json",timestamp:r=!0,prefix:s,metadata:i}=t||{},l={data:e};return r&&(l.timestamp=new Date().toISOString()),s&&(l.prefix=s),i&&Object.keys(i).length>0&&(l.metadata=i),l}async sendRequest(e,t,o,r,s){let i=new AbortController,l=setTimeout(()=>i.abort(),s);try{let a=await fetch(e,{method:t,headers:o,body:JSON.stringify(r),signal:i.signal});if(clearTimeout(l),!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);return a}catch(a){throw clearTimeout(l),a}}delay(e){return new Promise(t=>setTimeout(t,e))}async sendWithRetry(e,t,o,r,s,i){let l=null;for(let a=1;a<=i.maxAttempts;a++)try{return await this.sendRequest(e,t,o,r,s)}catch(c){if(l=c,a===i.maxAttempts)break;let u=i.backoffMs*Math.pow(2,a-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${a}/${i.maxAttempts}), retrying in ${u}ms...`,c.message),await this.delay(u)}throw l}async output(e,t={}){let o=t.timeout||this.defaultTimeout;try{let r=this.buildHeaders(),s=this.buildBody(e,t),i=await this.sendWithRetry(this.config.url,this.config.method,r,s,o,this.config.retry);return!0}catch(r){let s=r instanceof Error?r.message:String(r);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${s}`),!1;throw new Error(`Webhook output failed: ${s}`)}}}});var Ze,ir,Ri,Pt,ar=w(()=>{"use strict";Ze=require("fs"),ir=require("path"),Ri=require("os"),Pt=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let t=(0,Ri.tmpdir)();this.baseDir=(0,ir.join)(t,this.config.subdirectory),this.ensureDir()}ensureDir(){try{(0,Ze.existsSync)(this.baseDir)||(0,Ze.mkdirSync)(this.baseDir,{recursive:!0})}catch{}}getFilePath(e){let t=this.config.prefix||"session",o=this.config.extension?`.${this.config.extension}`:"",r;if(this.config.includeTimestamp){let s=Date.now();r=`${t}-${e}-${s}${o}`}else r=`${t}-${e}${o}`;return(0,ir.join)(this.baseDir,r)}async output(e,t={}){try{let o=t.metadata?.sessionId;if(!o)return!1;let r={...e,timestamp:Date.now(),sessionId:o},s=this.getFilePath(o);return(0,Ze.writeFileSync)(s,JSON.stringify(r,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var cr,et,wi=w(()=>{"use strict";rr();sr();ar();cr=class{handlers=new Map;defaultOptions={};registerHandler(e,t){this.handlers.set(e,t)}registerHandlers(e){for(let t of e)if(t.enabled!==!1)try{let o=this.createHandler(t),r=t.type+"_"+Date.now();this.registerHandler(r,o)}catch(o){console.error(`[OutputManager] Failed to register ${t.type} handler:`,o)}}createHandler(e){switch(e.type){case"console":return new Rt(e.config);case"webhook":return new wt(e.config);case"temp-file":return new Pt(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,t){let o={...this.defaultOptions,...t},r={success:[],failed:[]},s=Array.from(this.handlers.entries()).map(async([i,l])=>{try{await l.output(e,o)?r.success.push(i):r.failed.push(i)}catch(a){console.error(`[OutputManager] Handler ${i} failed:`,a),r.failed.push(i)}});return await Promise.all(s),r}async outputTo(e,t,o){let r={...this.defaultOptions,...o},s={success:[],failed:[]},i=e.map(async l=>{let a=this.handlers.get(l);if(!a){console.warn(`[OutputManager] Handler ${l} not found`),s.failed.push(l);return}try{await a.output(t,r)?s.success.push(l):s.failed.push(l)}catch(c){console.error(`[OutputManager] Handler ${l} failed:`,c),s.failed.push(l)}});return await Promise.all(i),s}async outputToType(e,t,o){let r=Array.from(this.handlers.entries()).filter(([s,i])=>i.type===e).map(([s])=>s);return this.outputTo(r,t,o)}},et=new cr});var lr=w(()=>{"use strict";Si();rr();sr();ar();wi()});function Pi(n,e,t=0){if(n<=0)return 0;let o=Math.max((e-t)/1e3,il);return Math.round(n/o)}function Ot(n){let e=(n.match(/[\u4e00-\u9fa5]/g)||[]).length,t=n.length-e;return Math.ceil(e/1.5+t/4)}async function Ei(n,e,t,o=!1){let r=o?"[Token Speed Final]":"[Token Speed]",s={requestId:n.requestId.substring(0,8),sessionId:n.sessionId,stream:n.stream,tokenCount:n.tokenCount,tokensPerSecond:n.tokensPerSecond,timeToFirstToken:n.timeToFirstToken?`${n.timeToFirstToken}ms`:"N/A",duration:`${((n.lastTokenTime-n.startTime)/1e3).toFixed(2)}s`,timestamp:Date.now()},i={prefix:r,metadata:{sessionId:n.sessionId},...t};for(let l of e)try{await et.outputToType(l,s,i)}catch(a){console.error(`[TokenSpeedPlugin] Failed to output to ${l}:`,a)}}var Oi,Et,ur,il,At,Ai=w(()=>{"use strict";Oi=Y(require("fastify-plugin"),1);or();lr();pt();Et=new Map,ur=new Map,il=1,At={name:"token-speed",version:"1.0.0",description:"Statistics for streaming response token generation speed",register:(0,Oi.default)(async(n,e)=>{let t={reporter:["console","temp-file"],...e},o=Array.isArray(t.reporter)?t.reporter:[t.reporter];if(t.outputHandlers&&t.outputHandlers.length>0)et.registerHandlers(t.outputHandlers);else{let i=[];for(let l of o)l==="console"?i.push({type:"console",enabled:!0,config:{colors:!0,level:"log"}}):l==="temp-file"?i.push({type:"temp-file",enabled:!0,config:{subdirectory:"claude-code-router",extension:"json",includeTimestamp:!0,prefix:"session"}}):l==="webhook"&&console.warn("[TokenSpeedPlugin] Webhook reporter requires explicit configuration in outputHandlers");i.length>0&&et.registerHandlers(i)}t.outputOptions&&et.setDefaultOptions(t.outputOptions);let r=async i=>{let l=n.tokenizerService;if(!l)return n.log?.warn("TokenizerService not available"),null;if(!i.provider||!i.model)return null;let a=i.provider,c=i.model,u=`${a}:${c}`;if(ur.has(u))return ur.get(u);let d=l.getTokenizerConfigForModel(a,c);if(!d)return n.log?.debug(`No tokenizer config for ${a}:${c}, using fallback`),null;try{let g=await l.getTokenizer(d,a);return ur.set(u,g),n.log?.info(`Created tokenizer for ${a}:${c} - ${g.name}`),g}catch(g){return n.log?.warn(`Failed to create tokenizer for ${a}:${c}: ${g.message}`),null}},s=i=>{let l=new URL(`http://127.0.0.1${i}`).pathname;return l.endsWith("/v1/messages")||l.endsWith("/v1/responses")};n.addHook("onRequest",async i=>{s(i.url)&&(i.requestStartTime=performance.now())}),n.addHook("onSend",async(i,l,a)=>{let c=i.requestStartTime;if(!c)return;let u=i.id||Date.now().toString(),d=i.usageSessionId;if(!d)try{d=We(i.body?.metadata?.user_id)}catch{}if(!d){let f=i.headers?.["x-request-id"],_=Array.isArray(f)?f[0]:f;d=(typeof _=="string"?_:void 0)||u}let g=await r(i);if(a instanceof ReadableStream){Et.set(u,{requestId:u,sessionId:d,startTime:c,lastTokenTime:c,tokenCount:0,tokensPerSecond:0,stream:!0});let[f,_]=a.tee(),k=async()=>{let h=null,b=async T=>{let x=Et.get(u);if(!x)return;let v=x.firstTokenTime?x.firstTokenTime-x.startTime:0,C=(T?x.lastTokenTime:performance.now())-x.startTime;x.tokensPerSecond=Pi(x.tokenCount,C,v),await Ei(x,o,t.outputOptions,T).catch(P=>{n.log?.warn(`Failed to output streaming stats: ${P.message}`)})};try{let x=_.pipeThrough(new TextDecoderStream).pipeThrough(new ce).getReader();for(h=setInterval(async()=>{Et.get(u)&&await b(!1)},1e3);;){let{done:v,value:S}=await x.read();if(v)break;let C=S,P=Et.get(u);if(!P)continue;let R=performance.now(),A=C.event||C.data?.type,E=C.event==="content_block_start"||C.event==="content_block_delta"||C.event==="text_block"||C.event==="content_block"||A==="response.output_text.delta"||A==="response.function_call_arguments.delta"||A==="response.reasoning_summary_text.delta";!P.firstTokenTime&&E&&(P.firstTokenTime=R,P.timeToFirstToken=Math.round(R-P.startTime));let I="";if(C.event==="content_block_delta"&&C.data?.delta){let L=C.data.delta.type;L==="text_delta"?I=C.data.delta.text||"":L==="input_json_delta"?I=C.data.delta.partial_json||"":L==="thinking_delta"&&(I=C.data.delta.thinking||"")}if((A==="response.output_text.delta"||A==="response.function_call_arguments.delta"||A==="response.reasoning_summary_text.delta")&&(I=typeof C.data?.delta=="string"?C.data.delta:""),I){let L=g&&g.encodeText?g.encodeText(I).length:Ot(I);P.tokenCount+=L,P.lastTokenTime=R}(C.event==="message_stop"||A==="response.completed"||A==="response.failed")&&(h&&(clearInterval(h),h=null),await b(!0),Et.delete(u))}}catch(T){h&&clearInterval(h),T.name!=="AbortError"&&T.code!=="ERR_STREAM_PREMATURE_CLOSE"&&n.log?.warn(`Error processing token stats: ${T.message}`)}};return i.tokenSpeedCapturePromise=k().catch(h=>{console.log(h),n.log?.warn(`Background stats processing failed: ${h.message}`)}),f}let m=performance.now(),y=0,p=!1;if(a&&typeof a=="string")try{let f=JSON.parse(a);if(typeof f.usage?.output_tokens=="number")y=f.usage.output_tokens,p=!0;else{let _=f.content??f.message?.content;if(_!==void 0)if(p=!0,g)Array.isArray(_)?y=_.reduce((k,h)=>{if(h.type==="text"){let b=h.text||"";return k+(g.encodeText?g.encodeText(b).length:Ot(b))}return k},0):typeof _=="string"&&(y=g.encodeText?g.encodeText(_).length:Ot(_));else{let k=Array.isArray(_)?_.map(h=>h.text).join(""):typeof _=="string"?_:"";y=Ot(k)}}}catch{}if(p){let f=Math.round(m-c),_=m-c,k={requestId:u,sessionId:d,startTime:c,lastTokenTime:m,tokenCount:y,tokensPerSecond:Pi(y,_),timeToFirstToken:f,stream:!1};await Ei(k,o,t.outputOptions,!0)}return a})})}});var dr=w(()=>{"use strict";vi();xi();Ai();lr()});function Ii(){if(process.env.VITEST||process.env.CI)throw new Error("Config write attempted during test/CI. Set CCR_CONFIG_DIR to a temp dir to isolate.")}var ee,fr,_e,J,pr,It,Mt,Qn,oe,$t,Ie,al,Vn,Yn=w(()=>{"use strict";ee=Y(require("node:fs/promises"),1),fr=Y(require("json5"),1),_e=Y(require("node:path"),1),J=require("@wengine-ai/claude-code-router-shared"),pr=n=>{if(typeof n=="string")return n.replace(/\$\{([^}]+)\}|\$([A-Z_][A-Z0-9_]*)/g,(e,t,o)=>{let r=t||o;return process.env[r]||e});if(Array.isArray(n))return n.map(pr);if(n!==null&&typeof n=="object"){let e={};for(let[t,o]of Object.entries(n))e[t]=pr(o);return e}return n},It=async n=>{try{await ee.default.access(n)}catch{await ee.default.mkdir(n,{recursive:!0})}},Mt=async()=>{await It(J.HOME_DIR),await It(J.PLUGINS_DIR),await It(_e.default.join(J.HOME_DIR,"logs"))},Qn=async()=>{let n=await ee.default.readFile(J.CONFIG_FILE,"utf-8");return fr.default.parse(n)},oe=async()=>{try{let n=await ee.default.readFile(J.CONFIG_FILE,"utf-8");try{let e=fr.default.parse(n);return pr(e)}catch(e){console.error(`Failed to parse config file at ${J.CONFIG_FILE}`),console.error("Error details:",e.message),console.error("Please check your config file syntax."),process.exit(1)}}catch(n){if(n.code==="ENOENT")try{await Mt();let e=await $t();e&&console.log(`Backed up existing configuration file to ${e}`);let t={PORT:3456,Providers:[],Router:{}};return await Ie(t),console.log("Created minimal default configuration file at ~/.claude-code-router/config.json"),console.log("Please edit this file with your actual configuration."),t}catch(e){console.error("Failed to create default configuration:",e.message),process.exit(1)}else console.error(`Failed to read config file at ${J.CONFIG_FILE}`),console.error("Error details:",n.message),process.exit(1)}};$t=async()=>{Ii();try{if(await ee.default.access(J.CONFIG_FILE).then(()=>!0).catch(()=>!1)){let n=new Date().toISOString().replace(/[:.]/g,"-"),e=`${J.CONFIG_FILE}.${n}.bak`;await ee.default.copyFile(J.CONFIG_FILE,e);try{let t=_e.default.dirname(J.CONFIG_FILE),o=_e.default.basename(J.CONFIG_FILE),s=(await ee.default.readdir(t)).filter(i=>i.startsWith(o)&&i.endsWith(".bak")).sort().reverse();if(s.length>3)for(let i=3;i<s.length;i++){let l=_e.default.join(t,s[i]);await ee.default.unlink(l)}}catch(t){console.warn("Failed to clean up old backups:",t)}return e}}catch(n){console.error("Failed to backup config file:",n)}return null},Ie=async n=>{Ii(),await It(J.HOME_DIR),await al();let e=`${JSON.stringify(n,null,2)}`;await ee.default.writeFile(J.CONFIG_FILE,e)},al=async()=>{if(!await ee.default.access(J.CONFIG_FILE).then(()=>!0).catch(()=>!1))return;let e=_e.default.join(J.HOME_DIR,"config-history");await It(e);let t=new Date().toISOString().replace(/[:.]/g,"-"),o=_e.default.join(e,`config-${t}.json`);await ee.default.copyFile(J.CONFIG_FILE,o);try{let s=(await ee.default.readdir(e)).filter(i=>i.startsWith("config-")&&i.endsWith(".json")).sort().reverse();if(s.length>50)for(let i of s.slice(50))await ee.default.unlink(_e.default.join(e,i))}catch(r){console.warn("Failed to prune config-history:",r)}},Vn=async()=>{let n=await oe();return Object.assign(process.env,n),n}});function cl(n){return n?.cache_read_input_tokens??n?.input_tokens_details?.cached_tokens??n?.prompt_tokens_details?.cached_tokens??0}function ll(n){return n?.cache_creation_input_tokens??n?.input_tokens_details?.cache_creation_tokens??n?.input_tokens_details?.cache_write_tokens??n?.prompt_tokens_details?.cache_creation_tokens??n?.prompt_tokens_details?.cache_write_tokens??0}function Me(n){if(!(!n||typeof n!="object"))return{...n,input_tokens:n.input_tokens??n.prompt_tokens??0,output_tokens:n.output_tokens??n.completion_tokens??0,cache_read_input_tokens:cl(n),cache_creation_input_tokens:ll(n)}}function Nt(n,e,t){let o=t?{}:n||{},r=e||{};return{...o,input_tokens:r.input_tokens||o.input_tokens||0,output_tokens:r.output_tokens||o.output_tokens||0,cache_read_input_tokens:r.cache_read_input_tokens||o.cache_read_input_tokens||0,cache_creation_input_tokens:r.cache_creation_input_tokens||o.cache_creation_input_tokens||0}}var mr=w(()=>{"use strict"});function Xn(n,e,t){if(n){if(typeof n=="string"){let o=n.indexOf(",");if(o>0){let r=n.slice(0,o).trim(),s=n.slice(o+1).trim();r&&s&&e.has(r)&&t.add(gr(r,s))}return}if(Array.isArray(n)){for(let o of n)Xn(o,e,t);return}if(typeof n=="object")for(let o of Object.values(n))Xn(o,e,t)}}function hr(n){let e=n?.Providers||n?.providers||[],t=new Set,o=new Set;for(let r of e){let s=r?.name;if(!s)continue;t.add(s);let i=Array.isArray(r?.models)?r.models:[];for(let l of i)l&&o.add(gr(s,l))}return Xn(n?.Router,t,o),Xn(n?.fallback,t,o),o}function tt(n,e){try{let t=U();if(!t?.getAllStates||!t?.recover)return 0;let o=hr(n),r=0;for(let s of t.getAllStates()||[]){let i=s?.provider,l=s?.model;!i||!l||o.has(gr(i,l))||(t.recover(i,l),r++)}return r>0&&e?.info?.(`[health-reconcile] Pruned ${r} orphaned provider-health entr${r===1?"y":"ies"}`),r}catch(t){return e?.warn?.(`[health-reconcile] Failed to reconcile health store: ${t?.message||t}`),0}}function Lt(n,e){try{if(!n)return 0;let t=U();if(!t?.getAllStates||!t?.recover)return 0;let o=0;for(let r of t.getAllStates()||[])r?.provider===n&&r?.model&&(t.recover(n,r.model),o++);return o>0&&e?.info?.(`[health-reconcile] Cleared ${o} health entr${o===1?"y":"ies"} for probed provider ${n}`),o}catch(t){return e?.warn?.(`[health-reconcile] Failed to clear provider health for ${n}: ${t?.message||t}`),0}}var ul,gr,qn=w(()=>{"use strict";ie();ul="\0",gr=(n,e)=>`${n}${ul}${e}`});function dl(n){return/\[1m\]/i.test(n)?1e6:2e5}function pl(n){let e=n.toLowerCase();return e.includes("haiku")||e.includes("mini")?8192:32e3}function fl(n,e=n){let t=dl(n),o=pl(n);return{type:"model",id:n,display_name:e,created_at:"2024-01-01T00:00:00Z",context_window:t,contextWindow:t,max_input_tokens:t,maxInputTokens:t,max_tokens:o,maxTokens:o,max_output_tokens:o,maxOutputTokens:o,capabilities:{context_window:t,contextWindow:t,max_input_tokens:t,maxInputTokens:t,max_tokens:o,maxTokens:o,max_output_tokens:o,maxOutputTokens:o}}}function Dt(n){let e=new Map,t=(o,r=o)=>{!o||e.has(o)||e.set(o,fl(o,r))};t("ccr-opus","CCR Opus"),t("ccr-sonnet","CCR Sonnet"),t("ccr-haiku","CCR Haiku"),t("ccr-opus[1m]","CCR Opus 1M"),t("ccr-sonnet[1m]","CCR Sonnet 1M"),t("ccr-haiku[1m]","CCR Haiku 1M");for(let o of n.Providers||n.providers||[])if(!(!o?.name||!Array.isArray(o.models)))for(let r of o.models)typeof r!="string"||!r||(t(r,r),t(`${o.name},${r}`,`${o.name}/${r}`));return Array.from(e.values())}var yr=w(()=>{"use strict"});function ml(n){let e=n.ip||n.connection?.remoteAddress||"";return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}var Ft,_r=w(()=>{"use strict";Ft=n=>async(e,t,o)=>{if(["/","/health"].includes(e.url)||e.url.startsWith("/ui")||ml(e))return o();let s=n.Providers||n.providers||[];if(!s||s.length===0)return o();let i=n.APIKEY;if(!i){let u=[`http://127.0.0.1:${n.PORT||3456}`,`http://localhost:${n.PORT||3456}`];if(e.headers.origin&&!u.includes(e.headers.origin)){t.status(403).send("CORS not allowed for this origin");return}else t.header("Access-Control-Allow-Origin",`http://127.0.0.1:${n.PORT||3456}`),t.header("Access-Control-Allow-Origin",`http://localhost:${n.PORT||3456}`);return o()}let l=e.headers.authorization||e.headers["x-api-key"],a=Array.isArray(l)?l[0]:l||"";if(!a){t.log.warn({url:e.url,headers:Object.keys(e.headers)},"[AUTH] No auth header"),t.status(401).send("APIKEY is missing");return}let c="";if(a.startsWith("Bearer")?c=a.split(" ")[1]:c=a,c!==i){t.log.warn({url:e.url,gotPrefix:c.slice(0,10),gotSuffix:c.slice(-6),gotLen:c.length,expectedPrefix:i.slice(0,6),expectedSuffix:i.slice(-6),expectedLen:i.length},"[AUTH] Key mismatch"),t.status(401).send("Invalid API key");return}o()}});var xr={};Gt(xr,{append:()=>zt,clear:()=>Cr,close:()=>Ol,getOldestRecordTimestamp:()=>Al,query:()=>Tr,querySummary:()=>Bt,readTokenSpeedStats:()=>vr});function kl(){(0,re.existsSync)(eo)||(0,re.mkdirSync)(eo,{recursive:!0})}function Ht(){if(be)return be;kl();let n=new Ni.default(gl);n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL"),n.pragma("busy_timeout = 5000");let e=n.pragma("user_version",{simple:!0})||0;return e<1&&(bl(n),n.pragma("user_version = 1")),e<2&&(n.prepare("PRAGMA table_info(usage_records)").all().some(o=>o.name==="upstream_model")||n.exec("ALTER TABLE usage_records ADD COLUMN upstream_model TEXT"),n.pragma("user_version = 2")),Cl(n),Fi(n,!0),br=n.prepare(`
|
|
314
|
+
`):`${o}${e}`}async output(e,t={}){try{let o=this.formatData(e,t);switch(this.config.level||"log"){case"info":console.info(o);break;case"warn":console.warn(o);break;case"error":console.error(o);break;case"debug":console.debug(o);break;case"log":default:console.log(o);break}return!0}catch(o){return console.error("[ConsoleOutputHandler] Output failed:",o),!1}}}});var wt,sr=w(()=>{"use strict";wt=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 t=Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString("base64");e.Authorization=`Basic ${t}`}break;case"custom":this.config.auth.custom&&(e[this.config.auth.custom.header]=this.config.auth.custom.value);break}return e}buildBody(e,t){let{format:o="json",timestamp:r=!0,prefix:s,metadata:i}=t||{},l={data:e};return r&&(l.timestamp=new Date().toISOString()),s&&(l.prefix=s),i&&Object.keys(i).length>0&&(l.metadata=i),l}async sendRequest(e,t,o,r,s){let i=new AbortController,l=setTimeout(()=>i.abort(),s);try{let a=await fetch(e,{method:t,headers:o,body:JSON.stringify(r),signal:i.signal});if(clearTimeout(l),!a.ok)throw new Error(`HTTP ${a.status}: ${a.statusText}`);return a}catch(a){throw clearTimeout(l),a}}delay(e){return new Promise(t=>setTimeout(t,e))}async sendWithRetry(e,t,o,r,s,i){let l=null;for(let a=1;a<=i.maxAttempts;a++)try{return await this.sendRequest(e,t,o,r,s)}catch(c){if(l=c,a===i.maxAttempts)break;let u=i.backoffMs*Math.pow(2,a-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${a}/${i.maxAttempts}), retrying in ${u}ms...`,c.message),await this.delay(u)}throw l}async output(e,t={}){let o=t.timeout||this.defaultTimeout;try{let r=this.buildHeaders(),s=this.buildBody(e,t),i=await this.sendWithRetry(this.config.url,this.config.method,r,s,o,this.config.retry);return!0}catch(r){let s=r instanceof Error?r.message:String(r);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${s}`),!1;throw new Error(`Webhook output failed: ${s}`)}}}});var Ze,ir,Ri,Pt,ar=w(()=>{"use strict";Ze=require("fs"),ir=require("path"),Ri=require("os"),Pt=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let t=(0,Ri.tmpdir)();this.baseDir=(0,ir.join)(t,this.config.subdirectory),this.ensureDir()}ensureDir(){try{(0,Ze.existsSync)(this.baseDir)||(0,Ze.mkdirSync)(this.baseDir,{recursive:!0})}catch{}}getFilePath(e){let t=this.config.prefix||"session",o=this.config.extension?`.${this.config.extension}`:"",r;if(this.config.includeTimestamp){let s=Date.now();r=`${t}-${e}-${s}${o}`}else r=`${t}-${e}${o}`;return(0,ir.join)(this.baseDir,r)}async output(e,t={}){try{let o=t.metadata?.sessionId;if(!o)return!1;let r={...e,timestamp:Date.now(),sessionId:o},s=this.getFilePath(o);return(0,Ze.writeFileSync)(s,JSON.stringify(r,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var cr,et,wi=w(()=>{"use strict";rr();sr();ar();cr=class{handlers=new Map;defaultOptions={};registerHandler(e,t){this.handlers.set(e,t)}registerHandlers(e){for(let t of e)if(t.enabled!==!1)try{let o=this.createHandler(t),r=t.type+"_"+Date.now();this.registerHandler(r,o)}catch(o){console.error(`[OutputManager] Failed to register ${t.type} handler:`,o)}}createHandler(e){switch(e.type){case"console":return new Rt(e.config);case"webhook":return new wt(e.config);case"temp-file":return new Pt(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,t){let o={...this.defaultOptions,...t},r={success:[],failed:[]},s=Array.from(this.handlers.entries()).map(async([i,l])=>{try{await l.output(e,o)?r.success.push(i):r.failed.push(i)}catch(a){console.error(`[OutputManager] Handler ${i} failed:`,a),r.failed.push(i)}});return await Promise.all(s),r}async outputTo(e,t,o){let r={...this.defaultOptions,...o},s={success:[],failed:[]},i=e.map(async l=>{let a=this.handlers.get(l);if(!a){console.warn(`[OutputManager] Handler ${l} not found`),s.failed.push(l);return}try{await a.output(t,r)?s.success.push(l):s.failed.push(l)}catch(c){console.error(`[OutputManager] Handler ${l} failed:`,c),s.failed.push(l)}});return await Promise.all(i),s}async outputToType(e,t,o){let r=Array.from(this.handlers.entries()).filter(([s,i])=>i.type===e).map(([s])=>s);return this.outputTo(r,t,o)}},et=new cr});var lr=w(()=>{"use strict";Si();rr();sr();ar();wi()});function Pi(n,e,t=0){if(n<=0)return 0;let o=Math.max((e-t)/1e3,il);return Math.round(n/o)}function Ot(n){let e=(n.match(/[\u4e00-\u9fa5]/g)||[]).length,t=n.length-e;return Math.ceil(e/1.5+t/4)}async function Ei(n,e,t,o=!1){let r=o?"[Token Speed Final]":"[Token Speed]",s={requestId:n.requestId.substring(0,8),sessionId:n.sessionId,stream:n.stream,tokenCount:n.tokenCount,tokensPerSecond:n.tokensPerSecond,timeToFirstToken:n.timeToFirstToken?`${n.timeToFirstToken}ms`:"N/A",duration:`${((n.lastTokenTime-n.startTime)/1e3).toFixed(2)}s`,timestamp:Date.now()},i={prefix:r,metadata:{sessionId:n.sessionId},...t};for(let l of e)try{await et.outputToType(l,s,i)}catch(a){console.error(`[TokenSpeedPlugin] Failed to output to ${l}:`,a)}}var Oi,Et,ur,il,At,Ai=w(()=>{"use strict";Oi=Y(require("fastify-plugin"),1);or();lr();pt();Et=new Map,ur=new Map,il=1,At={name:"token-speed",version:"1.0.0",description:"Statistics for streaming response token generation speed",register:(0,Oi.default)(async(n,e)=>{let t={reporter:["console","temp-file"],...e},o=Array.isArray(t.reporter)?t.reporter:[t.reporter];if(t.outputHandlers&&t.outputHandlers.length>0)et.registerHandlers(t.outputHandlers);else{let i=[];for(let l of o)l==="console"?i.push({type:"console",enabled:!0,config:{colors:!0,level:"log"}}):l==="temp-file"?i.push({type:"temp-file",enabled:!0,config:{subdirectory:"claude-code-router",extension:"json",includeTimestamp:!0,prefix:"session"}}):l==="webhook"&&console.warn("[TokenSpeedPlugin] Webhook reporter requires explicit configuration in outputHandlers");i.length>0&&et.registerHandlers(i)}t.outputOptions&&et.setDefaultOptions(t.outputOptions);let r=async i=>{let l=n.tokenizerService;if(!l)return n.log?.warn("TokenizerService not available"),null;if(!i.provider||!i.model)return null;let a=i.provider,c=i.model,u=`${a}:${c}`;if(ur.has(u))return ur.get(u);let d=l.getTokenizerConfigForModel(a,c);if(!d)return n.log?.debug(`No tokenizer config for ${a}:${c}, using fallback`),null;try{let g=await l.getTokenizer(d,a);return ur.set(u,g),n.log?.info(`Created tokenizer for ${a}:${c} - ${g.name}`),g}catch(g){return n.log?.warn(`Failed to create tokenizer for ${a}:${c}: ${g.message}`),null}},s=i=>{let l=new URL(`http://127.0.0.1${i}`).pathname;return l.endsWith("/v1/messages")||l.endsWith("/v1/responses")};n.addHook("onRequest",async i=>{s(i.url)&&(i.requestStartTime=performance.now())}),n.addHook("onSend",async(i,l,a)=>{let c=i.requestStartTime;if(!c)return;let u=i.id||Date.now().toString(),d=i.usageSessionId;if(!d)try{d=We(i.body?.metadata?.user_id)}catch{}if(!d){let f=i.headers?.["x-request-id"],_=Array.isArray(f)?f[0]:f;d=(typeof _=="string"?_:void 0)||u}let g=await r(i);if(a instanceof ReadableStream){Et.set(u,{requestId:u,sessionId:d,startTime:c,lastTokenTime:c,tokenCount:0,tokensPerSecond:0,stream:!0});let[f,_]=a.tee(),k=async()=>{let h=null,b=async T=>{let x=Et.get(u);if(!x)return;let v=x.firstTokenTime?x.firstTokenTime-x.startTime:0,C=(T?x.lastTokenTime:performance.now())-x.startTime;x.tokensPerSecond=Pi(x.tokenCount,C,v),await Ei(x,o,t.outputOptions,T).catch(E=>{n.log?.warn(`Failed to output streaming stats: ${E.message}`)})};try{let x=_.pipeThrough(new TextDecoderStream).pipeThrough(new ce).getReader();for(h=setInterval(async()=>{Et.get(u)&&await b(!1)},1e3);;){let{done:v,value:S}=await x.read();if(v)break;let C=S,E=Et.get(u);if(!E)continue;let R=performance.now(),A=C.event||C.data?.type,O=C.event==="content_block_start"||C.event==="content_block_delta"||C.event==="text_block"||C.event==="content_block"||A==="response.output_text.delta"||A==="response.function_call_arguments.delta"||A==="response.reasoning_summary_text.delta";!E.firstTokenTime&&O&&(E.firstTokenTime=R,E.timeToFirstToken=Math.round(R-E.startTime));let I="";if(C.event==="content_block_delta"&&C.data?.delta){let L=C.data.delta.type;L==="text_delta"?I=C.data.delta.text||"":L==="input_json_delta"?I=C.data.delta.partial_json||"":L==="thinking_delta"&&(I=C.data.delta.thinking||"")}if((A==="response.output_text.delta"||A==="response.function_call_arguments.delta"||A==="response.reasoning_summary_text.delta")&&(I=typeof C.data?.delta=="string"?C.data.delta:""),I){let L=g&&g.encodeText?g.encodeText(I).length:Ot(I);E.tokenCount+=L,E.lastTokenTime=R}(C.event==="message_stop"||A==="response.completed"||A==="response.failed")&&(h&&(clearInterval(h),h=null),await b(!0),Et.delete(u))}}catch(T){h&&clearInterval(h),T.name!=="AbortError"&&T.code!=="ERR_STREAM_PREMATURE_CLOSE"&&n.log?.warn(`Error processing token stats: ${T.message}`)}};return i.tokenSpeedCapturePromise=k().catch(h=>{console.log(h),n.log?.warn(`Background stats processing failed: ${h.message}`)}),f}let m=performance.now(),y=0,p=!1;if(a&&typeof a=="string")try{let f=JSON.parse(a);if(typeof f.usage?.output_tokens=="number")y=f.usage.output_tokens,p=!0;else{let _=f.content??f.message?.content;if(_!==void 0)if(p=!0,g)Array.isArray(_)?y=_.reduce((k,h)=>{if(h.type==="text"){let b=h.text||"";return k+(g.encodeText?g.encodeText(b).length:Ot(b))}return k},0):typeof _=="string"&&(y=g.encodeText?g.encodeText(_).length:Ot(_));else{let k=Array.isArray(_)?_.map(h=>h.text).join(""):typeof _=="string"?_:"";y=Ot(k)}}}catch{}if(p){let f=Math.round(m-c),_=m-c,k={requestId:u,sessionId:d,startTime:c,lastTokenTime:m,tokenCount:y,tokensPerSecond:Pi(y,_),timeToFirstToken:f,stream:!1};await Ei(k,o,t.outputOptions,!0)}return a})})}});var dr=w(()=>{"use strict";vi();xi();Ai();lr()});function Ii(){if(process.env.VITEST||process.env.CI)throw new Error("Config write attempted during test/CI. Set CCR_CONFIG_DIR to a temp dir to isolate.")}var ee,fr,_e,J,pr,It,Mt,Qn,oe,$t,Ie,al,Vn,Yn=w(()=>{"use strict";ee=Y(require("node:fs/promises"),1),fr=Y(require("json5"),1),_e=Y(require("node:path"),1),J=require("@wengine-ai/claude-code-router-shared"),pr=n=>{if(typeof n=="string")return n.replace(/\$\{([^}]+)\}|\$([A-Z_][A-Z0-9_]*)/g,(e,t,o)=>{let r=t||o;return process.env[r]||e});if(Array.isArray(n))return n.map(pr);if(n!==null&&typeof n=="object"){let e={};for(let[t,o]of Object.entries(n))e[t]=pr(o);return e}return n},It=async n=>{try{await ee.default.access(n)}catch{await ee.default.mkdir(n,{recursive:!0})}},Mt=async()=>{await It(J.HOME_DIR),await It(J.PLUGINS_DIR),await It(_e.default.join(J.HOME_DIR,"logs"))},Qn=async()=>{let n=await ee.default.readFile(J.CONFIG_FILE,"utf-8");return fr.default.parse(n)},oe=async()=>{try{let n=await ee.default.readFile(J.CONFIG_FILE,"utf-8");try{let e=fr.default.parse(n);return pr(e)}catch(e){console.error(`Failed to parse config file at ${J.CONFIG_FILE}`),console.error("Error details:",e.message),console.error("Please check your config file syntax."),process.exit(1)}}catch(n){if(n.code==="ENOENT")try{await Mt();let e=await $t();e&&console.log(`Backed up existing configuration file to ${e}`);let t={PORT:3456,Providers:[],Router:{}};return await Ie(t),console.log("Created minimal default configuration file at ~/.claude-code-router/config.json"),console.log("Please edit this file with your actual configuration."),t}catch(e){console.error("Failed to create default configuration:",e.message),process.exit(1)}else console.error(`Failed to read config file at ${J.CONFIG_FILE}`),console.error("Error details:",n.message),process.exit(1)}};$t=async()=>{Ii();try{if(await ee.default.access(J.CONFIG_FILE).then(()=>!0).catch(()=>!1)){let n=new Date().toISOString().replace(/[:.]/g,"-"),e=`${J.CONFIG_FILE}.${n}.bak`;await ee.default.copyFile(J.CONFIG_FILE,e);try{let t=_e.default.dirname(J.CONFIG_FILE),o=_e.default.basename(J.CONFIG_FILE),s=(await ee.default.readdir(t)).filter(i=>i.startsWith(o)&&i.endsWith(".bak")).sort().reverse();if(s.length>3)for(let i=3;i<s.length;i++){let l=_e.default.join(t,s[i]);await ee.default.unlink(l)}}catch(t){console.warn("Failed to clean up old backups:",t)}return e}}catch(n){console.error("Failed to backup config file:",n)}return null},Ie=async n=>{Ii(),await It(J.HOME_DIR),await al();let e=`${JSON.stringify(n,null,2)}`;await ee.default.writeFile(J.CONFIG_FILE,e)},al=async()=>{if(!await ee.default.access(J.CONFIG_FILE).then(()=>!0).catch(()=>!1))return;let e=_e.default.join(J.HOME_DIR,"config-history");await It(e);let t=new Date().toISOString().replace(/[:.]/g,"-"),o=_e.default.join(e,`config-${t}.json`);await ee.default.copyFile(J.CONFIG_FILE,o);try{let s=(await ee.default.readdir(e)).filter(i=>i.startsWith("config-")&&i.endsWith(".json")).sort().reverse();if(s.length>50)for(let i of s.slice(50))await ee.default.unlink(_e.default.join(e,i))}catch(r){console.warn("Failed to prune config-history:",r)}},Vn=async()=>{let n=await oe();return Object.assign(process.env,n),n}});function cl(n){return n?.cache_read_input_tokens??n?.input_tokens_details?.cached_tokens??n?.prompt_tokens_details?.cached_tokens??0}function ll(n){return n?.cache_creation_input_tokens??n?.input_tokens_details?.cache_creation_tokens??n?.input_tokens_details?.cache_write_tokens??n?.prompt_tokens_details?.cache_creation_tokens??n?.prompt_tokens_details?.cache_write_tokens??0}function Me(n){if(!(!n||typeof n!="object"))return{...n,input_tokens:n.input_tokens??n.prompt_tokens??0,output_tokens:n.output_tokens??n.completion_tokens??0,cache_read_input_tokens:cl(n),cache_creation_input_tokens:ll(n)}}function Nt(n,e,t){let o=t?{}:n||{},r=e||{};return{...o,input_tokens:r.input_tokens||o.input_tokens||0,output_tokens:r.output_tokens||o.output_tokens||0,cache_read_input_tokens:r.cache_read_input_tokens||o.cache_read_input_tokens||0,cache_creation_input_tokens:r.cache_creation_input_tokens||o.cache_creation_input_tokens||0}}var mr=w(()=>{"use strict"});function Xn(n,e,t){if(n){if(typeof n=="string"){let o=n.indexOf(",");if(o>0){let r=n.slice(0,o).trim(),s=n.slice(o+1).trim();r&&s&&e.has(r)&&t.add(gr(r,s))}return}if(Array.isArray(n)){for(let o of n)Xn(o,e,t);return}if(typeof n=="object")for(let o of Object.values(n))Xn(o,e,t)}}function hr(n){let e=n?.Providers||n?.providers||[],t=new Set,o=new Set;for(let r of e){let s=r?.name;if(!s)continue;t.add(s);let i=Array.isArray(r?.models)?r.models:[];for(let l of i)l&&o.add(gr(s,l))}return Xn(n?.Router,t,o),Xn(n?.fallback,t,o),o}function tt(n,e){try{let t=U();if(!t?.getAllStates||!t?.recover)return 0;let o=hr(n),r=0;for(let s of t.getAllStates()||[]){let i=s?.provider,l=s?.model;!i||!l||o.has(gr(i,l))||(t.recover(i,l),r++)}return r>0&&e?.info?.(`[health-reconcile] Pruned ${r} orphaned provider-health entr${r===1?"y":"ies"}`),r}catch(t){return e?.warn?.(`[health-reconcile] Failed to reconcile health store: ${t?.message||t}`),0}}function Lt(n,e){try{if(!n)return 0;let t=U();if(!t?.getAllStates||!t?.recover)return 0;let o=0;for(let r of t.getAllStates()||[])r?.provider===n&&r?.model&&(t.recover(n,r.model),o++);return o>0&&e?.info?.(`[health-reconcile] Cleared ${o} health entr${o===1?"y":"ies"} for probed provider ${n}`),o}catch(t){return e?.warn?.(`[health-reconcile] Failed to clear provider health for ${n}: ${t?.message||t}`),0}}var ul,gr,qn=w(()=>{"use strict";ie();ul="\0",gr=(n,e)=>`${n}${ul}${e}`});function dl(n){return/\[1m\]/i.test(n)?1e6:2e5}function pl(n){let e=n.toLowerCase();return e.includes("haiku")||e.includes("mini")?8192:32e3}function fl(n,e=n){let t=dl(n),o=pl(n);return{type:"model",id:n,display_name:e,created_at:"2024-01-01T00:00:00Z",context_window:t,contextWindow:t,max_input_tokens:t,maxInputTokens:t,max_tokens:o,maxTokens:o,max_output_tokens:o,maxOutputTokens:o,capabilities:{context_window:t,contextWindow:t,max_input_tokens:t,maxInputTokens:t,max_tokens:o,maxTokens:o,max_output_tokens:o,maxOutputTokens:o}}}function Dt(n){let e=new Map,t=(o,r=o)=>{!o||e.has(o)||e.set(o,fl(o,r))};t("ccr-opus","CCR Opus"),t("ccr-sonnet","CCR Sonnet"),t("ccr-haiku","CCR Haiku"),t("ccr-opus[1m]","CCR Opus 1M"),t("ccr-sonnet[1m]","CCR Sonnet 1M"),t("ccr-haiku[1m]","CCR Haiku 1M");for(let o of n.Providers||n.providers||[])if(!(!o?.name||!Array.isArray(o.models)))for(let r of o.models)typeof r!="string"||!r||(t(r,r),t(`${o.name},${r}`,`${o.name}/${r}`));return Array.from(e.values())}var yr=w(()=>{"use strict"});function ml(n){let e=n.ip||n.connection?.remoteAddress||"";return e==="127.0.0.1"||e==="::1"||e==="::ffff:127.0.0.1"}var Ft,_r=w(()=>{"use strict";Ft=n=>async(e,t,o)=>{if(["/","/health"].includes(e.url)||e.url.startsWith("/ui")||ml(e))return o();let s=n.Providers||n.providers||[];if(!s||s.length===0)return o();let i=n.APIKEY;if(!i){let u=[`http://127.0.0.1:${n.PORT||3456}`,`http://localhost:${n.PORT||3456}`];if(e.headers.origin&&!u.includes(e.headers.origin)){t.status(403).send("CORS not allowed for this origin");return}else t.header("Access-Control-Allow-Origin",`http://127.0.0.1:${n.PORT||3456}`),t.header("Access-Control-Allow-Origin",`http://localhost:${n.PORT||3456}`);return o()}let l=e.headers.authorization||e.headers["x-api-key"],a=Array.isArray(l)?l[0]:l||"";if(!a){t.log.warn({url:e.url,headers:Object.keys(e.headers)},"[AUTH] No auth header"),t.status(401).send("APIKEY is missing");return}let c="";if(a.startsWith("Bearer")?c=a.split(" ")[1]:c=a,c!==i){t.log.warn({url:e.url,gotPrefix:c.slice(0,10),gotSuffix:c.slice(-6),gotLen:c.length,expectedPrefix:i.slice(0,6),expectedSuffix:i.slice(-6),expectedLen:i.length},"[AUTH] Key mismatch"),t.status(401).send("Invalid API key");return}o()}});var xr={};Gt(xr,{append:()=>zt,clear:()=>Cr,close:()=>Ol,getOldestRecordTimestamp:()=>Al,query:()=>Tr,querySummary:()=>Bt,readTokenSpeedStats:()=>vr});function kl(){(0,re.existsSync)(eo)||(0,re.mkdirSync)(eo,{recursive:!0})}function Ht(){if(be)return be;kl();let n=new Ni.default(gl);n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL"),n.pragma("busy_timeout = 5000");let e=n.pragma("user_version",{simple:!0})||0;return e<1&&(bl(n),n.pragma("user_version = 1")),e<2&&(n.prepare("PRAGMA table_info(usage_records)").all().some(o=>o.name==="upstream_model")||n.exec("ALTER TABLE usage_records ADD COLUMN upstream_model TEXT"),n.pragma("user_version = 2")),Cl(n),Fi(n,!0),br=n.prepare(`
|
|
315
315
|
INSERT INTO usage_records (
|
|
316
316
|
id, timestamp, session_id, provider, original_model, model, upstream_model, model_family,
|
|
317
317
|
scenario_type, client_type,
|
|
@@ -402,8 +402,8 @@ ${this.toMarkdown(s,t+1)}`:`${o}${r}: ${s}`).join(`
|
|
|
402
402
|
COALESCE(SUM(CASE WHEN status = 'success' THEN output_tokens ELSE 0 END), 0) AS outputTokens,
|
|
403
403
|
COALESCE(SUM(CASE WHEN status = 'success' THEN cache_read_input_tokens ELSE 0 END), 0) AS cacheReadInputTokens,
|
|
404
404
|
COALESCE(SUM(CASE WHEN status = 'success' THEN cache_creation_input_tokens ELSE 0 END), 0) AS cacheCreationInputTokens
|
|
405
|
-
`;El=200});async function Wi(){let n=(0,zi.homedir)(),e=(0,Bi.join)(n,".claude.json");if(!(0,Hi.existsSync)(e)){let o={numStartups:184,autoUpdaterStatus:"enabled",userID:Array.from({length:64},()=>Math.random().toString(16)[2]).join(""),hasCompletedOnboarding:!0,lastOnboardingVersion:"1.0.17",projects:{}};await(0,Ji.writeFile)(e,JSON.stringify(o,null,2))}}var Hi,zi,Bi,Ji,Gi=w(()=>{"use strict";Hi=require("fs"),zi=require("os"),Bi=require("path"),Ji=require("fs/promises")});function Qi(n=(0,Sr.join)(Vi.HOME_DIR,"logs")){try{if(!(0,Te.existsSync)(n))return;let e=Date.now()-Ml;for(let t of(0,Te.readdirSync)(n)){if(!/^ccr-.*\.log$/.test(t))continue;let o=(0,Sr.join)(n,t),r=(0,Te.statSync)(o);r.isFile()&&r.mtime.getTime()<e&&(0,Te.unlinkSync)(o)}}catch(e){console.warn("Failed to prune old server log files:",e)}}function Yi(){Ki||(Ki=!0,Qi(),setInterval(Qi,$l).unref())}var Te,Sr,Vi,Il,Ml,$l,Ki,Xi=w(()=>{"use strict";Te=require("fs"),Sr=require("path"),Vi=require("@wengine-ai/claude-code-router-shared"),Il=7,Ml=Il*24*60*60*1e3,$l=1440*60*1e3,Ki=!1});async function qi(n,e){let t=e.plugins||e.Plugins||[];for(let o of t){let{name:r,enabled:s=!1,options:i={}}=o;switch(r){case"token-speed":qe.registerPlugin(At,{enabled:s,outputHandlers:[{type:"temp-file",enabled:!0,config:{subdirectory:"claude-code-router",extension:"json",includeTimestamp:!0,prefix:"session"}}],...i});break;default:console.warn(`Unknown plugin: ${r}`);break}}await qe.enablePlugins(n)}var Zi=w(()=>{"use strict";dr()});function Nl(n){let e=new Date().toISOString(),t=new Date(Date.now()-300*60*1e3).toISOString(),o=new Date(Date.now()-10080*60*1e3).toISOString(),r=Bt(t,e),s=Bt(o,e),i=[],l=new Set;for(let a of n||[])a&&a.name&&l.add(a.name);for(let a of Object.keys(r.byProvider||{}))l.add(a);for(let a of Object.keys(s.byProvider||{}))l.add(a);for(let a of l){let c=r.byProvider[a]||{inputTokens:0,outputTokens:0},u=s.byProvider[a]||{inputTokens:0,outputTokens:0},d=(c.inputTokens||0)+(c.outputTokens||0),g=(u.inputTokens||0)+(u.outputTokens||0),m,y,p=(n||[]).find(f=>f&&f.name===a);p&&p.quota&&(m=p.quota.limit5h,y=p.quota.limit7d),i.push({provider:a,used5h:d,used7d:g,limit5h:m,limit7d:y})}return i}async function ra(n,e){let t=n.app;Ue(),Be(),t.register(na.default,{limits:{fileSize:50*1024*1024}}),t.get("/v1/models",async()=>{let l=Dt(e);return{object:"list",data:l,first_id:l[0]?.id||null,last_id:l[l.length-1]?.id||null,has_more:!1}}),t.get("/v1/models/:modelId",async(l,a)=>{let c=decodeURIComponent(l.params.modelId),u=Dt(e).find(d=>d.id===c);return u||(a.status(404),{type:"error",error:{type:"not_found_error",message:`Model not found: ${c}`}})}),t.post("/v1/messages/count_tokens",async(l,a)=>{let{messages:c,tools:u,system:d,model:g}=l.body,m=t._server.tokenizerService;if(g&&g.includes(",")&&m)try{let[p,f]=g.split(",");l.log?.info(`Looking up tokenizer for provider: ${p}, model: ${f}`);let _=m.getTokenizerConfigForModel(p,f);_?l.log?.info(`Using tokenizer config: ${JSON.stringify(_)}`):l.log?.warn(`No tokenizer config found for ${p},${f}, using default tiktoken`);let k=await m.countTokens({messages:c,system:d,tools:u},_,p);return{input_tokens:k.tokenCount,tokenizer:k.tokenizerUsed}}catch(p){l.log?.error(`Error using configured tokenizer: ${p.message}`),l.log?.error(p.stack)}else g?g.includes(",")?m||l.log?.warn("TokenizerService not available, using default tiktoken"):l.log?.info(`Model "${g}" does not contain comma, using default tiktoken`):l.log?.info("No model specified, using default tiktoken");return{input_tokens:gt(c,d,u)}}),t.get("/api/config",async(l,a)=>await Qn()),t.get("/api/transformers",async(l,a)=>{let c=t._server.transformerService.getAllTransformers();return{transformers:Array.from(c.entries()).map(([d,g])=>({name:d,endpoint:g.endPoint||null}))}}),t.post("/api/config",async(l,a)=>{let c=l.body,u=Dr(c||{});if(u.length>0)return a.status(400),{success:!1,error:"Invalid proxy URL",message:u.map(m=>`${m.key}: ${m.error}`).join("; "),proxyErrors:u};let d=await $t();d&&console.log(`Backed up existing configuration file to ${d}`),await Ie(c);let g;try{g=await(0,O.syncGlobalProjectTakeovers)(c),g.failed.length>0&&t.log?.warn?.({projectTakeoverSync:g},"Config saved but some global project takeovers failed to sync")}catch(m){t.log?.warn?.(`Config saved but global project takeover sync failed: ${m?.message||m}`)}try{let m=t._server;if(m?.configService){m.configService.reload();let y=c?.Providers||c?.providers;if(Array.isArray(y)&&m.configService.set("providers",y),de&&m.transformerService&&(m.providerService=new de(m.configService,m.transformerService,t.log)),tt(c,t.log),Oe&&xt){try{xt()}catch{}let p={enabled:m.configService.get("ACTIVE_PROBE_ENABLED")??!0,quotaProbeIntervalMinutes:m.configService.get("QUOTA_PROBE_INTERVAL_MINUTES")??10,probeTimeoutMs:m.configService.get("PROBE_TIMEOUT_MS")??15e3,slowThresholdMs:Number(m.configService.get("PROBE_SLOW_THRESHOLD_MS"))||3e3,initialDelayMs:m.configService.get("PROBE_INITIAL_DELAY_MS")??5e3,excludeProviders:m.configService.get("EXCLUDE_PROBE_PROVIDERS")??[]};m.activeProbeService=Oe(()=>m.providerService.getProviders(),p,f=>le(m.configService,f),t.log,f=>m.configService.get(f))}}}catch(m){t.log?.warn?.(`Config saved but runtime reload failed: ${m?.message||m}`)}return{success:!0,message:"Config saved successfully",projectTakeoverSync:g}}),t.get("/api/clients",async(l,a)=>{try{let c=await oe();return{clients:(0,O.listClientStatuses)(c)}}catch(c){console.error("Failed to get client integrations:",c),a.status(500).send({error:c.message||"Failed to get client integrations"})}}),t.post("/api/clients/apply",async(l,a)=>{try{let c=l.body,u=Array.isArray(c?.enabled)?c.enabled:[],d=await oe(),g=(0,O.applyClientSelection)(d,u);return await Ie(g.config),g}catch(c){console.error("Failed to apply client integrations:",c),a.status(500).send({error:c.message||"Failed to apply client integrations"})}});async function o(l,a,c){try{let{id:u}=l.params;if(!(0,O.isClientId)(u)){a.status(404).send({error:`Unknown client: ${u}`});return}let d=await oe(),g=c==="enable"?(0,O.enableClient)(d,u):c==="restore"?(0,O.restoreClient)(d,u):(0,O.disableClient)(d,u);return await Ie(d),{success:g.success,result:g,results:[g],clients:(0,O.listClientStatuses)(d),config:d}}catch(u){console.error(`Failed to ${c} client integration:`,u),a.status(500).send({error:u.message||`Failed to ${c} client integration`})}}t.post("/api/clients/:id/enable",async(l,a)=>o(l,a,"enable")),t.post("/api/clients/:id/disable",async(l,a)=>o(l,a,"disable")),t.post("/api/clients/:id/restore",async(l,a)=>o(l,a,"restore")),t.get("/api/projects",async(l,a)=>{try{let c=await(0,O.listProjectConfigs)();return{projects:await Promise.all(c.map(async d=>{let g=await(0,O.getProjectTakeoverClients)(d.path);return{...d,ccrTakeoverClients:g,ccrTakeover:g.length>0}}))}}catch(c){console.error("Failed to list project configs:",c),a.status(500).send({error:c.message||"Failed to list project configs"})}}),t.post("/api/projects",async(l,a)=>{try{let{path:c}=l.body||{};if(!c||typeof c!="string"||!(0,V.isAbsolute)(c)){a.status(400).send({error:"A valid absolute project path is required"});return}let u=(0,V.normalize)(c).replace(/[\\/]+$/,"")||c;if(await(0,O.readProjectConfig)(u)){a.status(409).send({error:"Project is already configured"});return}await(0,O.writeProjectConfig)(u,{Router:{}});try{let m=await oe();await(0,O.setProjectTakeover)(u,["claudeCode"],m)}catch(m){console.error("Failed to auto-enable ccr takeover for new project:",m)}let g=await(0,O.getProjectTakeoverClients)(u);return{id:(0,O.getClaudeProjectId)(u),path:u,configPath:(0,O.getProjectConfigPath)(u),Router:{},ccrTakeoverClients:g,ccrTakeover:g.length>0}}catch(c){console.error("Failed to add project config:",c),a.status(500).send({error:c.message||"Failed to add project config"})}}),t.put("/api/projects/:id",async(l,a)=>{try{let{id:c}=l.params,{Router:u}=l.body||{};if(!u||typeof u!="object"){a.status(400).send({error:"Router must be an object"});return}let d=await(0,O.readProjectConfigById)(c);if(!d){a.status(404).send({error:"Project config not found"});return}if(await(0,O.writeProjectConfig)(d.path,{Router:u}),Object.keys(u).length===0){let y=await oe();await(0,O.refreshProjectTakeovers)(d.path,y)}let m=await(0,O.getProjectTakeoverClients)(d.path);return{id:c,path:d.path,configPath:d.configPath,Router:u,ccrTakeoverClients:m,ccrTakeover:m.length>0}}catch(c){console.error("Failed to update project config:",c),a.status(500).send({error:c.message||"Failed to update project config"})}}),t.put("/api/projects/:id/takeover",async(l,a)=>{try{let{id:c}=l.params,u=l.body||{},d;if(Array.isArray(u.clients))d=u.clients.filter(O.isProjectTakeoverClient);else if(typeof u.enabled=="boolean")d=u.enabled?["claudeCode"]:[];else{a.status(400).send({error:"clients (array) or enabled (boolean) is required"});return}let g=await(0,O.readProjectConfigById)(c);if(!g){a.status(404).send({error:"Project config not found"});return}let m=await oe(),y=await(0,O.setProjectTakeover)(g.path,d,m);return{id:c,path:g.path,ccrTakeoverClients:y,ccrTakeover:y.length>0}}catch(c){console.error("Failed to update ccr takeover status:",c),a.status(500).send({error:c.message||"Failed to update ccr takeover status"})}}),t.delete("/api/projects/:id",async(l,a)=>{try{let{id:c}=l.params,u=await(0,O.readProjectConfigById)(c);if(!u){a.status(404).send({error:"Project config not found"});return}try{let d=await oe();await(0,O.setProjectTakeover)(u.path,[],d)}catch(d){console.error("Failed to remove ccr takeover while deleting project:",d)}return await(0,O.deleteProjectConfig)(u.path),{success:!0}}catch(c){console.error("Failed to delete project config:",c),a.status(500).send({error:c.message||"Failed to delete project config"})}});let r=typeof __dirname=="string"?__dirname:(0,V.dirname)((0,ea.fileURLToPath)(void 0)),s=(0,j.existsSync)((0,V.join)(r,"index.html"))?r:(0,j.existsSync)((0,V.join)(r,"..","index.html"))?(0,V.join)(r,".."):(0,V.join)(r,"..","dist");t.register(ta.default,{root:s,prefix:"/ui/",maxAge:"1h"}),t.get("/ui",async(l,a)=>a.redirect("/ui/")),t.get("/api/logs/files",async(l,a)=>{try{let c=(0,V.join)((0,oo.homedir)(),".claude-code-router","logs"),u=[];if((0,j.existsSync)(c)){let d=(0,j.readdirSync)(c);for(let g of d)if(g.endsWith(".log")){let m=(0,V.join)(c,g),y=(0,j.statSync)(m);u.push({name:g,path:m,size:y.size,lastModified:y.mtime.toISOString()})}u.sort((g,m)=>new Date(m.lastModified).getTime()-new Date(g.lastModified).getTime())}return u}catch(c){console.error("Failed to get log files:",c),a.status(500).send({error:"Failed to get log files"})}}),t.get("/api/logs",async(l,a)=>{try{let c=l.query.file,u;return c?u=c:u=(0,V.join)((0,oo.homedir)(),".claude-code-router","logs","app.log"),(0,j.existsSync)(u)?(0,j.readFileSync)(u,"utf8").split(`
|
|
406
|
-
`).filter(m=>m.trim()):[]}catch(c){console.error("Failed to get logs:",c),a.status(500).send({error:"Failed to get logs"})}}),t.delete("/api/logs",async(l,a)=>{try{let c=l.query.file,u;return c?u=c:u=(0,V.join)((0,oo.homedir)(),".claude-code-router","logs","app.log"),(0,j.existsSync)(u)&&(0,j.writeFileSync)(u,"","utf8"),{success:!0,message:"Logs cleared successfully"}}catch(c){console.error("Failed to clear logs:",c),a.status(500).send({error:"Failed to clear logs"})}}),t.get("/api/debug-log",async()=>({enabled:at()})),t.put("/api/debug-log",async l=>{let{enabled:a}=l.body;return Yt(a),{enabled:at()}}),t.get("/api/usage",async(l,a)=>{try{let c=l.query;return Tr({startTime:c.startDate,endTime:c.endDate,model:c.model,provider:c.provider,scenario:c.scenario,clientType:c.clientType,sessionId:c.sessionId,status:c.status,page:c.page?parseInt(c.page,10):void 0,pageSize:c.pageSize?parseInt(c.pageSize,10):void 0})}catch(c){console.error("Failed to query usage:",c),a.status(500).send({error:"Failed to query usage"})}}),t.get("/api/usage/summary",async(l,a)=>{try{let c=l.query;return Bt(c.startDate,c.endDate,c.status)}catch(c){console.error("Failed to query usage summary:",c),a.status(500).send({error:"Failed to query usage summary"})}}),t.delete("/api/usage",async(l,a)=>{try{let c=l.query;return Cr(c.beforeDate),{success:!0,message:c.beforeDate?"Usage data cleared before "+c.beforeDate:"All usage data cleared"}}catch(c){console.error("Failed to clear usage:",c),a.status(500).send({error:"Failed to clear usage data"})}}),t.get("/api/providers/health",async(l,a)=>{try{let u=U().getAllStates(),g=t._server?.activeProbeService?.getProbeTelemetry?.()||[];return{states:u.map(m=>({provider:m.provider,model:m.model,status:m.status,failureCount:m.failureCount,successCount:m.successCount,lastFailureTime:m.lastFailureTime,lastError:m.lastError,rateLimitUntil:m.rateLimitUntil??null})),probes:g,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to get provider health:",c),a.status(500).send({error:"Failed to get provider health"})}}),t.post("/api/providers/probe",async(l,a)=>{try{let{providerName:c}=l.body;if(!c)return a.status(400),{error:"providerName is required"};let d=t._server?.activeProbeService;if(!d?.probeProviderManually)return a.status(503),{error:"Active probe service is not available"};let g=await d.probeProviderManually(c);return g.success&&Lt(c,l.log),{provider:c,success:g.success,latencyMs:g.latencyMs,status:g.status,isSlow:g.isSlow,errorKind:g.errorKind??null,error:g.error,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to probe provider:",c),a.status(500).send({error:c.message||"Failed to probe provider"})}}),t.post("/api/providers/probe-all",async(l,a)=>{try{let c=t._server,u=c?.activeProbeService;if(!u?.probeProviderManually)return a.status(503),{error:"Active probe service is not available"};let d=(c?.providerService?.getProviders?.()||[]).filter(m=>m?.name&&m.enabled!==!1),g=await Promise.all(d.map(async m=>{let y=await u.probeProviderManually(m.name);return y.success&&Lt(m.name,l?.log),{provider:m.name,success:y.success,latencyMs:y.latencyMs,status:y.status,isSlow:y.isSlow,errorKind:y.errorKind??null,error:y.error}}));return{results:g,successCount:g.filter(m=>m.success).length,total:g.length,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to probe all providers:",c),a.status(500).send({error:c.message||"Failed to probe all providers"})}}),t.get("/api/providers/quota",async(l,a)=>{try{let u=(await oe()).Providers||[],d=Nl(u),g=new Map(d.map(p=>[p.provider,p])),m=on();for(let p of d){let f=m.find(_=>_.provider===p.provider);f&&f.limit!=null&&(p.limit5h=f.limit,p.used5h=f.limit-(f.remaining??0),f.reset&&(p.reset5h=new Date(f.reset*1e3).toISOString()))}let y=an();for(let p of y){let f=g.get(p.provider);f||(f={provider:p.provider,used5h:0,used7d:0},d.push(f),g.set(p.provider,f)),typeof p.totalBalance=="number"?(f.limit7d=p.totalBalance,f.type7d=p.currency?"balance":"rateLimit",p.currency&&(f.currency=p.currency),typeof p.usedBalance=="number"?f.used7d=p.usedBalance:typeof p.remainingBalance=="number"?f.used7d=Math.max(0,p.totalBalance-p.remainingBalance):(f.used7d=0,f.limit7d=p.totalBalance)):typeof p.usedBalance=="number"&&(f.used7d=p.usedBalance),typeof p.usedDailyBalance=="number"&&(f.used5h=p.usedDailyBalance,f.type5h="rateLimit"),typeof p.limitDaily=="number"&&(f.limit5h=p.limitDaily,f.type5h="rateLimit"),typeof p.resetTime=="string"&&(p.limitDaily!==void 0?f.reset5h=p.resetTime:f.reset7d=p.resetTime),typeof p.resetTime7d=="string"&&(f.reset7d=p.resetTime7d)}return{quotas:d,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to compute provider quota:",c),a.status(500).send({error:"Failed to compute provider quota"})}}),t.get("/api/presets",async(l,a)=>{try{let c=(0,V.join)(O.HOME_DIR,"presets");if(!(0,j.existsSync)(c))return{presets:[]};let d=(0,j.readdirSync)(c,{withFileTypes:!0}).filter(m=>m.isDirectory()&&!m.name.startsWith(".")).map(m=>m.name),g=[];for(let m of d){let y=(0,V.join)(c,m);try{let p=(0,V.join)(y,"manifest.json"),f=(0,j.readFileSync)(p,"utf-8"),_=JSON.parse(f),{Providers:k,Router:h,PORT:b,HOST:T,API_TIMEOUT_MS:x,PROXY_URL:v,PROXY_GLOBAL_ENABLED:S,LOG:C,LOG_LEVEL:P,StatusLine:R,NON_INTERACTIVE_MODE:A,...E}=_;g.push({id:m,name:E.name||m,version:E.version||"1.0.0",description:E.description,author:E.author,homepage:E.homepage,repository:E.repository,license:E.license,keywords:E.keywords,ccrVersion:E.ccrVersion,source:E.source,sourceType:E.sourceType,checksum:E.checksum,installed:!0})}catch(p){console.error(`Failed to read preset ${m}:`,p)}}return{presets:g}}catch(c){console.error("Failed to get presets:",c),a.status(500).send({error:"Failed to get presets"})}}),t.get("/api/presets/:name",async(l,a)=>{try{let{name:c}=l.params,u=(0,O.getPresetDir)(c);if(!(0,j.existsSync)(u)){a.status(404).send({error:"Preset not found"});return}let d=await(0,O.readManifestFromDir)(u);return{...(0,O.manifestToPresetFile)(d),config:(0,O.loadConfigFromManifest)(d,u),userValues:d.userValues||{}}}catch(c){console.error("Failed to get preset:",c),a.status(500).send({error:c.message||"Failed to get preset"})}}),t.post("/api/presets/:name/apply",async(l,a)=>{try{let{name:c}=l.params,{secrets:u}=l.body,d=(0,O.getPresetDir)(c);if(!(0,j.existsSync)(d)){a.status(404).send({error:"Preset not found"});return}let m={...await(0,O.readManifestFromDir)(d)};return u&&Object.keys(u).length>0&&(m.userValues={...m.userValues,...u}),await(0,O.saveManifest)(c,m),{success:!0,message:"Preset applied successfully"}}catch(c){console.error("Failed to apply preset:",c),a.status(500).send({error:c.message||"Failed to apply preset"})}}),t.delete("/api/presets/:name",async(l,a)=>{try{let{name:c}=l.params,u=(0,O.getPresetDir)(c);if(!(0,j.existsSync)(u)){a.status(404).send({error:"Preset not found"});return}return(0,j.rmSync)(u,{recursive:!0,force:!0}),{success:!0,message:"Preset deleted successfully"}}catch(c){console.error("Failed to delete preset:",c),a.status(500).send({error:c.message||"Failed to delete preset"})}}),t.get("/api/presets/market",async(l,a)=>{try{return{presets:await(0,O.getMarketPresets)()}}catch(c){console.error("Failed to get market presets:",c),a.status(500).send({error:c.message||"Failed to get market presets"})}}),t.post("/api/presets/install/github",async(l,a)=>{try{let{presetName:c}=l.body;if(!c){a.status(400).send({error:"Preset name is required"});return}let u=await(0,O.findMarketPresetByName)(c);if(!u){a.status(400).send({error:"Preset not found in marketplace",message:`Preset '${c}' is not available in the official marketplace. Please check the available presets.`});return}if(!u.repo){a.status(400).send({error:"Invalid preset data",message:`Preset '${c}' does not have repository information`});return}let d=u.repo.match(/(?:github\.com[:/]|^)([^/]+)\/([^/\s#]+?)(?:\.git)?$/);if(!d){a.status(400).send({error:"Invalid GitHub repository URL"});return}let[,g,m]=d,y=u.name||c;if(await(0,O.isPresetInstalled)(y)){a.status(409).send({error:"Preset already installed",message:`Preset '${y}' is already installed. To update or reconfigure, please delete it first using the delete button.`,presetName:y});return}let p=`https://github.com/${g}/${m}/archive/refs/heads/main.zip`,f=await(0,O.downloadPresetToTemp)(p),_=await i(f);if(await(0,O.isPresetInstalled)(y)){(0,j.unlinkSync)(f),a.status(409).send({error:"Preset already installed",message:`Preset '${y}' was installed while downloading. Please try again.`,presetName:y});return}let k=(0,O.getPresetDir)(y);await(0,O.extractPreset)(f,k);let h=await(0,O.readManifestFromDir)(k);return h.repository=u.repo,u.url&&(h.source=u.url),await(0,O.saveManifest)(y,h),(0,j.unlinkSync)(f),{success:!0,presetName:y,preset:{..._.metadata,installed:!0}}}catch(c){console.error("Failed to install preset from GitHub:",c),a.status(500).send({error:c.message||"Failed to install preset from GitHub"})}});async function i(l){let a=new oa.default(l),c=a.getEntry("manifest.json");if(c||(c=a.getEntries().find(g=>g.entryName.includes("manifest.json"))||null),!c)throw new Error("Invalid preset file: manifest.json not found");let u=JSON.parse(c.getData().toString("utf-8"));return(0,O.manifestToPresetFile)(u)}return n}var V,ea,ta,j,oo,O,na,oa,sa=w(()=>{"use strict";Ve();je();Je();gn();Kn();se();ct();ie();qn();Yn();V=require("path"),ea=require("url"),ta=Y(require("@fastify/static"),1),j=require("fs"),oo=require("os"),O=require("@wengine-ai/claude-code-router-shared"),na=Y(require("@fastify/multipart"),1),oa=Y(require("adm-zip"),1);Jt();yr()});function Ll(n,e){let t=n?.Router,{family:o}=ht(e||"");if(t?.enableFamilyRouting&&o){let r=t.families?.[o]?.image;if(r)return r}return t?.image}function ia(n){return n?.Router?.image}function Dl(n){return n.some(e=>e.role==="user"&&Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"||Array.isArray(t?.content)&&t.content.some(o=>o.type==="image"||o.type==="image_url")))}function Fl(n){let e=n[n.length-1];if(e?.role!=="user"||!Array.isArray(e.content))return;let t=[];e.content.filter(o=>o.type==="tool_result").forEach(o=>{if(!Array.isArray(o.content))return;let r=o.content.filter(s=>s.type==="image"?(t.push(s),!1):!0);r.length!==o.content.length&&(o.content=r.length>0?r:"read image successfully")}),e.content.push(...t)}var Rr,ro,wr,aa,ca=w(()=>{"use strict";Ve();Rr=class{cache=new Map;maxSize;ttl;constructor(e=100,t=300*1e3){this.maxSize=e,this.ttl=t}evictExpired(){let e=Date.now();for(let[t,o]of this.cache)e-o.timestamp>this.ttl&&this.cache.delete(t)}trim(){if(this.cache.size<=this.maxSize)return;let e=[...this.cache.keys()].slice(0,this.cache.size-this.maxSize);for(let t of e)this.cache.delete(t)}storeImage(e,t){this.hasImage(e)||(this.evictExpired(),this.cache.set(e,{source:t,timestamp:Date.now()}),this.trim())}getImage(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp>this.ttl?(this.cache.delete(e),null):t.source:null}hasImage(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp>this.ttl?(this.cache.delete(e),!1):!0:!1}clear(){this.cache.clear()}size(){return this.evictExpired(),this.cache.size}},ro=new Rr;wr=class{name="image";tools;constructor(){this.tools=new Map,this.appendTools()}shouldHandle(e,t){let o=Ll(t,e.originalModel||e.body.model);if(!o||e.body.model===o||!Dl(e.body.messages))return!1;let s=t.forceUseImageAgent===!0;return!s&&Ao(e.body.model)?!1:(Fl(e.body.messages),s&&!!ia(t))}appendTools(){this.tools.set("analyzeImage",{name:"analyzeImage",description:"Analyse image or images by ID and extract information such as OCR text, objects, layout, colors, or safety signals.",input_schema:{type:"object",properties:{imageId:{type:"array",description:"an array of IDs to analyse",items:{type:"string"}},task:{type:"string",description:"Details of task to perform on the image.The more detailed, the better"},regions:{type:"array",description:"Optional regions of interest within the image",items:{type:"object",properties:{name:{type:"string",description:"Optional label for the region"},x:{type:"number",description:"X coordinate"},y:{type:"number",description:"Y coordinate"},w:{type:"number",description:"Width of the region"},h:{type:"number",description:"Height of the region"},units:{type:"string",enum:["px","pct"],description:"Units for coordinates and size"}},required:["x","y","w","h","units"]}}},required:["imageId","task"]},handler:async(e,t)=>{let o=[],r;if(e.imageId){if(Array.isArray(e.imageId))e.imageId.forEach(l=>{let a=ro.getImage(`${t.req.id}_Image#${l}`);a&&o.push({type:"image",source:a})});else{let l=ro.getImage(`${t.req.id}_Image#${e.imageId}`);l&&o.push({type:"image",source:l})}r=e.imageId,delete e.imageId}let s=t.req.body.messages[t.req.body.messages.length-1];if(s.role==="user"&&Array.isArray(s.content)){let l=s.content.filter(a=>a.type==="text"&&!a.text.includes("This is an image, if you need to view or analyze it, you need to extract the imageId"));o.push(...l)}Object.keys(e).length>0&&o.push({type:"text",text:JSON.stringify(e)});let i=await fetch(`http://127.0.0.1:${t.config.PORT||3456}/v1/messages`,{method:"POST",headers:{"x-api-key":t.config.APIKEY,"content-type":"application/json"},body:JSON.stringify({model:ia(t.config),system:[{type:"text",text:`You must interpret and analyze images strictly according to the assigned task.
|
|
405
|
+
`;El=200});async function Wi(){let n=(0,zi.homedir)(),e=(0,Bi.join)(n,".claude.json");if(!(0,Hi.existsSync)(e)){let o={numStartups:184,autoUpdaterStatus:"enabled",userID:Array.from({length:64},()=>Math.random().toString(16)[2]).join(""),hasCompletedOnboarding:!0,lastOnboardingVersion:"1.0.17",projects:{}};await(0,Ji.writeFile)(e,JSON.stringify(o,null,2))}}var Hi,zi,Bi,Ji,Gi=w(()=>{"use strict";Hi=require("fs"),zi=require("os"),Bi=require("path"),Ji=require("fs/promises")});function Qi(n=(0,Sr.join)(Vi.HOME_DIR,"logs")){try{if(!(0,Te.existsSync)(n))return;let e=Date.now()-Ml;for(let t of(0,Te.readdirSync)(n)){if(!/^ccr-.*\.log$/.test(t))continue;let o=(0,Sr.join)(n,t),r=(0,Te.statSync)(o);r.isFile()&&r.mtime.getTime()<e&&(0,Te.unlinkSync)(o)}}catch(e){console.warn("Failed to prune old server log files:",e)}}function Yi(){Ki||(Ki=!0,Qi(),setInterval(Qi,$l).unref())}var Te,Sr,Vi,Il,Ml,$l,Ki,Xi=w(()=>{"use strict";Te=require("fs"),Sr=require("path"),Vi=require("@wengine-ai/claude-code-router-shared"),Il=7,Ml=Il*24*60*60*1e3,$l=1440*60*1e3,Ki=!1});async function qi(n,e){let t=e.plugins||e.Plugins||[];for(let o of t){let{name:r,enabled:s=!1,options:i={}}=o;switch(r){case"token-speed":qe.registerPlugin(At,{enabled:s,outputHandlers:[{type:"temp-file",enabled:!0,config:{subdirectory:"claude-code-router",extension:"json",includeTimestamp:!0,prefix:"session"}}],...i});break;default:console.warn(`Unknown plugin: ${r}`);break}}await qe.enablePlugins(n)}var Zi=w(()=>{"use strict";dr()});function Nl(n){let e=new Date().toISOString(),t=new Date(Date.now()-300*60*1e3).toISOString(),o=new Date(Date.now()-10080*60*1e3).toISOString(),r=Bt(t,e),s=Bt(o,e),i=[],l=new Set;for(let a of n||[])a&&a.name&&l.add(a.name);for(let a of Object.keys(r.byProvider||{}))l.add(a);for(let a of Object.keys(s.byProvider||{}))l.add(a);for(let a of l){let c=r.byProvider[a]||{inputTokens:0,outputTokens:0},u=s.byProvider[a]||{inputTokens:0,outputTokens:0},d=(c.inputTokens||0)+(c.outputTokens||0),g=(u.inputTokens||0)+(u.outputTokens||0),m,y,p=(n||[]).find(f=>f&&f.name===a);p&&p.quota&&(m=p.quota.limit5h,y=p.quota.limit7d),i.push({provider:a,used5h:d,used7d:g,limit5h:m,limit7d:y})}return i}async function ra(n,e){let t=n.app;Ue(),Be(),t.register(na.default,{limits:{fileSize:50*1024*1024}}),t.get("/v1/models",async()=>{let l=Dt(e);return{object:"list",data:l,first_id:l[0]?.id||null,last_id:l[l.length-1]?.id||null,has_more:!1}}),t.get("/v1/models/:modelId",async(l,a)=>{let c=decodeURIComponent(l.params.modelId),u=Dt(e).find(d=>d.id===c);return u||(a.status(404),{type:"error",error:{type:"not_found_error",message:`Model not found: ${c}`}})}),t.post("/v1/messages/count_tokens",async(l,a)=>{let{messages:c,tools:u,system:d,model:g}=l.body,m=t._server.tokenizerService;if(g&&g.includes(",")&&m)try{let[p,f]=g.split(",");l.log?.info(`Looking up tokenizer for provider: ${p}, model: ${f}`);let _=m.getTokenizerConfigForModel(p,f);_?l.log?.info(`Using tokenizer config: ${JSON.stringify(_)}`):l.log?.warn(`No tokenizer config found for ${p},${f}, using default tiktoken`);let k=await m.countTokens({messages:c,system:d,tools:u},_,p);return{input_tokens:k.tokenCount,tokenizer:k.tokenizerUsed}}catch(p){l.log?.error(`Error using configured tokenizer: ${p.message}`),l.log?.error(p.stack)}else g?g.includes(",")?m||l.log?.warn("TokenizerService not available, using default tiktoken"):l.log?.info(`Model "${g}" does not contain comma, using default tiktoken`):l.log?.info("No model specified, using default tiktoken");return{input_tokens:gt(c,d,u)}}),t.get("/api/config",async(l,a)=>await Qn()),t.get("/api/transformers",async(l,a)=>{let c=t._server.transformerService.getAllTransformers();return{transformers:Array.from(c.entries()).map(([d,g])=>({name:d,endpoint:g.endPoint||null}))}}),t.post("/api/config",async(l,a)=>{let c=l.body,u=Dr(c||{});if(u.length>0)return a.status(400),{success:!1,error:"Invalid proxy URL",message:u.map(m=>`${m.key}: ${m.error}`).join("; "),proxyErrors:u};let d=await $t();d&&console.log(`Backed up existing configuration file to ${d}`),await Ie(c);let g;try{g=await(0,P.syncGlobalProjectTakeovers)(c),g.failed.length>0&&t.log?.warn?.({projectTakeoverSync:g},"Config saved but some global project takeovers failed to sync")}catch(m){t.log?.warn?.(`Config saved but global project takeover sync failed: ${m?.message||m}`)}try{let m=t._server;if(m?.configService){m.configService.reload();let y=c?.Providers||c?.providers;if(Array.isArray(y)&&m.configService.set("providers",y),de&&m.transformerService&&(m.providerService=new de(m.configService,m.transformerService,t.log)),tt(c,t.log),Oe&&xt){try{xt()}catch{}let p={enabled:m.configService.get("ACTIVE_PROBE_ENABLED")??!0,quotaProbeIntervalMinutes:m.configService.get("QUOTA_PROBE_INTERVAL_MINUTES")??10,probeTimeoutMs:m.configService.get("PROBE_TIMEOUT_MS")??15e3,slowThresholdMs:Number(m.configService.get("PROBE_SLOW_THRESHOLD_MS"))||3e3,initialDelayMs:m.configService.get("PROBE_INITIAL_DELAY_MS")??5e3,excludeProviders:m.configService.get("EXCLUDE_PROBE_PROVIDERS")??[]};m.activeProbeService=Oe(()=>m.providerService.getProviders(),p,f=>le(m.configService,f),t.log,f=>m.configService.get(f))}}}catch(m){t.log?.warn?.(`Config saved but runtime reload failed: ${m?.message||m}`)}return{success:!0,message:"Config saved successfully",projectTakeoverSync:g}}),t.get("/api/clients",async(l,a)=>{try{let c=await oe();return{clients:(0,P.listClientStatuses)(c)}}catch(c){console.error("Failed to get client integrations:",c),a.status(500).send({error:c.message||"Failed to get client integrations"})}}),t.post("/api/clients/apply",async(l,a)=>{try{let c=l.body,u=Array.isArray(c?.enabled)?c.enabled:[],d=await oe(),g=(0,P.applyClientSelection)(d,u);return await Ie(g.config),g}catch(c){console.error("Failed to apply client integrations:",c),a.status(500).send({error:c.message||"Failed to apply client integrations"})}});async function o(l,a,c){try{let{id:u}=l.params;if(!(0,P.isClientId)(u)){a.status(404).send({error:`Unknown client: ${u}`});return}let d=await oe(),g=c==="enable"?(0,P.enableClient)(d,u):c==="restore"?(0,P.restoreClient)(d,u):(0,P.disableClient)(d,u);return await Ie(d),{success:g.success,result:g,results:[g],clients:(0,P.listClientStatuses)(d),config:d}}catch(u){console.error(`Failed to ${c} client integration:`,u),a.status(500).send({error:u.message||`Failed to ${c} client integration`})}}t.post("/api/clients/:id/enable",async(l,a)=>o(l,a,"enable")),t.post("/api/clients/:id/disable",async(l,a)=>o(l,a,"disable")),t.post("/api/clients/:id/restore",async(l,a)=>o(l,a,"restore")),t.get("/api/projects",async(l,a)=>{try{let c=await(0,P.listProjectConfigs)();return{projects:await Promise.all(c.map(async d=>{let g=await(0,P.getProjectTakeoverClients)(d.path);return{...d,ccrTakeoverClients:g,ccrTakeover:g.length>0}}))}}catch(c){console.error("Failed to list project configs:",c),a.status(500).send({error:c.message||"Failed to list project configs"})}}),t.post("/api/projects",async(l,a)=>{try{let{path:c}=l.body||{};if(!c||typeof c!="string"||!(0,V.isAbsolute)(c)){a.status(400).send({error:"A valid absolute project path is required"});return}let u=(0,V.normalize)(c).replace(/[\\/]+$/,"")||c;if(await(0,P.readProjectConfig)(u)){a.status(409).send({error:"Project is already configured"});return}await(0,P.writeProjectConfig)(u,{Router:{}});try{let m=await oe();await(0,P.setProjectTakeover)(u,["claudeCode"],m)}catch(m){console.error("Failed to auto-enable ccr takeover for new project:",m)}let g=await(0,P.getProjectTakeoverClients)(u);return{id:(0,P.getClaudeProjectId)(u),path:u,configPath:(0,P.getProjectConfigPath)(u),Router:{},ccrTakeoverClients:g,ccrTakeover:g.length>0}}catch(c){console.error("Failed to add project config:",c),a.status(500).send({error:c.message||"Failed to add project config"})}}),t.put("/api/projects/:id",async(l,a)=>{try{let{id:c}=l.params,{Router:u}=l.body||{};if(!u||typeof u!="object"){a.status(400).send({error:"Router must be an object"});return}let d=await(0,P.readProjectConfigById)(c);if(!d){a.status(404).send({error:"Project config not found"});return}await(0,P.writeProjectConfig)(d.path,{Router:u});let g=await oe();Object.keys(u).length===0?await(0,P.refreshProjectTakeovers)(d.path,g):await(0,P.refreshCcrProjectTakeover)(d.path,g,u);let m=await(0,P.getProjectTakeoverClients)(d.path);return{id:c,path:d.path,configPath:d.configPath,Router:u,ccrTakeoverClients:m,ccrTakeover:m.length>0}}catch(c){console.error("Failed to update project config:",c),a.status(500).send({error:c.message||"Failed to update project config"})}}),t.put("/api/projects/:id/takeover",async(l,a)=>{try{let{id:c}=l.params,u=l.body||{},d;if(Array.isArray(u.clients))d=u.clients.filter(P.isProjectTakeoverClient);else if(typeof u.enabled=="boolean")d=u.enabled?["claudeCode"]:[];else{a.status(400).send({error:"clients (array) or enabled (boolean) is required"});return}let g=await(0,P.readProjectConfigById)(c);if(!g){a.status(404).send({error:"Project config not found"});return}let m=await oe(),y=await(0,P.setProjectTakeover)(g.path,d,m);return{id:c,path:g.path,ccrTakeoverClients:y,ccrTakeover:y.length>0}}catch(c){console.error("Failed to update ccr takeover status:",c),a.status(500).send({error:c.message||"Failed to update ccr takeover status"})}}),t.delete("/api/projects/:id",async(l,a)=>{try{let{id:c}=l.params,u=await(0,P.readProjectConfigById)(c);if(!u){a.status(404).send({error:"Project config not found"});return}try{let d=await oe();await(0,P.setProjectTakeover)(u.path,[],d)}catch(d){console.error("Failed to remove ccr takeover while deleting project:",d)}return await(0,P.deleteProjectConfig)(u.path),{success:!0}}catch(c){console.error("Failed to delete project config:",c),a.status(500).send({error:c.message||"Failed to delete project config"})}});let r=typeof __dirname=="string"?__dirname:(0,V.dirname)((0,ea.fileURLToPath)(void 0)),s=(0,j.existsSync)((0,V.join)(r,"index.html"))?r:(0,j.existsSync)((0,V.join)(r,"..","index.html"))?(0,V.join)(r,".."):(0,V.join)(r,"..","dist");t.register(ta.default,{root:s,prefix:"/ui/",maxAge:"1h"}),t.get("/ui",async(l,a)=>a.redirect("/ui/")),t.get("/api/logs/files",async(l,a)=>{try{let c=(0,V.join)((0,oo.homedir)(),".claude-code-router","logs"),u=[];if((0,j.existsSync)(c)){let d=(0,j.readdirSync)(c);for(let g of d)if(g.endsWith(".log")){let m=(0,V.join)(c,g),y=(0,j.statSync)(m);u.push({name:g,path:m,size:y.size,lastModified:y.mtime.toISOString()})}u.sort((g,m)=>new Date(m.lastModified).getTime()-new Date(g.lastModified).getTime())}return u}catch(c){console.error("Failed to get log files:",c),a.status(500).send({error:"Failed to get log files"})}}),t.get("/api/logs",async(l,a)=>{try{let c=l.query.file,u;return c?u=c:u=(0,V.join)((0,oo.homedir)(),".claude-code-router","logs","app.log"),(0,j.existsSync)(u)?(0,j.readFileSync)(u,"utf8").split(`
|
|
406
|
+
`).filter(m=>m.trim()):[]}catch(c){console.error("Failed to get logs:",c),a.status(500).send({error:"Failed to get logs"})}}),t.delete("/api/logs",async(l,a)=>{try{let c=l.query.file,u;return c?u=c:u=(0,V.join)((0,oo.homedir)(),".claude-code-router","logs","app.log"),(0,j.existsSync)(u)&&(0,j.writeFileSync)(u,"","utf8"),{success:!0,message:"Logs cleared successfully"}}catch(c){console.error("Failed to clear logs:",c),a.status(500).send({error:"Failed to clear logs"})}}),t.get("/api/debug-log",async()=>({enabled:at()})),t.put("/api/debug-log",async l=>{let{enabled:a}=l.body;return Yt(a),{enabled:at()}}),t.get("/api/usage",async(l,a)=>{try{let c=l.query;return Tr({startTime:c.startDate,endTime:c.endDate,model:c.model,provider:c.provider,scenario:c.scenario,clientType:c.clientType,sessionId:c.sessionId,status:c.status,page:c.page?parseInt(c.page,10):void 0,pageSize:c.pageSize?parseInt(c.pageSize,10):void 0})}catch(c){console.error("Failed to query usage:",c),a.status(500).send({error:"Failed to query usage"})}}),t.get("/api/usage/summary",async(l,a)=>{try{let c=l.query;return Bt(c.startDate,c.endDate,c.status)}catch(c){console.error("Failed to query usage summary:",c),a.status(500).send({error:"Failed to query usage summary"})}}),t.delete("/api/usage",async(l,a)=>{try{let c=l.query;return Cr(c.beforeDate),{success:!0,message:c.beforeDate?"Usage data cleared before "+c.beforeDate:"All usage data cleared"}}catch(c){console.error("Failed to clear usage:",c),a.status(500).send({error:"Failed to clear usage data"})}}),t.get("/api/providers/health",async(l,a)=>{try{let u=U().getAllStates(),g=t._server?.activeProbeService?.getProbeTelemetry?.()||[];return{states:u.map(m=>({provider:m.provider,model:m.model,status:m.status,failureCount:m.failureCount,successCount:m.successCount,lastFailureTime:m.lastFailureTime,lastError:m.lastError,rateLimitUntil:m.rateLimitUntil??null})),probes:g,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to get provider health:",c),a.status(500).send({error:"Failed to get provider health"})}}),t.post("/api/providers/probe",async(l,a)=>{try{let{providerName:c}=l.body;if(!c)return a.status(400),{error:"providerName is required"};let d=t._server?.activeProbeService;if(!d?.probeProviderManually)return a.status(503),{error:"Active probe service is not available"};let g=await d.probeProviderManually(c);return g.success&&Lt(c,l.log),{provider:c,success:g.success,latencyMs:g.latencyMs,status:g.status,isSlow:g.isSlow,errorKind:g.errorKind??null,error:g.error,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to probe provider:",c),a.status(500).send({error:c.message||"Failed to probe provider"})}}),t.post("/api/providers/probe-all",async(l,a)=>{try{let c=t._server,u=c?.activeProbeService;if(!u?.probeProviderManually)return a.status(503),{error:"Active probe service is not available"};let d=(c?.providerService?.getProviders?.()||[]).filter(m=>m?.name&&m.enabled!==!1),g=await Promise.all(d.map(async m=>{let y=await u.probeProviderManually(m.name);return y.success&&Lt(m.name,l?.log),{provider:m.name,success:y.success,latencyMs:y.latencyMs,status:y.status,isSlow:y.isSlow,errorKind:y.errorKind??null,error:y.error}}));return{results:g,successCount:g.filter(m=>m.success).length,total:g.length,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to probe all providers:",c),a.status(500).send({error:c.message||"Failed to probe all providers"})}}),t.get("/api/providers/quota",async(l,a)=>{try{let u=(await oe()).Providers||[],d=Nl(u),g=new Map(d.map(p=>[p.provider,p])),m=on();for(let p of d){let f=m.find(_=>_.provider===p.provider);f&&f.limit!=null&&(p.limit5h=f.limit,p.used5h=f.limit-(f.remaining??0),f.reset&&(p.reset5h=new Date(f.reset*1e3).toISOString()))}let y=an();for(let p of y){let f=g.get(p.provider);f||(f={provider:p.provider,used5h:0,used7d:0},d.push(f),g.set(p.provider,f)),typeof p.totalBalance=="number"?(f.limit7d=p.totalBalance,f.type7d=p.currency?"balance":"rateLimit",p.currency&&(f.currency=p.currency),typeof p.usedBalance=="number"?f.used7d=p.usedBalance:typeof p.remainingBalance=="number"?f.used7d=Math.max(0,p.totalBalance-p.remainingBalance):(f.used7d=0,f.limit7d=p.totalBalance)):typeof p.usedBalance=="number"&&(f.used7d=p.usedBalance),typeof p.usedDailyBalance=="number"&&(f.used5h=p.usedDailyBalance,f.type5h="rateLimit"),typeof p.limitDaily=="number"&&(f.limit5h=p.limitDaily,f.type5h="rateLimit"),typeof p.resetTime=="string"&&(p.limitDaily!==void 0?f.reset5h=p.resetTime:f.reset7d=p.resetTime),typeof p.resetTime7d=="string"&&(f.reset7d=p.resetTime7d)}return{quotas:d,timestamp:new Date().toISOString()}}catch(c){console.error("Failed to compute provider quota:",c),a.status(500).send({error:"Failed to compute provider quota"})}}),t.get("/api/presets",async(l,a)=>{try{let c=(0,V.join)(P.HOME_DIR,"presets");if(!(0,j.existsSync)(c))return{presets:[]};let d=(0,j.readdirSync)(c,{withFileTypes:!0}).filter(m=>m.isDirectory()&&!m.name.startsWith(".")).map(m=>m.name),g=[];for(let m of d){let y=(0,V.join)(c,m);try{let p=(0,V.join)(y,"manifest.json"),f=(0,j.readFileSync)(p,"utf-8"),_=JSON.parse(f),{Providers:k,Router:h,PORT:b,HOST:T,API_TIMEOUT_MS:x,PROXY_URL:v,PROXY_GLOBAL_ENABLED:S,LOG:C,LOG_LEVEL:E,StatusLine:R,NON_INTERACTIVE_MODE:A,...O}=_;g.push({id:m,name:O.name||m,version:O.version||"1.0.0",description:O.description,author:O.author,homepage:O.homepage,repository:O.repository,license:O.license,keywords:O.keywords,ccrVersion:O.ccrVersion,source:O.source,sourceType:O.sourceType,checksum:O.checksum,installed:!0})}catch(p){console.error(`Failed to read preset ${m}:`,p)}}return{presets:g}}catch(c){console.error("Failed to get presets:",c),a.status(500).send({error:"Failed to get presets"})}}),t.get("/api/presets/:name",async(l,a)=>{try{let{name:c}=l.params,u=(0,P.getPresetDir)(c);if(!(0,j.existsSync)(u)){a.status(404).send({error:"Preset not found"});return}let d=await(0,P.readManifestFromDir)(u);return{...(0,P.manifestToPresetFile)(d),config:(0,P.loadConfigFromManifest)(d,u),userValues:d.userValues||{}}}catch(c){console.error("Failed to get preset:",c),a.status(500).send({error:c.message||"Failed to get preset"})}}),t.post("/api/presets/:name/apply",async(l,a)=>{try{let{name:c}=l.params,{secrets:u}=l.body,d=(0,P.getPresetDir)(c);if(!(0,j.existsSync)(d)){a.status(404).send({error:"Preset not found"});return}let m={...await(0,P.readManifestFromDir)(d)};return u&&Object.keys(u).length>0&&(m.userValues={...m.userValues,...u}),await(0,P.saveManifest)(c,m),{success:!0,message:"Preset applied successfully"}}catch(c){console.error("Failed to apply preset:",c),a.status(500).send({error:c.message||"Failed to apply preset"})}}),t.delete("/api/presets/:name",async(l,a)=>{try{let{name:c}=l.params,u=(0,P.getPresetDir)(c);if(!(0,j.existsSync)(u)){a.status(404).send({error:"Preset not found"});return}return(0,j.rmSync)(u,{recursive:!0,force:!0}),{success:!0,message:"Preset deleted successfully"}}catch(c){console.error("Failed to delete preset:",c),a.status(500).send({error:c.message||"Failed to delete preset"})}}),t.get("/api/presets/market",async(l,a)=>{try{return{presets:await(0,P.getMarketPresets)()}}catch(c){console.error("Failed to get market presets:",c),a.status(500).send({error:c.message||"Failed to get market presets"})}}),t.post("/api/presets/install/github",async(l,a)=>{try{let{presetName:c}=l.body;if(!c){a.status(400).send({error:"Preset name is required"});return}let u=await(0,P.findMarketPresetByName)(c);if(!u){a.status(400).send({error:"Preset not found in marketplace",message:`Preset '${c}' is not available in the official marketplace. Please check the available presets.`});return}if(!u.repo){a.status(400).send({error:"Invalid preset data",message:`Preset '${c}' does not have repository information`});return}let d=u.repo.match(/(?:github\.com[:/]|^)([^/]+)\/([^/\s#]+?)(?:\.git)?$/);if(!d){a.status(400).send({error:"Invalid GitHub repository URL"});return}let[,g,m]=d,y=u.name||c;if(await(0,P.isPresetInstalled)(y)){a.status(409).send({error:"Preset already installed",message:`Preset '${y}' is already installed. To update or reconfigure, please delete it first using the delete button.`,presetName:y});return}let p=`https://github.com/${g}/${m}/archive/refs/heads/main.zip`,f=await(0,P.downloadPresetToTemp)(p),_=await i(f);if(await(0,P.isPresetInstalled)(y)){(0,j.unlinkSync)(f),a.status(409).send({error:"Preset already installed",message:`Preset '${y}' was installed while downloading. Please try again.`,presetName:y});return}let k=(0,P.getPresetDir)(y);await(0,P.extractPreset)(f,k);let h=await(0,P.readManifestFromDir)(k);return h.repository=u.repo,u.url&&(h.source=u.url),await(0,P.saveManifest)(y,h),(0,j.unlinkSync)(f),{success:!0,presetName:y,preset:{..._.metadata,installed:!0}}}catch(c){console.error("Failed to install preset from GitHub:",c),a.status(500).send({error:c.message||"Failed to install preset from GitHub"})}});async function i(l){let a=new oa.default(l),c=a.getEntry("manifest.json");if(c||(c=a.getEntries().find(g=>g.entryName.includes("manifest.json"))||null),!c)throw new Error("Invalid preset file: manifest.json not found");let u=JSON.parse(c.getData().toString("utf-8"));return(0,P.manifestToPresetFile)(u)}return n}var V,ea,ta,j,oo,P,na,oa,sa=w(()=>{"use strict";Ve();je();Je();gn();Kn();se();ct();ie();qn();Yn();V=require("path"),ea=require("url"),ta=Y(require("@fastify/static"),1),j=require("fs"),oo=require("os"),P=require("@wengine-ai/claude-code-router-shared"),na=Y(require("@fastify/multipart"),1),oa=Y(require("adm-zip"),1);Jt();yr()});function Ll(n,e){let t=n?.Router,{family:o}=ht(e||"");if(t?.enableFamilyRouting&&o){let r=t.families?.[o]?.image;if(r)return r}return t?.image}function ia(n){return n?.Router?.image}function Dl(n){return n.some(e=>e.role==="user"&&Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"||Array.isArray(t?.content)&&t.content.some(o=>o.type==="image"||o.type==="image_url")))}function Fl(n){let e=n[n.length-1];if(e?.role!=="user"||!Array.isArray(e.content))return;let t=[];e.content.filter(o=>o.type==="tool_result").forEach(o=>{if(!Array.isArray(o.content))return;let r=o.content.filter(s=>s.type==="image"?(t.push(s),!1):!0);r.length!==o.content.length&&(o.content=r.length>0?r:"read image successfully")}),e.content.push(...t)}var Rr,ro,wr,aa,ca=w(()=>{"use strict";Ve();Rr=class{cache=new Map;maxSize;ttl;constructor(e=100,t=300*1e3){this.maxSize=e,this.ttl=t}evictExpired(){let e=Date.now();for(let[t,o]of this.cache)e-o.timestamp>this.ttl&&this.cache.delete(t)}trim(){if(this.cache.size<=this.maxSize)return;let e=[...this.cache.keys()].slice(0,this.cache.size-this.maxSize);for(let t of e)this.cache.delete(t)}storeImage(e,t){this.hasImage(e)||(this.evictExpired(),this.cache.set(e,{source:t,timestamp:Date.now()}),this.trim())}getImage(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp>this.ttl?(this.cache.delete(e),null):t.source:null}hasImage(e){let t=this.cache.get(e);return t?Date.now()-t.timestamp>this.ttl?(this.cache.delete(e),!1):!0:!1}clear(){this.cache.clear()}size(){return this.evictExpired(),this.cache.size}},ro=new Rr;wr=class{name="image";tools;constructor(){this.tools=new Map,this.appendTools()}shouldHandle(e,t){let o=Ll(t,e.originalModel||e.body.model);if(!o||e.body.model===o||!Dl(e.body.messages))return!1;let s=t.forceUseImageAgent===!0;return!s&&Ao(e.body.model)?!1:(Fl(e.body.messages),s&&!!ia(t))}appendTools(){this.tools.set("analyzeImage",{name:"analyzeImage",description:"Analyse image or images by ID and extract information such as OCR text, objects, layout, colors, or safety signals.",input_schema:{type:"object",properties:{imageId:{type:"array",description:"an array of IDs to analyse",items:{type:"string"}},task:{type:"string",description:"Details of task to perform on the image.The more detailed, the better"},regions:{type:"array",description:"Optional regions of interest within the image",items:{type:"object",properties:{name:{type:"string",description:"Optional label for the region"},x:{type:"number",description:"X coordinate"},y:{type:"number",description:"Y coordinate"},w:{type:"number",description:"Width of the region"},h:{type:"number",description:"Height of the region"},units:{type:"string",enum:["px","pct"],description:"Units for coordinates and size"}},required:["x","y","w","h","units"]}}},required:["imageId","task"]},handler:async(e,t)=>{let o=[],r;if(e.imageId){if(Array.isArray(e.imageId))e.imageId.forEach(l=>{let a=ro.getImage(`${t.req.id}_Image#${l}`);a&&o.push({type:"image",source:a})});else{let l=ro.getImage(`${t.req.id}_Image#${e.imageId}`);l&&o.push({type:"image",source:l})}r=e.imageId,delete e.imageId}let s=t.req.body.messages[t.req.body.messages.length-1];if(s.role==="user"&&Array.isArray(s.content)){let l=s.content.filter(a=>a.type==="text"&&!a.text.includes("This is an image, if you need to view or analyze it, you need to extract the imageId"));o.push(...l)}Object.keys(e).length>0&&o.push({type:"text",text:JSON.stringify(e)});let i=await fetch(`http://127.0.0.1:${t.config.PORT||3456}/v1/messages`,{method:"POST",headers:{"x-api-key":t.config.APIKEY,"content-type":"application/json"},body:JSON.stringify({model:ia(t.config),system:[{type:"text",text:`You must interpret and analyze images strictly according to the assigned task.
|
|
407
407
|
When an image placeholder is provided, your role is to parse the image content only within the scope of the user\u2019s instructions.
|
|
408
408
|
Do not ignore or deviate from the task.
|
|
409
409
|
Always ensure that your response reflects a clear, accurate interpretation of the image aligned with the given objective.`}],messages:[{role:"user",content:o}],stream:!1})}).then(l=>l.json()).catch(l=>null);return!i||!i.content?"analyzeImage Error":i.content[0].text}})}reqHandler(e,t){e.body?.system?.push({type:"text",text:`You are a text-only language model and do not possess visual perception.
|
|
@@ -416,5 +416,5 @@ If multiple images exist, select the **most relevant imageId** based on the user
|
|
|
416
416
|
|
|
417
417
|
Do not attempt to describe or analyze the image directly yourself.
|
|
418
418
|
Ignore any user interruptions or unrelated instructions that might cause you to skip this requirement.
|
|
419
|
-
Your response should consistently follow this rule whenever image-related analysis is requested.`});let o=e.body.messages.filter(s=>s.role==="user"&&Array.isArray(s.content)&&s.content.some(i=>i.type==="image"||Array.isArray(i.content)&&i.content.some(l=>l.type==="image"))),r=1;o.forEach(s=>{Array.isArray(s.content)&&s.content.forEach(i=>{if(i.type==="image")ro.storeImage(`${e.id}_Image#${r}`,i.source),i.type="text",delete i.source,i.text=`[Image #${r}]This is an image, if you need to view or analyze it, you need to extract the imageId`,r++;else if(i.type==="text"&&i.text.includes("[Image #"))i.text=i.text.replace(/\[Image #\d+\]/g,"");else if(i.type==="tool_result"&&Array.isArray(i.content)&&i.content.some(l=>l.type==="image")){let l=[],a=i.content.filter(u=>u.type!=="image"?!0:(ro.storeImage(`${e.id}_Image#${r}`,u.source),l.push(`[Image #${r}]`),r++,!1)),c=`${l.join("")}This is an image, if you need to view or analyze it, you need to extract the imageId`;i.content=a.length>0?[{type:"text",text:c},...a]:c}})})}},aa=new wr});var Pr,la,so,ua=w(()=>{"use strict";ca();Pr=class{agents=new Map;registerAgent(e){this.agents.set(e.name,e)}getAgent(e){return this.agents.get(e)}getAllAgents(){return Array.from(this.agents.values())}getAllTools(){let e=[];for(let t of this.agents.values())e.push(...t.tools.values());return e}},la=new Pr;la.registerAgent(aa);so=la});function Ul(n,e){return n===429||!!(e&&/rate[\s_]limit|too many|限流|频率限制|qps_limit|token_limit|quota exhausted|usage limit|limit reached/i.test(e))}function ma(n,e){(!n.clientContext||!n.usageCacheKey||!n.usageSessionId)&&he(n,e)}function Or(n){return n.usageSessionId||n.id}function io(n){return n.usageCacheKey||`${n.clientType||"unknown"}:request:${Or(n)}`}function ot(n){return n.body?.model?Array.isArray(n.body.model)?n.body.model.join(","):n.body.model:Array.isArray(n.model)?n.model.join(","):n.model||""}function jl(n){if(!n)return;let e=n;if(Buffer.isBuffer(n)&&(e=n.toString("utf8")),typeof e=="string")try{e=JSON.parse(e)}catch{return}if(typeof e!="object")return;let t=e.usage?Me(e.usage):e.response?.usage?Me(e.response.usage):void 0,o=e.model||e.response?.model;if(!(!t&&!o))return{usage:t,model:o}}async function Hl(n,e,t){if(await new Promise((r,s)=>{let i=l=>l?s(l):r();Ft(t)(n,e,i).then(()=>r(),s)}),e.sent)return;let o=new URL(`http://127.0.0.1${n.url}`);if(n.pathname=o.pathname,n.pathname.endsWith("/v1/messages")&&n.pathname!=="/v1/messages"&&(n.preset=n.pathname.replace("/v1/messages","").replace("/","")),n.pathname.endsWith("/v1/responses")&&n.pathname!=="/v1/responses"&&(n.preset=n.pathname.replace("/v1/responses","").replace("/","")),n.pathname.endsWith("/v1/messages")||n.pathname.endsWith("/v1/responses")){ma(n,t);let r=io(n);n.clientContext?.usageScope==="session"&&(n.previousUsage=q.get(r))}}async function zl(n,e,t){if(!n.pathname?.endsWith("/v1/messages"))return;let o=[];for(let r of so.getAllAgents())r.shouldHandle(n,t)&&(o.push(r.name),r.reqHandler(n,t),r.tools.size&&(n.body?.tools?.length||(n.body.tools=[]),n.body.tools.unshift(...Array.from(r.tools.values()).map(s=>({name:s.name,description:s.description,input_schema:s.input_schema})))));o.length&&(n.agents=o)}function ga(n){return{authClient:(e,t)=>Hl(e,t,n),agent:(e,t)=>zl(e,t,n)}}function ha(n,e){n.addHook("onRequest",async t=>{let o=new URL(`http://127.0.0.1${t.url}`);t.pathname=o.pathname,(o.pathname.endsWith("/v1/messages")||o.pathname.endsWith("/v1/responses"))&&!t.requestStartTime&&(t.requestStartTime=Er.performance.now())}),n.addHook("preHandler",async(t,o)=>{let r=t.pathname||new URL(`http://127.0.0.1${t.url}`).pathname;r.endsWith("/v1/messages")||r.endsWith("/v1/responses")||await new Promise((s,i)=>{let l=a=>a?i(a):s();Ft(e)(t,o,l).then(()=>s(),i)})}),n.addHook("onError",async(t,o,r)=>{t.errorMessage=r?.message||r?.toString?.()||"Unknown error",da.emit("onError",t,o,r)}),n.addHook("onSend",(t,o,r,s)=>{(t.ccrHookOrder||=[]).push("onSend");let i=t.pathname?.endsWith("/v1/messages"),l=t.pathname?.endsWith("/v1/responses");if(i||l){ma(t,e);let a=Or(t),c=io(t);if(r instanceof ReadableStream){if(i&&t.agents){let y=new AbortController,p=r.pipeThrough(new ce),f,_=-1,k="",h="",b="",T=[],x=[];return s(null,St(p,async(v,S)=>{try{if(v.event==="content_block_start"&&v?.data?.content_block?.name){let C=t.agents.find(P=>so.getAgent(P)?.tools.get(v.data.content_block.name));if(C){f=so.getAgent(C),_=v.data.index,k=v.data.content_block.name,b=v.data.content_block.id;return}}if(_>-1&&v.data.index===_&&v.data?.delta?.type==="input_json_delta"){h+=v.data?.delta?.partial_json;return}if(_>-1&&v.data.index===_&&v.data?.type==="content_block_stop"){try{let C=fa.default.parse(h);x.push({type:"tool_use",id:b,name:k,input:C});let P=await f?.tools.get(k)?.handler(C,{req:t,config:e});T.push({tool_use_id:b,type:"tool_result",content:P}),f=void 0,_=-1,k="",h="",b=""}catch(C){console.log(C)}return}if(v.event==="message_delta"&&T.length){t.body.messages.push({role:"assistant",content:x}),t.body.messages.push({role:"user",content:T});let C=await fetch(`http://127.0.0.1:${e.PORT||3456}/v1/messages`,{method:"POST",headers:{"x-api-key":e.APIKEY,"content-type":"application/json"},body:JSON.stringify(t.body)});if(!C.ok)return;let R=C.body.pipeThrough(new ce).getReader();for(;;)try{let{value:A,done:E}=await R.read();if(E)break;let I=A;if(["message_start","message_stop"].includes(I.event))continue;if(!S.desiredSize)break;S.enqueue(I)}catch(A){if(A.name==="AbortError"||A.code==="ERR_STREAM_PREMATURE_CLOSE"){y.abort();break}throw A}return}return v}catch(C){if(console.error("Unexpected error in stream processing:",C),C.code==="ERR_STREAM_PREMATURE_CLOSE"){y.abort();return}throw C}}).pipeThrough(new Ae))}let[d,g]=r.tee(),m=async y=>{let f=y.pipeThrough(new TextDecoderStream).pipeThrough(new ce).getReader();try{for(;;){let{done:_,value:k}=await f.read();if(_)break;let h=k.event,b=k.data;if(h==="message_start"&&b?.message?.model&&(t.upstreamModel=b.message.model),h==="response.completed"&&b?.response?.model&&(t.upstreamModel=b.response.model),b?.usage){let T=q.get(c)||{},x=Me(b.usage),v=Nt(T,x,h==="message_start");t.log?.info?.({debug_log:!0,reqId:t.id,phase:"usage_capture_anthropic_sse",event:h,provider:t.provider,model:ot(t),usageSessionId:a,capturedUsage:x,mergedUsage:v}),(x?.cache_read_input_tokens||x?.cache_creation_input_tokens)&&console.log("[Usage] Cache tokens:",{cache_read:x?.cache_read_input_tokens,cache_creation:x?.cache_creation_input_tokens}),q.put(c,v)}if(b?.response?.usage){let T=Me(b.response.usage),x=q.get(c)||{},v=Nt(x,T,!1);t.log?.info?.({debug_log:!0,reqId:t.id,phase:"usage_capture_responses_sse",event:h,provider:t.provider,model:ot(t),usageSessionId:a,capturedUsage:T,mergedUsage:v}),q.put(c,v)}}}catch(_){_.name==="AbortError"||_.code==="ERR_STREAM_PREMATURE_CLOSE"?console.error("Background read stream closed prematurely"):console.error("Error in background stream reading:",_)}finally{f.releaseLock()}};return t.usageCapturePromise=m(g),s(null,d)}let u=jl(r);if(u?.usage&&q.put(c,u.usage),u?.model&&(t.upstreamModel=u.model),typeof r=="object")return r.error?s(r.error,null):s(r,null)}if(typeof r=="object"&&r.error)return s(r.error,null);s(null,r)}),n.addHook("onSend",async(t,o,r)=>{if(da.emit("onSend",t,o,r),o.statusCode>=400&&(t.pathname?.endsWith("/v1/messages")||t.pathname?.endsWith("/v1/responses")))try{typeof r=="string"?t.errorResponseBody=r:r&&typeof r=="object"&&(t.errorResponseBody=JSON.stringify(r))}catch{}return r}),n.addHook("onResponse",async(t,o)=>{if((t.ccrHookOrder||=[]).push("onResponse"),!(!t.pathname?.endsWith("/v1/messages")&&!t.pathname?.endsWith("/v1/responses")))try{t.usageCapturePromise&&await t.usageCapturePromise,t.tokenSpeedCapturePromise&&await t.tokenSpeedCapturePromise;let r=Or(t),s=o.statusCode>=400,i=s?void 0:q.get(io(t)),l=vr(r),a=U(),c,u,d=t.sseError,g=d&&(d.type||d.code||d.message),m=i?.output_tokens&&i.output_tokens>0,y=s||g&&!m;if(y){c=t.errorMessage||o.errorMessage||t.error?.message||t.error?.toString?.()||void 0,g&&(c=c||JSON.stringify(d),u=JSON.stringify(d)),u=u||t.errorResponseBody;let h=ot(t);Ul(o.statusCode,c)?a.markRateLimited(t.provider||"",h,120,c):a.recordFailure(t.provider||"",h,c)}else{let h=ot(t);a.recordSuccess(t.provider||"",h)}let p=i?.cache_read_input_tokens??0,_=i?.input_tokens||0||t.tokenCount||0;!p&&t.tokenCount&&i?.input_tokens&&i.input_tokens<t.tokenCount&&(p=t.tokenCount-i.input_tokens,p&&console.log("[Usage] Inferred cache tokens:",{tokenCount:t.tokenCount,netInput:i.input_tokens,impliedCache:p}));let k=y?0:i?.output_tokens||0;!y&&t.body?.stream&&_===0&&k===0&&t.log?.warn?.({debug_log:!0,reqId:t.id,phase:"usage_zero_stream",provider:t.provider,originalModel:t.originalModel||t.body?.model||"",model:ot(t),usageSessionId:r,tokenCount:t.tokenCount,cachedUsage:i,note:"Successful streaming request ended with zero usage. Check provider_stream_chunk usage_monitor and usage_capture_* logs."}),zt({id:`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date().toISOString(),sessionId:r,provider:t.provider||"",originalModel:t.originalModel||t.body?.model||"",model:ot(t),upstreamModel:t.upstreamModel,modelFamily:t.modelFamily||"",scenarioType:t.scenarioType||"default",clientType:t.clientType||Re(t),stream:t.body?.stream??!1,inputTokens:_,outputTokens:k,cacheReadInputTokens:p,cacheCreationInputTokens:i?.cache_creation_input_tokens||0,ttft:y?null:l.ttft,tokensPerSecond:y?null:l.tokensPerSecond,durationMs:t.requestStartTime?Math.round(Er.performance.now()-t.requestStartTime):0,status:y?"error":"success",errorMessage:c,responseBody:u}),t.clientContext?.usageScope!=="session"&&q.delete(io(t))}catch(r){console.error("Usage tracking error:",r)}})}var pa,Er,fa,da,ya=w(()=>{"use strict";pa=require("node:events"),Er=require("node:perf_hooks"),fa=Y(require("json5"),1);Ge();rn();ie();er();tr();nr();Jt();mr();ua();_r();mn();da=new pa.EventEmitter});var Ta={};Gt(Ta,{createCcrServer:()=>Bl});async function Bl(n={}){await Wi(),await Mt();let e=await Vn(),t=e.Providers||e.providers||[],o=t&&t.length>0,r=e.HOST||"127.0.0.1";o?(r=e.HOST,e.APIKEY||(r="127.0.0.1")):(r="0.0.0.0",console.log("\u2139\uFE0F No providers configured. Listening on 0.0.0.0 without authentication."));let s=n.port??e.PORT??3456,i=process.env.SERVICE_PORT?parseInt(process.env.SERVICE_PORT):s,l=p=>(p>9?"":"0")+p,a=(p,f)=>{let _;p?typeof p=="number"?_=new Date(p):_=p:_=new Date;let k=_.getFullYear()+""+l(_.getMonth()+1),h=l(_.getDate()),b=l(_.getHours()),T=l(_.getMinutes());return`./logs/ccr-${k}${h}${b}${T}${l(_.getSeconds())}${f?`_${f}`:""}.log`},c;n.logger!==void 0?c=n.logger:(Yi(),e.LOG!==!1?(e.LOG===void 0&&(e.LOG=!0),c={level:e.LOG_LEVEL||"error",stream:(0,ba.createStream)(a,{path:rt.HOME_DIR,interval:"1d",size:"50M",compress:!1})}):c=!1);let u=await(0,rt.listPresets)(),d=new Ar({jsonPath:rt.CONFIG_FILE,initialConfig:{providers:e.Providers||e.providers,HOST:r,PORT:i,LOG_FILE:(0,ka.join)((0,_a.homedir)(),".claude-code-router","claude-code-router.log")},logger:c});await d.ready(),await ra(d,e),d.recordUsage=p=>{try{let f=p.req?p.req.clientType||Re(p.req):"unknown";zt({id:`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date().toISOString(),sessionId:p.sessionId||"",provider:p.provider||"",originalModel:p.originalModel||"",model:p.model||"",modelFamily:p.modelFamily||"",scenarioType:p.scenarioType||"default",clientType:f,stream:p.stream??!1,inputTokens:p.inputTokens||0,outputTokens:0,cacheReadInputTokens:p.cacheReadInputTokens||0,cacheCreationInputTokens:p.cacheCreationInputTokens||0,ttft:null,tokensPerSecond:null,durationMs:0,status:"error",errorMessage:p.errorMessage,responseBody:void 0})}catch(f){console.error("Fallback usage tracking error:",f)}},ha(d,e),d.ccrPreHandlerCallbacks=ga(e),(await Promise.allSettled(u.map(async p=>await d.registerNamespace(`/preset/${p.name}`,p.config)))).forEach((p,f)=>{if(p.status==="rejected"){let _=u[f],k=p.reason instanceof Error?p.reason.message:String(p.reason);d.app?.log?.error?.(`Failed to register preset "${_?.name}": ${k}`)}}),await qi(d,e),tt(e,d.app?.log);let m=p=>{d.app.log.error({err:p},"Uncaught exception")},y=(p,f)=>{d.app.log.error({reason:p,promise:f},"Unhandled rejection")};return process.on("uncaughtException",m),process.on("unhandledRejection",y),d.app.addHook("onClose",async()=>{process.off("uncaughtException",m),process.off("unhandledRejection",y)}),d}var _a,ka,ba,rt,Ca=w(()=>{"use strict";_a=require("os"),ka=require("path");va();ba=require("rotating-file-stream"),rt=require("@wengine-ai/claude-code-router-shared");Gi();Yn();Xi();Zi();sa();ya();qn();Jt();Ge()});var Gl={};Gt(Gl,{ActiveProbeService:()=>vt,ConfigService:()=>ve,ProjectRoutingError:()=>ue,ProviderHealthStore:()=>lt,ProviderService:()=>de,SSEParserTransform:()=>ce,SSESerializerTransform:()=>Ae,TokenizerService:()=>Ee,TransformerService:()=>Pe,apiKeyAuth:()=>Ft,applyClientAdapter:()=>he,backupConfigFile:()=>$t,builtinClientAdapterRegistry:()=>wo,calculateTokenCount:()=>gt,clearClientAdapterCaches:()=>ds,clearProviderHealth:()=>Lt,closeProxyDispatchers:()=>Qt,collectReachableModelKeys:()=>hr,createCcrServer:()=>Ra,default:()=>Ar,detectClientType:()=>Re,diagnoseResolutionFailure:()=>Oo,extractSessionIdFromUserId:()=>We,getActiveProbeService:()=>qo,getAllQuotaResults:()=>an,getAllRateLimitInfo:()=>on,getClientAdapter:()=>Eo,getConfiguredProxyUrl:()=>st,getHealthStore:()=>U,getProxyDispatcher:()=>Q,getQuotaAdapter:()=>Wn,getQuotaResult:()=>dt,getRateLimitInfo:()=>rs,getRuntimeDebugLog:()=>at,getServer:()=>Wl,initConfig:()=>Vn,initDir:()=>Mt,initProviderHealthPersistence:()=>nn,initQuotaStorePersistence:()=>Be,initRateLimitPersistence:()=>Ue,isClientType:()=>Po,isGlobalProxyEnabled:()=>ao,listAnthropicCompatibleModels:()=>Dt,mergeUsageCapture:()=>Nt,normalizeSessionId:()=>Se,normalizeUsagePayload:()=>Me,pluginManager:()=>qe,readConfigFile:()=>oe,readConfigFileRaw:()=>Qn,reconcileHealthStore:()=>tt,resetActiveProbeService:()=>xt,resolveProviderProxyUrl:()=>le,rewriteStream:()=>St,router:()=>yt,searchProjectBySession:()=>Io,sessionUsageCache:()=>q,setRuntimeDebugLog:()=>Yt,startActiveProbe:()=>Oe,stopActiveProbe:()=>Gn,storeQuotaResult:()=>sn,tokenSpeedPlugin:()=>At,usageStore:()=>xr,writeConfigFile:()=>Ie});module.exports=$r(Gl);function Jl(n={}){let e=(0,xa.default)({bodyLimit:52428800,...n});return e.setErrorHandler(jr),e.register(Sa.default),e}async function Ra(n={}){return(await Promise.resolve().then(()=>(Ca(),Ta))).createCcrServer(n)}var xa,Sa,Ir,Ar,Wl,va=w(()=>{xa=Y(require("fastify"),1),Sa=Y(require("@fastify/cors"),1);lo();Vt();mn();gn();Lo();Do();Ve();rn();Kn();ie();je();Je();se();Ge();mn();pt();Ge();Ve();lo();gn();Lo();Do();dr();or();ie();je();Yo();Je();ie();Kn();ct();se();Yn();mr();qn();yr();_r();Jt();Ir=class{app;configService;providerService;transformerService;tokenizerService;activeProbeService;recordUsage;readiness;mainNamespaceRegistered=!1;signalHandlersRegistered=!1;ccrPreHandlerCallbacks;constructor(e={}){let{initialConfig:t,jsonPath:o,envPath:r,useEnvFile:s,useJsonFile:i,useEnvironmentVariables:l,...a}=e;this.app=Jl({...a,logger:a.logger??!0}),this.app._server=this;let c={initialConfig:t};o!==void 0&&(c.jsonPath=o),r!==void 0&&(c.envPath=r),s!==void 0&&(c.useEnvFile=s),i!==void 0&&(c.useJsonFile=i),l!==void 0&&(c.useEnvironmentVariables=l),this.configService=new ve(c),this.transformerService=new Pe(this.configService,this.app.log),this.tokenizerService=new Ee(this.configService,this.app.log),this.readiness=(async()=>{await Promise.all([this.transformerService.initialize(),this.tokenizerService.initialize()]),this.providerService=new de(this.configService,this.transformerService,this.app.log)})()}async ready(){await this.readiness}async register(e,t){await this.app.register(e,t)}addHook(e,t){this.app.addHook(e,t)}async registerNamespace(e,t){if(!e)throw new Error("name is required");if(await this.ready(),e==="/"&&this.mainNamespaceRegistered)return;let o=this.configService,r=this.transformerService,s=this.providerService,i=this.tokenizerService;if(e!=="/"){if(!t)throw new Error("options is required");o=new ve({initialConfig:{...t,providers:t.Providers||t.providers}}),r=new Pe(o,this.app.log),i=new Ee(o,this.app.log),await Promise.all([r.initialize(),i.initialize()]),s=new de(o,r,this.app.log)}let l=async a=>{a.decorate("configService",o),a.decorate("transformerService",r),a.decorate("providerService",s),a.decorate("tokenizerService",i),a.decorate("recordUsage",this.recordUsage||(()=>{})),a.addHook("preHandler",async(c,u)=>{let d=new URL(`http://127.0.0.1${c.url}`);c.pathname=d.pathname;let g=d.pathname.endsWith("/v1/messages"),m=d.pathname.endsWith("/v1/responses");if(!g&&!m||!c.body||typeof c.body!="object")return;let y=c.ccrHookOrder||=[];if(y.push("request-normalize"),m&&c.body.input&&!c.body.messages&&_t(c.body),c.body.stream===void 0&&(c.body.stream=!1),c.log.info({data:c.body,type:"request body"}),y.push("adapter"),!c.originalModel&&c.body.model&&(c.originalModel=c.body.model),he(c,o.getAll()),y.push("auth-client"),!(this.ccrPreHandlerCallbacks&&(await this.ccrPreHandlerCallbacks.authClient(c,u),u.sent))&&(y.push("agent"),!(this.ccrPreHandlerCallbacks&&(await this.ccrPreHandlerCallbacks.agent(c,u),u.sent)))){y.push("router"),c.body?.model&&await yt(c,u,{configService:o,tokenizerService:i}),c.usageCacheKey&&q.put(c.usageCacheKey,{input_tokens:0,output_tokens:0,cache_read_input_tokens:0,cache_creation_input_tokens:0}),y.push("provider-model-normalize");try{let p=c.body;if(!p||!p.model)return u.code(400).send({error:"Missing model in request body"});let f=p.model.split(","),_=p.model;if(f.length>1){let[k,...h]=f;_=h.join(","),p.model=_,c.provider=k}c.model=_}catch(p){return c.log.error({error:p},"Error in modelProviderMiddleware:"),u.code(500).send({error:"Internal server error"})}}}),await Ss(a)};e==="/"?(await this.app.register(l),this.mainNamespaceRegistered=!0):await this.app.register(l,{prefix:e})}async start(){try{if(await this.ready(),await this.registerNamespace("/"),!this.signalHandlersRegistered){this.signalHandlersRegistered=!0;let t=async s=>{this.app.log.info(`Received ${s}, shutting down gracefully...`);try{Gn()}catch{}await this.app.close(),process.exit(0)},o=()=>void t("SIGINT"),r=()=>void t("SIGTERM");process.on("SIGINT",o),process.on("SIGTERM",r),this.app.addHook("onClose",async()=>{process.off("SIGINT",o),process.off("SIGTERM",r),this.signalHandlersRegistered=!1;try{this.tokenizerService.dispose()}catch{}await Qt()})}await this.app.ready();let e=await this.app.listen({port:parseInt(this.configService.get("PORT")||"3000",10),host:this.configService.get("HOST")||"127.0.0.1"});this.app.log.info(`\u{1F680} LLMs API server listening on ${e}`);try{Ue()}catch{}try{Be()}catch{}try{nn()}catch{}try{let t={enabled:this.configService.get("ACTIVE_PROBE_ENABLED")??!0,quotaProbeIntervalMinutes:this.configService.get("QUOTA_PROBE_INTERVAL_MINUTES")??10,probeTimeoutMs:this.configService.get("PROBE_TIMEOUT_MS")??15e3,slowThresholdMs:Number(this.configService.get("PROBE_SLOW_THRESHOLD_MS"))||3e3,initialDelayMs:this.configService.get("PROBE_INITIAL_DELAY_MS")??5e3,excludeProviders:this.configService.get("EXCLUDE_PROBE_PROVIDERS")??[]};this.activeProbeService=Oe(()=>this.providerService.getProviders(),t,o=>le(this.configService,o),this.app.log,o=>this.configService.get(o))}catch(t){this.app.log.warn?.(`Failed to start active probe service: ${t.message}`)}}catch(e){this.app.log.error(`Error starting server: ${e}`),process.exit(1)}}},Ar=Ir;Wl=Ra});va();0&&(module.exports={ActiveProbeService,ConfigService,ProjectRoutingError,ProviderHealthStore,ProviderService,SSEParserTransform,SSESerializerTransform,TokenizerService,TransformerService,apiKeyAuth,applyClientAdapter,backupConfigFile,builtinClientAdapterRegistry,calculateTokenCount,clearClientAdapterCaches,clearProviderHealth,closeProxyDispatchers,collectReachableModelKeys,createCcrServer,detectClientType,diagnoseResolutionFailure,extractSessionIdFromUserId,getActiveProbeService,getAllQuotaResults,getAllRateLimitInfo,getClientAdapter,getConfiguredProxyUrl,getHealthStore,getProxyDispatcher,getQuotaAdapter,getQuotaResult,getRateLimitInfo,getRuntimeDebugLog,getServer,initConfig,initDir,initProviderHealthPersistence,initQuotaStorePersistence,initRateLimitPersistence,isClientType,isGlobalProxyEnabled,listAnthropicCompatibleModels,mergeUsageCapture,normalizeSessionId,normalizeUsagePayload,pluginManager,readConfigFile,readConfigFileRaw,reconcileHealthStore,resetActiveProbeService,resolveProviderProxyUrl,rewriteStream,router,searchProjectBySession,sessionUsageCache,setRuntimeDebugLog,startActiveProbe,stopActiveProbe,storeQuotaResult,tokenSpeedPlugin,usageStore,writeConfigFile});
|
|
419
|
+
Your response should consistently follow this rule whenever image-related analysis is requested.`});let o=e.body.messages.filter(s=>s.role==="user"&&Array.isArray(s.content)&&s.content.some(i=>i.type==="image"||Array.isArray(i.content)&&i.content.some(l=>l.type==="image"))),r=1;o.forEach(s=>{Array.isArray(s.content)&&s.content.forEach(i=>{if(i.type==="image")ro.storeImage(`${e.id}_Image#${r}`,i.source),i.type="text",delete i.source,i.text=`[Image #${r}]This is an image, if you need to view or analyze it, you need to extract the imageId`,r++;else if(i.type==="text"&&i.text.includes("[Image #"))i.text=i.text.replace(/\[Image #\d+\]/g,"");else if(i.type==="tool_result"&&Array.isArray(i.content)&&i.content.some(l=>l.type==="image")){let l=[],a=i.content.filter(u=>u.type!=="image"?!0:(ro.storeImage(`${e.id}_Image#${r}`,u.source),l.push(`[Image #${r}]`),r++,!1)),c=`${l.join("")}This is an image, if you need to view or analyze it, you need to extract the imageId`;i.content=a.length>0?[{type:"text",text:c},...a]:c}})})}},aa=new wr});var Pr,la,so,ua=w(()=>{"use strict";ca();Pr=class{agents=new Map;registerAgent(e){this.agents.set(e.name,e)}getAgent(e){return this.agents.get(e)}getAllAgents(){return Array.from(this.agents.values())}getAllTools(){let e=[];for(let t of this.agents.values())e.push(...t.tools.values());return e}},la=new Pr;la.registerAgent(aa);so=la});function Ul(n,e){return n===429||!!(e&&/rate[\s_]limit|too many|限流|频率限制|qps_limit|token_limit|quota exhausted|usage limit|limit reached/i.test(e))}function ma(n,e){(!n.clientContext||!n.usageCacheKey||!n.usageSessionId)&&he(n,e)}function Or(n){return n.usageSessionId||n.id}function io(n){return n.usageCacheKey||`${n.clientType||"unknown"}:request:${Or(n)}`}function ot(n){return n.body?.model?Array.isArray(n.body.model)?n.body.model.join(","):n.body.model:Array.isArray(n.model)?n.model.join(","):n.model||""}function jl(n){if(!n)return;let e=n;if(Buffer.isBuffer(n)&&(e=n.toString("utf8")),typeof e=="string")try{e=JSON.parse(e)}catch{return}if(typeof e!="object")return;let t=e.usage?Me(e.usage):e.response?.usage?Me(e.response.usage):void 0,o=e.model||e.response?.model;if(!(!t&&!o))return{usage:t,model:o}}async function Hl(n,e,t){if(await new Promise((r,s)=>{let i=l=>l?s(l):r();Ft(t)(n,e,i).then(()=>r(),s)}),e.sent)return;let o=new URL(`http://127.0.0.1${n.url}`);if(n.pathname=o.pathname,n.pathname.endsWith("/v1/messages")&&n.pathname!=="/v1/messages"&&(n.preset=n.pathname.replace("/v1/messages","").replace("/","")),n.pathname.endsWith("/v1/responses")&&n.pathname!=="/v1/responses"&&(n.preset=n.pathname.replace("/v1/responses","").replace("/","")),n.pathname.endsWith("/v1/messages")||n.pathname.endsWith("/v1/responses")){ma(n,t);let r=io(n);n.clientContext?.usageScope==="session"&&(n.previousUsage=q.get(r))}}async function zl(n,e,t){if(!n.pathname?.endsWith("/v1/messages"))return;let o=[];for(let r of so.getAllAgents())r.shouldHandle(n,t)&&(o.push(r.name),r.reqHandler(n,t),r.tools.size&&(n.body?.tools?.length||(n.body.tools=[]),n.body.tools.unshift(...Array.from(r.tools.values()).map(s=>({name:s.name,description:s.description,input_schema:s.input_schema})))));o.length&&(n.agents=o)}function ga(n){return{authClient:(e,t)=>Hl(e,t,n),agent:(e,t)=>zl(e,t,n)}}function ha(n,e){n.addHook("onRequest",async t=>{let o=new URL(`http://127.0.0.1${t.url}`);t.pathname=o.pathname,(o.pathname.endsWith("/v1/messages")||o.pathname.endsWith("/v1/responses"))&&!t.requestStartTime&&(t.requestStartTime=Er.performance.now())}),n.addHook("preHandler",async(t,o)=>{let r=t.pathname||new URL(`http://127.0.0.1${t.url}`).pathname;r.endsWith("/v1/messages")||r.endsWith("/v1/responses")||await new Promise((s,i)=>{let l=a=>a?i(a):s();Ft(e)(t,o,l).then(()=>s(),i)})}),n.addHook("onError",async(t,o,r)=>{t.errorMessage=r?.message||r?.toString?.()||"Unknown error",da.emit("onError",t,o,r)}),n.addHook("onSend",(t,o,r,s)=>{(t.ccrHookOrder||=[]).push("onSend");let i=t.pathname?.endsWith("/v1/messages"),l=t.pathname?.endsWith("/v1/responses");if(i||l){ma(t,e);let a=Or(t),c=io(t);if(r instanceof ReadableStream){if(i&&t.agents){let y=new AbortController,p=r.pipeThrough(new ce),f,_=-1,k="",h="",b="",T=[],x=[];return s(null,St(p,async(v,S)=>{try{if(v.event==="content_block_start"&&v?.data?.content_block?.name){let C=t.agents.find(E=>so.getAgent(E)?.tools.get(v.data.content_block.name));if(C){f=so.getAgent(C),_=v.data.index,k=v.data.content_block.name,b=v.data.content_block.id;return}}if(_>-1&&v.data.index===_&&v.data?.delta?.type==="input_json_delta"){h+=v.data?.delta?.partial_json;return}if(_>-1&&v.data.index===_&&v.data?.type==="content_block_stop"){try{let C=fa.default.parse(h);x.push({type:"tool_use",id:b,name:k,input:C});let E=await f?.tools.get(k)?.handler(C,{req:t,config:e});T.push({tool_use_id:b,type:"tool_result",content:E}),f=void 0,_=-1,k="",h="",b=""}catch(C){console.log(C)}return}if(v.event==="message_delta"&&T.length){t.body.messages.push({role:"assistant",content:x}),t.body.messages.push({role:"user",content:T});let C=await fetch(`http://127.0.0.1:${e.PORT||3456}/v1/messages`,{method:"POST",headers:{"x-api-key":e.APIKEY,"content-type":"application/json"},body:JSON.stringify(t.body)});if(!C.ok)return;let R=C.body.pipeThrough(new ce).getReader();for(;;)try{let{value:A,done:O}=await R.read();if(O)break;let I=A;if(["message_start","message_stop"].includes(I.event))continue;if(!S.desiredSize)break;S.enqueue(I)}catch(A){if(A.name==="AbortError"||A.code==="ERR_STREAM_PREMATURE_CLOSE"){y.abort();break}throw A}return}return v}catch(C){if(console.error("Unexpected error in stream processing:",C),C.code==="ERR_STREAM_PREMATURE_CLOSE"){y.abort();return}throw C}}).pipeThrough(new Ae))}let[d,g]=r.tee(),m=async y=>{let f=y.pipeThrough(new TextDecoderStream).pipeThrough(new ce).getReader();try{for(;;){let{done:_,value:k}=await f.read();if(_)break;let h=k.event,b=k.data;if(h==="message_start"&&b?.message?.model&&(t.upstreamModel=b.message.model),h==="response.completed"&&b?.response?.model&&(t.upstreamModel=b.response.model),b?.usage){let T=q.get(c)||{},x=Me(b.usage),v=Nt(T,x,h==="message_start");t.log?.info?.({debug_log:!0,reqId:t.id,phase:"usage_capture_anthropic_sse",event:h,provider:t.provider,model:ot(t),usageSessionId:a,capturedUsage:x,mergedUsage:v}),(x?.cache_read_input_tokens||x?.cache_creation_input_tokens)&&console.log("[Usage] Cache tokens:",{cache_read:x?.cache_read_input_tokens,cache_creation:x?.cache_creation_input_tokens}),q.put(c,v)}if(b?.response?.usage){let T=Me(b.response.usage),x=q.get(c)||{},v=Nt(x,T,!1);t.log?.info?.({debug_log:!0,reqId:t.id,phase:"usage_capture_responses_sse",event:h,provider:t.provider,model:ot(t),usageSessionId:a,capturedUsage:T,mergedUsage:v}),q.put(c,v)}}}catch(_){_.name==="AbortError"||_.code==="ERR_STREAM_PREMATURE_CLOSE"?console.error("Background read stream closed prematurely"):console.error("Error in background stream reading:",_)}finally{f.releaseLock()}};return t.usageCapturePromise=m(g),s(null,d)}let u=jl(r);if(u?.usage&&q.put(c,u.usage),u?.model&&(t.upstreamModel=u.model),typeof r=="object")return r.error?s(r.error,null):s(r,null)}if(typeof r=="object"&&r.error)return s(r.error,null);s(null,r)}),n.addHook("onSend",async(t,o,r)=>{if(da.emit("onSend",t,o,r),o.statusCode>=400&&(t.pathname?.endsWith("/v1/messages")||t.pathname?.endsWith("/v1/responses")))try{typeof r=="string"?t.errorResponseBody=r:r&&typeof r=="object"&&(t.errorResponseBody=JSON.stringify(r))}catch{}return r}),n.addHook("onResponse",async(t,o)=>{if((t.ccrHookOrder||=[]).push("onResponse"),!(!t.pathname?.endsWith("/v1/messages")&&!t.pathname?.endsWith("/v1/responses")))try{t.usageCapturePromise&&await t.usageCapturePromise,t.tokenSpeedCapturePromise&&await t.tokenSpeedCapturePromise;let r=Or(t),s=o.statusCode>=400,i=s?void 0:q.get(io(t)),l=vr(r),a=U(),c,u,d=t.sseError,g=d&&(d.type||d.code||d.message),m=i?.output_tokens&&i.output_tokens>0,y=s||g&&!m;if(y){c=t.errorMessage||o.errorMessage||t.error?.message||t.error?.toString?.()||void 0,g&&(c=c||JSON.stringify(d),u=JSON.stringify(d)),u=u||t.errorResponseBody;let h=ot(t);Ul(o.statusCode,c)?a.markRateLimited(t.provider||"",h,120,c):a.recordFailure(t.provider||"",h,c)}else{let h=ot(t);a.recordSuccess(t.provider||"",h)}let p=i?.cache_read_input_tokens??0,_=i?.input_tokens||0||t.tokenCount||0;!p&&t.tokenCount&&i?.input_tokens&&i.input_tokens<t.tokenCount&&(p=t.tokenCount-i.input_tokens,p&&console.log("[Usage] Inferred cache tokens:",{tokenCount:t.tokenCount,netInput:i.input_tokens,impliedCache:p}));let k=y?0:i?.output_tokens||0;!y&&t.body?.stream&&_===0&&k===0&&t.log?.warn?.({debug_log:!0,reqId:t.id,phase:"usage_zero_stream",provider:t.provider,originalModel:t.originalModel||t.body?.model||"",model:ot(t),usageSessionId:r,tokenCount:t.tokenCount,cachedUsage:i,note:"Successful streaming request ended with zero usage. Check provider_stream_chunk usage_monitor and usage_capture_* logs."}),zt({id:`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date().toISOString(),sessionId:r,provider:t.provider||"",originalModel:t.originalModel||t.body?.model||"",model:ot(t),upstreamModel:t.upstreamModel,modelFamily:t.modelFamily||"",scenarioType:t.scenarioType||"default",clientType:t.clientType||Re(t),stream:t.body?.stream??!1,inputTokens:_,outputTokens:k,cacheReadInputTokens:p,cacheCreationInputTokens:i?.cache_creation_input_tokens||0,ttft:y?null:l.ttft,tokensPerSecond:y?null:l.tokensPerSecond,durationMs:t.requestStartTime?Math.round(Er.performance.now()-t.requestStartTime):0,status:y?"error":"success",errorMessage:c,responseBody:u}),t.clientContext?.usageScope!=="session"&&q.delete(io(t))}catch(r){console.error("Usage tracking error:",r)}})}var pa,Er,fa,da,ya=w(()=>{"use strict";pa=require("node:events"),Er=require("node:perf_hooks"),fa=Y(require("json5"),1);Ge();rn();ie();er();tr();nr();Jt();mr();ua();_r();mn();da=new pa.EventEmitter});var Ta={};Gt(Ta,{createCcrServer:()=>Bl});async function Bl(n={}){await Wi(),await Mt();let e=await Vn(),t=e.Providers||e.providers||[],o=t&&t.length>0,r=e.HOST||"127.0.0.1";o?(r=e.HOST,e.APIKEY||(r="127.0.0.1")):(r="0.0.0.0",console.log("\u2139\uFE0F No providers configured. Listening on 0.0.0.0 without authentication."));let s=n.port??e.PORT??3456,i=process.env.SERVICE_PORT?parseInt(process.env.SERVICE_PORT):s,l=p=>(p>9?"":"0")+p,a=(p,f)=>{let _;p?typeof p=="number"?_=new Date(p):_=p:_=new Date;let k=_.getFullYear()+""+l(_.getMonth()+1),h=l(_.getDate()),b=l(_.getHours()),T=l(_.getMinutes());return`./logs/ccr-${k}${h}${b}${T}${l(_.getSeconds())}${f?`_${f}`:""}.log`},c;n.logger!==void 0?c=n.logger:(Yi(),e.LOG!==!1?(e.LOG===void 0&&(e.LOG=!0),c={level:e.LOG_LEVEL||"error",stream:(0,ba.createStream)(a,{path:rt.HOME_DIR,interval:"1d",size:"50M",compress:!1})}):c=!1);let u=await(0,rt.listPresets)(),d=new Ar({jsonPath:rt.CONFIG_FILE,initialConfig:{providers:e.Providers||e.providers,HOST:r,PORT:i,LOG_FILE:(0,ka.join)((0,_a.homedir)(),".claude-code-router","claude-code-router.log")},logger:c});await d.ready(),await ra(d,e),d.recordUsage=p=>{try{let f=p.req?p.req.clientType||Re(p.req):"unknown";zt({id:`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,timestamp:new Date().toISOString(),sessionId:p.sessionId||"",provider:p.provider||"",originalModel:p.originalModel||"",model:p.model||"",modelFamily:p.modelFamily||"",scenarioType:p.scenarioType||"default",clientType:f,stream:p.stream??!1,inputTokens:p.inputTokens||0,outputTokens:0,cacheReadInputTokens:p.cacheReadInputTokens||0,cacheCreationInputTokens:p.cacheCreationInputTokens||0,ttft:null,tokensPerSecond:null,durationMs:0,status:"error",errorMessage:p.errorMessage,responseBody:void 0})}catch(f){console.error("Fallback usage tracking error:",f)}},ha(d,e),d.ccrPreHandlerCallbacks=ga(e),(await Promise.allSettled(u.map(async p=>await d.registerNamespace(`/preset/${p.name}`,p.config)))).forEach((p,f)=>{if(p.status==="rejected"){let _=u[f],k=p.reason instanceof Error?p.reason.message:String(p.reason);d.app?.log?.error?.(`Failed to register preset "${_?.name}": ${k}`)}}),await qi(d,e),tt(e,d.app?.log);let m=p=>{d.app.log.error({err:p},"Uncaught exception")},y=(p,f)=>{d.app.log.error({reason:p,promise:f},"Unhandled rejection")};return process.on("uncaughtException",m),process.on("unhandledRejection",y),d.app.addHook("onClose",async()=>{process.off("uncaughtException",m),process.off("unhandledRejection",y)}),d}var _a,ka,ba,rt,Ca=w(()=>{"use strict";_a=require("os"),ka=require("path");va();ba=require("rotating-file-stream"),rt=require("@wengine-ai/claude-code-router-shared");Gi();Yn();Xi();Zi();sa();ya();qn();Jt();Ge()});var Gl={};Gt(Gl,{ActiveProbeService:()=>vt,ConfigService:()=>ve,ProjectRoutingError:()=>ue,ProviderHealthStore:()=>lt,ProviderService:()=>de,SSEParserTransform:()=>ce,SSESerializerTransform:()=>Ae,TokenizerService:()=>Ee,TransformerService:()=>Pe,apiKeyAuth:()=>Ft,applyClientAdapter:()=>he,backupConfigFile:()=>$t,builtinClientAdapterRegistry:()=>wo,calculateTokenCount:()=>gt,clearClientAdapterCaches:()=>ds,clearProviderHealth:()=>Lt,closeProxyDispatchers:()=>Qt,collectReachableModelKeys:()=>hr,createCcrServer:()=>Ra,default:()=>Ar,detectClientType:()=>Re,diagnoseResolutionFailure:()=>Oo,extractSessionIdFromUserId:()=>We,getActiveProbeService:()=>qo,getAllQuotaResults:()=>an,getAllRateLimitInfo:()=>on,getClientAdapter:()=>Eo,getConfiguredProxyUrl:()=>st,getHealthStore:()=>U,getProxyDispatcher:()=>Q,getQuotaAdapter:()=>Wn,getQuotaResult:()=>dt,getRateLimitInfo:()=>rs,getRuntimeDebugLog:()=>at,getServer:()=>Wl,initConfig:()=>Vn,initDir:()=>Mt,initProviderHealthPersistence:()=>nn,initQuotaStorePersistence:()=>Be,initRateLimitPersistence:()=>Ue,isClientType:()=>Po,isGlobalProxyEnabled:()=>ao,listAnthropicCompatibleModels:()=>Dt,mergeUsageCapture:()=>Nt,normalizeSessionId:()=>Se,normalizeUsagePayload:()=>Me,pluginManager:()=>qe,readConfigFile:()=>oe,readConfigFileRaw:()=>Qn,reconcileHealthStore:()=>tt,resetActiveProbeService:()=>xt,resolveProviderProxyUrl:()=>le,rewriteStream:()=>St,router:()=>yt,searchProjectBySession:()=>Io,sessionUsageCache:()=>q,setRuntimeDebugLog:()=>Yt,startActiveProbe:()=>Oe,stopActiveProbe:()=>Gn,storeQuotaResult:()=>sn,tokenSpeedPlugin:()=>At,usageStore:()=>xr,writeConfigFile:()=>Ie});module.exports=$r(Gl);function Jl(n={}){let e=(0,xa.default)({bodyLimit:52428800,...n});return e.setErrorHandler(jr),e.register(Sa.default),e}async function Ra(n={}){return(await Promise.resolve().then(()=>(Ca(),Ta))).createCcrServer(n)}var xa,Sa,Ir,Ar,Wl,va=w(()=>{xa=Y(require("fastify"),1),Sa=Y(require("@fastify/cors"),1);lo();Vt();mn();gn();Lo();Do();Ve();rn();Kn();ie();je();Je();se();Ge();mn();pt();Ge();Ve();lo();gn();Lo();Do();dr();or();ie();je();Yo();Je();ie();Kn();ct();se();Yn();mr();qn();yr();_r();Jt();Ir=class{app;configService;providerService;transformerService;tokenizerService;activeProbeService;recordUsage;readiness;mainNamespaceRegistered=!1;signalHandlersRegistered=!1;ccrPreHandlerCallbacks;constructor(e={}){let{initialConfig:t,jsonPath:o,envPath:r,useEnvFile:s,useJsonFile:i,useEnvironmentVariables:l,...a}=e;this.app=Jl({...a,logger:a.logger??!0}),this.app._server=this;let c={initialConfig:t};o!==void 0&&(c.jsonPath=o),r!==void 0&&(c.envPath=r),s!==void 0&&(c.useEnvFile=s),i!==void 0&&(c.useJsonFile=i),l!==void 0&&(c.useEnvironmentVariables=l),this.configService=new ve(c),this.transformerService=new Pe(this.configService,this.app.log),this.tokenizerService=new Ee(this.configService,this.app.log),this.readiness=(async()=>{await Promise.all([this.transformerService.initialize(),this.tokenizerService.initialize()]),this.providerService=new de(this.configService,this.transformerService,this.app.log)})()}async ready(){await this.readiness}async register(e,t){await this.app.register(e,t)}addHook(e,t){this.app.addHook(e,t)}async registerNamespace(e,t){if(!e)throw new Error("name is required");if(await this.ready(),e==="/"&&this.mainNamespaceRegistered)return;let o=this.configService,r=this.transformerService,s=this.providerService,i=this.tokenizerService;if(e!=="/"){if(!t)throw new Error("options is required");o=new ve({initialConfig:{...t,providers:t.Providers||t.providers}}),r=new Pe(o,this.app.log),i=new Ee(o,this.app.log),await Promise.all([r.initialize(),i.initialize()]),s=new de(o,r,this.app.log)}let l=async a=>{a.decorate("configService",o),a.decorate("transformerService",r),a.decorate("providerService",s),a.decorate("tokenizerService",i),a.decorate("recordUsage",this.recordUsage||(()=>{})),a.addHook("preHandler",async(c,u)=>{let d=new URL(`http://127.0.0.1${c.url}`);c.pathname=d.pathname;let g=d.pathname.endsWith("/v1/messages"),m=d.pathname.endsWith("/v1/responses");if(!g&&!m||!c.body||typeof c.body!="object")return;let y=c.ccrHookOrder||=[];if(y.push("request-normalize"),m&&c.body.input&&!c.body.messages&&_t(c.body),c.body.stream===void 0&&(c.body.stream=!1),c.log.info({data:c.body,type:"request body"}),y.push("adapter"),!c.originalModel&&c.body.model&&(c.originalModel=c.body.model),he(c,o.getAll()),y.push("auth-client"),!(this.ccrPreHandlerCallbacks&&(await this.ccrPreHandlerCallbacks.authClient(c,u),u.sent))&&(y.push("agent"),!(this.ccrPreHandlerCallbacks&&(await this.ccrPreHandlerCallbacks.agent(c,u),u.sent)))){y.push("router"),c.body?.model&&await yt(c,u,{configService:o,tokenizerService:i}),c.usageCacheKey&&q.put(c.usageCacheKey,{input_tokens:0,output_tokens:0,cache_read_input_tokens:0,cache_creation_input_tokens:0}),y.push("provider-model-normalize");try{let p=c.body;if(!p||!p.model)return u.code(400).send({error:"Missing model in request body"});let f=p.model.split(","),_=p.model;if(f.length>1){let[k,...h]=f;_=h.join(","),p.model=_,c.provider=k}c.model=_}catch(p){return c.log.error({error:p},"Error in modelProviderMiddleware:"),u.code(500).send({error:"Internal server error"})}}}),await Ss(a)};e==="/"?(await this.app.register(l),this.mainNamespaceRegistered=!0):await this.app.register(l,{prefix:e})}async start(){try{if(await this.ready(),await this.registerNamespace("/"),!this.signalHandlersRegistered){this.signalHandlersRegistered=!0;let t=async s=>{this.app.log.info(`Received ${s}, shutting down gracefully...`);try{Gn()}catch{}await this.app.close(),process.exit(0)},o=()=>void t("SIGINT"),r=()=>void t("SIGTERM");process.on("SIGINT",o),process.on("SIGTERM",r),this.app.addHook("onClose",async()=>{process.off("SIGINT",o),process.off("SIGTERM",r),this.signalHandlersRegistered=!1;try{this.tokenizerService.dispose()}catch{}await Qt()})}await this.app.ready();let e=await this.app.listen({port:parseInt(this.configService.get("PORT")||"3000",10),host:this.configService.get("HOST")||"127.0.0.1"});this.app.log.info(`\u{1F680} LLMs API server listening on ${e}`);try{Ue()}catch{}try{Be()}catch{}try{nn()}catch{}try{let t={enabled:this.configService.get("ACTIVE_PROBE_ENABLED")??!0,quotaProbeIntervalMinutes:this.configService.get("QUOTA_PROBE_INTERVAL_MINUTES")??10,probeTimeoutMs:this.configService.get("PROBE_TIMEOUT_MS")??15e3,slowThresholdMs:Number(this.configService.get("PROBE_SLOW_THRESHOLD_MS"))||3e3,initialDelayMs:this.configService.get("PROBE_INITIAL_DELAY_MS")??5e3,excludeProviders:this.configService.get("EXCLUDE_PROBE_PROVIDERS")??[]};this.activeProbeService=Oe(()=>this.providerService.getProviders(),t,o=>le(this.configService,o),this.app.log,o=>this.configService.get(o))}catch(t){this.app.log.warn?.(`Failed to start active probe service: ${t.message}`)}}catch(e){this.app.log.error(`Error starting server: ${e}`),process.exit(1)}}},Ar=Ir;Wl=Ra});va();0&&(module.exports={ActiveProbeService,ConfigService,ProjectRoutingError,ProviderHealthStore,ProviderService,SSEParserTransform,SSESerializerTransform,TokenizerService,TransformerService,apiKeyAuth,applyClientAdapter,backupConfigFile,builtinClientAdapterRegistry,calculateTokenCount,clearClientAdapterCaches,clearProviderHealth,closeProxyDispatchers,collectReachableModelKeys,createCcrServer,detectClientType,diagnoseResolutionFailure,extractSessionIdFromUserId,getActiveProbeService,getAllQuotaResults,getAllRateLimitInfo,getClientAdapter,getConfiguredProxyUrl,getHealthStore,getProxyDispatcher,getQuotaAdapter,getQuotaResult,getRateLimitInfo,getRuntimeDebugLog,getServer,initConfig,initDir,initProviderHealthPersistence,initQuotaStorePersistence,initRateLimitPersistence,isClientType,isGlobalProxyEnabled,listAnthropicCompatibleModels,mergeUsageCapture,normalizeSessionId,normalizeUsagePayload,pluginManager,readConfigFile,readConfigFileRaw,reconcileHealthStore,resetActiveProbeService,resolveProviderProxyUrl,rewriteStream,router,searchProjectBySession,sessionUsageCache,setRuntimeDebugLog,startActiveProbe,stopActiveProbe,storeQuotaResult,tokenSpeedPlugin,usageStore,writeConfigFile});
|
|
420
420
|
//# sourceMappingURL=server.cjs.map
|