@wengine-ai/llms 2.3.6 → 2.3.7

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.7** | <ul><li>**新增项目默认接管并跟随全局**:在「项目配置」页添加项目时,默认开启「CCR 接管」与「使用全局配置」,自动写入 ccr 代理配置并保持项目路由实时跟随全局,新项目开箱即用。</li><li>**项目级 fallback 复制修复**:自定义项目路由时正确复制全局顶层 `fallback`,避免备用模型链丢失。</li><li>**接管模型配置同步修复**:切换接管开关时按当前全局配置重新生成托管字段,确保全局变更后重新接管能同步最新模型路由,同时保留 `permissions`/`hooks` 等非托管配置。</li></ul> |
96
97
  | **v2.3.6** | <ul><li>**项目级 CCR 接管**:Web UI 项目配置页新增「CCR 接管」开关,开启后会将 `ANTHROPIC_BASE_URL`/`ANTHROPIC_AUTH_TOKEN`、模型族路由环境变量、auto-compact 设置及状态栏命令同步写入该项目的 `.claude/settings.local.json`,使该项目的 Claude Code CLI 无需 `ccr code` 即可直接通过 CCR 路由;关闭接管时会备份当前配置,下次重新接管自动还原,避免个性化配置丢失。</li><li>**项目配置页折叠与同步修复**:项目卡片支持折叠/展开;关闭「使用全局配置」后正确同步全局路由的 fallback 与模型族配置。</li></ul> |
97
98
  | **v2.1.36** | <ul><li>**Codex 最新 RT 导出**:Codex 账号管理支持导出当前或指定托管账号的最新 refresh token,CLI 新增 `ccr clients codex export-rt [account-id]`,Web UI 新增复制最新 RT 按钮,并会在当前 auth 文件更新时同步托管快照。</li></ul> |
98
99
  | **v2.1.35** | <ul><li>**定时唤醒稳定性修复**:提供商定时唤醒在 macOS 睡眠/唤醒或系统时间跳变后会重新计算下一次触发时间,避免错过或重复执行唤醒任务。</li></ul> |
@@ -102,11 +103,8 @@ npm install -g @wengine-ai/claude-code-router-next@latest && ccr restart
102
103
  | **v2.1.30** | <ul><li>**Codex 多账号限额展示**:Codex 账号管理页新增官方限额信息展示,通过 `chatgpt.com/backend-api/wham/usage` 获取 5 小时速率限制与 7 天周限制的使用百分比和重置时间。</li><li>**Codex 账号自动切换**:Codex 请求前会检查当前账号官方限额,默认任一窗口达到 95% 自动切换到下一个可用账号;仍保留 429/限流错误后的自动切换兜底。</li></ul> |
103
104
  | **v2.1.27** | <ul><li>**DeepSeek / GLM 工具调用兼容修复**:修复部分 DeepSeek 与 GLM 兼容接口因 `tool_choice` 参数格式不一致导致的请求失败问题。</li></ul> |
104
105
  | **v2.1.26** | <ul><li>**修复 Anthropic Transformer URI 覆盖问题**:当 `Anthropic` 与 DeepSeek/OpenAI 兼容提供商组合使用时,不再把 `chat/completions` 端点错误改写为 `/v1/messages`,避免 DeepSeek 返回 404。</li><li>**协议转换边界收紧**:仅当 provider 的 `api_base_url` 明确指向 `/messages` 端点时,才将请求体转换为 Anthropic messages 结构。</li></ul> |
105
- | **v2.1.25** | <ul><li>**修复新版 Claude Code (v2.1.154+) 422 报错**:完美解决请求 `/v1/messages` 兼容提供商时因 messages 数组中包含 `role: "system"` 造成的 400/422 报错。</li><li>**动态 Passthrough 绕过自愈**:强制拦截带有 system 消息的 Anthropic 兼容提供商透传,自动进行双向协议规范化与 system 字段合并。</li><li>**响应无损透传修复**:支持目标为 Anthropic 协议响应的原样直出,解决了第三方接口转发时“请求成功但无数据返回”的重大漏洞。</li></ul> |
106
- | **v2.1.22** | <ul><li>**提供商定时唤醒功能 (定时唤醒)**:新增通用及提供商级别的清晨定时自动重置/唤醒机制,通过发送 dummy 消息提前激活额度。</li><li>**对称用量展示面板**:将 Web 控制台的用量统计网格从 8 张卡片升级为更美观对称的 10 卡片布局。</li><li>**高级用量指标统计**:新增对缓存命中率 (Cache Hit Rate) 及生成速度 (Average Speed) 的多维度计算与动态展示。</li></ul> |
107
- | **v2.1.7** | <ul><li>**Gemini 思考模式签名支持**:完美支持 Gemini 思考模式 (thinking mode) 及思维链签名 (thought_signature),防止转发时出现 400 校验异常并拦截 API Key 泄露。</li><li>**系统级调试日志面板**:引入运行时一键切换的系统调试日志,与 Web 控制台深度集成,提供实时请求响应细节。</li></ul> |
108
- | **v2.1.2** | <ul><li>**状态栏 Token 缓存计数**:支持 CLI 状态栏 (statusline) 中的 Token 计数正确显示缓存命中详情,并在响应速度及文字格式上完成多项优化。</li></ul> |
109
- | **v2.0.87** | <ul><li>**Web 控制台额度支持**:正式打通并适配智谱 GLM 与百炼 Qwen 等主流渠道的额度使用详情实时分析。</li><li>**健康失败记录优化**:修复 HTTP 429 速率限制请求在健康监测系统中未被记录为失败并导致熔断延迟的 Bug。</li></ul> |
106
+
107
+ > 仅保留最近 10 个版本,更早版本的发布摘要见 [CHANGELOG-archive.md](./CHANGELOG-archive.md),完整详细变更记录见 [CHANGELOG.md](./CHANGELOG.md)
110
108
 
111
109
  ### 2. 配置
112
110
 
@@ -71,7 +71,7 @@ ${this.toMarkdown(o,n+1)}`:`${r}- ${o}`).join(`
71
71
  ${this.toMarkdown(s,n+1)}`:`${r}${o}: ${s}`).join(`
72
72
  `):`${r}${e}`}async output(e,n={}){try{let r=this.formatData(e,n);switch(this.config.level||"log"){case"info":console.info(r);break;case"warn":console.warn(r);break;case"error":console.error(r);break;case"debug":console.debug(r);break;case"log":default:console.log(r);break}return!0}catch(r){return console.error("[ConsoleOutputHandler] Output failed:",r),!1}}}});var Os,Df=Le(()=>{"use strict";Os=class{type="webhook";config;defaultTimeout=3e4;constructor(e){if(!e.url)throw new Error("Webhook URL is required");this.config={method:"POST",retry:{maxAttempts:3,backoffMs:1e3},silent:!1,...e}}buildHeaders(){let e={"Content-Type":"application/json",...this.config.headers||{}};if(this.config.auth)switch(this.config.auth.type){case"bearer":this.config.auth.token&&(e.Authorization=`Bearer ${this.config.auth.token}`);break;case"basic":if(this.config.auth.username&&this.config.auth.password){let n=Buffer.from(`${this.config.auth.username}:${this.config.auth.password}`).toString("base64");e.Authorization=`Basic ${n}`}break;case"custom":this.config.auth.custom&&(e[this.config.auth.custom.header]=this.config.auth.custom.value);break}return e}buildBody(e,n){let{format:r="json",timestamp:o=!0,prefix:s,metadata:a}=n||{},c={data:e};return o&&(c.timestamp=new Date().toISOString()),s&&(c.prefix=s),a&&Object.keys(a).length>0&&(c.metadata=a),c}async sendRequest(e,n,r,o,s){let a=new AbortController,c=setTimeout(()=>a.abort(),s);try{let l=await fetch(e,{method:n,headers:r,body:JSON.stringify(o),signal:a.signal});if(clearTimeout(c),!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);return l}catch(l){throw clearTimeout(c),l}}delay(e){return new Promise(n=>setTimeout(n,e))}async sendWithRetry(e,n,r,o,s,a){let c=null;for(let l=1;l<=a.maxAttempts;l++)try{return await this.sendRequest(e,n,r,o,s)}catch(d){if(c=d,l===a.maxAttempts)break;let f=a.backoffMs*Math.pow(2,l-1);console.warn(`[WebhookOutputHandler] Request failed (attempt ${l}/${a.maxAttempts}), retrying in ${f}ms...`,d.message),await this.delay(f)}throw c}async output(e,n={}){let r=n.timeout||this.defaultTimeout;try{let o=this.buildHeaders(),s=this.buildBody(e,n),a=await this.sendWithRetry(this.config.url,this.config.method,o,s,r,this.config.retry);return!0}catch(o){let s=o instanceof Error?o.message:String(o);if(this.config.silent)return console.error(`[WebhookOutputHandler] Failed to send data: ${s}`),!1;throw new Error(`Webhook output failed: ${s}`)}}}});var vo,Rf,D_,Ps,xf=Le(()=>{"use strict";vo=require("fs"),Rf=require("path"),D_=require("os"),Ps=class{type="temp-file";config;baseDir;constructor(e={}){this.config={subdirectory:"claude-code-router",extension:"json",includeTimestamp:!1,prefix:"session",...e};let n=(0,D_.tmpdir)();this.baseDir=(0,Rf.join)(n,this.config.subdirectory),this.ensureDir()}ensureDir(){try{(0,vo.existsSync)(this.baseDir)||(0,vo.mkdirSync)(this.baseDir,{recursive:!0})}catch{}}extractSessionId(e){try{let n=e.match(/_session_([a-f0-9-]+)/i);return n?n[1]:null}catch{return null}}getFilePath(e){let n=this.config.prefix||"session",r=this.config.extension?`.${this.config.extension}`:"",o;if(this.config.includeTimestamp){let s=Date.now();o=`${n}-${e}-${s}${r}`}else o=`${n}-${e}${r}`;return(0,Rf.join)(this.baseDir,o)}async output(e,n={}){try{let r=n.metadata?.sessionId;if(!r)return!1;let o={...e,timestamp:Date.now(),sessionId:r},s=this.getFilePath(r);return(0,vo.writeFileSync)(s,JSON.stringify(o,null,2),"utf-8"),!0}catch{return!1}}getBaseDir(){return this.baseDir}}});var Of,Do,R_=Le(()=>{"use strict";vf();Df();xf();Of=class{handlers=new Map;defaultOptions={};registerHandler(e,n){this.handlers.set(e,n)}registerHandlers(e){for(let n of e)if(n.enabled!==!1)try{let r=this.createHandler(n),o=n.type+"_"+Date.now();this.registerHandler(o,r)}catch(r){console.error(`[OutputManager] Failed to register ${n.type} handler:`,r)}}createHandler(e){switch(e.type){case"console":return new xs(e.config);case"webhook":return new Os(e.config);case"temp-file":return new Ps(e.config);default:throw new Error(`Unknown output handler type: ${e.type}`)}}unregisterHandler(e){return this.handlers.delete(e)}getHandler(e){return this.handlers.get(e)}getAllHandlers(){return new Map(this.handlers)}clearHandlers(){this.handlers.clear()}setDefaultOptions(e){this.defaultOptions={...this.defaultOptions,...e}}getDefaultOptions(){return{...this.defaultOptions}}async output(e,n){let r={...this.defaultOptions,...n},o={success:[],failed:[]},s=Array.from(this.handlers.entries()).map(async([a,c])=>{try{await c.output(e,r)?o.success.push(a):o.failed.push(a)}catch(l){console.error(`[OutputManager] Handler ${a} failed:`,l),o.failed.push(a)}});return await Promise.all(s),o}async outputTo(e,n,r){let o={...this.defaultOptions,...r},s={success:[],failed:[]},a=e.map(async c=>{let l=this.handlers.get(c);if(!l){console.warn(`[OutputManager] Handler ${c} not found`),s.failed.push(c);return}try{await l.output(n,o)?s.success.push(c):s.failed.push(c)}catch(d){console.error(`[OutputManager] Handler ${c} failed:`,d),s.failed.push(c)}});return await Promise.all(a),s}async outputToType(e,n,r){let o=Array.from(this.handlers.entries()).filter(([s,a])=>a.type===e).map(([s])=>s);return this.outputTo(o,n,r)}},Do=new Of});var yR={};ci(yR,{ActiveProbeService:()=>Ds,ConfigService:()=>pr,ProviderHealthStore:()=>$o,ProviderService:()=>gr,SSEParserTransform:()=>xr,SSESerializerTransform:()=>Rs,TokenizerService:()=>Rr,TransformerService:()=>Dr,calculateTokenCount:()=>Ac,default:()=>gR,getActiveProbeService:()=>wf,getAllQuotaResults:()=>kp,getAllRateLimitInfo:()=>bp,getHealthStore:()=>Je,getQuotaAdapter:()=>Eu,getQuotaResult:()=>wi,getRateLimitInfo:()=>_p,getRuntimeDebugLog:()=>rp,initProviderHealthPersistence:()=>yi,initQuotaStorePersistence:()=>Ei,initRateLimitPersistence:()=>_i,pluginManager:()=>kf,resetActiveProbeService:()=>E_,rewriteStream:()=>Tf,router:()=>Qr,searchProjectBySession:()=>Sc,sessionUsageCache:()=>bi,setRuntimeDebugLog:()=>np,startActiveProbe:()=>ku,stopActiveProbe:()=>Au,storeQuotaResult:()=>Ci,tokenSpeedPlugin:()=>Ff});module.exports=Lh(yR);var F_=xe(require("fastify"),1),I_=xe(require("@fastify/cors"),1);var jo=require("fs"),uc=require("path"),Kh=require("dotenv"),Qh=xe(ac(),1),pr=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,uc.join)(process.cwd(),this.options.jsonPath);if((0,jo.existsSync)(e))try{let n=(0,jo.readFileSync)(e,"utf-8"),r=Qh.default.parse(n);this.config={...this.config,...r},console.log(`Loaded JSON config from: ${e}`)}catch(n){console.warn(`Failed to load JSON config from ${e}:`,n)}else console.warn(`JSON config file not found: ${e}`)}loadEnvConfig(){let e=this.isAbsolutePath(this.options.envPath)?this.options.envPath:(0,uc.join)(process.cwd(),this.options.envPath);if((0,jo.existsSync)(e))try{let n=(0,Kh.config)({path:e});n.parsed&&(this.config={...this.config,...this.parseEnvConfig(n.parsed)})}catch(n){console.warn(`Failed to load .env config from ${e}:`,n)}}loadEnvironmentVariables(){let e=this.parseEnvConfig(process.env);this.config={...this.config,...e}}parseEnvConfig(e){let n={};return Object.assign(n,e),n}isAbsolutePath(e){return e.startsWith("/")||e.includes(":")}get(e,n){let r=this.config[e];return r!==void 0?r:n}getAll(){return{...this.config}}getHttpsProxy(){return this.get("HTTPS_PROXY")||this.get("https_proxy")||this.get("httpsProxy")||this.get("PROXY_URL")}has(e){return this.config[e]!==void 0}set(e,n){this.config[e]=n}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 He(t,e=500,n="internal_error",r="api_error"){let o=new Error(t);return o.statusCode=e,o.code=n,o.type=r,o}async function Yh(t,e,n){e.log.error(t);let r=t.statusCode||500;if(t.rawBody)try{let s=JSON.parse(t.rawBody);return n.code(r).send(s)}catch{return n.code(r).send(t.rawBody)}let o={error:{message:t.message+(t.stack||"Internal Server Error"),type:t.type||"api_error",code:t.code||"internal_error"}};return n.code(r).send(o)}var Xh=require("undici");function Zh(t,e,n,r,o){let s=new Headers({"Content-Type":"application/json"});n.headers&&Object.entries(n.headers).forEach(([d,f])=>{f&&s.set(d,f)});let a,c=AbortSignal.timeout(n.TIMEOUT??60*1e3*60);if(n.signal){let d=new AbortController,f=()=>d.abort();n.signal.addEventListener("abort",f),c.addEventListener("abort",f),a=d.signal}else a=c;let l={method:"POST",headers:s,body:JSON.stringify(e),signal:a};return n.httpsProxy&&(l.dispatcher=new Xh.ProxyAgent(new URL(n.httpsProxy).toString())),o?.debug({reqId:r.req.id,request:l,headers:Object.fromEntries(s.entries()),requestUrl:typeof t=="string"?t:t.toString(),useProxy:n.httpsProxy},"final request"),fetch(typeof t=="string"?t:t.toString(),l)}var RC=new Set(["authorization","x-api-key","x-goog-api-key","cookie","set-cookie"]),Wr={maxBodyLength:4096,maxStreamChunks:100},cc=!1;function np(t){cc=t}function rp(){return cc}function pi(t){return cc||t.get("DEBUG_LOG")===!0}function op(t){let e=t.get("DEBUG_LOG_OPTIONS");return!e||typeof e!="object"?Wr:{maxBodyLength:e.maxBodyLength??Wr.maxBodyLength,maxStreamChunks:e.maxStreamChunks??Wr.maxStreamChunks}}function sp(t){let e={};for(let[n,r]of Object.entries(t))RC.has(n.toLowerCase())?e[n]="***MASKED***":e[n]=r;return e}function mi(t,e){return t.length<=e?t:t.slice(0,e)+`...[truncated, total ${t.length} bytes]`}function ip(t,e,n){let r=typeof n.body=="string"?n.body:JSON.stringify(n.body);t.info({debug_log:!0,reqId:e,phase:"provider_request",url:n.url,headers:sp(n.headers),body:mi(r,Wr.maxBodyLength)})}function ap(t,e,n){t.info({debug_log:!0,reqId:e,phase:"provider_response",status:n.status,headers:sp(n.headers),...n.body!==void 0?{body:mi(n.body,Wr.maxBodyLength)}:{}})}function ep(t,e,n,r){let o=xC(r);t.info({debug_log:!0,reqId:e,phase:"provider_stream_chunk",chunkIndex:n,...o?{usage_monitor:o}:{},data:mi(r,Wr.maxBodyLength)})}function xC(t){let e=[];for(let n of t.split(/\r?\n/)){if(!n.startsWith("data:"))continue;let r=n.slice(5).trim();if(!(!r||r==="[DONE]"))try{let o=JSON.parse(r),s=o?.usage||o?.response?.usage;s&&e.push({path:o?.usage?"usage":"response.usage",usage:s,choicesLength:Array.isArray(o?.choices)?o.choices.length:void 0,finishReason:o?.choices?.[0]?.finish_reason})}catch{e.push({parseError:!0,data:mi(r,512)})}}if(e.length)return e.length===1?e[0]:e}function tp(t,e,n){t.info({debug_log:!0,reqId:e,phase:"provider_stream_end",totalChunks:n})}function up(t,e,n,r){(async()=>{let o=t.pipeThrough(new TextDecoderStream).getReader(),s=0;try{let a="";for(;;){let{done:c,value:l}=await o.read();if(c)break;a+=l;let d=a.split(`
73
73
 
74
- `);a=d.pop()||"";for(let f of d)f.trim()&&(s<r.maxStreamChunks?ep(e,n,s,f):s===r.maxStreamChunks&&e.info({debug_log:!0,reqId:n,phase:"provider_stream_chunk_omitted",message:`[chunks after #${s} omitted, maxStreamChunks=${r.maxStreamChunks}]`}),s++)}a.trim()&&(s<r.maxStreamChunks&&ep(e,n,s,a.trim()),s++),tp(e,n,s)}catch(a){console.error(`[debug_log] Error reading debug stream for reqId=${n}:`,a),tp(e,n,s)}finally{o.releaseLock()}})()}var cp="2.3.6";Gn();var Sn=require("fs"),_c=require("path"),yp=require("@wengine-ai/claude-code-router-shared"),gc=(0,_c.join)(yp.HOME_DIR,"runtime"),yc=(0,_c.join)(gc,"rate-limit.json"),Gr=new Map,pp=!1,LC=null,jC=["x-ratelimit-remaining-tokens","x-ratelimit-remaining-requests","x-ratelimit-remaining"],UC=["x-ratelimit-limit-tokens","x-ratelimit-limit-requests","x-ratelimit-limit"],$C=["x-ratelimit-reset-tokens","x-ratelimit-reset-requests","x-ratelimit-reset"];function qo(t,e,n){let r=c=>{if(n instanceof Headers)return n.get(c);let l=Object.keys(n).find(d=>d.toLowerCase()===c);return l?n[l]:null},o=mc(r,jC),s=mc(r,UC),a=mc(r,$C);(o||s||a)&&Gr.set(t,{provider:t,remaining:mp(o),limit:mp(s),reset:qC(a),capturedAt:Date.now()})}function _p(t){return Gr.get(t)}function bp(){return Array.from(Gr.values())}function mc(t,e){for(let n of e){let r=t(n);if(r)return r}return null}function mp(t){if(!t)return null;let e=Number(t.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function qC(t){if(!t)return null;let e=t.trim();if(!e)return null;let n=Number(e);if(Number.isFinite(n))return n>1e12?Math.floor(n/1e3):n>1e9?Math.floor(n):Math.floor(Date.now()/1e3+n);let r=Date.parse(e);if(Number.isFinite(r))return Math.floor(r/1e3);let o=zC(e);return o===null?null:Math.floor((Date.now()+o)/1e3)}function zC(t){let e=/(\d+(?:\.\d+)?)(ms|s|m|h|d)/gi,n=0,r=!1;for(let o of t.matchAll(e)){r=!0;let s=Number(o[1]),a=o[2].toLowerCase();if(Number.isFinite(s))switch(a){case"ms":n+=s;break;case"s":n+=s*1e3;break;case"m":n+=s*60*1e3;break;case"h":n+=s*60*60*1e3;break;case"d":n+=s*24*60*60*1e3;break}}return r?n:null}function HC(){try{if(!(0,Sn.existsSync)(yc))return;let t=JSON.parse((0,Sn.readFileSync)(yc,"utf-8"));if(!Array.isArray(t))return;let e=Date.now();for(let n of t)if(n&&n.provider){if(n.capturedAt&&e-n.capturedAt>3600*1e3)continue;Gr.set(n.provider,n)}}catch{}}function gp(){try{if(Gr.size===0)return;(0,Sn.existsSync)(gc)||(0,Sn.mkdirSync)(gc,{recursive:!0}),(0,Sn.writeFileSync)(yc,JSON.stringify(Array.from(Gr.values()),null,2),"utf-8")}catch{}}function _i(){pp||(pp=!0,HC(),LC=setInterval(gp,6e4),process.on("exit",gp))}gi();var Jr=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 n=e?.input_tokens??e?.prompt_tokens??0,r=e?.output_tokens??e?.completion_tokens??0,o=this.getCacheReadInputTokens(e),s=this.getCacheCreationInputTokens(e);return{input_tokens:n,output_tokens:r,total_tokens:e?.total_tokens??n+r,input_tokens_details:{cached_tokens:o,cache_creation_tokens:s},output_tokens_details:{reasoning_tokens:e?.output_tokens_details?.reasoning_tokens??0},cache_read_input_tokens:o,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 n=[],r=e.messages.filter(o=>o.role==="system");if(r.length>0){let o=r[0];Array.isArray(o.content)?o.content.forEach(s=>{let a="";typeof s=="string"?a=s:s&&typeof s=="object"&&"text"in s&&(a=s.text),n.push({role:"system",content:a})}):e.instructions=o.content}if(e.messages.forEach(o=>{if(o.role!=="system"){if(Array.isArray(o.content)){let s=o.content.map(a=>this.normalizeRequestContent(a,o.role)).filter(a=>a!==null);s.length>0?o.content=s:delete o.content}if(o.role==="tool"){let s={...o};s.type="function_call_output",s.call_id=o.tool_call_id,s.output=o.content,delete s.cache_control,delete s.role,delete s.tool_call_id,delete s.content,n.push(s);return}if(o.role==="assistant"&&Array.isArray(o.tool_calls)){o.tool_calls.forEach(s=>{n.push({type:"function_call",arguments:s.function.arguments,name:s.function.name,call_id:s.id})});return}n.push(o)}}),e.input=n,delete e.messages,Array.isArray(e.tools)){let o=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})),o&&e.tools.push({type:"web_search"})}return e.parallel_tool_calls=!1,e}async transformResponseOut(e){let n=e.headers.get("Content-Type")||"";if(n.includes("application/json")){let r=await e.json();if(r.object==="response"&&r.output){let o=this.convertResponseToChat(r);return new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers})}return r.type==="message"&&Array.isArray(r.content)?new Response(JSON.stringify(r),{status:e.status,statusText:e.statusText,headers:e.headers}):new Response(JSON.stringify(r),{status:e.status,statusText:e.statusText,headers:e.headers})}else if(n.includes("text/event-stream")){if(!e.body)return e;let[r,o]=e.body.tee(),s=r.getReader(),a="";try{let{value:y,done:g}=await s.read();!g&&y&&(a=new TextDecoder().decode(y))}finally{s.releaseLock()}if(r.cancel().catch(()=>{}),a.includes("message_start")||a.includes("content_block_start")){let y=this.prependToStream(a,o);return new Response(y,{status:e.status,statusText:e.statusText,headers:e.headers})}if(a.includes("response.created")||a.includes("response.output_text.delta")||a.includes("response.in_progress")||a.includes("response.output_item.added")){let y=this.prependToStream(a,o);return new Response(y,{status:e.status,statusText:e.statusText,headers:e.headers})}let d=this.prependToStream(a,o),f=new TextDecoder,p=new TextEncoder,m="",b=!1,C=this,_=new ReadableStream({async start(y){let g=d.getReader(),S=-1,w="",A=v=>(v!==w&&(S++,w=v),S);try{for(;;){let{done:v,value:R}=await g.read();if(v){b||y.enqueue(p.encode(`data: [DONE]
74
+ `);a=d.pop()||"";for(let f of d)f.trim()&&(s<r.maxStreamChunks?ep(e,n,s,f):s===r.maxStreamChunks&&e.info({debug_log:!0,reqId:n,phase:"provider_stream_chunk_omitted",message:`[chunks after #${s} omitted, maxStreamChunks=${r.maxStreamChunks}]`}),s++)}a.trim()&&(s<r.maxStreamChunks&&ep(e,n,s,a.trim()),s++),tp(e,n,s)}catch(a){console.error(`[debug_log] Error reading debug stream for reqId=${n}:`,a),tp(e,n,s)}finally{o.releaseLock()}})()}var cp="2.3.7";Gn();var Sn=require("fs"),_c=require("path"),yp=require("@wengine-ai/claude-code-router-shared"),gc=(0,_c.join)(yp.HOME_DIR,"runtime"),yc=(0,_c.join)(gc,"rate-limit.json"),Gr=new Map,pp=!1,LC=null,jC=["x-ratelimit-remaining-tokens","x-ratelimit-remaining-requests","x-ratelimit-remaining"],UC=["x-ratelimit-limit-tokens","x-ratelimit-limit-requests","x-ratelimit-limit"],$C=["x-ratelimit-reset-tokens","x-ratelimit-reset-requests","x-ratelimit-reset"];function qo(t,e,n){let r=c=>{if(n instanceof Headers)return n.get(c);let l=Object.keys(n).find(d=>d.toLowerCase()===c);return l?n[l]:null},o=mc(r,jC),s=mc(r,UC),a=mc(r,$C);(o||s||a)&&Gr.set(t,{provider:t,remaining:mp(o),limit:mp(s),reset:qC(a),capturedAt:Date.now()})}function _p(t){return Gr.get(t)}function bp(){return Array.from(Gr.values())}function mc(t,e){for(let n of e){let r=t(n);if(r)return r}return null}function mp(t){if(!t)return null;let e=Number(t.trim().replace(/,/g,""));return Number.isFinite(e)?e:null}function qC(t){if(!t)return null;let e=t.trim();if(!e)return null;let n=Number(e);if(Number.isFinite(n))return n>1e12?Math.floor(n/1e3):n>1e9?Math.floor(n):Math.floor(Date.now()/1e3+n);let r=Date.parse(e);if(Number.isFinite(r))return Math.floor(r/1e3);let o=zC(e);return o===null?null:Math.floor((Date.now()+o)/1e3)}function zC(t){let e=/(\d+(?:\.\d+)?)(ms|s|m|h|d)/gi,n=0,r=!1;for(let o of t.matchAll(e)){r=!0;let s=Number(o[1]),a=o[2].toLowerCase();if(Number.isFinite(s))switch(a){case"ms":n+=s;break;case"s":n+=s*1e3;break;case"m":n+=s*60*1e3;break;case"h":n+=s*60*60*1e3;break;case"d":n+=s*24*60*60*1e3;break}}return r?n:null}function HC(){try{if(!(0,Sn.existsSync)(yc))return;let t=JSON.parse((0,Sn.readFileSync)(yc,"utf-8"));if(!Array.isArray(t))return;let e=Date.now();for(let n of t)if(n&&n.provider){if(n.capturedAt&&e-n.capturedAt>3600*1e3)continue;Gr.set(n.provider,n)}}catch{}}function gp(){try{if(Gr.size===0)return;(0,Sn.existsSync)(gc)||(0,Sn.mkdirSync)(gc,{recursive:!0}),(0,Sn.writeFileSync)(yc,JSON.stringify(Array.from(Gr.values()),null,2),"utf-8")}catch{}}function _i(){pp||(pp=!0,HC(),LC=setInterval(gp,6e4),process.on("exit",gp))}gi();var Jr=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 n=e?.input_tokens??e?.prompt_tokens??0,r=e?.output_tokens??e?.completion_tokens??0,o=this.getCacheReadInputTokens(e),s=this.getCacheCreationInputTokens(e);return{input_tokens:n,output_tokens:r,total_tokens:e?.total_tokens??n+r,input_tokens_details:{cached_tokens:o,cache_creation_tokens:s},output_tokens_details:{reasoning_tokens:e?.output_tokens_details?.reasoning_tokens??0},cache_read_input_tokens:o,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 n=[],r=e.messages.filter(o=>o.role==="system");if(r.length>0){let o=r[0];Array.isArray(o.content)?o.content.forEach(s=>{let a="";typeof s=="string"?a=s:s&&typeof s=="object"&&"text"in s&&(a=s.text),n.push({role:"system",content:a})}):e.instructions=o.content}if(e.messages.forEach(o=>{if(o.role!=="system"){if(Array.isArray(o.content)){let s=o.content.map(a=>this.normalizeRequestContent(a,o.role)).filter(a=>a!==null);s.length>0?o.content=s:delete o.content}if(o.role==="tool"){let s={...o};s.type="function_call_output",s.call_id=o.tool_call_id,s.output=o.content,delete s.cache_control,delete s.role,delete s.tool_call_id,delete s.content,n.push(s);return}if(o.role==="assistant"&&Array.isArray(o.tool_calls)){o.tool_calls.forEach(s=>{n.push({type:"function_call",arguments:s.function.arguments,name:s.function.name,call_id:s.id})});return}n.push(o)}}),e.input=n,delete e.messages,Array.isArray(e.tools)){let o=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})),o&&e.tools.push({type:"web_search"})}return e.parallel_tool_calls=!1,e}async transformResponseOut(e){let n=e.headers.get("Content-Type")||"";if(n.includes("application/json")){let r=await e.json();if(r.object==="response"&&r.output){let o=this.convertResponseToChat(r);return new Response(JSON.stringify(o),{status:e.status,statusText:e.statusText,headers:e.headers})}return r.type==="message"&&Array.isArray(r.content)?new Response(JSON.stringify(r),{status:e.status,statusText:e.statusText,headers:e.headers}):new Response(JSON.stringify(r),{status:e.status,statusText:e.statusText,headers:e.headers})}else if(n.includes("text/event-stream")){if(!e.body)return e;let[r,o]=e.body.tee(),s=r.getReader(),a="";try{let{value:y,done:g}=await s.read();!g&&y&&(a=new TextDecoder().decode(y))}finally{s.releaseLock()}if(r.cancel().catch(()=>{}),a.includes("message_start")||a.includes("content_block_start")){let y=this.prependToStream(a,o);return new Response(y,{status:e.status,statusText:e.statusText,headers:e.headers})}if(a.includes("response.created")||a.includes("response.output_text.delta")||a.includes("response.in_progress")||a.includes("response.output_item.added")){let y=this.prependToStream(a,o);return new Response(y,{status:e.status,statusText:e.statusText,headers:e.headers})}let d=this.prependToStream(a,o),f=new TextDecoder,p=new TextEncoder,m="",b=!1,C=this,_=new ReadableStream({async start(y){let g=d.getReader(),S=-1,w="",A=v=>(v!==w&&(S++,w=v),S);try{for(;;){let{done:v,value:R}=await g.read();if(v){b||y.enqueue(p.encode(`data: [DONE]
75
75
 
76
76
  `));break}let $=f.decode(R,{stream:!0});m+=$;let V=m.split(/\r?\n/);m=V.pop()||"";for(let P of V)if(P.trim())try{if(P.startsWith("event: "))continue;if(P.startsWith("data: ")){let Q=P.slice(5).trim();if(Q==="[DONE]"){b=!0,y.enqueue(p.encode(`data: [DONE]
77
77