@wengine-ai/llms 2.3.2400 → 2.3.2401

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/README.md CHANGED
@@ -93,6 +93,7 @@ npm install -g @wengine-ai/claude-code-router-next@latest && ccr restart
93
93
 
94
94
  | 版本 | 发布内容 |
95
95
  | --- | --- |
96
+ | **v2.3.2401** | <ul><li>**formatResponse SSE 识别放宽**: 之前仅对 `application/json` 头 peek,上游用非标准 Content-Type(`text/plain`/空)返回 SSE 仍会报 non-JSON;现对任何非流式响应都先 peek 判 SSE。</li></ul> |
96
97
  | **v2.3.2400** | <ul><li>**SSE 误标 JSON 的多层彻底修复**: v2.3.2397–2399 只看首个 chunk,遇空首块/心跳(`: ping`)/分片(`ev`/`ent:`)仍误判报错;现改为累积多 chunk 判定,并统一修复 formatResponse、两个 transformer、hidden-error-check 与 validateStreamingResponse 四处,误标 SSE 全部按流式透传。</li></ul> |
97
98
  | **v2.3.2399** | <ul><li>**bypass 模式下 SSE 误标 application/json 兜底修复**: bypass 的 provider 跳过 transformer 链后,SSE body + JSON 头的响应直达 formatResponse 仍会抛 non-JSON;现在 formatResponse 先 peek body 实际内容,SSE 按流式透传,作为该问题的最后一层兜底。</li></ul> |
98
99
  | **v2.3.2398** | <ul><li>**修复 Codex 中转 SSE 被误标 application/json 时丢失内容**: 补齐 v2.3.2397 漏掉的 `OpenAIResponsesTransformer` 同类问题——上游返回 SSE body 但 Content-Type 标 `application/json` 时不再抛 `non-JSON` 错误,改为 peek body 实际内容后按 SSE 透传。</li></ul> |
@@ -102,7 +103,6 @@ npm install -g @wengine-ai/claude-code-router-next@latest && ccr restart
102
103
  | **v2.3.2394** | <ul><li>**严格项目路由不再因熔断目标返回 503**: 项目目标仅因 health fail-pool 不可用且无备用模型时,CCR 跳过健康检查继续请求项目配置的同一模型,让客户端收到真实上游结果;供应商/模型缺失、禁用、格式或额度错误仍拒绝,不逃逸项目边界。</li><li>**修复非流式 TTFT 与 token 速率统计**: 非流式响应不再把总耗时冒充 TTFT(显示 `-`),速率改为输出 token ÷ 总耗时,并阻止假 TTFT 污染平均值。</li></ul> |
103
104
  | **v2.3.2393** | <ul><li>**项目接管按项目 Router 封顶上下文窗口**: 项目级接管此前只按全局 Router/ContextWindow 写 auto-compact 窗口,全局开 `[1m]` 而项目未启用扩展上下文时项目仍带 >200k 窗口,超 200k 后无可用模型;现在项目默认 family 或顶层 `enableExtendedContext` 未启用时窗口封顶 `min(ContextWindow, 200000)` 并清除陈旧 `[1m]` alias,保存项目 Router 与全局配置后都会刷新自定义 Router 项目的接管。用户手写窗口与 state 审计行为不变。</li><li>**opencode go 缓存命中从 0% 恢复**: zen 上游的提示词缓存以显式 `cache_control` 为前提(实测带标记第 2 次起 ≈98% 命中),transformer 此前把标记全部剥除导致永不缓存;现在保留标记,并在 `cached_tokens` 缺失时兜底映射 DeepSeek 风格 `prompt_cache_hit_tokens`。</li></ul> |
104
105
  | **v2.3.2392** | <ul><li>**用量按日统计按本地时区分组**: `byDay` 此前取 UTC 日期,本地 0:00–8:00 的请求(UTC 仍是昨天)被归到前一天——表现为「过了零点后昨天的消耗还在涨、今天的偏少」;改用 `date(timestamp,'localtime')` 按进程时区分组,历史记录无需迁移即自动重新归类。</li></ul> |
105
- | **v2.3.239** | <ul><li>**供应商慢网探测与黄色 ⚠️ 告警**: 后台对每个供应商的 `/models` 可达性探测现在记录延迟,超过 `PROBE_SLOW_THRESHOLD_MS`(默认 3000ms)在 provider 卡片显示黄色 ⚠️;`GET /api/providers/health` 追加 `probes`,手动探测返回 latency/status/isSlow。慢但成功不开熔断,仅作 UI 提示。</li><li>**用量汇总改 SQL 聚合,UI 不再随机卡顿**: `/api/providers/quota`、`/api/usage` 的 summary 此前 `SELECT *` 全量物化 + JS 聚合阻塞 event loop,是 health/quota 随机卡顿的共享根因;改为 SQL `COUNT/SUM/AVG/GROUP BY`,语义不变。</li><li>**UI 刷新循环重做,杜绝请求重叠**: Providers health/quota 改 60s 自调度 single-flight;Usage 改 30s 串行队列(上一个未返回下一个顺延);`/api/clients` 仅 mount 刷新(操作后复用响应、不再 visibility 补拉);页面隐藏时暂停。</li><li>**Image 路由根因修复**: image agent 此前在路由前改写 `req.body.model`,导致用量记录丢失客户端真实模型(如 ccr-opus)并绕过 family image 路由;现按客户端原始模型识别 family 路由图片。同时修复 `promoteToolResultImages` 把所有数组型 tool_result 内容替换为占位符、丢失文本/结构化内容的问题。</li><li>**移除已弃用的 Codex 多账号管理**: 删除账号列表、切换、后台自动维护及对应 API/CLI/UI;Codex 仍作为普通 provider/client 完整支持(检测、`/v1/responses`、transformer、takeover、用量归属),历史账号文件与 `~/.codex/auth.json` 保持不动。</li><li>**路由优先级:模型族优先于 explicit `provider,model`**: 开启 family routing 时请求先走模型族映射,命中即用;family 未命中才解析客户端显式指定,最后落默认路由。</li></ul> |
106
106
 
107
107
  > 仅保留最近 10 个版本,更早版本的发布摘要见 [CHANGELOG-archive.md](./CHANGELOG-archive.md),完整详细变更记录见 [CHANGELOG.md](./CHANGELOG.md)。
108
108
 
@@ -1,6 +1,6 @@
1
1
  "use strict";var $a=Object.create;var Yt=Object.defineProperty;var Na=Object.getOwnPropertyDescriptor;var La=Object.getOwnPropertyNames;var Da=Object.getPrototypeOf,Fa=Object.prototype.hasOwnProperty;var w=(n,e)=>()=>(n&&(e=n(n=0)),e);var Xt=(n,e)=>{for(var t in e)Yt(n,t,{get:e[t],enumerable:!0})},Fr=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of La(e))!Fa.call(n,r)&&r!==t&&Yt(n,r,{get:()=>e[r],enumerable:!(o=Na(e,r))||o.enumerable});return n};var X=(n,e,t)=>(t=n!=null?$a(Da(n)):{},Fr(e||!n||!n.__esModule?Yt(t,"default",{value:n,enumerable:!0}):t,n)),Ur=n=>Fr(Yt({},"__esModule",{value:!0}),n);function ja(n){if(n==null)return{ok:!0};let e=String(n).trim();if(!e)return{ok:!0};if(Ua.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 zr(n){let e=[];for(let t of Hr){let o=n[t];if(o==null)continue;let r=ja(o);r.ok||e.push({key:t,error:r.error})}return e}function lt(n){for(let e of Hr){let t=n.get(e);if(t==null)continue;let o=String(t).trim();if(o)return o}}function fo(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 de(n,e){let t=lt(n);if(t)return fo(n.get("PROXY_GLOBAL_ENABLED"))||e?.proxyEnabled===!0||e?.proxy_enabled===!0?t:void 0}function V(n){let e=Ha(n),t=qt.get(e);if(t)return t;let o=new jr.ProxyAgent(e);return qt.set(e,o),o}async function Zt(){let n=Array.from(qt.values());qt.clear(),await Promise.allSettled(n.map(e=>e.close()))}function Ha(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 jr,Hr,Ua,qt,ae=w(()=>{"use strict";jr=require("undici"),Hr=["HTTPS_PROXY","https_proxy","httpsProxy","PROXY_URL"],Ua=/\$\{[^}]+\}|\$[A-Z_][A-Z0-9_]*/;qt=new Map});var ut,mo,Jr,Br,Se,go=w(()=>{"use strict";ut=require("fs"),mo=require("path"),Jr=require("dotenv"),Br=X(require("json5"),1);ae();Se=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,mo.join)(process.cwd(),this.options.jsonPath);if((0,ut.existsSync)(e))try{let t=(0,ut.readFileSync)(e,"utf-8"),o=Br.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,mo.join)(process.cwd(),this.options.envPath);if((0,ut.existsSync)(e))try{let t=(0,Jr.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 lt(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 K(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 Wr(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 en=w(()=>{"use strict"});function tn(n){ho=n}function dt(){return ho}function nn(n){return ho||n.get("DEBUG_LOG")===!0}function Qr(n){let e=n.get("DEBUG_LOG_OPTIONS");return!e||typeof e!="object"?Fe:{maxBodyLength:e.maxBodyLength??Fe.maxBodyLength,maxStreamChunks:e.maxStreamChunks??Fe.maxStreamChunks}}function on(n){let e={};for(let[t,o]of Object.entries(n))za.has(t.toLowerCase())?e[t]="***MASKED***":e[t]=o;return e}function rn(n,e){return n.length<=e?n:n.slice(0,e)+`...[truncated, total ${n.length} bytes]`}function Vr(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:on(t.headers),body:rn(o,Fe.maxBodyLength)})}function Yr(n,e,t){n.info({debug_log:!0,reqId:e,phase:"provider_response",status:t.status,headers:on(t.headers),...t.body!==void 0?{body:rn(t.body,Fe.maxBodyLength)}:{}})}function Gr(n,e,t,o){let r=Ja(o);n.info({debug_log:!0,reqId:e,phase:"provider_stream_chunk",chunkIndex:t,...r?{usage_monitor:r}:{},data:rn(o,Fe.maxBodyLength)})}function Ja(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:rn(o,512)})}}if(e.length)return e.length===1?e[0]:e}function Kr(n,e,t){n.info({debug_log:!0,reqId:e,phase:"provider_stream_end",totalChunks:t})}function Xr(n,e,t,o){(async()=>{let r=n.pipeThrough(new TextDecoderStream).getReader(),s=0;try{let i="";for(;;){let{done:l,value:c}=await r.read();if(l)break;i+=c;let a=i.split(`
2
2
 
3
- `);i=a.pop()||"";for(let u of a)u.trim()&&(s<o.maxStreamChunks?Gr(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&&Gr(e,t,s,i.trim()),s++),Kr(e,t,s)}catch(i){console.error(`[debug_log] Error reading debug stream for reqId=${t}:`,i),Kr(e,t,s)}finally{r.releaseLock()}})()}var za,Fe,ho,pt=w(()=>{"use strict";za=new Set(["authorization","x-api-key","x-goog-api-key","cookie","set-cookie"]),Fe={maxBodyLength:4096,maxStreamChunks:100},ho=!1});function qr(n,e,t,o,r){let s=new Headers({"Content-Type":"application/json"});t.headers&&Object.entries(t.headers).forEach(([a,u])=>{u&&s.set(a,u)});let i,l=AbortSignal.timeout(t.TIMEOUT??60*1e3*60);if(t.signal){let a=new AbortController,u=()=>a.abort();t.signal.addEventListener("abort",u),l.addEventListener("abort",u),i=a.signal}else i=l;let c={method:"POST",headers:s,body:JSON.stringify(e),signal:i};return t.httpsProxy&&(c.dispatcher=V(t.httpsProxy)),r?.debug({reqId:o.req.id,method:"POST",headers:on(Object.fromEntries(s.entries())),requestUrl:typeof n=="string"?n:n.toString(),useProxy:Ba(t.httpsProxy)},"final request"),fetch(typeof n=="string"?n:n.toString(),c)}function Ba(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 Zr=w(()=>{ae();pt()});var sn,yo=w(()=>{sn="2.3.2400"});var es={};Xt(es,{getFallbackPromotionStore:()=>Ue,resetFallbackPromotionStore:()=>Ka});function Ue(n){return Re||(Re=new _o,n&&Re.configure(n)),Re}function Ka(){Re&&(Re.clearAll(),Re=null)}var Ga,_o,Re,an=w(()=>{"use strict";ce();Ga=600*1e3,_o=class{promotions=new Map;enabled=!0;ttlMs=Ga;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),c=`${r},${s}`;this.promotions.set(l,{promotedModel:c,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[c,...a]=i.promotedModel.split(","),u=a.join(",");if(!j().isAvailable(c,u))return this.promotions.delete(s),null;let g=r.find(y=>y.name.toLowerCase()===c.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}},Re=null});function Xa(n){try{if(!(0,me.existsSync)(To))return;let e=JSON.parse((0,me.readFileSync)(To,"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 ns(n){try{let e=n.getAllStates();if(e.length===0)return;(0,me.existsSync)(bo)||(0,me.mkdirSync)(bo,{recursive:!0});let t=e.map(o=>({...o,updatedAt:Date.now()}));(0,me.writeFileSync)(To,JSON.stringify(t,null,2),"utf-8")}catch{}}function cn(){if(ts)return;ts=!0;let n=j();Xa(n),Ya=setInterval(()=>ns(n),6e4),process.on("exit",()=>ns(n))}function j(n){return ko||(ko=new ft(n)),ko}var me,Co,os,Qa,Va,ft,bo,To,ts,Ya,ko,ce=w(()=>{"use strict";me=require("fs"),Co=require("path"),os=require("@wengine-ai/claude-code-router-shared"),Qa=120,Va={enabled:!0,failureThreshold:3,probeIntervalMinutes:5,halfOpenSuccessThreshold:2},ft=class{states=new Map;config;probeTimer;constructor(e){this.config={...Va,...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}=(an(),Ur(es));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??Qa)*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)}},bo=(0,Co.join)(os.HOME_DIR,"runtime"),To=(0,Co.join)(bo,"provider-health.json"),ts=!1,Ya=null;ko=null});function mt(n,e,t){let o=l=>{if(t instanceof Headers)return t.get(l);let c=Object.keys(t).find(a=>a.toLowerCase()===l);return c?t[c]:null},r=vo(o,qa),s=vo(o,Za),i=vo(o,ec);(r||s||i)&&je.set(n,{provider:n,remaining:is(r),limit:is(s),reset:tc(i),capturedAt:Date.now()})}function ls(n){return je.get(n)}function ln(){return Array.from(je.values())}function vo(n,e){for(let t of e){let o=n(t);if(o)return o}return null}function is(n){if(!n)return null;let e=Number(n.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function tc(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=nc(e);return r===null?null:Math.floor((Date.now()+r)/1e3)}function nc(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 oc(){try{if(!(0,ge.existsSync)(So))return;let n=JSON.parse((0,ge.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>3600*1e3)continue;je.set(t.provider,t)}}catch{}}function as(){try{if(je.size===0)return;(0,ge.existsSync)(xo)||(0,ge.mkdirSync)(xo,{recursive:!0}),(0,ge.writeFileSync)(So,JSON.stringify(Array.from(je.values()),null,2),"utf-8")}catch{}}function He(){rs||(rs=!0,oc(),ss=setInterval(as,6e4),ss.unref?.(),process.on("exit",as))}var ge,Ro,cs,xo,So,je,rs,ss,qa,Za,ec,ze=w(()=>{"use strict";ge=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,"rate-limit.json"),je=new Map,rs=!1,ss=null,qa=["x-ratelimit-remaining-tokens","x-ratelimit-remaining-requests","x-ratelimit-remaining"],Za=["x-ratelimit-limit-tokens","x-ratelimit-limit-requests","x-ratelimit-limit"],ec=["x-ratelimit-reset-tokens","x-ratelimit-reset-requests","x-ratelimit-reset"]});async function U(n){let e=await n.text();return rc(e,n.status)}function rc(n,e){let t=n.replace(/^/,"").trim();try{return JSON.parse(t)}catch{let o=t.length>200?`${t.slice(0,200)}...`:t,r=e!==void 0?` (HTTP ${e})`:"";throw new Error(`Upstream returned a non-JSON response${r}: ${o||"(empty body)"}`)}}function us(n){return(n.headers.get("Content-Type")||"").includes("text/event-stream")}function gt(n){return/^\s*(event:|data:|:\s*[A-Z])/m.test(n)||n.startsWith("data:")}async function Je(n){if(!n.body||n.body.locked)return null;let[e,t]=n.body.tee(),o=e.getReader(),r=new TextDecoder,s="";try{for(let i=0;i<8;i++){let{value:l,done:c}=await o.read();if(c||(l&&(s+=r.decode(l,{stream:!0})),gt(s))||/^\s*[\[{]/.test(s))break}s+=r.decode()}finally{o.releaseLock()}return e.cancel().catch(()=>{}),{body:t,isSSE:gt(s)}}async function Be(n){try{let e=await n.text();if(gt(e)){let o=new TextEncoder,r=new ReadableStream({start(s){s.enqueue(o.encode(e)),s.close()}});return{response:new Response(r,{status:n.status,statusText:n.statusText,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}),isSSE:!0}}return{response:new Response(e,{status:n.status,statusText:n.statusText,headers:n.headers}),isSSE:!1}}catch{return{response:n,isSSE:!1}}}var Z=w(()=>{"use strict"});var We,wo=w(()=>{"use strict";Z();We=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 Je(e);if(o?.isSSE&&o.body){let r=new Response(o.body,{status:e.status,statusText:e.statusText,headers:new Headers({...Object.fromEntries(e.headers.entries()),"content-type":"text/event-stream"})});return this.transformResponseOut(r)}if(o?.body)e=new Response(o.body,{status:e.status,statusText:e.statusText,headers:e.headers});else if(o===null){let r=await Be(e);if(r.isSSE)return this.transformResponseOut(r.response);e=r.response}}if(t.includes("application/json")){let o=await U(e);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 a=this.prependToStream(i,r),u=new TextDecoder,d=new TextEncoder,g="",m=!1,y=this,p=new ReadableStream({async start(f){let _=a.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=a.pop()||"";for(let u of a)u.trim()&&(s<o.maxStreamChunks?Gr(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&&Gr(e,t,s,i.trim()),s++),Kr(e,t,s)}catch(i){console.error(`[debug_log] Error reading debug stream for reqId=${t}:`,i),Kr(e,t,s)}finally{r.releaseLock()}})()}var za,Fe,ho,pt=w(()=>{"use strict";za=new Set(["authorization","x-api-key","x-goog-api-key","cookie","set-cookie"]),Fe={maxBodyLength:4096,maxStreamChunks:100},ho=!1});function qr(n,e,t,o,r){let s=new Headers({"Content-Type":"application/json"});t.headers&&Object.entries(t.headers).forEach(([a,u])=>{u&&s.set(a,u)});let i,l=AbortSignal.timeout(t.TIMEOUT??60*1e3*60);if(t.signal){let a=new AbortController,u=()=>a.abort();t.signal.addEventListener("abort",u),l.addEventListener("abort",u),i=a.signal}else i=l;let c={method:"POST",headers:s,body:JSON.stringify(e),signal:i};return t.httpsProxy&&(c.dispatcher=V(t.httpsProxy)),r?.debug({reqId:o.req.id,method:"POST",headers:on(Object.fromEntries(s.entries())),requestUrl:typeof n=="string"?n:n.toString(),useProxy:Ba(t.httpsProxy)},"final request"),fetch(typeof n=="string"?n:n.toString(),c)}function Ba(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 Zr=w(()=>{ae();pt()});var sn,yo=w(()=>{sn="2.3.2401"});var es={};Xt(es,{getFallbackPromotionStore:()=>Ue,resetFallbackPromotionStore:()=>Ka});function Ue(n){return Re||(Re=new _o,n&&Re.configure(n)),Re}function Ka(){Re&&(Re.clearAll(),Re=null)}var Ga,_o,Re,an=w(()=>{"use strict";ce();Ga=600*1e3,_o=class{promotions=new Map;enabled=!0;ttlMs=Ga;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),c=`${r},${s}`;this.promotions.set(l,{promotedModel:c,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[c,...a]=i.promotedModel.split(","),u=a.join(",");if(!j().isAvailable(c,u))return this.promotions.delete(s),null;let g=r.find(y=>y.name.toLowerCase()===c.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}},Re=null});function Xa(n){try{if(!(0,me.existsSync)(To))return;let e=JSON.parse((0,me.readFileSync)(To,"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 ns(n){try{let e=n.getAllStates();if(e.length===0)return;(0,me.existsSync)(bo)||(0,me.mkdirSync)(bo,{recursive:!0});let t=e.map(o=>({...o,updatedAt:Date.now()}));(0,me.writeFileSync)(To,JSON.stringify(t,null,2),"utf-8")}catch{}}function cn(){if(ts)return;ts=!0;let n=j();Xa(n),Ya=setInterval(()=>ns(n),6e4),process.on("exit",()=>ns(n))}function j(n){return ko||(ko=new ft(n)),ko}var me,Co,os,Qa,Va,ft,bo,To,ts,Ya,ko,ce=w(()=>{"use strict";me=require("fs"),Co=require("path"),os=require("@wengine-ai/claude-code-router-shared"),Qa=120,Va={enabled:!0,failureThreshold:3,probeIntervalMinutes:5,halfOpenSuccessThreshold:2},ft=class{states=new Map;config;probeTimer;constructor(e){this.config={...Va,...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}=(an(),Ur(es));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??Qa)*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)}},bo=(0,Co.join)(os.HOME_DIR,"runtime"),To=(0,Co.join)(bo,"provider-health.json"),ts=!1,Ya=null;ko=null});function mt(n,e,t){let o=l=>{if(t instanceof Headers)return t.get(l);let c=Object.keys(t).find(a=>a.toLowerCase()===l);return c?t[c]:null},r=vo(o,qa),s=vo(o,Za),i=vo(o,ec);(r||s||i)&&je.set(n,{provider:n,remaining:is(r),limit:is(s),reset:tc(i),capturedAt:Date.now()})}function ls(n){return je.get(n)}function ln(){return Array.from(je.values())}function vo(n,e){for(let t of e){let o=n(t);if(o)return o}return null}function is(n){if(!n)return null;let e=Number(n.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function tc(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=nc(e);return r===null?null:Math.floor((Date.now()+r)/1e3)}function nc(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 oc(){try{if(!(0,ge.existsSync)(So))return;let n=JSON.parse((0,ge.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>3600*1e3)continue;je.set(t.provider,t)}}catch{}}function as(){try{if(je.size===0)return;(0,ge.existsSync)(xo)||(0,ge.mkdirSync)(xo,{recursive:!0}),(0,ge.writeFileSync)(So,JSON.stringify(Array.from(je.values()),null,2),"utf-8")}catch{}}function He(){rs||(rs=!0,oc(),ss=setInterval(as,6e4),ss.unref?.(),process.on("exit",as))}var ge,Ro,cs,xo,So,je,rs,ss,qa,Za,ec,ze=w(()=>{"use strict";ge=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,"rate-limit.json"),je=new Map,rs=!1,ss=null,qa=["x-ratelimit-remaining-tokens","x-ratelimit-remaining-requests","x-ratelimit-remaining"],Za=["x-ratelimit-limit-tokens","x-ratelimit-limit-requests","x-ratelimit-limit"],ec=["x-ratelimit-reset-tokens","x-ratelimit-reset-requests","x-ratelimit-reset"]});async function U(n){let e=await n.text();return rc(e,n.status)}function rc(n,e){let t=n.replace(/^/,"").trim();try{return JSON.parse(t)}catch{let o=t.length>200?`${t.slice(0,200)}...`:t,r=e!==void 0?` (HTTP ${e})`:"";throw new Error(`Upstream returned a non-JSON response${r}: ${o||"(empty body)"}`)}}function us(n){return(n.headers.get("Content-Type")||"").includes("text/event-stream")}function gt(n){return/^\s*(event:|data:|:\s*[A-Z])/m.test(n)||n.startsWith("data:")}async function Je(n){if(!n.body||n.body.locked)return null;let[e,t]=n.body.tee(),o=e.getReader(),r=new TextDecoder,s="";try{for(let i=0;i<8;i++){let{value:l,done:c}=await o.read();if(c||(l&&(s+=r.decode(l,{stream:!0})),gt(s))||/^\s*[\[{]/.test(s))break}s+=r.decode()}finally{o.releaseLock()}return e.cancel().catch(()=>{}),{body:t,isSSE:gt(s)}}async function Be(n){try{let e=await n.text();if(gt(e)){let o=new TextEncoder,r=new ReadableStream({start(s){s.enqueue(o.encode(e)),s.close()}});return{response:new Response(r,{status:n.status,statusText:n.statusText,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}),isSSE:!0}}return{response:new Response(e,{status:n.status,statusText:n.statusText,headers:n.headers}),isSSE:!1}}catch{return{response:n,isSSE:!1}}}var Z=w(()=>{"use strict"});var We,wo=w(()=>{"use strict";Z();We=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 Je(e);if(o?.isSSE&&o.body){let r=new Response(o.body,{status:e.status,statusText:e.statusText,headers:new Headers({...Object.fromEntries(e.headers.entries()),"content-type":"text/event-stream"})});return this.transformResponseOut(r)}if(o?.body)e=new Response(o.body,{status:e.status,statusText:e.statusText,headers:e.headers});else if(o===null){let r=await Be(e);if(r.isSSE)return this.transformResponseOut(r.response);e=r.response}}if(t.includes("application/json")){let o=await U(e);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 a=this.prependToStream(i,r),u=new TextDecoder,d=new TextEncoder,g="",m=!1,y=this,p=new ReadableStream({async start(f){let _=a.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
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 P=C.slice(5).trim();if(P==="[DONE]"){m=!0,f.enqueue(d.encode(`data: [DONE]
6
6
 
@@ -42,7 +42,7 @@ data: ${JSON.stringify(L)}
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 Ss(n,e,t,o){let r=n.body;(n.ccrHookOrder||=[]).push("handler"),o.endPoint==="/v1/responses"&&r?.input&&!r?.messages&&vt(r),o.endPoint==="/v1/responses"&&!n.provider&&typeof r?.model=="string"&&Ec.test(r.model)&&await Ct(n,e,{configService:t.configService,tokenizerService:t.tokenizerService});let s=n.provider;if(!s&&r?.model){let a=r.model.split(",");a.length>1&&(s=a[0],r.model=a.slice(1).join(","))}let i=s?t.providerService.getProvider(s):void 0;if(!i&&r?.model){let a=t.providerService.resolveModelRoute(r.model);a&&(i=a.provider,r.model=a.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 K(`Provider '${s}' not found`,404,"provider_not_found");n.provider=i.name||s;let l=Ic(n),c=o.endPoint==="/v1/messages"&&l;l&&e.header("X-Codex-Detected","true"),c&&e.header("X-Codex-On-Messages","true"),n.isCodexOnMessagesEndpoint=c,n.codexDetected=l;try{o.endPoint==="/v1/responses"&&r.input&&!r.messages&&vt(r);let{requestBody:a,config:u,bypass:d}=await ws(r,i,o,n.headers,{req:n});if(a?.messages&&!d&&!n.isTargetAnthropic){let p=a.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&&(a.messages=[..._,...k])}let g=await Ps(a,u,i,t,d,o,{req:n});try{i?.baseUrl&&g?.headers&&mt(s,i.baseUrl,g.headers)}catch{}let m=await Es(a,g,i,o,d,{req:n,isCodexOnMessagesEndpoint:c});m=await Rs(r,m,i.name||s);let y=Os(m,e,r,t);try{let p=r.model||n.originalModel;s&&p&&j().recordSuccess(s,p)}catch{}return y}catch(a){if(a instanceof pe)throw a;if(!n.__retryAttempted){n.__retryAttempted=!0;try{return await Ss(n,e,t,o)}catch(d){if(n.__fallbackExhausted)throw d;a=d}}let u=await Oc(n,e,t,o,a);if(u)return u;throw n.__fallbackExhausted=!0,a}}async function Rs(n,e,t){if(!n?.stream||!e?.body)return e;let o=e.body.getReader(),r=new TextDecoder,s=[],i="";for(let a=0;a<8;a++){let u=await o.read();if(u.done||(u.value&&(s.push(u.value),i+=r.decode(u.value,{stream:!0})),i.split(`
44
44
  `).some(d=>d.startsWith("data:"))))break}if(i+=r.decode(),s.length===0)throw o.releaseLock(),K(`Provider returned empty streaming response from ${t}`,400,"provider_response_error");if(i.includes("event: error")){o.releaseLock();let a=i.length<500?i:i.slice(0,500);throw K(`Provider ${t} returned error in SSE stream: ${a}`,400,"provider_response_error")}if(i.split(`
45
- `).filter(a=>a.startsWith("data:")&&a.trim().length>5).length===0){o.releaseLock();let a=i.length<500?i:i.slice(0,500);throw K(`Provider ${t} returned streaming response with no SSE data lines: ${a}`,400,"provider_response_error")}let c=new ReadableStream({start:a=>{for(let d of s)a.enqueue(d);let u=()=>{o.read().then(({done:d,value:g})=>{d?a.close():(a.enqueue(g),u())}).catch(d=>a.error(d))};u()},cancel:()=>{o.cancel()}});return new Response(c,{headers:e.headers,status:e.status,statusText:e.statusText})}async function Oc(n,e,t,o,r){let s=n.scenarioType||"default",i=n.familyFallback,l=n.modelFamily,c=n.strictProjectRouting?n.fallbackConfig:n.fallbackConfig??t.configService.get("fallback"),a=j(),u=n.provider||"",d=n.body.model||"",g=new Set,m=r?.statusCode===429||r?.isRateLimit===!0||r?.rawBody&&_n(r.rawBody)||r?.message&&_n(r.message);if(u&&d&&(m?(a.markRateLimited(u,d,120,r?.message),n.log.warn(`Primary model ${u},${d} rate-limited, will try fallbacks`)):a.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(c?.[s])&&c[s].length>0&&f.push({name:`global/${s}`,models:c[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(c?.image)&&c.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:c.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=kt(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(!a.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},O=x.provider,{requestBody:I,config:L,bypass:F}=await ws(R,O,o,n.headers,{req:A}),J=await Ps(I,L,O,t,F,o,{req:A});try{O?.baseUrl&&J?.headers&&mt(v,O.baseUrl,J.headers)}catch{}let N=await Es(I,J,O,o,F,{req:A,isCodexOnMessagesEndpoint:n.isCodexOnMessagesEndpoint||!1});return N=await Rs(R,N,v),n.log.info(`Fallback model ${v},${S} succeeded`),a.recordSuccess(v,S),u&&d&&!n.strictProjectRouting&&(Ue().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`):(a.forceOpen(u,d,r?.message),n.log.info(`Marked original model ${u},${d} as unavailable`))),n.provider=v,n.body=R,Os(N,e,R,t)}catch(R){if(C=R,P===1){n.log.warn(`Fallback model ${v},${S} failed, retrying once: ${R.message}`);continue}}a.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 ws(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 a=0;a<i.length;a++){let u=i[a],d=typeof u=="string"?u:u?.text??"";if(d.includes("cch=")){let g=d.replace(/cch=[^;]+;?/g,"cch=ccr-stable;");typeof u=="string"?i[a]=g:typeof u?.text=="string"&&(u.text=g)}}let l={},c=!1;if(c=Ac(e,t,n),c&&(o instanceof Headers?o.delete("content-length"):delete o["content-length"],l.headers=o),!c&&typeof t.transformRequestOut=="function"){let a=await t.transformRequestOut(s);a.body?(s=a.body,l=a.config||{}):s=a}if(!c&&e.transformer?.use?.length)for(let a of e.transformer.use){if(!a||typeof a.transformRequestIn!="function")continue;let u=await a.transformRequestIn(s,e,r);u.body?(s=u.body,l={...l,...u.config}):s=u}if(!c&&e.transformer?.[n.model]?.use?.length)for(let a of e.transformer[n.model].use)!a||typeof a.transformRequestIn!="function"||(s=await a.transformRequestIn(s,e,r));return{requestBody:s,config:l,bypass:c}}function Ac(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 Ic(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 Ps(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 c={Authorization:`Bearer ${t.apiKey}`,...e?.headers||{}};for(let u in c)(c[u]==="undefined"||["authorization","Authorization"].includes(u)&&c[u]?.includes("undefined"))&&delete c[u];nn(o.configService)&&Vr(o.log,i.req.id,{url:String(l),headers:c,body:n});let a=await qr(l,n,{...e,headers:JSON.parse(JSON.stringify(c)),httpsProxy:de(o.configService,t)},i,o.log);if(!a.ok){let u=await a.text();o.log.error(`[provider_response_error] Error from provider(${t.name},${n.model}: ${a.status}): ${u}`);let d=K(`Error from provider(${t.name},${n.model}: ${a.status}): ${u}`,a.status,"provider_response_error");throw d.isRateLimit=a.status===429||_n(u),d.rawBody=u,d}if(a.ok){let u=a.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=${a.ok} status=${a.status} hasBody=${!!a.body}`),!d||u.includes("application/json")){let g=a.clone(),m="";try{if(m=await g.text(),!m||m.trim()==="")throw new SyntaxError("Empty JSON body");if(gt(m))return o.log.info(`[hidden-error-check] body is SSE mislabeled as ${u}, skipping JSON validation`),a;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}: ${a.status}): ${m}`);let f=_n(m),_=K(`Error from provider(${t.name},${n.model}: ${a.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=K(`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&&nn(o.configService)){let d=await a.clone().text();Yr(o.log,i.req.id,{status:a.status,headers:Object.fromEntries(a.headers.entries()),body:d})}return a}async function Es(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 We().transformResponseIn(i,{...s,provider:t})}catch(l){console.error("Failed to apply Responses API conversion for codex client:",l)}return i}async function Os(n,e,t,o){n.ok||e.code(n.status);let r=us(n);if(!r&&(n.headers?.get?.("Content-Type")||"").includes("application/json")){let s=await Je(n);if(s)s.isSSE&&(r=!0),n=new Response(s.body,{status:n.status,statusText:n.statusText,headers:n.headers});else{let i=await Be(n);n=i.response,i.isSSE&&(r=!0)}}if(r){if(e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),o&&nn(o.configService)){let[s,i]=n.body.tee(),l=Qr(o.configService);return Xr(s,o.log,e.request.id,l),e.send(i)}return e.send(n.body)}else return U(n)}function _n(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 Mc(n){try{return new URL(n),!0}catch{return!1}}var Ec,As,kn=w(()=>{"use strict";Zr();en();pt();yo();ce();ze();an();wo();Z();Ze();ae();Ec=/^ccr-(opus|sonnet|haiku)(\[1m\])?$/i;As=async n=>{n.get("/",async()=>({message:"LLMs API",version:sn})),n.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()})),n.get("/providers/health",async()=>({states:j().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)=>Ss(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 K("Provider name is required",400,"invalid_request");if(!s||!Mc(s))throw K("Valid base URL is required",400,"invalid_request");if(!i?.trim())throw K("API key is required",400,"invalid_request");if(!l||!Array.isArray(l)||l.length===0)throw K("At least one model is required",400,"invalid_request");if(n.providerService.getProvider(t.body.name))throw K(`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 K("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 K("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 K("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 K("Provider not found",404,"provider_not_found");return{message:`Provider ${t.body.enabled?"enabled":"disabled"} successfully`}})}});var fe,bn=w(()=>{"use strict";fe=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 Is,Ms=w(()=>{Is=n=>n<=0?"none":n<=1024?"low":n<=8192?"medium":"high"});var $s,Ns=w(()=>{$s=(n,e)=>(n.includes("base64")&&(n=n.split("base64").pop(),n.startsWith(",")&&(n=n.slice(1))),`data:${e};base64,${n}`)});function $c(n){return n.filter(e=>!!e?.function?.name).map(e=>({name:e.function.name,description:e.function.description,input_schema:e.function.parameters}))}function Ls(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"},c=()=>{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"}},a=(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=c(),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;a(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
+ `).filter(a=>a.startsWith("data:")&&a.trim().length>5).length===0){o.releaseLock();let a=i.length<500?i:i.slice(0,500);throw K(`Provider ${t} returned streaming response with no SSE data lines: ${a}`,400,"provider_response_error")}let c=new ReadableStream({start:a=>{for(let d of s)a.enqueue(d);let u=()=>{o.read().then(({done:d,value:g})=>{d?a.close():(a.enqueue(g),u())}).catch(d=>a.error(d))};u()},cancel:()=>{o.cancel()}});return new Response(c,{headers:e.headers,status:e.status,statusText:e.statusText})}async function Oc(n,e,t,o,r){let s=n.scenarioType||"default",i=n.familyFallback,l=n.modelFamily,c=n.strictProjectRouting?n.fallbackConfig:n.fallbackConfig??t.configService.get("fallback"),a=j(),u=n.provider||"",d=n.body.model||"",g=new Set,m=r?.statusCode===429||r?.isRateLimit===!0||r?.rawBody&&_n(r.rawBody)||r?.message&&_n(r.message);if(u&&d&&(m?(a.markRateLimited(u,d,120,r?.message),n.log.warn(`Primary model ${u},${d} rate-limited, will try fallbacks`)):a.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(c?.[s])&&c[s].length>0&&f.push({name:`global/${s}`,models:c[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(c?.image)&&c.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:c.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=kt(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(!a.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},O=x.provider,{requestBody:I,config:L,bypass:F}=await ws(R,O,o,n.headers,{req:A}),J=await Ps(I,L,O,t,F,o,{req:A});try{O?.baseUrl&&J?.headers&&mt(v,O.baseUrl,J.headers)}catch{}let N=await Es(I,J,O,o,F,{req:A,isCodexOnMessagesEndpoint:n.isCodexOnMessagesEndpoint||!1});return N=await Rs(R,N,v),n.log.info(`Fallback model ${v},${S} succeeded`),a.recordSuccess(v,S),u&&d&&!n.strictProjectRouting&&(Ue().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`):(a.forceOpen(u,d,r?.message),n.log.info(`Marked original model ${u},${d} as unavailable`))),n.provider=v,n.body=R,Os(N,e,R,t)}catch(R){if(C=R,P===1){n.log.warn(`Fallback model ${v},${S} failed, retrying once: ${R.message}`);continue}}a.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 ws(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 a=0;a<i.length;a++){let u=i[a],d=typeof u=="string"?u:u?.text??"";if(d.includes("cch=")){let g=d.replace(/cch=[^;]+;?/g,"cch=ccr-stable;");typeof u=="string"?i[a]=g:typeof u?.text=="string"&&(u.text=g)}}let l={},c=!1;if(c=Ac(e,t,n),c&&(o instanceof Headers?o.delete("content-length"):delete o["content-length"],l.headers=o),!c&&typeof t.transformRequestOut=="function"){let a=await t.transformRequestOut(s);a.body?(s=a.body,l=a.config||{}):s=a}if(!c&&e.transformer?.use?.length)for(let a of e.transformer.use){if(!a||typeof a.transformRequestIn!="function")continue;let u=await a.transformRequestIn(s,e,r);u.body?(s=u.body,l={...l,...u.config}):s=u}if(!c&&e.transformer?.[n.model]?.use?.length)for(let a of e.transformer[n.model].use)!a||typeof a.transformRequestIn!="function"||(s=await a.transformRequestIn(s,e,r));return{requestBody:s,config:l,bypass:c}}function Ac(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 Ic(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 Ps(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 c={Authorization:`Bearer ${t.apiKey}`,...e?.headers||{}};for(let u in c)(c[u]==="undefined"||["authorization","Authorization"].includes(u)&&c[u]?.includes("undefined"))&&delete c[u];nn(o.configService)&&Vr(o.log,i.req.id,{url:String(l),headers:c,body:n});let a=await qr(l,n,{...e,headers:JSON.parse(JSON.stringify(c)),httpsProxy:de(o.configService,t)},i,o.log);if(!a.ok){let u=await a.text();o.log.error(`[provider_response_error] Error from provider(${t.name},${n.model}: ${a.status}): ${u}`);let d=K(`Error from provider(${t.name},${n.model}: ${a.status}): ${u}`,a.status,"provider_response_error");throw d.isRateLimit=a.status===429||_n(u),d.rawBody=u,d}if(a.ok){let u=a.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=${a.ok} status=${a.status} hasBody=${!!a.body}`),!d||u.includes("application/json")){let g=a.clone(),m="";try{if(m=await g.text(),!m||m.trim()==="")throw new SyntaxError("Empty JSON body");if(gt(m))return o.log.info(`[hidden-error-check] body is SSE mislabeled as ${u}, skipping JSON validation`),a;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}: ${a.status}): ${m}`);let f=_n(m),_=K(`Error from provider(${t.name},${n.model}: ${a.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=K(`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&&nn(o.configService)){let d=await a.clone().text();Yr(o.log,i.req.id,{status:a.status,headers:Object.fromEntries(a.headers.entries()),body:d})}return a}async function Es(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 We().transformResponseIn(i,{...s,provider:t})}catch(l){console.error("Failed to apply Responses API conversion for codex client:",l)}return i}async function Os(n,e,t,o){n.ok||e.code(n.status);let r=us(n);if(!r){let s=await Je(n);if(s)s.isSSE&&(r=!0),n=new Response(s.body,{status:n.status,statusText:n.statusText,headers:n.headers});else{let i=await Be(n);n=i.response,i.isSSE&&(r=!0)}}if(r){if(e.header("Content-Type","text/event-stream"),e.header("Cache-Control","no-cache"),e.header("Connection","keep-alive"),o&&nn(o.configService)){let[s,i]=n.body.tee(),l=Qr(o.configService);return Xr(s,o.log,e.request.id,l),e.send(i)}return e.send(n.body)}else return U(n)}function _n(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 Mc(n){try{return new URL(n),!0}catch{return!1}}var Ec,As,kn=w(()=>{"use strict";Zr();en();pt();yo();ce();ze();an();wo();Z();Ze();ae();Ec=/^ccr-(opus|sonnet|haiku)(\[1m\])?$/i;As=async n=>{n.get("/",async()=>({message:"LLMs API",version:sn})),n.get("/health",async()=>({status:"ok",timestamp:new Date().toISOString()})),n.get("/providers/health",async()=>({states:j().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)=>Ss(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 K("Provider name is required",400,"invalid_request");if(!s||!Mc(s))throw K("Valid base URL is required",400,"invalid_request");if(!i?.trim())throw K("API key is required",400,"invalid_request");if(!l||!Array.isArray(l)||l.length===0)throw K("At least one model is required",400,"invalid_request");if(n.providerService.getProvider(t.body.name))throw K(`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 K("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 K("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 K("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 K("Provider not found",404,"provider_not_found");return{message:`Provider ${t.body.enabled?"enabled":"disabled"} successfully`}})}});var fe,bn=w(()=>{"use strict";fe=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 Is,Ms=w(()=>{Is=n=>n<=0?"none":n<=1024?"low":n<=8192?"medium":"high"});var $s,Ns=w(()=>{$s=(n,e)=>(n.includes("base64")&&(n=n.split("base64").pop(),n.startsWith(",")&&(n=n.slice(1))),`data:${e};base64,${n}`)});function $c(n){return n.filter(e=>!!e?.function?.name).map(e=>({name:e.function.name,description:e.function.description,input_schema:e.function.parameters}))}function Ls(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"},c=()=>{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"}},a=(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=c(),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;a(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(`
46
46
 
47
47
  `)}return n.tools&&n.tools.length>0&&(d.tools=$c(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 Ds=w(()=>{});var Tn,Cn,Fs=w(()=>{"use strict";Tn=require("uuid");Ms();en();Z();Ns();Ds();Cn=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(c=>c.type==="tool_result"&&c.tool_use_id);i.length&&i.forEach(c=>{let a={role:"tool",content:typeof c.content=="string"?c.content:JSON.stringify(c.content),tool_call_id:c.tool_use_id,cache_control:c.cache_control};t.push(a)});let l=s.content.filter(c=>c.type==="text"&&c.text||c.type==="image"&&c.source);l.length&&t.push({role:"user",content:l.map(c=>c?.type==="image"?{type:"image_url",image_url:{url:c.source?.type==="base64"?$s(c.source.data,c.source.media_type):c.source.url},media_type:c.source.media_type}:c)})}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(`
48
48
  `));let c=s.content.filter(u=>u.type==="tool_use"&&u.id);c.length&&(i.tool_calls=c.map(u=>({id:u.id,type:"function",function:{name:u.name,arguments:JSON.stringify(u.input||{})}})));let a=s.content.find(u=>u.type==="thinking");a&&(i.thinking={content:a.thinking,signature:a.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:Is(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=Ls(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 Je(e);if((r?.isSSE??!1)&&r?.body){let a=await this.convertOpenAIStreamToAnthropic(r.body,t);return new Response(a,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}let i;if(r?.body)i=new Response(r.body,{status:e.status,statusText:e.statusText,headers:e.headers});else{let a=await Be(e);if(a.isSSE){let u=await this.convertOpenAIStreamToAnthropic(a.response.body,t);return new Response(u,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}i=a.response}let l=await U(i),c=this.convertOpenAIResponseToAnthropic(l,t);return new Response(JSON.stringify(c),{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,c="unknown",a=!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 P=new TextDecoder().decode(C);this.logger.debug({reqId:t.req.id,data:P,type:"send data"})}catch(P){if(P instanceof TypeError&&P.message.includes("Controller is already closed"))_=!0;else throw this.logger.debug({reqId:t.req.id,error:P instanceof Error?P.message:String(P),type:"send data error"}),P}},v=()=>{if(!_)try{if(!a){this.logger?.warn("[empty_stream] Upstream produced no data, closing silently"),r.close(),_=!0;return}if(b>=0){let P={type:"content_block_stop",index:b};x(s.encode(`event: content_block_stop