inference-relay 1.6.12 → 1.6.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/main.js CHANGED
@@ -8,12 +8,12 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
8
8
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
9
9
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
10
10
  UQIDAQAB
11
- -----END PUBLIC KEY-----`,Ve={version:"1.0.0",cliVersion:"2.1.87",eventTypes:{system:"system",streamEvent:"stream_event",assistant:"assistant",result:"result"},fieldMappings:{sessionId:"session_id",model:"model",cliVersion:"claude_code_version",content:"content",usage:"usage",inputTokens:"input_tokens",outputTokens:"output_tokens",stopReason:"stop_reason",isError:"is_error",totalCostUsd:"total_cost_usd",durationMs:"duration_ms",error:"error",event:"event"},syntheticModel:"<synthetic>"},K=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),i=await r(Ae,"RS256"),{payload:a}=await t(e,i),s=JSON.parse(new TextDecoder().decode(a));return this.verificationFailures=0,this.cachedManifest=s,this.currentSecurityState="SEC_NOMINAL",{manifest:s,securityState:"SEC_NOMINAL"}}catch{if(this.verificationFailures++,this.verificationFailures>=3){this.currentSecurityState="SEC_DEGRADED";let t=2e3+Math.random()*3e3;return await new Promise(r=>setTimeout(r,t)),console.warn("[inference-relay] Logic synchronization mismatch. Routing via local recovery."),{manifest:Ve,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Ve,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Mt=new K;});function I(n,...e){process.env.IR_DEBUG==="1"&&console.error(`[ir-debug:${n}]`,...e);}var we=v(()=>{});function Se(n){return join(homedir(),".inference-relay","gateway",n)}function We(n){return join(Se(n),"bundle.js")}function qe(n){return join(Se(n),"meta.json")}function Vt(n){let e=(r,i)=>{if(!Array.isArray(r)||r.length===0)return null;let a=[];for(let s of r){let o=typeof s=="string"?Number(s):s;if(typeof o!="number"||!Number.isFinite(o)||o<0)return I("loader.retry-config-invalid",{source:i,badValue:s}),null;a.push(o);}return a};if(n!==void 0){let r=e(n,"option");if(r)return r}let t=process.env.IR_GATEWAY_RETRY_DELAYS_MS;if(t){let r=e(t.split(",").map(i=>i.trim()),"env");if(r)return r}return $t}var Bt,C,U,W,$t,q,Pe=v(()=>{ke();we();Bt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";C=class extends Error{constructor(t,r,i){super(t);this.code=r;this.cause=i;this.name="GatewayLoaderError";}code;cause},U=class extends C{constructor(e,t){super(e,"GATEWAY_FETCH_FAILED",t);}},W=new Map,$t=[0,1e3,4e3];q=class{static async load(e,t,r=Bt,i){let a=`${t}:${e.slice(-8)}`;if(W.has(a))return W.get(a);try{let m=await this.tryLoadFromDisk(t);if(m)return I("loader.cache-hit",{libraryVersion:t}),W.set(a,m),m}catch{}I("loader.cache-miss",{libraryVersion:t});let{bytes:s,sha256:o,signature:l,libraryVersion:d}=await this.fetchFromAuthority(e,t,r,i);if(createHash("sha256").update(s).digest("hex")!==o)throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,d,o);try{let m=Se(t);mkdirSync(m,{recursive:!0}),writeFileSync(We(t),s),writeFileSync(qe(t),JSON.stringify({sha256:o,signature:l,libraryVersion:d}));}catch{}let h=this.loadIntoVm(s.toString("utf-8"));return W.set(a,h),h}static async loadFromDisk(e){if(!existsSync(e))throw new C(`[ir-system]: GATEWAY_LOAD_FAILED (REASON: BUNDLE_NOT_FOUND at ${e})`,"GATEWAY_LOAD_FAILED");let t=readFileSync(e,"utf-8");return this.loadIntoVm(t)}static async tryLoadFromDisk(e){let t=We(e),r=qe(e);if(!existsSync(t)||!existsSync(r))return null;let i=readFileSync(t),a=JSON.parse(readFileSync(r,"utf-8"));return createHash("sha256").update(i).digest("hex")!==a.sha256?null:(await this.verifySignature(a.signature,a.libraryVersion,a.sha256),this.loadIntoVm(i.toString("utf-8")))}static async fetchFromAuthority(e,t,r,i){let a,s=Vt(i?.retryDelaysMs),o;for(let h=0;h<s.length;h++){let m=s[h];m>0&&await new Promise(y=>setTimeout(y,m)),I("loader.fetch",{url:`${r}/v1/gateway/fetch`,libraryVersion:t,attempt:h+1,delayMs:m});try{let y=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(I("loader.fetch-result",{status:y.status,attempt:h+1}),y.status===401||y.status===403)throw new C("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(y.status>=500&&y.status<600){o=new U(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);continue}if(!y.ok)throw new U(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);a=await y.json(),o=null;break}catch(y){if(y instanceof C&&y.code==="LICENSE_REJECTED")throw y;o=y;}}if(o||!a)throw o instanceof C?o:new U("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)",o);let l;try{l=await fetch(a.bundleUrl);}catch(h){throw new U("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)",h)}if(!l.ok)throw new U(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`);let d=await l.arrayBuffer();return {bytes:Buffer.from(d),sha256:a.sha256,signature:a.signature,libraryVersion:a.libraryVersion,bundleVersion:a.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:i,importSPKI:a}=await import('jose'),s=await a(Ae,"RS256"),{payload:o}=await i(e,s),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(i){throw i instanceof C?i:new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SIGNATURE_INVALID)","GATEWAY_VERIFICATION_FAILED",i)}}static loadIntoVm(e){try{let t=join(homedir(),".inference-relay","gateway","runtime.cjs"),r=dirname(t),i=createRequire(t),a={exports:{}};compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(a.exports,i,a,t,r);let o=a.exports;if(!o.ClaudeCLIProvider)throw new C("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof C?t:new C("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){W.clear();}};});var Je={};$e(Je,{detectCLI:()=>$});function qt(n){let e=process.env.PATH;if(!e)return null;let t=process.platform==="win32",r=t?";":":",i=t?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(a=>a.toLowerCase()):[""];for(let a of e.split(r))if(a)for(let s of i){let o=join(a,n+s);if(existsSync(o))return o}return null}async function $(){if(!qt("claude"))return {available:false,authenticated:false};let e=null;try{let r=execSync("claude --version",{encoding:"utf-8",timeout:5e3}).trim(),i=r.match(/(\d+\.\d+\.\d+)/);e=i?i[1]:r;}catch{}let t;return e&&!Wt.some(r=>e.startsWith(r.split(".").slice(0,2).join(".")))&&(t=`CLI version ${e} is not tested with this version of inference-relay. Streaming may be unstable.`),{available:true,authenticated:true,cliVersion:e||void 0,versionWarning:t}}var Wt,te=v(()=>{Wt=["2.1.87"];});var ze,ne,re,Xe=v(()=>{G();Pe();ze="1.6.12",ne=class extends S{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await q.load(this.licenseKey,ze,void 0,this.loadOptions)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof C?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(te(),Je));return e()}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let r=JSON.stringify(e.messages).length/4+5e3,i=(r*3+1e3*15)/1e6;return {estimatedInputTokens:Math.round(r),estimatedCost:Math.round(i*1e4)/1e4,model:e.model,provider:"claude-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}},re=class extends S{type="kimi-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await q.load(this.licenseKey,ze,void 0,this.loadOptions)).KimiCLIProvider;if(!t)throw new C("[ir-system]: GATEWAY_LOAD_FAILED (REASON: STALE_BUNDLE_NO_KIMI_CLI)","GATEWAY_LOAD_FAILED");let r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,this.health.lastError=e instanceof Error?e.message:String(e),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{existsSync:e}=await import('fs'),{homedir:t}=await import('os'),{join:r}=await import('path'),i=process.env.KIMI_CODE_HOME||r(t(),".kimi-code"),a=process.env.IR_KIMI_BIN||r(i,"bin","kimi"),s=e(a),o=e(r(i,"credentials"))||e(r(i,"oauth"));return {available:s,authenticated:o,subscriptionType:o?"kimi-code":void 0}}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let t=JSON.stringify(e.messages).length/4;return {estimatedInputTokens:Math.round(t+2e3),estimatedCost:0,model:e.model,provider:"kimi-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}};});function Ze(n){return se[n]||n}function Le(n){return Qe.find(e=>e.canonical===n)?.provider}var Qe,se,xe=v(()=>{Qe=[{canonical:"claude-haiku-4-5",apiId:"claude-haiku-4-5-20251001",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[.8,4]},{canonical:"claude-sonnet-4-6",apiId:"claude-sonnet-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[3,15]},{canonical:"claude-opus-4-6",apiId:"claude-opus-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[15,75]},{canonical:"gpt-4.1",apiId:"gpt-4.1",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[2,8]},{canonical:"gpt-4.1-mini",apiId:"gpt-4.1-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.4,1.6]},{canonical:"gpt-4.1-nano",apiId:"gpt-4.1-nano",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.1,.4]},{canonical:"gpt-4o",apiId:"gpt-4o",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[2.5,10]},{canonical:"gpt-4o-mini",apiId:"gpt-4o-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[.15,.6]},{canonical:"o4-mini",apiId:"o4-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o3",apiId:"o3",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[.4,1.6]},{canonical:"o3-mini",apiId:"o3-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o1",apiId:"o1",provider:"openai-api",capabilities:{streaming:false,tools:false,multimodal:false,contextWindow:2e5},pricing:[15,60]},{canonical:"llama3.1",apiId:"llama3.1",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"mistral",apiId:"mistral",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}},{canonical:"mistral-nemo",apiId:"mistral-nemo",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"llava",apiId:"llava",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:true,contextWindow:32e3}},{canonical:"qwen2:0.5b",apiId:"qwen2:0.5b",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}}],se=Object.fromEntries(Qe.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));se["claude-sonnet-4"]="claude-sonnet-4-20250514";se["claude-opus-4"]="claude-opus-4-20250514";se["claude-haiku-4"]="claude-haiku-4-5-20251001";});function et(n){if(Oe[n])return Oe[n];for(let[e,t]of Object.entries(Oe))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var jt,Jt,Oe,ie,tt=v(()=>{G();xe();jt="https://api.anthropic.com/v1/messages",Jt="2023-06-01",Oe={"claude-sonnet-4-5-20250514":[3,15],"claude-sonnet-4-20250514":[3,15],"claude-haiku-4-5-20250414":[.8,4],"claude-opus-4-20250514":[15,75]};ie=class extends S{type="anthropic-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;dangerousDirectBrowserAccess;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||jt,this.dangerousDirectBrowserAccess=e.dangerousDirectBrowserAccess??false;}async probe(){try{let e=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{available:!0,authenticated:!1}:e.ok||e.status===429?{available:!0,authenticated:!0,rateLimitTier:e.headers.get("anthropic-ratelimit-tier")??void 0}:e.status===529?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),i=this.buildRequestBody(e,false),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(i),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let s=await a.json(),o=Date.now()-r;this.recordSuccess();let[l,d]=et(s.model||e.model),c=((s.usage?.input_tokens||0)*l+(s.usage?.output_tokens||0)*d)/1e6,h={},m=["request-id","x-request-id","anthropic-ratelimit-requests-limit","anthropic-ratelimit-requests-remaining","anthropic-ratelimit-requests-reset","anthropic-ratelimit-tokens-limit","anthropic-ratelimit-tokens-remaining","anthropic-ratelimit-tokens-reset","anthropic-ratelimit-tier"];for(let y of m){let b=a.headers.get(y);b&&(h[y]=b);}return {content:s.content||[],model:s.model||e.model,usage:{input_tokens:s.usage?.input_tokens||0,output_tokens:s.usage?.output_tokens||0},stop_reason:s.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:o,fallbackChain:["anthropic-api:success"],headers:Object.keys(h).length>0?h:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(i.ok||this.handleErrorResponse(i),!i.body)throw new Error("ANTHROPIC_API_ERROR: Response body is null \u2014 streaming unavailable");let a=i.body.getReader(),s=new TextDecoder;return (async function*(){let o="",l=false;try{for(;;){let{done:d,value:c}=await a.read();if(d)break;o+=s.decode(c,{stream:!0});let h=o.split(`
11
+ -----END PUBLIC KEY-----`,Ve={version:"1.0.0",cliVersion:"2.1.87",eventTypes:{system:"system",streamEvent:"stream_event",assistant:"assistant",result:"result"},fieldMappings:{sessionId:"session_id",model:"model",cliVersion:"claude_code_version",content:"content",usage:"usage",inputTokens:"input_tokens",outputTokens:"output_tokens",stopReason:"stop_reason",isError:"is_error",totalCostUsd:"total_cost_usd",durationMs:"duration_ms",error:"error",event:"event"},syntheticModel:"<synthetic>"},K=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),i=await r(Ae,"RS256"),{payload:a}=await t(e,i),s=JSON.parse(new TextDecoder().decode(a));return this.verificationFailures=0,this.cachedManifest=s,this.currentSecurityState="SEC_NOMINAL",{manifest:s,securityState:"SEC_NOMINAL"}}catch{if(this.verificationFailures++,this.verificationFailures>=3){this.currentSecurityState="SEC_DEGRADED";let t=2e3+Math.random()*3e3;return await new Promise(r=>setTimeout(r,t)),console.warn("[inference-relay] Logic synchronization mismatch. Routing via local recovery."),{manifest:Ve,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Ve,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Mt=new K;});function I(n,...e){process.env.IR_DEBUG==="1"&&console.error(`[ir-debug:${n}]`,...e);}var we=v(()=>{});function Se(n){return join(homedir(),".inference-relay","gateway",n)}function We(n){return join(Se(n),"bundle.js")}function qe(n){return join(Se(n),"meta.json")}function Vt(n){let e=(r,i)=>{if(!Array.isArray(r)||r.length===0)return null;let a=[];for(let s of r){let o=typeof s=="string"?Number(s):s;if(typeof o!="number"||!Number.isFinite(o)||o<0)return I("loader.retry-config-invalid",{source:i,badValue:s}),null;a.push(o);}return a};if(n!==void 0){let r=e(n,"option");if(r)return r}let t=process.env.IR_GATEWAY_RETRY_DELAYS_MS;if(t){let r=e(t.split(",").map(i=>i.trim()),"env");if(r)return r}return $t}var Bt,C,U,W,$t,q,Pe=v(()=>{ke();we();Bt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";C=class extends Error{constructor(t,r,i){super(t);this.code=r;this.cause=i;this.name="GatewayLoaderError";}code;cause},U=class extends C{constructor(e,t){super(e,"GATEWAY_FETCH_FAILED",t);}},W=new Map,$t=[0,1e3,4e3];q=class{static async load(e,t,r=Bt,i){let a=`${t}:${e.slice(-8)}`;if(W.has(a))return W.get(a);try{let m=await this.tryLoadFromDisk(t);if(m)return I("loader.cache-hit",{libraryVersion:t}),W.set(a,m),m}catch{}I("loader.cache-miss",{libraryVersion:t});let{bytes:s,sha256:o,signature:l,libraryVersion:d}=await this.fetchFromAuthority(e,t,r,i);if(createHash("sha256").update(s).digest("hex")!==o)throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,d,o);try{let m=Se(t);mkdirSync(m,{recursive:!0}),writeFileSync(We(t),s),writeFileSync(qe(t),JSON.stringify({sha256:o,signature:l,libraryVersion:d}));}catch{}let h=this.loadIntoVm(s.toString("utf-8"));return W.set(a,h),h}static async loadFromDisk(e){if(!existsSync(e))throw new C(`[ir-system]: GATEWAY_LOAD_FAILED (REASON: BUNDLE_NOT_FOUND at ${e})`,"GATEWAY_LOAD_FAILED");let t=readFileSync(e,"utf-8");return this.loadIntoVm(t)}static async tryLoadFromDisk(e){let t=We(e),r=qe(e);if(!existsSync(t)||!existsSync(r))return null;let i=readFileSync(t),a=JSON.parse(readFileSync(r,"utf-8"));return createHash("sha256").update(i).digest("hex")!==a.sha256?null:(await this.verifySignature(a.signature,a.libraryVersion,a.sha256),this.loadIntoVm(i.toString("utf-8")))}static async fetchFromAuthority(e,t,r,i){let a,s=Vt(i?.retryDelaysMs),o;for(let h=0;h<s.length;h++){let m=s[h];m>0&&await new Promise(y=>setTimeout(y,m)),I("loader.fetch",{url:`${r}/v1/gateway/fetch`,libraryVersion:t,attempt:h+1,delayMs:m});try{let y=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(I("loader.fetch-result",{status:y.status,attempt:h+1}),y.status===401||y.status===403)throw new C("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(y.status>=500&&y.status<600){o=new U(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);continue}if(!y.ok)throw new U(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);a=await y.json(),o=null;break}catch(y){if(y instanceof C&&y.code==="LICENSE_REJECTED")throw y;o=y;}}if(o||!a)throw o instanceof C?o:new U("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)",o);let l;try{l=await fetch(a.bundleUrl);}catch(h){throw new U("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)",h)}if(!l.ok)throw new U(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`);let d=await l.arrayBuffer();return {bytes:Buffer.from(d),sha256:a.sha256,signature:a.signature,libraryVersion:a.libraryVersion,bundleVersion:a.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:i,importSPKI:a}=await import('jose'),s=await a(Ae,"RS256"),{payload:o}=await i(e,s),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(i){throw i instanceof C?i:new C("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SIGNATURE_INVALID)","GATEWAY_VERIFICATION_FAILED",i)}}static loadIntoVm(e){try{let t=join(homedir(),".inference-relay","gateway","runtime.cjs"),r=dirname(t),i=createRequire(t),a={exports:{}};compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(a.exports,i,a,t,r);let o=a.exports;if(!o.ClaudeCLIProvider)throw new C("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof C?t:new C("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){W.clear();}};});var Je={};$e(Je,{detectCLI:()=>$});function qt(n){let e=process.env.PATH;if(!e)return null;let t=process.platform==="win32",r=t?";":":",i=t?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(a=>a.toLowerCase()):[""];for(let a of e.split(r))if(a)for(let s of i){let o=join(a,n+s);if(existsSync(o))return o}return null}async function $(){if(!qt("claude"))return {available:false,authenticated:false};let e=null;try{let r=execSync("claude --version",{encoding:"utf-8",timeout:5e3}).trim(),i=r.match(/(\d+\.\d+\.\d+)/);e=i?i[1]:r;}catch{}let t;return e&&!Wt.some(r=>e.startsWith(r.split(".").slice(0,2).join(".")))&&(t=`CLI version ${e} is not tested with this version of inference-relay. Streaming may be unstable.`),{available:true,authenticated:true,cliVersion:e||void 0,versionWarning:t}}var Wt,te=v(()=>{Wt=["2.1.87"];});var ze,ne,re,Xe=v(()=>{G();Pe();ze="1.6.13",ne=class extends S{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await q.load(this.licenseKey,ze,void 0,this.loadOptions)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof C?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(te(),Je));return e()}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let r=JSON.stringify(e.messages).length/4+5e3,i=(r*3+1e3*15)/1e6;return {estimatedInputTokens:Math.round(r),estimatedCost:Math.round(i*1e4)/1e4,model:e.model,provider:"claude-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}},re=class extends S{type="kimi-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await q.load(this.licenseKey,ze,void 0,this.loadOptions)).KimiCLIProvider;if(!t)throw new C("[ir-system]: GATEWAY_LOAD_FAILED (REASON: STALE_BUNDLE_NO_KIMI_CLI)","GATEWAY_LOAD_FAILED");let r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,this.health.lastError=e instanceof Error?e.message:String(e),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{existsSync:e}=await import('fs'),{homedir:t}=await import('os'),{join:r}=await import('path'),i=process.env.KIMI_CODE_HOME||r(t(),".kimi-code"),a=process.env.IR_KIMI_BIN||r(i,"bin","kimi"),s=e(a),o=e(r(i,"credentials"))||e(r(i,"oauth"));return {available:s,authenticated:o,subscriptionType:o?"kimi-code":void 0}}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let t=JSON.stringify(e.messages).length/4;return {estimatedInputTokens:Math.round(t+2e3),estimatedCost:0,model:e.model,provider:"kimi-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}};});function Ze(n){return se[n]||n}function Le(n){return Qe.find(e=>e.canonical===n)?.provider}var Qe,se,xe=v(()=>{Qe=[{canonical:"claude-haiku-4-5",apiId:"claude-haiku-4-5-20251001",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[.8,4]},{canonical:"claude-sonnet-4-6",apiId:"claude-sonnet-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[3,15]},{canonical:"claude-opus-4-6",apiId:"claude-opus-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[15,75]},{canonical:"gpt-4.1",apiId:"gpt-4.1",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[2,8]},{canonical:"gpt-4.1-mini",apiId:"gpt-4.1-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.4,1.6]},{canonical:"gpt-4.1-nano",apiId:"gpt-4.1-nano",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.1,.4]},{canonical:"gpt-4o",apiId:"gpt-4o",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[2.5,10]},{canonical:"gpt-4o-mini",apiId:"gpt-4o-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[.15,.6]},{canonical:"o4-mini",apiId:"o4-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o3",apiId:"o3",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[.4,1.6]},{canonical:"o3-mini",apiId:"o3-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o1",apiId:"o1",provider:"openai-api",capabilities:{streaming:false,tools:false,multimodal:false,contextWindow:2e5},pricing:[15,60]},{canonical:"llama3.1",apiId:"llama3.1",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"mistral",apiId:"mistral",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}},{canonical:"mistral-nemo",apiId:"mistral-nemo",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"llava",apiId:"llava",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:true,contextWindow:32e3}},{canonical:"qwen2:0.5b",apiId:"qwen2:0.5b",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}}],se=Object.fromEntries(Qe.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));se["claude-sonnet-4"]="claude-sonnet-4-20250514";se["claude-opus-4"]="claude-opus-4-20250514";se["claude-haiku-4"]="claude-haiku-4-5-20251001";});function et(n){if(Oe[n])return Oe[n];for(let[e,t]of Object.entries(Oe))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var jt,Jt,Oe,ie,tt=v(()=>{G();xe();jt="https://api.anthropic.com/v1/messages",Jt="2023-06-01",Oe={"claude-sonnet-4-5-20250514":[3,15],"claude-sonnet-4-20250514":[3,15],"claude-haiku-4-5-20250414":[.8,4],"claude-opus-4-20250514":[15,75]};ie=class extends S{type="anthropic-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;dangerousDirectBrowserAccess;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||jt,this.dangerousDirectBrowserAccess=e.dangerousDirectBrowserAccess??false;}async probe(){try{let e=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{available:!0,authenticated:!1}:e.ok||e.status===429?{available:!0,authenticated:!0,rateLimitTier:e.headers.get("anthropic-ratelimit-tier")??void 0}:e.status===529?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),i=this.buildRequestBody(e,false),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(i),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let s=await a.json(),o=Date.now()-r;this.recordSuccess();let[l,d]=et(s.model||e.model),c=((s.usage?.input_tokens||0)*l+(s.usage?.output_tokens||0)*d)/1e6,h={},m=["request-id","x-request-id","anthropic-ratelimit-requests-limit","anthropic-ratelimit-requests-remaining","anthropic-ratelimit-requests-reset","anthropic-ratelimit-tokens-limit","anthropic-ratelimit-tokens-remaining","anthropic-ratelimit-tokens-reset","anthropic-ratelimit-tier"];for(let y of m){let b=a.headers.get(y);b&&(h[y]=b);}return {content:s.content||[],model:s.model||e.model,usage:{input_tokens:s.usage?.input_tokens||0,output_tokens:s.usage?.output_tokens||0},stop_reason:s.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:o,fallbackChain:["anthropic-api:success"],headers:Object.keys(h).length>0?h:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(i.ok||this.handleErrorResponse(i),!i.body)throw new Error("ANTHROPIC_API_ERROR: Response body is null \u2014 streaming unavailable");let a=i.body.getReader(),s=new TextDecoder;return (async function*(){let o="",l=false;try{for(;;){let{done:d,value:c}=await a.read();if(d)break;o+=s.decode(c,{stream:!0});let h=o.split(`
12
12
  `);o=h.pop()||"";let m=null;for(let y of h)if(y.startsWith("event: "))m=y.slice(7).trim();else if(y.startsWith("data: ")){let b=y.slice(6);if(m&&b)try{let p=JSON.parse(b);p.type==="message_stop"&&(l=!0),yield p;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",b.substring(0,100));}m=null;}else y.trim()===""&&(m=null);}l||(yield {type:"message_stop"});}finally{try{a.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,i=t+r,[a,s]=et(e.model),o=(i*a+1e3*s)/1e6;return {estimatedInputTokens:i,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"anthropic-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){let e={"content-type":"application/json","x-api-key":this.apiKey,"anthropic-version":Jt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:Ze(e.model),max_tokens:e.max_tokens,messages:e.messages};return t&&(r.stream=true),e.system&&(r.system=e.system),e.temperature!==void 0&&(r.temperature=e.temperature),e.tools&&e.tools.length>0&&(r.tools=e.tools),e.metadata&&(r.metadata=e.metadata),r}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),i=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${i}ms`,this.health.lastCheckAt=Date.now();let a=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${i}ms`);throw a.retryAfterMs=i,a}throw t===529?(this.health.status="degraded",this.health.lastError="API overloaded",this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_OVERLOADED: API is temporarily overloaded (529)")):(this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`ANTHROPIC_API_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};});function rt(n){if(De[n])return De[n];for(let[e,t]of Object.entries(De))if(n.startsWith(e))return t;return [2.5,10]}function Xt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Qt(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let i=Xt(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let a=r.content.filter(s=>s.type==="tool_use");if(a.length>0){t.push({role:"assistant",content:i||"",tool_calls:a.map(s=>({id:s.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:s.name,arguments:typeof s.input=="string"?s.input:JSON.stringify(s.input)}}))});continue}}t.push({role:r.role,content:i});}return t}function st(n){switch(n){case "stop":return "end_turn";case "length":return "max_tokens";case "tool_calls":case "function_call":return "tool_use";default:return "end_turn"}}var zt,nt,De,ae,it=v(()=>{G();zt="https://api.openai.com/v1/chat/completions",nt=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],De={"gpt-4.1":[2,8],"gpt-4.1-mini":[.4,1.6],"gpt-4.1-nano":[.1,.4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"o4-mini":[1.1,4.4],o3:[.4,1.6],"o3-mini":[1.1,4.4],o1:[15,60],"o1-mini":[3,12],"gpt-4-turbo":[10,30],"gpt-4":[30,60],"gpt-3.5-turbo":[.5,1.5]};ae=class extends S{type="openai-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||zt;}async probe(){try{let e=this.baseUrl.replace(/\/chat\/completions$/,"/models"),t=await fetch(e,{method:"GET",headers:this.buildHeaders()});return t.status===401?{available:!0,authenticated:!1}:t.ok||t.status===429?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),i=this.buildRequestBody(e,false),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(i),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let s=await a.json(),o=Date.now()-r;this.recordSuccess();let l=s.choices?.[0],d=[];if(l?.message?.content&&d.push({type:"text",text:l.message.content}),l?.message?.tool_calls)for(let u of l.message.tool_calls)d.push({type:"tool_use",id:u.id,name:u.function?.name,input:u.function?.arguments?JSON.parse(u.function.arguments):{}});let c=s.usage?.prompt_tokens||0,h=s.usage?.completion_tokens||0,[m,y]=rt(s.model||e.model),b=(c*m+h*y)/1e6,p={},f=["x-request-id","x-ratelimit-limit-requests","x-ratelimit-remaining-requests","x-ratelimit-limit-tokens","x-ratelimit-remaining-tokens","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];for(let u of f){let g=a.headers.get(u);g&&(p[u]=g);}return {content:d,model:s.model||e.model,usage:{input_tokens:c,output_tokens:h},stop_reason:st(l?.finish_reason),provider:"openai-api",costUsd:Math.round(b*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(p).length>0?p:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(i.ok||this.handleErrorResponse(i),!i.body)throw new Error("OPENAI_API_ERROR: Response body is null \u2014 streaming unavailable");let a=i.body.getReader(),s=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false,h,m;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:y,value:b}=await a.read();if(y)break;l+=s.decode(b,{stream:!0});let p=l.split(`
13
13
  `);l=p.pop()||"";for(let f of p){if(!f.startsWith("data: "))continue;let u=f.slice(6).trim();if(u==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:h||{}},yield {type:"message_stop"},c=!0;return}try{let g=JSON.parse(u);g.usage&&(h={input_tokens:g.usage.prompt_tokens||0,output_tokens:g.usage.completion_tokens||0});let R=g.choices?.[0];if(!R)continue;let E=R.delta;E?.content&&!d&&(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),E?.content&&(yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:E.content}}),R.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),m=st(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:h||{}},yield {type:"message_stop"});}finally{try{a.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,i=t+r,[a,s]=rt(e.model),o=(i*a+1e3*s)/1e6;return {estimatedInputTokens:i,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"openai-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}buildRequestBody(e,t){let r=e.model.toLowerCase();if(!nt.some(o=>r.startsWith(o)))throw new Error(`OPENAI_MODEL_TRANSLATION_REQUIRED: The OpenAI provider received the model name '${e.model}', which does not match any known OpenAI model prefix (${nt.join(", ")}). The relay does NOT auto-translate model names across providers in v1.3.x. Either (a) pass an OpenAI model name like 'gpt-4o-mini' when routing to this provider, or (b) route non-OpenAI models through a provider that understands them (e.g. 'anthropic-api' for Claude models).`);let a=Qt(e.messages,e.system),s={model:e.model,max_tokens:e.max_tokens,messages:a};return t&&(s.stream=true,s.stream_options={include_usage:true}),e.temperature!==void 0&&(s.temperature=e.temperature),e.tools&&e.tools.length>0&&(s.tools=e.tools),s}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("OPENAI_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),i=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${i}ms`,this.health.lastCheckAt=Date.now();let a=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${i}ms`);throw a.retryAfterMs=i,a}throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`OPENAI_API_ERROR: Request failed with status ${t}`)}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};});function en(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function tn(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:en(r.content)});return t}var Zt,oe,at=v(()=>{G();Zt="http://localhost:11434";oe=class extends S{type="ollama";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.baseUrl=e?.baseUrl?.replace(/\/$/,"")||Zt;}async probe(){try{return (await fetch(`${this.baseUrl}/api/tags`,{method:"GET"})).ok?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),i=this.buildRequestBody(e,false),a=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let s=await a.json(),o=Date.now()-r;this.recordSuccess();let l=[];s.message?.content&&l.push({type:"text",text:s.message.content});let d=s.prompt_eval_count||0,c=s.eval_count||0;return {content:l,model:s.model||e.model,usage:{input_tokens:d,output_tokens:c},stop_reason:(s.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:o,fallbackChain:["ollama:success"]}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),i=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),signal:t?.signal});if(i.ok||this.handleErrorResponse(i),!i.body)throw new Error("OLLAMA_ERROR: Response body is null \u2014 streaming unavailable");let a=i.body.getReader(),s=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:h,value:m}=await a.read();if(h)break;l+=s.decode(m,{stream:!0});let y=l.split(`
14
14
  `);l=y.pop()||"";for(let b of y){let p=b.trim();if(p)try{let f=JSON.parse(p);if(f.message?.content&&(d||(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:f.message.content}}),f.done){d&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:f.prompt_eval_count||0,output_tokens:f.eval_count||0}},yield {type:"message_stop"},c=!0;return}}catch{}}}c||(yield {type:"message_stop"});}finally{try{a.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0;return {estimatedInputTokens:t+r,estimatedCost:0,model:e.model,provider:"ollama"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildRequestBody(e,t){if(e.tools&&e.tools.length>0)throw new Error(`OLLAMA_TOOLS_NOT_SUPPORTED: The Ollama provider received ${e.tools.length} tool definition(s) in params.tools, but this provider does not implement function calling in v1.3.x. For tool-use workflows route to 'anthropic-api' or 'openai-api' instead. Tracking issue: 1.4.0 ships an Ollama tool-use shim for models that support native function calling (llama3.1, mistral-nemo, etc.).`);let r=tn(e.messages,e.system),i={model:e.model,messages:r,stream:t};return e.temperature!==void 0&&(i.options={temperature:e.temperature}),i}handleErrorResponse(e){let t=e.status;throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),t===404?(this.health.status="unhealthy",this.health.lastError="Model not found",new Error("OLLAMA_MODEL_NOT_FOUND: Requested model is not available locally (404)")):(this.health.status="unhealthy",this.health.lastError=`Request failed with status ${t}`,new Error(`OLLAMA_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};});var le,ot=v(()=>{le=class extends EventEmitter{constructor(){super(),this.setMaxListeners(50);}emitTyped(e){return this.emit(e.kind,e)}onTyped(e,t){return this.on(e,t)}offTyped(e,t){return this.off(e,t)}};});function ce(n,e){if(e instanceof C)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,gt)||"unknown"}`}function lt(n){let e=n.filter(t=>t.includes(":failed:"));return e.length===0?false:e.every(t=>t.endsWith(":failed:request_too_large"))}function ut(n){return n.messages.some(e=>typeof e.content=="string"?false:Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"))}function ue(n){if(!(n instanceof Error))return "unknown";let e=n.code;if(typeof e=="string"){if(e==="LICENSE_REJECTED")return "auth_failed";if(e==="GATEWAY_FETCH_FAILED"||e==="GATEWAY_VERIFICATION_FAILED"||e==="GATEWAY_LOAD_FAILED")return "gateway_unavailable"}let t=n.message.toLowerCase(),r=n.name.toLowerCase();return t.includes("prompt is too long")||t.includes("prompt too long")||t.includes("prompt_too_large")||t.includes("input length")||t.includes("input is too long")||t.includes("context_length_exceeded")||t.includes("context length exceeded")||t.includes("request too large")||t.includes("tokens exceed")||t.includes("exceeds the maximum")||t.includes("too many tokens")?"request_too_large":t.includes("code 3221226505")||t.includes("cli exited with code 3 ")||t.includes("cli stream exited with code 3 ")||t.includes("bun has crashed")||t.includes("illegal instruction")||t.includes("stream ended without producing any content")||t.includes("cli returned empty response")||t.includes("cli closed stdout without sending any response")||t.includes("kimi_stall_silent")?"transient":t.includes("credit balance is too low")||t.includes("credit balance too low")?"auth_failed":t.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_cli_too_old:")||t.startsWith("stream_json_cli_too_old:")?"provider_incompatible":t.includes("rate limit")||t.includes("429")||r.includes("ratelimit")?"rate_limited":t.includes("auth")||t.includes("401")||t.includes("403")||t.includes("unauthorized")||t.includes("forbidden")?"auth_failed":t.includes("timeout")||t.includes("timed out")||t.includes("aborted")||r==="aborterror"||r==="timeouterror"?"timeout":"unknown"}function dt(n){return [...n].sort((e,t)=>e.priority-t.priority)}function pt(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function rn(n,e,t){typeof t.input_tokens=="number"&&(n.inputTokens=t.input_tokens),typeof t.output_tokens=="number"&&(e==="anthropic-api"||e==="claude-cli"?n.outputTokens+=t.output_tokens:n.outputTokens=t.output_tokens);}function mt(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function sn(n,e){if(e.type==="content_block_start"){let t=e.content_block;t?.type==="text"?n.content.push({type:"text",text:t.text||"",open:true}):t?.type==="tool_use"&&n.content.push({type:"tool_use",id:t.id,name:t.name,input:{},_partialJson:"",open:true});}else if(e.type==="content_block_delta"){let t=n.content[n.content.length-1];if(!t)return;t.type==="text"&&e.delta?.type==="text_delta"?t.text+=e.delta.text||"":t.type==="tool_use"&&e.delta?.type==="input_json_delta"&&(t._partialJson=(t._partialJson||"")+(e.delta.partial_json||""));}else if(e.type==="content_block_stop"){for(let t=n.content.length-1;t>=0;t--)if(n.content[t].open){if(n.content[t].open=false,n.content[t].type==="tool_use"){let r=n.content[t];try{r.input=JSON.parse(r._partialJson||"{}");}catch{}delete r._partialJson;}break}}}function an(n,e,t,r,i){if(i&&n.type==="content_block_delta"&&n.index===i.fromIndex)return {action:"yield",event:{...n,index:i.toIndex}};if(i&&n.type==="content_block_stop"&&n.index===i.fromIndex)return {action:"suppress",coalesceMode:null,coalesceModeCleared:true};if(r&&n.type==="content_block_start"&&n.content_block?.type==="text"){let s=t.content[t.content.length-1];if(s?.type==="text"&&s.open===true)return {action:"suppress",coalesceMode:{fromIndex:n.index+e,toIndex:t.content.length-1},clearedJustFailedOver:true}}let a=r&&n.type==="content_block_start";return typeof n.index=="number"&&e>0?{action:"yield",event:{...n,index:n.index+e},clearedJustFailedOver:a}:{action:"yield",event:n,clearedJustFailedOver:a}}function on(n){let e=[];for(let t of n)t.type==="text"?t.text&&e.push({type:"text",text:t.text}):t.type==="tool_use"&&!t.open&&t.input&&Object.keys(t.input).length>0&&e.push({type:"tool_use",id:t.id,name:t.name,input:t.input});return e}function ln(n,e){return n?`${n}
15
15
 
16
- ${e}`:e}function ht(n){let e=0;for(let t of n.content)t.type==="text"?e+=t.text.length:t.type==="tool_use"&&(e+=(t._partialJson||"").length);return e}function cn(n){return Math.max(0,n.content.length-1)}async function*un(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}var gt,ct,F,de,pe,Me=v(()=>{Ce();ot();xe();Pe();we();gt=200;ct=new Set(["anthropic-api","openai-api","ollama"]),F=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}},de=class extends F{constructor(e){super(e);}};pe=class n{healthMap=new Map;engineEvents=new le;static UNHEALTHY_TTL_DEFAULT_MS=300*1e3;static UNHEALTHY_TTL_AUTH_MS=30*1e3;getHealthStatus(e){let t=this.healthMap.get(e);if(!t)return "healthy";let r=t.ttlMs??n.UNHEALTHY_TTL_DEFAULT_MS;if(t.status==="unhealthy"&&Date.now()-t.updatedAt>=r){let i=Date.now()-t.updatedAt;return this.healthMap.delete(e),I("engine.recovered",{providerType:e,ageMs:i,ttlMs:r}),"healthy"}return t.status}markUnhealthy(e,t,r){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now(),ttlMs:r}),I("engine.unhealthy",{providerType:e,reason:t,ttlMs:r});}markDegraded(e,t){this.healthMap.set(e,{status:"degraded",lastError:t,updatedAt:Date.now()});}markHealthy(e){this.healthMap.set(e,{status:"healthy",updatedAt:Date.now()});}resetHealth(){this.healthMap.clear();}async execute(e,t,r){let i=dt(t),a=[],s=ut(e),o=randomUUID(),l=Date.now();for(let d of i){let c=d.type;if(this.getHealthStatus(c)==="unhealthy"){a.push(`${c}:skipped:unhealthy`);continue}if(s&&!d.supportsMultimodal){a.push(`${c}:skipped:no_multimodal`);continue}let m=Le(e.model);if(m&&m!==c&&ct.has(c)){a.push(`${c}:skipped:wrong_provider`);continue}let y=r?.maxSameProviderRetries??2,b=0,p=null,f=false;for(;!f;)try{let u=await d.execute(e,{signal:r?.signal});return f=!0,this.markHealthy(c),b>0&&a.push(`${c}:retry_success:${b}`),a.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd??0}],provider:c,model:u.model,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd,durationMs:u.durationMs??Date.now()-l,stopReason:u.stop_reason,fallbackChain:a,rateLimitHit:!1,securityState:r?.licenseState}),{...u,fallbackChain:a}}catch(u){if(u?.name==="AbortError"||r?.signal?.aborted)throw u;if(ue(u)==="transient"&&b<y){b++;let R=250*Math.pow(2,b-1);I("engine.transient-retry",{id:c,attempt:b,backoffMs:R,msg:String(u?.message||"").slice(0,120)}),a.push(`${c}:retry:${b}`),await new Promise(E=>setTimeout(E,R));continue}p=u;break}if(!f){let u=p;switch(ue(u)){case "rate_limited":d.reportRateLimit({provider:c,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(c,"rate_limited"),a.push(`${c}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(c,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),a.push(`${c}:failed:auth_failed`);break;case "timeout":a.push(`${c}:failed:timeout`);break;case "provider_incompatible":a.push(`${c}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(c,"gateway_unavailable"),a.push(ce(c,u));break;case "request_too_large":a.push(`${c}:failed:request_too_large`);break;case "transient":this.markDegraded(c,"transient_exhausted"),a.push(`${c}:failed:transient_exhausted`);break;default:a.push(ce(c,u));break}if(r?.subscriptionOnly&&c==="claude-cli"){a.push("subscription_only:cascade_halted");break}}}throw I("engine.cascade-exhausted",{chain:a,mode:"execute"}),lt(a)?new de(a):new F(a)}async stream(e,t,r){let i=randomUUID(),a=dt(t),s=ut(e),o=Date.now(),l=[],d=null,c=null;for(let u of a){let g=u.type;if(this.getHealthStatus(g)==="unhealthy"){l.push(`${g}:skipped:unhealthy`);continue}if(s&&!u.supportsMultimodal){l.push(`${g}:skipped:no_multimodal`);continue}if(!u.supportsStreaming){l.push(`${g}:skipped:no_streaming`);continue}let R=Le(e.model);if(R&&R!==g&&ct.has(g)){l.push(`${g}:skipped:wrong_provider`);continue}try{c=await u.streamRaw(e,{signal:r?.signal}),d=u,l.push(`${g}:success`);break}catch(E){if(E?.name==="AbortError"||r?.signal?.aborted)throw E;switch(ue(E)){case "rate_limited":u.reportRateLimit({provider:g,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(g,"rate_limited"),l.push(`${g}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(g,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),l.push(`${g}:failed:auth_failed`);break;case "timeout":l.push(`${g}:failed:timeout`);break;case "provider_incompatible":l.push(`${g}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(g,"gateway_unavailable"),l.push(ce(g,E));break;case "request_too_large":l.push(`${g}:failed:request_too_large`);break;case "transient":this.markDegraded(g,"transient_exhausted"),l.push(`${g}:failed:transient_exhausted`);break;default:l.push(ce(g,E));break}if(r?.subscriptionOnly&&g==="claude-cli"){l.push("subscription_only:cascade_halted");break}}}if(!d||!c)throw I("engine.cascade-exhausted",{chain:l,mode:"stream"}),lt(l)?new de(l):new F(l);let m=this,y=r?.maxMidStreamFailovers??2,b=new Set([d]);async function*p(){let u=d,g=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},E={segments:[]},k=pt(u.type);E.segments.push(k);let Fe=0,z=null,X=false,ve=y,V="",Y="";for(m.emitEngineEvent({kind:"segment_start",callId:i,id:randomUUID(),ts:Date.now(),provider:u.type});;)try{for(;;){let T=await g.next();if(T.done)break;let N=T.value,x=an(N,Fe,R,X,z);if(x.action==="suppress"){"coalesceMode"in x&&(z=x.coalesceMode),x.clearedJustFailedOver&&(X=!1);continue}x.coalesceModeCleared&&(z=null),x.clearedJustFailedOver&&(X=!1);let A=x.event;if(sn(R,A),A.type==="message_start"){if(E.segments.length>1)continue;V=A.message?.model||V,A.message?.usage?.input_tokens!=null&&(k.inputTokens=A.message.usage.input_tokens);}if(A.type==="message_delta"&&(A.delta?.stop_reason&&(Y=A.delta.stop_reason),A.usage)){rn(k,u.type,A.usage),yield {...A,usage:void 0};continue}if(A.type==="message_stop")break;yield A;}if(R.content.length===0&&k.outputTokens===0)throw new Error("stream ended without producing any content");m.markHealthy(u.type),m.emitEngineEvent({kind:"segment_complete",callId:i,id:randomUUID(),ts:Date.now(),provider:u.type,usage:{...k}});let P=mt(E.segments);yield {type:"message_delta",delta:{stop_reason:Y||"end_turn"},usage:P},yield {type:"message_stop"},m.emitEngineEvent({kind:"stream_complete",callId:i,id:randomUUID(),ts:Date.now(),stitched:E.segments.length>1,segments:E.segments.map(T=>({...T})),provider:E.segments.map(T=>T.provider).join("+"),model:V,inputTokens:P.input_tokens,outputTokens:P.output_tokens,costUsd:E.segments.reduce((T,N)=>T+N.costUsd,0),userCostUsd:E.segments.reduce((T,N)=>T+N.userCostUsd,0),durationMs:Date.now()-o,stopReason:Y||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(P){if(P?.name==="AbortError"||r?.signal?.aborted)throw P;let T=ue(P);try{await g.return?.();}catch{}if(m.markUnhealthy(u.type,String(P)),m.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:i,id:randomUUID(),ts:Date.now(),from:u.type,bytesBuffered:ht(R),errorClass:T,retriesLeft:ve}),l.push(`${u.type}:partial(${ht(R)}b)`),ve<=0)throw m.emitTerminalExhaustion(i,E,V,Y,l,o,r?.licenseState),P;let N=on(R.content),x=[...e.messages,{role:"assistant",content:N}],A=null,Q=null,He=u;for(;;){let O=m.nextHealthyProvider(a,He,s,b);if(!O)break;He=O,b.add(O);let Ot={...e,messages:x,...O.type!=="anthropic-api"&&O.type!=="claude-cli"?{system:ln(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{Q=await O.streamRaw(Ot,{signal:r?.signal}),A=O;break}catch(Be){m.markUnhealthy(O.type,String(Be)),l.push(`${O.type}:failed_connect:${String(Be).slice(0,gt)}`);}}if(!A||!Q)throw m.emitTerminalExhaustion(i,E,V,Y,l,o,r?.licenseState),P;l.push(`${A.type}:stitched`),m.emitEngineEvent({kind:"mid_stream_failover_success",callId:i,id:randomUUID(),ts:Date.now(),from:u.type,to:A.type}),Fe=cn(R)+1,ve--,u=A,g=Q[Symbol.asyncIterator](),X=true,z=null,k=pt(u.type),E.segments.push(k),m.emitEngineEvent({kind:"segment_start",callId:i,id:randomUUID(),ts:Date.now(),provider:u.type});}}let f=p();return r?.licenseState==="SEC_DEGRADED"&&(f=un(f)),Z(f)}nextHealthyProvider(e,t,r,i){let a=e.indexOf(t);if(a===-1)return null;for(let s=a+1;s<e.length;s++){let o=e[s];if(!i.has(o)&&!(r&&!o.supportsMultimodal)&&o.supportsStreaming)return o}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,i,a,s,o){let l=mt(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(d=>({...d})),provider:t.segments.map(d=>d.provider).join("+"),model:r,inputTokens:l.input_tokens,outputTokens:l.output_tokens,costUsd:t.segments.reduce((d,c)=>d+c.costUsd,0),userCostUsd:t.segments.reduce((d,c)=>d+c.userCostUsd,0),durationMs:Date.now()-s,stopReason:i||"error",fallbackChain:a,rateLimitHit:false,securityState:o});}};});function yt(n,e){if(e==="prefer-user"){let i=n.filter(s=>s.type==="claude-cli"),a=n.filter(s=>s.type!=="claude-cli");return [...i,...a]}if(e==="prefer-app"){let i=n.filter(s=>s.type==="claude-cli");return [...n.filter(s=>s.type!=="claude-cli"),...i]}let t=n.filter(i=>i.type===e),r=n.filter(i=>i.type!==e);return [...t,...r]}function ft(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var _t=v(()=>{});function bt(n){if(me[n])return me[n];let e=null;for(let t of Object.keys(me))n.startsWith(t)&&(e===null||t.length>e.length)&&(e=t);return e!==null?me[e]:[3,15]}var me,Et=v(()=>{me={"claude-fable-5":[10,50],"claude-mythos-5":[10,50],"claude-opus-5-5":[4,20],"claude-opus-5":[5,25],"claude-opus-4-8":[5,25],"claude-opus-4-7":[5,25],"claude-opus-4-6":[5,25],"claude-opus-4-5":[5,25],"claude-opus-4":[15,75],"claude-sonnet-5":[2,10],"claude-sonnet-4":[3,15],"claude-haiku-5-5":[.1,.5],"claude-haiku-4-5":[1,5],"claude-3-5-haiku":[.8,4],"claude-3-haiku":[.25,1.25],"kimi-k3":[3,15],"kimi-k2.7-code":[.95,4],"kimi-for-coding":[.95,4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"gpt-4-turbo":[10,30],"gpt-3.5-turbo":[.5,1.5],llama:[0,0],mistral:[0,0],codellama:[0,0]};});function vt(n){let e=0;for(let o of n.messages)if(typeof o.content=="string")e+=o.content.length;else if(Array.isArray(o.content))for(let l of o.content)l.type==="text"&&l.text&&(e+=l.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[i,a]=bt(n.model),s=(t*i+r*a)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(s*1e4)/1e4,model:n.model,provider:""}}var Rt=v(()=>{Et();});var he,Ct=v(()=>{he=class{endpoint;enabled;keyId;lineageBuffer=new Map;unsubscribers=[];constructor(e){this.endpoint=e.endpoint||"https://api.inference-relay.com/v1/events",this.enabled=e.enabled??true,this.keyId=e.keyId||"";}subscribeToEngine(e){let t=i=>this.bufferLineageEvent(i),r=i=>{i.kind==="stream_complete"&&this.flushLineageForCall(i);};e.engineEvents.onTyped("segment_start",t),e.engineEvents.onTyped("segment_complete",t),e.engineEvents.onTyped("mid_stream_failover_attempt",t),e.engineEvents.onTyped("mid_stream_failover_success",t),e.engineEvents.onTyped("stream_complete",r),this.unsubscribers.push(()=>{e.engineEvents.offTyped("segment_start",t),e.engineEvents.offTyped("segment_complete",t),e.engineEvents.offTyped("mid_stream_failover_attempt",t),e.engineEvents.offTyped("mid_stream_failover_success",t),e.engineEvents.offTyped("stream_complete",r);});}unsubscribe(){for(let e of this.unsubscribers)e();this.unsubscribers=[],this.lineageBuffer.clear();}bufferLineageEvent(e){let t=this.lineageBuffer.get(e.callId)??[];t.push(e),this.lineageBuffer.set(e.callId,t);}flushLineageForCall(e){let t=this.lineageBuffer.get(e.callId)??[];this.lineageBuffer.delete(e.callId);let r={timestamp:e.ts,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,userCostUsd:e.userCostUsd,durationMs:e.durationMs,stopReason:e.stopReason,fallbackChain:e.fallbackChain,rateLimitHit:e.rateLimitHit,securityState:e.securityState,stitched:e.stitched,segments:e.segments,lineage:t.map(i=>i.id),promptContent:false,completionContent:false};this.report(r);}report(e){!this.enabled||!this.keyId||fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({keyId:this.keyId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,...e.userCostUsd!==void 0?{userCostUsd:e.userCostUsd}:{},durationMs:e.durationMs,fallback:e.fallbackChain.length>1,timestamp:e.timestamp,...e.stitched?{stitched:true,segmentCount:e.segments?.length??0}:{},...e.lineage?{lineageIds:e.lineage}:{}})}).catch(()=>{});}};});function At(){return {name:"inference-relay",version:ge,features:Ne}}var ge,Ne,kt=v(()=>{ge="1.6.12",Ne=Object.freeze({streamKeepsHistory:true,streamToolBlocks:true,streamBareToolNames:true,stopsWhenCallerGoes:true});});function fn(n,e){let t=n?.signal;if(t===void 0)return {params:n,options:e};let{signal:r,...i}=n,a=i;if(!yn(t))return {params:a,options:e};let s=e?.signal;if(!s||s===t)return {params:a,options:{...e,signal:t}};let o=new AbortController,l=()=>{s.removeEventListener("abort",d),t.removeEventListener("abort",d);},d=()=>{l(),o.abort();};return s.aborted||t.aborted?o.abort():(s.addEventListener("abort",d,{once:true}),t.addEventListener("abort",d,{once:true})),{params:a,options:{...e,signal:o.signal},release:l}}async function ye(n,e){if(!n)return {valid:false,error:"License key required. Get one at inference-relay.com"};let t=H.get(n);if(t&&Date.now()-t.cachedAt<t.ttl)return t.result;let i=!H.has(n)?1e4:3e3,a=(e||dn)+pn,s=async()=>{let d=new AbortController,c=setTimeout(()=>d.abort(),i);try{return await(await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n}),signal:d.signal})).json()}finally{clearTimeout(c);}},o;try{o=await s();}catch{try{if(t)throw new Error("cached answer stands in");o=await s();}catch{return t&&Date.now()-t.cachedAt<hn?t.result:{valid:false,error:"License validation failed (network error). Visit inference-relay.com"}}}let l;if(o.jws)try{let{compactVerify:d,importSPKI:c}=await import('jose'),h=await c(gn,"RS256"),{payload:m}=await d(o.jws,h);l=JSON.parse(new TextDecoder().decode(m));}catch{return H.delete(n),{valid:false,error:"License validation signature invalid. Possible MITM \u2014 refusing to start."}}else if(l=o,l.valid)return H.delete(n),{valid:false,error:"License validation response not signed. Possible MITM."};return H.set(n,{result:l,cachedAt:Date.now(),ttl:l.valid?mn:6e4}),l}var dn,pn,mn,hn,gn,H,Ue,yn,fe,wt=v(()=>{Re();Xe();tt();it();at();Me();te();_t();Rt();ke();Ct();kt();dn="https://api.inference-relay.com",pn="/v1/validate",mn=1440*60*1e3,hn=10080*60*1e3,gn=`-----BEGIN PUBLIC KEY-----
16
+ ${e}`:e}function ht(n){let e=0;for(let t of n.content)t.type==="text"?e+=t.text.length:t.type==="tool_use"&&(e+=(t._partialJson||"").length);return e}function cn(n){return Math.max(0,n.content.length-1)}async function*un(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}var gt,ct,F,de,pe,Me=v(()=>{Ce();ot();xe();Pe();we();gt=200;ct=new Set(["anthropic-api","openai-api","ollama"]),F=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}},de=class extends F{constructor(e){super(e);}};pe=class n{healthMap=new Map;engineEvents=new le;static UNHEALTHY_TTL_DEFAULT_MS=300*1e3;static UNHEALTHY_TTL_AUTH_MS=30*1e3;getHealthStatus(e){let t=this.healthMap.get(e);if(!t)return "healthy";let r=t.ttlMs??n.UNHEALTHY_TTL_DEFAULT_MS;if(t.status==="unhealthy"&&Date.now()-t.updatedAt>=r){let i=Date.now()-t.updatedAt;return this.healthMap.delete(e),I("engine.recovered",{providerType:e,ageMs:i,ttlMs:r}),"healthy"}return t.status}markUnhealthy(e,t,r){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now(),ttlMs:r}),I("engine.unhealthy",{providerType:e,reason:t,ttlMs:r});}markDegraded(e,t){this.healthMap.set(e,{status:"degraded",lastError:t,updatedAt:Date.now()});}markHealthy(e){this.healthMap.set(e,{status:"healthy",updatedAt:Date.now()});}resetHealth(){this.healthMap.clear();}async execute(e,t,r){let i=dt(t),a=[],s=ut(e),o=randomUUID(),l=Date.now();for(let d of i){let c=d.type;if(this.getHealthStatus(c)==="unhealthy"){a.push(`${c}:skipped:unhealthy`);continue}if(s&&!d.supportsMultimodal){a.push(`${c}:skipped:no_multimodal`);continue}let m=Le(e.model);if(m&&m!==c&&ct.has(c)){a.push(`${c}:skipped:wrong_provider`);continue}let y=r?.maxSameProviderRetries??2,b=0,p=null,f=false;for(;!f;)try{let u=await d.execute(e,{signal:r?.signal});return f=!0,this.markHealthy(c),b>0&&a.push(`${c}:retry_success:${b}`),a.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd??0}],provider:c,model:u.model,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd,durationMs:u.durationMs??Date.now()-l,stopReason:u.stop_reason,fallbackChain:a,rateLimitHit:!1,securityState:r?.licenseState}),{...u,fallbackChain:a}}catch(u){if(u?.name==="AbortError"||r?.signal?.aborted)throw u;if(ue(u)==="transient"&&b<y){b++;let R=250*Math.pow(2,b-1);I("engine.transient-retry",{id:c,attempt:b,backoffMs:R,msg:String(u?.message||"").slice(0,120)}),a.push(`${c}:retry:${b}`),await new Promise(E=>setTimeout(E,R));continue}p=u;break}if(!f){let u=p;switch(ue(u)){case "rate_limited":d.reportRateLimit({provider:c,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(c,"rate_limited"),a.push(`${c}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(c,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),a.push(`${c}:failed:auth_failed`);break;case "timeout":a.push(`${c}:failed:timeout`);break;case "provider_incompatible":a.push(`${c}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(c,"gateway_unavailable"),a.push(ce(c,u));break;case "request_too_large":a.push(`${c}:failed:request_too_large`);break;case "transient":this.markDegraded(c,"transient_exhausted"),a.push(`${c}:failed:transient_exhausted`);break;default:a.push(ce(c,u));break}if(r?.subscriptionOnly&&c==="claude-cli"){a.push("subscription_only:cascade_halted");break}}}throw I("engine.cascade-exhausted",{chain:a,mode:"execute"}),lt(a)?new de(a):new F(a)}async stream(e,t,r){let i=randomUUID(),a=dt(t),s=ut(e),o=Date.now(),l=[],d=null,c=null;for(let u of a){let g=u.type;if(this.getHealthStatus(g)==="unhealthy"){l.push(`${g}:skipped:unhealthy`);continue}if(s&&!u.supportsMultimodal){l.push(`${g}:skipped:no_multimodal`);continue}if(!u.supportsStreaming){l.push(`${g}:skipped:no_streaming`);continue}let R=Le(e.model);if(R&&R!==g&&ct.has(g)){l.push(`${g}:skipped:wrong_provider`);continue}try{c=await u.streamRaw(e,{signal:r?.signal}),d=u,l.push(`${g}:success`);break}catch(E){if(E?.name==="AbortError"||r?.signal?.aborted)throw E;switch(ue(E)){case "rate_limited":u.reportRateLimit({provider:g,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(g,"rate_limited"),l.push(`${g}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(g,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),l.push(`${g}:failed:auth_failed`);break;case "timeout":l.push(`${g}:failed:timeout`);break;case "provider_incompatible":l.push(`${g}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(g,"gateway_unavailable"),l.push(ce(g,E));break;case "request_too_large":l.push(`${g}:failed:request_too_large`);break;case "transient":this.markDegraded(g,"transient_exhausted"),l.push(`${g}:failed:transient_exhausted`);break;default:l.push(ce(g,E));break}if(r?.subscriptionOnly&&g==="claude-cli"){l.push("subscription_only:cascade_halted");break}}}if(!d||!c)throw I("engine.cascade-exhausted",{chain:l,mode:"stream"}),lt(l)?new de(l):new F(l);let m=this,y=r?.maxMidStreamFailovers??2,b=new Set([d]);async function*p(){let u=d,g=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},E={segments:[]},k=pt(u.type);E.segments.push(k);let Fe=0,z=null,X=false,ve=y,V="",Y="";for(m.emitEngineEvent({kind:"segment_start",callId:i,id:randomUUID(),ts:Date.now(),provider:u.type});;)try{for(;;){let T=await g.next();if(T.done)break;let N=T.value,x=an(N,Fe,R,X,z);if(x.action==="suppress"){"coalesceMode"in x&&(z=x.coalesceMode),x.clearedJustFailedOver&&(X=!1);continue}x.coalesceModeCleared&&(z=null),x.clearedJustFailedOver&&(X=!1);let A=x.event;if(sn(R,A),A.type==="message_start"){if(E.segments.length>1)continue;V=A.message?.model||V,A.message?.usage?.input_tokens!=null&&(k.inputTokens=A.message.usage.input_tokens);}if(A.type==="message_delta"&&(A.delta?.stop_reason&&(Y=A.delta.stop_reason),A.usage)){rn(k,u.type,A.usage),yield {...A,usage:void 0};continue}if(A.type==="message_stop")break;yield A;}if(R.content.length===0&&k.outputTokens===0)throw new Error("stream ended without producing any content");m.markHealthy(u.type),m.emitEngineEvent({kind:"segment_complete",callId:i,id:randomUUID(),ts:Date.now(),provider:u.type,usage:{...k}});let P=mt(E.segments);yield {type:"message_delta",delta:{stop_reason:Y||"end_turn"},usage:P},yield {type:"message_stop"},m.emitEngineEvent({kind:"stream_complete",callId:i,id:randomUUID(),ts:Date.now(),stitched:E.segments.length>1,segments:E.segments.map(T=>({...T})),provider:E.segments.map(T=>T.provider).join("+"),model:V,inputTokens:P.input_tokens,outputTokens:P.output_tokens,costUsd:E.segments.reduce((T,N)=>T+N.costUsd,0),userCostUsd:E.segments.reduce((T,N)=>T+N.userCostUsd,0),durationMs:Date.now()-o,stopReason:Y||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(P){if(P?.name==="AbortError"||r?.signal?.aborted)throw P;let T=ue(P);try{await g.return?.();}catch{}if(m.markUnhealthy(u.type,String(P)),m.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:i,id:randomUUID(),ts:Date.now(),from:u.type,bytesBuffered:ht(R),errorClass:T,retriesLeft:ve}),l.push(`${u.type}:partial(${ht(R)}b)`),ve<=0)throw m.emitTerminalExhaustion(i,E,V,Y,l,o,r?.licenseState),P;let N=on(R.content),x=[...e.messages,{role:"assistant",content:N}],A=null,Q=null,He=u;for(;;){let O=m.nextHealthyProvider(a,He,s,b);if(!O)break;He=O,b.add(O);let Ot={...e,messages:x,...O.type!=="anthropic-api"&&O.type!=="claude-cli"?{system:ln(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{Q=await O.streamRaw(Ot,{signal:r?.signal}),A=O;break}catch(Be){m.markUnhealthy(O.type,String(Be)),l.push(`${O.type}:failed_connect:${String(Be).slice(0,gt)}`);}}if(!A||!Q)throw m.emitTerminalExhaustion(i,E,V,Y,l,o,r?.licenseState),P;l.push(`${A.type}:stitched`),m.emitEngineEvent({kind:"mid_stream_failover_success",callId:i,id:randomUUID(),ts:Date.now(),from:u.type,to:A.type}),Fe=cn(R)+1,ve--,u=A,g=Q[Symbol.asyncIterator](),X=true,z=null,k=pt(u.type),E.segments.push(k),m.emitEngineEvent({kind:"segment_start",callId:i,id:randomUUID(),ts:Date.now(),provider:u.type});}}let f=p();return r?.licenseState==="SEC_DEGRADED"&&(f=un(f)),Z(f)}nextHealthyProvider(e,t,r,i){let a=e.indexOf(t);if(a===-1)return null;for(let s=a+1;s<e.length;s++){let o=e[s];if(!i.has(o)&&!(r&&!o.supportsMultimodal)&&o.supportsStreaming)return o}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,i,a,s,o){let l=mt(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(d=>({...d})),provider:t.segments.map(d=>d.provider).join("+"),model:r,inputTokens:l.input_tokens,outputTokens:l.output_tokens,costUsd:t.segments.reduce((d,c)=>d+c.costUsd,0),userCostUsd:t.segments.reduce((d,c)=>d+c.userCostUsd,0),durationMs:Date.now()-s,stopReason:i||"error",fallbackChain:a,rateLimitHit:false,securityState:o});}};});function yt(n,e){if(e==="prefer-user"){let i=n.filter(s=>s.type==="claude-cli"),a=n.filter(s=>s.type!=="claude-cli");return [...i,...a]}if(e==="prefer-app"){let i=n.filter(s=>s.type==="claude-cli");return [...n.filter(s=>s.type!=="claude-cli"),...i]}let t=n.filter(i=>i.type===e),r=n.filter(i=>i.type!==e);return [...t,...r]}function ft(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var _t=v(()=>{});function bt(n){if(me[n])return me[n];let e=null;for(let t of Object.keys(me))n.startsWith(t)&&(e===null||t.length>e.length)&&(e=t);return e!==null?me[e]:[3,15]}var me,Et=v(()=>{me={"claude-fable-5":[10,50],"claude-mythos-5":[10,50],"claude-opus-5-5":[4,20],"claude-opus-5":[5,25],"claude-opus-4-8":[5,25],"claude-opus-4-7":[5,25],"claude-opus-4-6":[5,25],"claude-opus-4-5":[5,25],"claude-opus-4":[15,75],"claude-sonnet-5":[2,10],"claude-sonnet-4":[3,15],"claude-haiku-5-5":[.1,.5],"claude-haiku-4-5":[1,5],"claude-3-5-haiku":[.8,4],"claude-3-haiku":[.25,1.25],"kimi-k3":[3,15],"kimi-k2.7-code":[.95,4],"kimi-for-coding":[.95,4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"gpt-4-turbo":[10,30],"gpt-3.5-turbo":[.5,1.5],llama:[0,0],mistral:[0,0],codellama:[0,0]};});function vt(n){let e=0;for(let o of n.messages)if(typeof o.content=="string")e+=o.content.length;else if(Array.isArray(o.content))for(let l of o.content)l.type==="text"&&l.text&&(e+=l.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[i,a]=bt(n.model),s=(t*i+r*a)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(s*1e4)/1e4,model:n.model,provider:""}}var Rt=v(()=>{Et();});var he,Ct=v(()=>{he=class{endpoint;enabled;keyId;lineageBuffer=new Map;unsubscribers=[];constructor(e){this.endpoint=e.endpoint||"https://api.inference-relay.com/v1/events",this.enabled=e.enabled??true,this.keyId=e.keyId||"";}subscribeToEngine(e){let t=i=>this.bufferLineageEvent(i),r=i=>{i.kind==="stream_complete"&&this.flushLineageForCall(i);};e.engineEvents.onTyped("segment_start",t),e.engineEvents.onTyped("segment_complete",t),e.engineEvents.onTyped("mid_stream_failover_attempt",t),e.engineEvents.onTyped("mid_stream_failover_success",t),e.engineEvents.onTyped("stream_complete",r),this.unsubscribers.push(()=>{e.engineEvents.offTyped("segment_start",t),e.engineEvents.offTyped("segment_complete",t),e.engineEvents.offTyped("mid_stream_failover_attempt",t),e.engineEvents.offTyped("mid_stream_failover_success",t),e.engineEvents.offTyped("stream_complete",r);});}unsubscribe(){for(let e of this.unsubscribers)e();this.unsubscribers=[],this.lineageBuffer.clear();}bufferLineageEvent(e){let t=this.lineageBuffer.get(e.callId)??[];t.push(e),this.lineageBuffer.set(e.callId,t);}flushLineageForCall(e){let t=this.lineageBuffer.get(e.callId)??[];this.lineageBuffer.delete(e.callId);let r={timestamp:e.ts,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,userCostUsd:e.userCostUsd,durationMs:e.durationMs,stopReason:e.stopReason,fallbackChain:e.fallbackChain,rateLimitHit:e.rateLimitHit,securityState:e.securityState,stitched:e.stitched,segments:e.segments,lineage:t.map(i=>i.id),promptContent:false,completionContent:false};this.report(r);}report(e){!this.enabled||!this.keyId||fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({keyId:this.keyId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,...e.userCostUsd!==void 0?{userCostUsd:e.userCostUsd}:{},durationMs:e.durationMs,fallback:e.fallbackChain.length>1,timestamp:e.timestamp,...e.stitched?{stitched:true,segmentCount:e.segments?.length??0}:{},...e.lineage?{lineageIds:e.lineage}:{}})}).catch(()=>{});}};});function At(){return {name:"inference-relay",version:ge,features:Ne}}var ge,Ne,kt=v(()=>{ge="1.6.13",Ne=Object.freeze({streamKeepsHistory:true,streamToolBlocks:true,streamBareToolNames:true,stopsWhenCallerGoes:true,stopsAtFirstCap:true});});function fn(n,e){let t=n?.signal;if(t===void 0)return {params:n,options:e};let{signal:r,...i}=n,a=i;if(!yn(t))return {params:a,options:e};let s=e?.signal;if(!s||s===t)return {params:a,options:{...e,signal:t}};let o=new AbortController,l=()=>{s.removeEventListener("abort",d),t.removeEventListener("abort",d);},d=()=>{l(),o.abort();};return s.aborted||t.aborted?o.abort():(s.addEventListener("abort",d,{once:true}),t.addEventListener("abort",d,{once:true})),{params:a,options:{...e,signal:o.signal},release:l}}async function ye(n,e){if(!n)return {valid:false,error:"License key required. Get one at inference-relay.com"};let t=H.get(n);if(t&&Date.now()-t.cachedAt<t.ttl)return t.result;let i=!H.has(n)?1e4:3e3,a=(e||dn)+pn,s=async()=>{let d=new AbortController,c=setTimeout(()=>d.abort(),i);try{return await(await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n}),signal:d.signal})).json()}finally{clearTimeout(c);}},o;try{o=await s();}catch{try{if(t)throw new Error("cached answer stands in");o=await s();}catch{return t&&Date.now()-t.cachedAt<hn?t.result:{valid:false,error:"License validation failed (network error). Visit inference-relay.com"}}}let l;if(o.jws)try{let{compactVerify:d,importSPKI:c}=await import('jose'),h=await c(gn,"RS256"),{payload:m}=await d(o.jws,h);l=JSON.parse(new TextDecoder().decode(m));}catch{return H.delete(n),{valid:false,error:"License validation signature invalid. Possible MITM \u2014 refusing to start."}}else if(l=o,l.valid)return H.delete(n),{valid:false,error:"License validation response not signed. Possible MITM."};return H.set(n,{result:l,cachedAt:Date.now(),ttl:l.valid?mn:6e4}),l}var dn,pn,mn,hn,gn,H,Ue,yn,fe,wt=v(()=>{Re();Xe();tt();it();at();Me();te();_t();Rt();ke();Ct();kt();dn="https://api.inference-relay.com",pn="/v1/validate",mn=1440*60*1e3,hn=10080*60*1e3,gn=`-----BEGIN PUBLIC KEY-----
17
17
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
18
18
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
19
19
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  'use strict';var child_process=require('child_process'),fs=require('fs'),path=require('path'),os=require('os'),crypto$1=require('crypto'),vm=require('vm'),module$1=require('module'),events=require('events');/*! inference-relay (c) 2026 L2B II LLC. Patent pending. Proprietary. See LICENSE. */
2
- var it=Object.defineProperty;var at=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var ot=(n,e)=>()=>(n&&(e=n(n=0)),e);var lt=(n,e)=>{for(var t in e)it(n,t,{get:e[t],enumerable:true});};var Ke={};lt(Ke,{detectCLI:()=>V});function At(n){let e=process.env.PATH;if(!e)return null;let t=process.platform==="win32",r=t?";":":",s=t?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(i=>i.toLowerCase()):[""];for(let i of e.split(r))if(i)for(let a of s){let o=path.join(i,n+a);if(fs.existsSync(o))return o}return null}async function V(){if(!At("claude"))return {available:false,authenticated:false};let e=null;try{let r=child_process.execSync("claude --version",{encoding:"utf-8",timeout:5e3}).trim(),s=r.match(/(\d+\.\d+\.\d+)/);e=s?s[1]:r;}catch{}let t;return e&&!Rt.some(r=>e.startsWith(r.split(".").slice(0,2).join(".")))&&(t=`CLI version ${e} is not tested with this version of inference-relay. Streaming may be unstable.`),{available:true,authenticated:true,cliVersion:e||void 0,versionWarning:t}}var Rt,se=ot(()=>{Rt=["2.1.87"];});var K=class n extends Error{code="RELAY_CAP_EXCEEDED";tier;baseCap;topUps;effectiveCap;usedThisCycle;resolutionUrl;constructor(e){let t=e.resolutionUrl??"https://inference-relay.com/dashboard/billing?topup=1";super(`Cap reached (${e.usedThisCycle} / ${e.effectiveCap??"\u221E"} calls this cycle). Buy a top-up or upgrade at ${t}`),this.name="RelayCapExceededError",this.tier=e.tier,this.baseCap=e.baseCap,this.topUps=e.topUps,this.effectiveCap=e.effectiveCap,this.usedThisCycle=e.usedThisCycle,this.resolutionUrl=t,Object.setPrototypeOf(this,n.prototype);}};function M(n,e){let t=new Map,r=null,s=null,i=new Promise((p,f)=>{r=p,s=f;});i.catch(()=>{});let a=[],o=null,l="",d="";function c(p,...f){let u=t.get(p);u&&u.forEach(h=>h(...f));}async function*g(){try{for await(let p of n)if(yield p,p.type==="content_block_start")a[p.index]=p.content_block;else if(p.type==="content_block_delta"){let f=a[p.index];f&&p.delta?.type==="text_delta"&&(f.text=(f.text||"")+p.delta.text,c("text",p.delta.text));}else if(p.type==="message_start")l=p.message?.model||"",o=p.message?.usage;else if(p.type==="message_delta")d=p.delta?.stop_reason||"",p.usage&&(o={...o,...p.usage});else if(p.type==="message_stop"){let f={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d};c("message",f),r&&(r(f),r=null),e&&e(f);}if(r){let p={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d||"end_turn"};c("message",p),r(p),r=null,e&&e(p);}}catch(p){throw c("error",p),s&&(s(p),s=null),p}}let m=g(),y=false,_={[Symbol.asyncIterator](){if(y)throw new Error("[inference-relay] RelayStream can only be iterated once");return y=true,m},on(p,f){return t.has(p)||t.set(p,[]),t.get(p).push(f),_},finalMessage(){let p,f=new Promise((u,h)=>{p=setTimeout(()=>h(new Error("[inference-relay] finalMessage() timed out \u2014 no message_stop received after 5 minutes")),3e5);});return Promise.race([i,f]).finally(()=>clearTimeout(p))}};return _}var S=class{priority=100;async streamRaw(e,t){throw new Error(`[inference-relay] Provider '${this.type}' does not implement streamRaw(). Override either stream() or streamRaw() in the provider class.`)}async stream(e,t){return M(await this.streamRaw(e,t))}};var ve=`-----BEGIN PUBLIC KEY-----
2
+ var it=Object.defineProperty;var at=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var ot=(n,e)=>()=>(n&&(e=n(n=0)),e);var lt=(n,e)=>{for(var t in e)it(n,t,{get:e[t],enumerable:true});};var Ke={};lt(Ke,{detectCLI:()=>V});function At(n){let e=process.env.PATH;if(!e)return null;let t=process.platform==="win32",r=t?";":":",s=t?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(i=>i.toLowerCase()):[""];for(let i of e.split(r))if(i)for(let a of s){let o=path.join(i,n+a);if(fs.existsSync(o))return o}return null}async function V(){if(!At("claude"))return {available:false,authenticated:false};let e=null;try{let r=child_process.execSync("claude --version",{encoding:"utf-8",timeout:5e3}).trim(),s=r.match(/(\d+\.\d+\.\d+)/);e=s?s[1]:r;}catch{}let t;return e&&!Rt.some(r=>e.startsWith(r.split(".").slice(0,2).join(".")))&&(t=`CLI version ${e} is not tested with this version of inference-relay. Streaming may be unstable.`),{available:true,authenticated:true,cliVersion:e||void 0,versionWarning:t}}var Rt,se=ot(()=>{Rt=["2.1.87"];});var K=class n extends Error{code="RELAY_CAP_EXCEEDED";tier;baseCap;topUps;effectiveCap;usedThisCycle;resolutionUrl;constructor(e){let t=e.resolutionUrl??"https://inference-relay.com/dashboard/billing?topup=1";super(`Cap reached (${e.usedThisCycle} / ${e.effectiveCap??"\u221E"} calls this cycle). Buy a top-up or upgrade at ${t}`),this.name="RelayCapExceededError",this.tier=e.tier,this.baseCap=e.baseCap,this.topUps=e.topUps,this.effectiveCap=e.effectiveCap,this.usedThisCycle=e.usedThisCycle,this.resolutionUrl=t,Object.setPrototypeOf(this,n.prototype);}};function M(n,e){let t=new Map,r=null,s=null,i=new Promise((p,f)=>{r=p,s=f;});i.catch(()=>{});let a=[],o=null,l="",d="";function c(p,...f){let u=t.get(p);u&&u.forEach(h=>h(...f));}async function*g(){try{for await(let p of n)if(yield p,p.type==="content_block_start")a[p.index]=p.content_block;else if(p.type==="content_block_delta"){let f=a[p.index];f&&p.delta?.type==="text_delta"&&(f.text=(f.text||"")+p.delta.text,c("text",p.delta.text));}else if(p.type==="message_start")l=p.message?.model||"",o=p.message?.usage;else if(p.type==="message_delta")d=p.delta?.stop_reason||"",p.usage&&(o={...o,...p.usage});else if(p.type==="message_stop"){let f={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d};c("message",f),r&&(r(f),r=null),e&&e(f);}if(r){let p={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d||"end_turn"};c("message",p),r(p),r=null,e&&e(p);}}catch(p){throw c("error",p),s&&(s(p),s=null),p}}let m=g(),y=false,_={[Symbol.asyncIterator](){if(y)throw new Error("[inference-relay] RelayStream can only be iterated once");return y=true,m},on(p,f){return t.has(p)||t.set(p,[]),t.get(p).push(f),_},finalMessage(){let p,f=new Promise((u,h)=>{p=setTimeout(()=>h(new Error("[inference-relay] finalMessage() timed out \u2014 no message_stop received after 5 minutes")),3e5);});return Promise.race([i,f]).finally(()=>clearTimeout(p))}};return _}var C=class{priority=100;async streamRaw(e,t){throw new Error(`[inference-relay] Provider '${this.type}' does not implement streamRaw(). Override either stream() or streamRaw() in the provider class.`)}async stream(e,t){return M(await this.streamRaw(e,t))}};var ve=`-----BEGIN PUBLIC KEY-----
3
3
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
4
4
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
5
5
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
@@ -7,12 +7,12 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
7
7
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
8
8
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
9
9
  UQIDAQAB
10
- -----END PUBLIC KEY-----`,Ee={version:"1.0.0",cliVersion:"2.1.87",eventTypes:{system:"system",streamEvent:"stream_event",assistant:"assistant",result:"result"},fieldMappings:{sessionId:"session_id",model:"model",cliVersion:"claude_code_version",content:"content",usage:"usage",inputTokens:"input_tokens",outputTokens:"output_tokens",stopReason:"stop_reason",isError:"is_error",totalCostUsd:"total_cost_usd",durationMs:"duration_ms",error:"error",event:"event"},syntheticModel:"<synthetic>"},D=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(ve,"RS256"),{payload:i}=await t(e,s),a=JSON.parse(new TextDecoder().decode(i));return this.verificationFailures=0,this.cachedManifest=a,this.currentSecurityState="SEC_NOMINAL",{manifest:a,securityState:"SEC_NOMINAL"}}catch{if(this.verificationFailures++,this.verificationFailures>=3){this.currentSecurityState="SEC_DEGRADED";let t=2e3+Math.random()*3e3;return await new Promise(r=>setTimeout(r,t)),console.warn("[inference-relay] Logic synchronization mismatch. Routing via local recovery."),{manifest:Ee,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Ee,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},ct=new D;function De(){ct.clearCache();}function ut(){return Ee}function dt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}function C(n,...e){process.env.IR_DEBUG==="1"&&console.error(`[ir-debug:${n}]`,...e);}var gt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function Se(n){return path.join(os.homedir(),".inference-relay","gateway",n)}function Fe(n){return path.join(Se(n),"bundle.js")}function He(n){return path.join(Se(n),"meta.json")}var E=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},x=class extends E{constructor(e,t){super(e,"GATEWAY_FETCH_FAILED",t);}},G=new Map,ft=[0,1e3,4e3];function _t(n){let e=(r,s)=>{if(!Array.isArray(r)||r.length===0)return null;let i=[];for(let a of r){let o=typeof a=="string"?Number(a):a;if(typeof o!="number"||!Number.isFinite(o)||o<0)return C("loader.retry-config-invalid",{source:s,badValue:a}),null;i.push(o);}return i};if(n!==void 0){let r=e(n,"option");if(r)return r}let t=process.env.IR_GATEWAY_RETRY_DELAYS_MS;if(t){let r=e(t.split(",").map(s=>s.trim()),"env");if(r)return r}return ft}var N=class{static async load(e,t,r=gt,s){let i=`${t}:${e.slice(-8)}`;if(G.has(i))return G.get(i);try{let m=await this.tryLoadFromDisk(t);if(m)return C("loader.cache-hit",{libraryVersion:t}),G.set(i,m),m}catch{}C("loader.cache-miss",{libraryVersion:t});let{bytes:a,sha256:o,signature:l,libraryVersion:d}=await this.fetchFromAuthority(e,t,r,s);if(crypto$1.createHash("sha256").update(a).digest("hex")!==o)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,d,o);try{let m=Se(t);fs.mkdirSync(m,{recursive:!0}),fs.writeFileSync(Fe(t),a),fs.writeFileSync(He(t),JSON.stringify({sha256:o,signature:l,libraryVersion:d}));}catch{}let g=this.loadIntoVm(a.toString("utf-8"));return G.set(i,g),g}static async loadFromDisk(e){if(!fs.existsSync(e))throw new E(`[ir-system]: GATEWAY_LOAD_FAILED (REASON: BUNDLE_NOT_FOUND at ${e})`,"GATEWAY_LOAD_FAILED");let t=fs.readFileSync(e,"utf-8");return this.loadIntoVm(t)}static async tryLoadFromDisk(e){let t=Fe(e),r=He(e);if(!fs.existsSync(t)||!fs.existsSync(r))return null;let s=fs.readFileSync(t),i=JSON.parse(fs.readFileSync(r,"utf-8"));return crypto$1.createHash("sha256").update(s).digest("hex")!==i.sha256?null:(await this.verifySignature(i.signature,i.libraryVersion,i.sha256),this.loadIntoVm(s.toString("utf-8")))}static async fetchFromAuthority(e,t,r,s){let i,a=_t(s?.retryDelaysMs),o;for(let g=0;g<a.length;g++){let m=a[g];m>0&&await new Promise(y=>setTimeout(y,m)),C("loader.fetch",{url:`${r}/v1/gateway/fetch`,libraryVersion:t,attempt:g+1,delayMs:m});try{let y=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(C("loader.fetch-result",{status:y.status,attempt:g+1}),y.status===401||y.status===403)throw new E("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(y.status>=500&&y.status<600){o=new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);continue}if(!y.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);i=await y.json(),o=null;break}catch(y){if(y instanceof E&&y.code==="LICENSE_REJECTED")throw y;o=y;}}if(o||!i)throw o instanceof E?o:new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)",o);let l;try{l=await fetch(i.bundleUrl);}catch(g){throw new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)",g)}if(!l.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`);let d=await l.arrayBuffer();return {bytes:Buffer.from(d),sha256:i.sha256,signature:i.signature,libraryVersion:i.libraryVersion,bundleVersion:i.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(ve,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof E?s:new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SIGNATURE_INVALID)","GATEWAY_VERIFICATION_FAILED",s)}}static loadIntoVm(e){try{let t=path.join(os.homedir(),".inference-relay","gateway","runtime.cjs"),r=path.dirname(t),s=module$1.createRequire(t),i={exports:{}};vm.compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(i.exports,s,i,t,r);let o=i.exports;if(!o.ClaudeCLIProvider)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof E?t:new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){G.clear();}};var Ge="1.6.12",ie=class extends S{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof E?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(se(),Ke));return e()}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let r=JSON.stringify(e.messages).length/4+5e3,s=(r*3+1e3*15)/1e6;return {estimatedInputTokens:Math.round(r),estimatedCost:Math.round(s*1e4)/1e4,model:e.model,provider:"claude-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}},ae=class extends S{type="kimi-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).KimiCLIProvider;if(!t)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: STALE_BUNDLE_NO_KIMI_CLI)","GATEWAY_LOAD_FAILED");let r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,this.health.lastError=e instanceof Error?e.message:String(e),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{existsSync:e}=await import('fs'),{homedir:t}=await import('os'),{join:r}=await import('path'),s=process.env.KIMI_CODE_HOME||r(t(),".kimi-code"),i=process.env.IR_KIMI_BIN||r(s,"bin","kimi"),a=e(i),o=e(r(s,"credentials"))||e(r(s,"oauth"));return {available:a,authenticated:o,subscriptionType:o?"kimi-code":void 0}}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let t=JSON.stringify(e.messages).length/4;return {estimatedInputTokens:Math.round(t+2e3),estimatedCost:0,model:e.model,provider:"kimi-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}};var Y=[{canonical:"claude-haiku-4-5",apiId:"claude-haiku-4-5-20251001",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[.8,4]},{canonical:"claude-sonnet-4-6",apiId:"claude-sonnet-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[3,15]},{canonical:"claude-opus-4-6",apiId:"claude-opus-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[15,75]},{canonical:"gpt-4.1",apiId:"gpt-4.1",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[2,8]},{canonical:"gpt-4.1-mini",apiId:"gpt-4.1-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.4,1.6]},{canonical:"gpt-4.1-nano",apiId:"gpt-4.1-nano",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.1,.4]},{canonical:"gpt-4o",apiId:"gpt-4o",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[2.5,10]},{canonical:"gpt-4o-mini",apiId:"gpt-4o-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[.15,.6]},{canonical:"o4-mini",apiId:"o4-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o3",apiId:"o3",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[.4,1.6]},{canonical:"o3-mini",apiId:"o3-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o1",apiId:"o1",provider:"openai-api",capabilities:{streaming:false,tools:false,multimodal:false,contextWindow:2e5},pricing:[15,60]},{canonical:"llama3.1",apiId:"llama3.1",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"mistral",apiId:"mistral",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}},{canonical:"mistral-nemo",apiId:"mistral-nemo",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"llava",apiId:"llava",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:true,contextWindow:32e3}},{canonical:"qwen2:0.5b",apiId:"qwen2:0.5b",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}}],$=Object.fromEntries(Y.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));$["claude-sonnet-4"]="claude-sonnet-4-20250514";$["claude-opus-4"]="claude-opus-4-20250514";$["claude-haiku-4"]="claude-haiku-4-5-20251001";function Ce(n){return $[n]||n}function St(n){return Y.find(e=>e.canonical===n)}function oe(n){return Y.find(e=>e.canonical===n)?.provider}function Ct(n){return Y.filter(e=>e.provider===n)}var wt="https://api.anthropic.com/v1/messages",Pt="2023-06-01",we={"claude-sonnet-4-5-20250514":[3,15],"claude-sonnet-4-20250514":[3,15],"claude-haiku-4-5-20250414":[.8,4],"claude-opus-4-20250514":[15,75]};function Ve(n){if(we[n])return we[n];for(let[e,t]of Object.entries(we))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var W=class extends S{type="anthropic-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;dangerousDirectBrowserAccess;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||wt,this.dangerousDirectBrowserAccess=e.dangerousDirectBrowserAccess??false;}async probe(){try{let e=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{available:!0,authenticated:!1}:e.ok||e.status===429?{available:!0,authenticated:!0,rateLimitTier:e.headers.get("anthropic-ratelimit-tier")??void 0}:e.status===529?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let[l,d]=Ve(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,g={},m=["request-id","x-request-id","anthropic-ratelimit-requests-limit","anthropic-ratelimit-requests-remaining","anthropic-ratelimit-requests-reset","anthropic-ratelimit-tokens-limit","anthropic-ratelimit-tokens-remaining","anthropic-ratelimit-tokens-reset","anthropic-ratelimit-tier"];for(let y of m){let _=i.headers.get(y);_&&(g[y]=_);}return {content:a.content||[],model:a.model||e.model,usage:{input_tokens:a.usage?.input_tokens||0,output_tokens:a.usage?.output_tokens||0},stop_reason:a.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:o,fallbackChain:["anthropic-api:success"],headers:Object.keys(g).length>0?g:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("ANTHROPIC_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder;return (async function*(){let o="",l=false;try{for(;;){let{done:d,value:c}=await i.read();if(d)break;o+=a.decode(c,{stream:!0});let g=o.split(`
11
- `);o=g.pop()||"";let m=null;for(let y of g)if(y.startsWith("event: "))m=y.slice(7).trim();else if(y.startsWith("data: ")){let _=y.slice(6);if(m&&_)try{let p=JSON.parse(_);p.type==="message_stop"&&(l=!0),yield p;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}m=null;}else y.trim()===""&&(m=null);}l||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=Ve(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"anthropic-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){let e={"content-type":"application/json","x-api-key":this.apiKey,"anthropic-version":Pt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:Ce(e.model),max_tokens:e.max_tokens,messages:e.messages};return t&&(r.stream=true),e.system&&(r.system=e.system),e.temperature!==void 0&&(r.temperature=e.temperature),e.tools&&e.tools.length>0&&(r.tools=e.tools),e.metadata&&(r.metadata=e.metadata),r}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw t===529?(this.health.status="degraded",this.health.lastError="API overloaded",this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_OVERLOADED: API is temporarily overloaded (529)")):(this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`ANTHROPIC_API_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var kt="https://api.openai.com/v1/chat/completions",Ye=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Pe={"gpt-4.1":[2,8],"gpt-4.1-mini":[.4,1.6],"gpt-4.1-nano":[.1,.4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"o4-mini":[1.1,4.4],o3:[.4,1.6],"o3-mini":[1.1,4.4],o1:[15,60],"o1-mini":[3,12],"gpt-4-turbo":[10,30],"gpt-4":[30,60],"gpt-3.5-turbo":[.5,1.5]};function $e(n){if(Pe[n])return Pe[n];for(let[e,t]of Object.entries(Pe))if(n.startsWith(e))return t;return [2.5,10]}function It(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Tt(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=It(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let i=r.content.filter(a=>a.type==="tool_use");if(i.length>0){t.push({role:"assistant",content:s||"",tool_calls:i.map(a=>({id:a.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:a.name,arguments:typeof a.input=="string"?a.input:JSON.stringify(a.input)}}))});continue}}t.push({role:r.role,content:s});}return t}function We(n){switch(n){case "stop":return "end_turn";case "length":return "max_tokens";case "tool_calls":case "function_call":return "tool_use";default:return "end_turn"}}var q=class extends S{type="openai-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||kt;}async probe(){try{let e=this.baseUrl.replace(/\/chat\/completions$/,"/models"),t=await fetch(e,{method:"GET",headers:this.buildHeaders()});return t.status===401?{available:!0,authenticated:!1}:t.ok||t.status===429?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=a.choices?.[0],d=[];if(l?.message?.content&&d.push({type:"text",text:l.message.content}),l?.message?.tool_calls)for(let u of l.message.tool_calls)d.push({type:"tool_use",id:u.id,name:u.function?.name,input:u.function?.arguments?JSON.parse(u.function.arguments):{}});let c=a.usage?.prompt_tokens||0,g=a.usage?.completion_tokens||0,[m,y]=$e(a.model||e.model),_=(c*m+g*y)/1e6,p={},f=["x-request-id","x-ratelimit-limit-requests","x-ratelimit-remaining-requests","x-ratelimit-limit-tokens","x-ratelimit-remaining-tokens","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];for(let u of f){let h=i.headers.get(u);h&&(p[u]=h);}return {content:d,model:a.model||e.model,usage:{input_tokens:c,output_tokens:g},stop_reason:We(l?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(p).length>0?p:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OPENAI_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false,g,m;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:y,value:_}=await i.read();if(y)break;l+=a.decode(_,{stream:!0});let p=l.split(`
12
- `);l=p.pop()||"";for(let f of p){if(!f.startsWith("data: "))continue;let u=f.slice(6).trim();if(u==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"},c=!0;return}try{let h=JSON.parse(u);h.usage&&(g={input_tokens:h.usage.prompt_tokens||0,output_tokens:h.usage.completion_tokens||0});let R=h.choices?.[0];if(!R)continue;let b=R.delta;b?.content&&!d&&(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),b?.content&&(yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:b.content}}),R.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),m=We(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=$e(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"openai-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}buildRequestBody(e,t){let r=e.model.toLowerCase();if(!Ye.some(o=>r.startsWith(o)))throw new Error(`OPENAI_MODEL_TRANSLATION_REQUIRED: The OpenAI provider received the model name '${e.model}', which does not match any known OpenAI model prefix (${Ye.join(", ")}). The relay does NOT auto-translate model names across providers in v1.3.x. Either (a) pass an OpenAI model name like 'gpt-4o-mini' when routing to this provider, or (b) route non-OpenAI models through a provider that understands them (e.g. 'anthropic-api' for Claude models).`);let i=Tt(e.messages,e.system),a={model:e.model,max_tokens:e.max_tokens,messages:i};return t&&(a.stream=true,a.stream_options={include_usage:true}),e.temperature!==void 0&&(a.temperature=e.temperature),e.tools&&e.tools.length>0&&(a.tools=e.tools),a}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("OPENAI_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`OPENAI_API_ERROR: Request failed with status ${t}`)}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var xt="http://localhost:11434";function Lt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ot(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:Lt(r.content)});return t}var j=class extends S{type="ollama";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.baseUrl=e?.baseUrl?.replace(/\/$/,"")||xt;}async probe(){try{return (await fetch(`${this.baseUrl}/api/tags`,{method:"GET"})).ok?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=[];a.message?.content&&l.push({type:"text",text:a.message.content});let d=a.prompt_eval_count||0,c=a.eval_count||0;return {content:l,model:a.model||e.model,usage:{input_tokens:d,output_tokens:c},stop_reason:(a.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:o,fallbackChain:["ollama:success"]}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OLLAMA_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:g,value:m}=await i.read();if(g)break;l+=a.decode(m,{stream:!0});let y=l.split(`
13
- `);l=y.pop()||"";for(let _ of y){let p=_.trim();if(p)try{let f=JSON.parse(p);if(f.message?.content&&(d||(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:f.message.content}}),f.done){d&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:f.prompt_eval_count||0,output_tokens:f.eval_count||0}},yield {type:"message_stop"},c=!0;return}}catch{}}}c||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0;return {estimatedInputTokens:t+r,estimatedCost:0,model:e.model,provider:"ollama"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildRequestBody(e,t){if(e.tools&&e.tools.length>0)throw new Error(`OLLAMA_TOOLS_NOT_SUPPORTED: The Ollama provider received ${e.tools.length} tool definition(s) in params.tools, but this provider does not implement function calling in v1.3.x. For tool-use workflows route to 'anthropic-api' or 'openai-api' instead. Tracking issue: 1.4.0 ships an Ollama tool-use shim for models that support native function calling (llama3.1, mistral-nemo, etc.).`);let r=Ot(e.messages,e.system),s={model:e.model,messages:r,stream:t};return e.temperature!==void 0&&(s.options={temperature:e.temperature}),s}handleErrorResponse(e){let t=e.status;throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),t===404?(this.health.status="unhealthy",this.health.lastError="Model not found",new Error("OLLAMA_MODEL_NOT_FOUND: Requested model is not available locally (404)")):(this.health.status="unhealthy",this.health.lastError=`Request failed with status ${t}`,new Error(`OLLAMA_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var J=class extends events.EventEmitter{constructor(){super(),this.setMaxListeners(50);}emitTyped(e){return this.emit(e.kind,e)}onTyped(e,t){return this.on(e,t)}offTyped(e,t){return this.off(e,t)}};var et=200;function le(n,e){if(e instanceof E)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,et)||"unknown"}`}function qe(n){let e=n.filter(t=>t.includes(":failed:"));return e.length===0?false:e.every(t=>t.endsWith(":failed:request_too_large"))}var je=new Set(["anthropic-api","openai-api","ollama"]),U=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}},z=class extends U{constructor(e){super(e);}};function Je(n){return n.messages.some(e=>typeof e.content=="string"?false:Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"))}function ce(n){if(!(n instanceof Error))return "unknown";let e=n.code;if(typeof e=="string"){if(e==="LICENSE_REJECTED")return "auth_failed";if(e==="GATEWAY_FETCH_FAILED"||e==="GATEWAY_VERIFICATION_FAILED"||e==="GATEWAY_LOAD_FAILED")return "gateway_unavailable"}let t=n.message.toLowerCase(),r=n.name.toLowerCase();return t.includes("prompt is too long")||t.includes("prompt too long")||t.includes("prompt_too_large")||t.includes("input length")||t.includes("input is too long")||t.includes("context_length_exceeded")||t.includes("context length exceeded")||t.includes("request too large")||t.includes("tokens exceed")||t.includes("exceeds the maximum")||t.includes("too many tokens")?"request_too_large":t.includes("code 3221226505")||t.includes("cli exited with code 3 ")||t.includes("cli stream exited with code 3 ")||t.includes("bun has crashed")||t.includes("illegal instruction")||t.includes("stream ended without producing any content")||t.includes("cli returned empty response")||t.includes("cli closed stdout without sending any response")||t.includes("kimi_stall_silent")?"transient":t.includes("credit balance is too low")||t.includes("credit balance too low")?"auth_failed":t.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_cli_too_old:")||t.startsWith("stream_json_cli_too_old:")?"provider_incompatible":t.includes("rate limit")||t.includes("429")||r.includes("ratelimit")?"rate_limited":t.includes("auth")||t.includes("401")||t.includes("403")||t.includes("unauthorized")||t.includes("forbidden")?"auth_failed":t.includes("timeout")||t.includes("timed out")||t.includes("aborted")||r==="aborterror"||r==="timeouterror"?"timeout":"unknown"}function ze(n){return [...n].sort((e,t)=>e.priority-t.priority)}var X=class n{healthMap=new Map;engineEvents=new J;static UNHEALTHY_TTL_DEFAULT_MS=300*1e3;static UNHEALTHY_TTL_AUTH_MS=30*1e3;getHealthStatus(e){let t=this.healthMap.get(e);if(!t)return "healthy";let r=t.ttlMs??n.UNHEALTHY_TTL_DEFAULT_MS;if(t.status==="unhealthy"&&Date.now()-t.updatedAt>=r){let s=Date.now()-t.updatedAt;return this.healthMap.delete(e),C("engine.recovered",{providerType:e,ageMs:s,ttlMs:r}),"healthy"}return t.status}markUnhealthy(e,t,r){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now(),ttlMs:r}),C("engine.unhealthy",{providerType:e,reason:t,ttlMs:r});}markDegraded(e,t){this.healthMap.set(e,{status:"degraded",lastError:t,updatedAt:Date.now()});}markHealthy(e){this.healthMap.set(e,{status:"healthy",updatedAt:Date.now()});}resetHealth(){this.healthMap.clear();}async execute(e,t,r){let s=ze(t),i=[],a=Je(e),o=crypto$1.randomUUID(),l=Date.now();for(let d of s){let c=d.type;if(this.getHealthStatus(c)==="unhealthy"){i.push(`${c}:skipped:unhealthy`);continue}if(a&&!d.supportsMultimodal){i.push(`${c}:skipped:no_multimodal`);continue}let m=oe(e.model);if(m&&m!==c&&je.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}let y=r?.maxSameProviderRetries??2,_=0,p=null,f=false;for(;!f;)try{let u=await d.execute(e,{signal:r?.signal});return f=!0,this.markHealthy(c),_>0&&i.push(`${c}:retry_success:${_}`),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:crypto$1.randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd??0}],provider:c,model:u.model,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd,durationMs:u.durationMs??Date.now()-l,stopReason:u.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...u,fallbackChain:i}}catch(u){if(u?.name==="AbortError"||r?.signal?.aborted)throw u;if(ce(u)==="transient"&&_<y){_++;let R=250*Math.pow(2,_-1);C("engine.transient-retry",{id:c,attempt:_,backoffMs:R,msg:String(u?.message||"").slice(0,120)}),i.push(`${c}:retry:${_}`),await new Promise(b=>setTimeout(b,R));continue}p=u;break}if(!f){let u=p;switch(ce(u)){case "rate_limited":d.reportRateLimit({provider:c,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(c,"rate_limited"),i.push(`${c}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(c,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),i.push(`${c}:failed:auth_failed`);break;case "timeout":i.push(`${c}:failed:timeout`);break;case "provider_incompatible":i.push(`${c}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(c,"gateway_unavailable"),i.push(le(c,u));break;case "request_too_large":i.push(`${c}:failed:request_too_large`);break;case "transient":this.markDegraded(c,"transient_exhausted"),i.push(`${c}:failed:transient_exhausted`);break;default:i.push(le(c,u));break}if(r?.subscriptionOnly&&c==="claude-cli"){i.push("subscription_only:cascade_halted");break}}}throw C("engine.cascade-exhausted",{chain:i,mode:"execute"}),qe(i)?new z(i):new U(i)}async stream(e,t,r){let s=crypto$1.randomUUID(),i=ze(t),a=Je(e),o=Date.now(),l=[],d=null,c=null;for(let u of i){let h=u.type;if(this.getHealthStatus(h)==="unhealthy"){l.push(`${h}:skipped:unhealthy`);continue}if(a&&!u.supportsMultimodal){l.push(`${h}:skipped:no_multimodal`);continue}if(!u.supportsStreaming){l.push(`${h}:skipped:no_streaming`);continue}let R=oe(e.model);if(R&&R!==h&&je.has(h)){l.push(`${h}:skipped:wrong_provider`);continue}try{c=await u.streamRaw(e,{signal:r?.signal}),d=u,l.push(`${h}:success`);break}catch(b){if(b?.name==="AbortError"||r?.signal?.aborted)throw b;switch(ce(b)){case "rate_limited":u.reportRateLimit({provider:h,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(h,"rate_limited"),l.push(`${h}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(h,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),l.push(`${h}:failed:auth_failed`);break;case "timeout":l.push(`${h}:failed:timeout`);break;case "provider_incompatible":l.push(`${h}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(h,"gateway_unavailable"),l.push(le(h,b));break;case "request_too_large":l.push(`${h}:failed:request_too_large`);break;case "transient":this.markDegraded(h,"transient_exhausted"),l.push(`${h}:failed:transient_exhausted`);break;default:l.push(le(h,b));break}if(r?.subscriptionOnly&&h==="claude-cli"){l.push("subscription_only:cascade_halted");break}}}if(!d||!c)throw C("engine.cascade-exhausted",{chain:l,mode:"stream"}),qe(l)?new z(l):new U(l);let m=this,y=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*p(){let u=d,h=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},b={segments:[]},T=Xe(u.type);b.segments.push(T);let Le=0,ee=null,te=false,be=y,H="",B="";for(m.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:u.type});;)try{for(;;){let A=await h.next();if(A.done)break;let L=A.value,k=Ut(L,Le,R,te,ee);if(k.action==="suppress"){"coalesceMode"in k&&(ee=k.coalesceMode),k.clearedJustFailedOver&&(te=!1);continue}k.coalesceModeCleared&&(ee=null),k.clearedJustFailedOver&&(te=!1);let v=k.event;if(Nt(R,v),v.type==="message_start"){if(b.segments.length>1)continue;H=v.message?.model||H,v.message?.usage?.input_tokens!=null&&(T.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(B=v.delta.stop_reason),v.usage)){Dt(T,u.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(R.content.length===0&&T.outputTokens===0)throw new Error("stream ended without producing any content");m.markHealthy(u.type),m.emitEngineEvent({kind:"segment_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:u.type,usage:{...T}});let w=Qe(b.segments);yield {type:"message_delta",delta:{stop_reason:B||"end_turn"},usage:w},yield {type:"message_stop"},m.emitEngineEvent({kind:"stream_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),stitched:b.segments.length>1,segments:b.segments.map(A=>({...A})),provider:b.segments.map(A=>A.provider).join("+"),model:H,inputTokens:w.input_tokens,outputTokens:w.output_tokens,costUsd:b.segments.reduce((A,L)=>A+L.costUsd,0),userCostUsd:b.segments.reduce((A,L)=>A+L.userCostUsd,0),durationMs:Date.now()-o,stopReason:B||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(w){if(w?.name==="AbortError"||r?.signal?.aborted)throw w;let A=ce(w);try{await h.return?.();}catch{}if(m.markUnhealthy(u.type,String(w)),m.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:u.type,bytesBuffered:Ze(R),errorClass:A,retriesLeft:be}),l.push(`${u.type}:partial(${Ze(R)}b)`),be<=0)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;let L=Ft(R.content),k=[...e.messages,{role:"assistant",content:L}],v=null,re=null,Oe=u;for(;;){let I=m.nextHealthyProvider(i,Oe,a,_);if(!I)break;Oe=I,_.add(I);let st={...e,messages:k,...I.type!=="anthropic-api"&&I.type!=="claude-cli"?{system:Ht(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{re=await I.streamRaw(st,{signal:r?.signal}),v=I;break}catch(Me){m.markUnhealthy(I.type,String(Me)),l.push(`${I.type}:failed_connect:${String(Me).slice(0,et)}`);}}if(!v||!re)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;l.push(`${v.type}:stitched`),m.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:u.type,to:v.type}),Le=Bt(R)+1,be--,u=v,h=re[Symbol.asyncIterator](),te=true,ee=null,T=Xe(u.type),b.segments.push(T),m.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:u.type});}}let f=p();return r?.licenseState==="SEC_DEGRADED"&&(f=Kt(f)),M(f)}nextHealthyProvider(e,t,r,s){let i=e.indexOf(t);if(i===-1)return null;for(let a=i+1;a<e.length;a++){let o=e[a];if(!s.has(o)&&!(r&&!o.supportsMultimodal)&&o.supportsStreaming)return o}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,s,i,a,o){let l=Qe(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:crypto$1.randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(d=>({...d})),provider:t.segments.map(d=>d.provider).join("+"),model:r,inputTokens:l.input_tokens,outputTokens:l.output_tokens,costUsd:t.segments.reduce((d,c)=>d+c.costUsd,0),userCostUsd:t.segments.reduce((d,c)=>d+c.userCostUsd,0),durationMs:Date.now()-a,stopReason:s||"error",fallbackChain:i,rateLimitHit:false,securityState:o});}};function Xe(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Dt(n,e,t){typeof t.input_tokens=="number"&&(n.inputTokens=t.input_tokens),typeof t.output_tokens=="number"&&(e==="anthropic-api"||e==="claude-cli"?n.outputTokens+=t.output_tokens:n.outputTokens=t.output_tokens);}function Qe(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function Nt(n,e){if(e.type==="content_block_start"){let t=e.content_block;t?.type==="text"?n.content.push({type:"text",text:t.text||"",open:true}):t?.type==="tool_use"&&n.content.push({type:"tool_use",id:t.id,name:t.name,input:{},_partialJson:"",open:true});}else if(e.type==="content_block_delta"){let t=n.content[n.content.length-1];if(!t)return;t.type==="text"&&e.delta?.type==="text_delta"?t.text+=e.delta.text||"":t.type==="tool_use"&&e.delta?.type==="input_json_delta"&&(t._partialJson=(t._partialJson||"")+(e.delta.partial_json||""));}else if(e.type==="content_block_stop"){for(let t=n.content.length-1;t>=0;t--)if(n.content[t].open){if(n.content[t].open=false,n.content[t].type==="tool_use"){let r=n.content[t];try{r.input=JSON.parse(r._partialJson||"{}");}catch{}delete r._partialJson;}break}}}function Ut(n,e,t,r,s){if(s&&n.type==="content_block_delta"&&n.index===s.fromIndex)return {action:"yield",event:{...n,index:s.toIndex}};if(s&&n.type==="content_block_stop"&&n.index===s.fromIndex)return {action:"suppress",coalesceMode:null,coalesceModeCleared:true};if(r&&n.type==="content_block_start"&&n.content_block?.type==="text"){let a=t.content[t.content.length-1];if(a?.type==="text"&&a.open===true)return {action:"suppress",coalesceMode:{fromIndex:n.index+e,toIndex:t.content.length-1},clearedJustFailedOver:true}}let i=r&&n.type==="content_block_start";return typeof n.index=="number"&&e>0?{action:"yield",event:{...n,index:n.index+e},clearedJustFailedOver:i}:{action:"yield",event:n,clearedJustFailedOver:i}}function Ft(n){let e=[];for(let t of n)t.type==="text"?t.text&&e.push({type:"text",text:t.text}):t.type==="tool_use"&&!t.open&&t.input&&Object.keys(t.input).length>0&&e.push({type:"tool_use",id:t.id,name:t.name,input:t.input});return e}function Ht(n,e){return n?`${n}
10
+ -----END PUBLIC KEY-----`,Ee={version:"1.0.0",cliVersion:"2.1.87",eventTypes:{system:"system",streamEvent:"stream_event",assistant:"assistant",result:"result"},fieldMappings:{sessionId:"session_id",model:"model",cliVersion:"claude_code_version",content:"content",usage:"usage",inputTokens:"input_tokens",outputTokens:"output_tokens",stopReason:"stop_reason",isError:"is_error",totalCostUsd:"total_cost_usd",durationMs:"duration_ms",error:"error",event:"event"},syntheticModel:"<synthetic>"},D=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(ve,"RS256"),{payload:i}=await t(e,s),a=JSON.parse(new TextDecoder().decode(i));return this.verificationFailures=0,this.cachedManifest=a,this.currentSecurityState="SEC_NOMINAL",{manifest:a,securityState:"SEC_NOMINAL"}}catch{if(this.verificationFailures++,this.verificationFailures>=3){this.currentSecurityState="SEC_DEGRADED";let t=2e3+Math.random()*3e3;return await new Promise(r=>setTimeout(r,t)),console.warn("[inference-relay] Logic synchronization mismatch. Routing via local recovery."),{manifest:Ee,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Ee,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},ct=new D;function De(){ct.clearCache();}function ut(){return Ee}function dt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}function S(n,...e){process.env.IR_DEBUG==="1"&&console.error(`[ir-debug:${n}]`,...e);}var gt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function Ce(n){return path.join(os.homedir(),".inference-relay","gateway",n)}function Fe(n){return path.join(Ce(n),"bundle.js")}function He(n){return path.join(Ce(n),"meta.json")}var E=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},x=class extends E{constructor(e,t){super(e,"GATEWAY_FETCH_FAILED",t);}},G=new Map,ft=[0,1e3,4e3];function _t(n){let e=(r,s)=>{if(!Array.isArray(r)||r.length===0)return null;let i=[];for(let a of r){let o=typeof a=="string"?Number(a):a;if(typeof o!="number"||!Number.isFinite(o)||o<0)return S("loader.retry-config-invalid",{source:s,badValue:a}),null;i.push(o);}return i};if(n!==void 0){let r=e(n,"option");if(r)return r}let t=process.env.IR_GATEWAY_RETRY_DELAYS_MS;if(t){let r=e(t.split(",").map(s=>s.trim()),"env");if(r)return r}return ft}var N=class{static async load(e,t,r=gt,s){let i=`${t}:${e.slice(-8)}`;if(G.has(i))return G.get(i);try{let m=await this.tryLoadFromDisk(t);if(m)return S("loader.cache-hit",{libraryVersion:t}),G.set(i,m),m}catch{}S("loader.cache-miss",{libraryVersion:t});let{bytes:a,sha256:o,signature:l,libraryVersion:d}=await this.fetchFromAuthority(e,t,r,s);if(crypto$1.createHash("sha256").update(a).digest("hex")!==o)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,d,o);try{let m=Ce(t);fs.mkdirSync(m,{recursive:!0}),fs.writeFileSync(Fe(t),a),fs.writeFileSync(He(t),JSON.stringify({sha256:o,signature:l,libraryVersion:d}));}catch{}let g=this.loadIntoVm(a.toString("utf-8"));return G.set(i,g),g}static async loadFromDisk(e){if(!fs.existsSync(e))throw new E(`[ir-system]: GATEWAY_LOAD_FAILED (REASON: BUNDLE_NOT_FOUND at ${e})`,"GATEWAY_LOAD_FAILED");let t=fs.readFileSync(e,"utf-8");return this.loadIntoVm(t)}static async tryLoadFromDisk(e){let t=Fe(e),r=He(e);if(!fs.existsSync(t)||!fs.existsSync(r))return null;let s=fs.readFileSync(t),i=JSON.parse(fs.readFileSync(r,"utf-8"));return crypto$1.createHash("sha256").update(s).digest("hex")!==i.sha256?null:(await this.verifySignature(i.signature,i.libraryVersion,i.sha256),this.loadIntoVm(s.toString("utf-8")))}static async fetchFromAuthority(e,t,r,s){let i,a=_t(s?.retryDelaysMs),o;for(let g=0;g<a.length;g++){let m=a[g];m>0&&await new Promise(y=>setTimeout(y,m)),S("loader.fetch",{url:`${r}/v1/gateway/fetch`,libraryVersion:t,attempt:g+1,delayMs:m});try{let y=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(S("loader.fetch-result",{status:y.status,attempt:g+1}),y.status===401||y.status===403)throw new E("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(y.status>=500&&y.status<600){o=new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);continue}if(!y.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);i=await y.json(),o=null;break}catch(y){if(y instanceof E&&y.code==="LICENSE_REJECTED")throw y;o=y;}}if(o||!i)throw o instanceof E?o:new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)",o);let l;try{l=await fetch(i.bundleUrl);}catch(g){throw new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)",g)}if(!l.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`);let d=await l.arrayBuffer();return {bytes:Buffer.from(d),sha256:i.sha256,signature:i.signature,libraryVersion:i.libraryVersion,bundleVersion:i.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(ve,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof E?s:new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SIGNATURE_INVALID)","GATEWAY_VERIFICATION_FAILED",s)}}static loadIntoVm(e){try{let t=path.join(os.homedir(),".inference-relay","gateway","runtime.cjs"),r=path.dirname(t),s=module$1.createRequire(t),i={exports:{}};vm.compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(i.exports,s,i,t,r);let o=i.exports;if(!o.ClaudeCLIProvider)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof E?t:new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){G.clear();}};var Ge="1.6.13",ie=class extends C{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof E?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(se(),Ke));return e()}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let r=JSON.stringify(e.messages).length/4+5e3,s=(r*3+1e3*15)/1e6;return {estimatedInputTokens:Math.round(r),estimatedCost:Math.round(s*1e4)/1e4,model:e.model,provider:"claude-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}},ae=class extends C{type="kimi-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).KimiCLIProvider;if(!t)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: STALE_BUNDLE_NO_KIMI_CLI)","GATEWAY_LOAD_FAILED");let r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,this.health.lastError=e instanceof Error?e.message:String(e),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{existsSync:e}=await import('fs'),{homedir:t}=await import('os'),{join:r}=await import('path'),s=process.env.KIMI_CODE_HOME||r(t(),".kimi-code"),i=process.env.IR_KIMI_BIN||r(s,"bin","kimi"),a=e(i),o=e(r(s,"credentials"))||e(r(s,"oauth"));return {available:a,authenticated:o,subscriptionType:o?"kimi-code":void 0}}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let t=JSON.stringify(e.messages).length/4;return {estimatedInputTokens:Math.round(t+2e3),estimatedCost:0,model:e.model,provider:"kimi-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}};var Y=[{canonical:"claude-haiku-4-5",apiId:"claude-haiku-4-5-20251001",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[.8,4]},{canonical:"claude-sonnet-4-6",apiId:"claude-sonnet-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[3,15]},{canonical:"claude-opus-4-6",apiId:"claude-opus-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[15,75]},{canonical:"gpt-4.1",apiId:"gpt-4.1",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[2,8]},{canonical:"gpt-4.1-mini",apiId:"gpt-4.1-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.4,1.6]},{canonical:"gpt-4.1-nano",apiId:"gpt-4.1-nano",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.1,.4]},{canonical:"gpt-4o",apiId:"gpt-4o",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[2.5,10]},{canonical:"gpt-4o-mini",apiId:"gpt-4o-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[.15,.6]},{canonical:"o4-mini",apiId:"o4-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o3",apiId:"o3",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[.4,1.6]},{canonical:"o3-mini",apiId:"o3-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o1",apiId:"o1",provider:"openai-api",capabilities:{streaming:false,tools:false,multimodal:false,contextWindow:2e5},pricing:[15,60]},{canonical:"llama3.1",apiId:"llama3.1",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"mistral",apiId:"mistral",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}},{canonical:"mistral-nemo",apiId:"mistral-nemo",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"llava",apiId:"llava",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:true,contextWindow:32e3}},{canonical:"qwen2:0.5b",apiId:"qwen2:0.5b",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}}],$=Object.fromEntries(Y.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));$["claude-sonnet-4"]="claude-sonnet-4-20250514";$["claude-opus-4"]="claude-opus-4-20250514";$["claude-haiku-4"]="claude-haiku-4-5-20251001";function Se(n){return $[n]||n}function Ct(n){return Y.find(e=>e.canonical===n)}function oe(n){return Y.find(e=>e.canonical===n)?.provider}function St(n){return Y.filter(e=>e.provider===n)}var wt="https://api.anthropic.com/v1/messages",Pt="2023-06-01",we={"claude-sonnet-4-5-20250514":[3,15],"claude-sonnet-4-20250514":[3,15],"claude-haiku-4-5-20250414":[.8,4],"claude-opus-4-20250514":[15,75]};function Ve(n){if(we[n])return we[n];for(let[e,t]of Object.entries(we))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var W=class extends C{type="anthropic-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;dangerousDirectBrowserAccess;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||wt,this.dangerousDirectBrowserAccess=e.dangerousDirectBrowserAccess??false;}async probe(){try{let e=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{available:!0,authenticated:!1}:e.ok||e.status===429?{available:!0,authenticated:!0,rateLimitTier:e.headers.get("anthropic-ratelimit-tier")??void 0}:e.status===529?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let[l,d]=Ve(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,g={},m=["request-id","x-request-id","anthropic-ratelimit-requests-limit","anthropic-ratelimit-requests-remaining","anthropic-ratelimit-requests-reset","anthropic-ratelimit-tokens-limit","anthropic-ratelimit-tokens-remaining","anthropic-ratelimit-tokens-reset","anthropic-ratelimit-tier"];for(let y of m){let _=i.headers.get(y);_&&(g[y]=_);}return {content:a.content||[],model:a.model||e.model,usage:{input_tokens:a.usage?.input_tokens||0,output_tokens:a.usage?.output_tokens||0},stop_reason:a.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:o,fallbackChain:["anthropic-api:success"],headers:Object.keys(g).length>0?g:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("ANTHROPIC_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder;return (async function*(){let o="",l=false;try{for(;;){let{done:d,value:c}=await i.read();if(d)break;o+=a.decode(c,{stream:!0});let g=o.split(`
11
+ `);o=g.pop()||"";let m=null;for(let y of g)if(y.startsWith("event: "))m=y.slice(7).trim();else if(y.startsWith("data: ")){let _=y.slice(6);if(m&&_)try{let p=JSON.parse(_);p.type==="message_stop"&&(l=!0),yield p;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}m=null;}else y.trim()===""&&(m=null);}l||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=Ve(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"anthropic-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){let e={"content-type":"application/json","x-api-key":this.apiKey,"anthropic-version":Pt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:Se(e.model),max_tokens:e.max_tokens,messages:e.messages};return t&&(r.stream=true),e.system&&(r.system=e.system),e.temperature!==void 0&&(r.temperature=e.temperature),e.tools&&e.tools.length>0&&(r.tools=e.tools),e.metadata&&(r.metadata=e.metadata),r}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw t===529?(this.health.status="degraded",this.health.lastError="API overloaded",this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_OVERLOADED: API is temporarily overloaded (529)")):(this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`ANTHROPIC_API_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var kt="https://api.openai.com/v1/chat/completions",Ye=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Pe={"gpt-4.1":[2,8],"gpt-4.1-mini":[.4,1.6],"gpt-4.1-nano":[.1,.4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"o4-mini":[1.1,4.4],o3:[.4,1.6],"o3-mini":[1.1,4.4],o1:[15,60],"o1-mini":[3,12],"gpt-4-turbo":[10,30],"gpt-4":[30,60],"gpt-3.5-turbo":[.5,1.5]};function $e(n){if(Pe[n])return Pe[n];for(let[e,t]of Object.entries(Pe))if(n.startsWith(e))return t;return [2.5,10]}function It(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Tt(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=It(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let i=r.content.filter(a=>a.type==="tool_use");if(i.length>0){t.push({role:"assistant",content:s||"",tool_calls:i.map(a=>({id:a.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:a.name,arguments:typeof a.input=="string"?a.input:JSON.stringify(a.input)}}))});continue}}t.push({role:r.role,content:s});}return t}function We(n){switch(n){case "stop":return "end_turn";case "length":return "max_tokens";case "tool_calls":case "function_call":return "tool_use";default:return "end_turn"}}var q=class extends C{type="openai-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||kt;}async probe(){try{let e=this.baseUrl.replace(/\/chat\/completions$/,"/models"),t=await fetch(e,{method:"GET",headers:this.buildHeaders()});return t.status===401?{available:!0,authenticated:!1}:t.ok||t.status===429?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=a.choices?.[0],d=[];if(l?.message?.content&&d.push({type:"text",text:l.message.content}),l?.message?.tool_calls)for(let u of l.message.tool_calls)d.push({type:"tool_use",id:u.id,name:u.function?.name,input:u.function?.arguments?JSON.parse(u.function.arguments):{}});let c=a.usage?.prompt_tokens||0,g=a.usage?.completion_tokens||0,[m,y]=$e(a.model||e.model),_=(c*m+g*y)/1e6,p={},f=["x-request-id","x-ratelimit-limit-requests","x-ratelimit-remaining-requests","x-ratelimit-limit-tokens","x-ratelimit-remaining-tokens","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];for(let u of f){let h=i.headers.get(u);h&&(p[u]=h);}return {content:d,model:a.model||e.model,usage:{input_tokens:c,output_tokens:g},stop_reason:We(l?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(p).length>0?p:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OPENAI_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false,g,m;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:y,value:_}=await i.read();if(y)break;l+=a.decode(_,{stream:!0});let p=l.split(`
12
+ `);l=p.pop()||"";for(let f of p){if(!f.startsWith("data: "))continue;let u=f.slice(6).trim();if(u==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"},c=!0;return}try{let h=JSON.parse(u);h.usage&&(g={input_tokens:h.usage.prompt_tokens||0,output_tokens:h.usage.completion_tokens||0});let R=h.choices?.[0];if(!R)continue;let b=R.delta;b?.content&&!d&&(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),b?.content&&(yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:b.content}}),R.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),m=We(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=$e(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"openai-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}buildRequestBody(e,t){let r=e.model.toLowerCase();if(!Ye.some(o=>r.startsWith(o)))throw new Error(`OPENAI_MODEL_TRANSLATION_REQUIRED: The OpenAI provider received the model name '${e.model}', which does not match any known OpenAI model prefix (${Ye.join(", ")}). The relay does NOT auto-translate model names across providers in v1.3.x. Either (a) pass an OpenAI model name like 'gpt-4o-mini' when routing to this provider, or (b) route non-OpenAI models through a provider that understands them (e.g. 'anthropic-api' for Claude models).`);let i=Tt(e.messages,e.system),a={model:e.model,max_tokens:e.max_tokens,messages:i};return t&&(a.stream=true,a.stream_options={include_usage:true}),e.temperature!==void 0&&(a.temperature=e.temperature),e.tools&&e.tools.length>0&&(a.tools=e.tools),a}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("OPENAI_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`OPENAI_API_ERROR: Request failed with status ${t}`)}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var xt="http://localhost:11434";function Lt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ot(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:Lt(r.content)});return t}var j=class extends C{type="ollama";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.baseUrl=e?.baseUrl?.replace(/\/$/,"")||xt;}async probe(){try{return (await fetch(`${this.baseUrl}/api/tags`,{method:"GET"})).ok?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=[];a.message?.content&&l.push({type:"text",text:a.message.content});let d=a.prompt_eval_count||0,c=a.eval_count||0;return {content:l,model:a.model||e.model,usage:{input_tokens:d,output_tokens:c},stop_reason:(a.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:o,fallbackChain:["ollama:success"]}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OLLAMA_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:g,value:m}=await i.read();if(g)break;l+=a.decode(m,{stream:!0});let y=l.split(`
13
+ `);l=y.pop()||"";for(let _ of y){let p=_.trim();if(p)try{let f=JSON.parse(p);if(f.message?.content&&(d||(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:f.message.content}}),f.done){d&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:f.prompt_eval_count||0,output_tokens:f.eval_count||0}},yield {type:"message_stop"},c=!0;return}}catch{}}}c||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0;return {estimatedInputTokens:t+r,estimatedCost:0,model:e.model,provider:"ollama"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildRequestBody(e,t){if(e.tools&&e.tools.length>0)throw new Error(`OLLAMA_TOOLS_NOT_SUPPORTED: The Ollama provider received ${e.tools.length} tool definition(s) in params.tools, but this provider does not implement function calling in v1.3.x. For tool-use workflows route to 'anthropic-api' or 'openai-api' instead. Tracking issue: 1.4.0 ships an Ollama tool-use shim for models that support native function calling (llama3.1, mistral-nemo, etc.).`);let r=Ot(e.messages,e.system),s={model:e.model,messages:r,stream:t};return e.temperature!==void 0&&(s.options={temperature:e.temperature}),s}handleErrorResponse(e){let t=e.status;throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),t===404?(this.health.status="unhealthy",this.health.lastError="Model not found",new Error("OLLAMA_MODEL_NOT_FOUND: Requested model is not available locally (404)")):(this.health.status="unhealthy",this.health.lastError=`Request failed with status ${t}`,new Error(`OLLAMA_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var J=class extends events.EventEmitter{constructor(){super(),this.setMaxListeners(50);}emitTyped(e){return this.emit(e.kind,e)}onTyped(e,t){return this.on(e,t)}offTyped(e,t){return this.off(e,t)}};var et=200;function le(n,e){if(e instanceof E)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,et)||"unknown"}`}function qe(n){let e=n.filter(t=>t.includes(":failed:"));return e.length===0?false:e.every(t=>t.endsWith(":failed:request_too_large"))}var je=new Set(["anthropic-api","openai-api","ollama"]),U=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}},z=class extends U{constructor(e){super(e);}};function Je(n){return n.messages.some(e=>typeof e.content=="string"?false:Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"))}function ce(n){if(!(n instanceof Error))return "unknown";let e=n.code;if(typeof e=="string"){if(e==="LICENSE_REJECTED")return "auth_failed";if(e==="GATEWAY_FETCH_FAILED"||e==="GATEWAY_VERIFICATION_FAILED"||e==="GATEWAY_LOAD_FAILED")return "gateway_unavailable"}let t=n.message.toLowerCase(),r=n.name.toLowerCase();return t.includes("prompt is too long")||t.includes("prompt too long")||t.includes("prompt_too_large")||t.includes("input length")||t.includes("input is too long")||t.includes("context_length_exceeded")||t.includes("context length exceeded")||t.includes("request too large")||t.includes("tokens exceed")||t.includes("exceeds the maximum")||t.includes("too many tokens")?"request_too_large":t.includes("code 3221226505")||t.includes("cli exited with code 3 ")||t.includes("cli stream exited with code 3 ")||t.includes("bun has crashed")||t.includes("illegal instruction")||t.includes("stream ended without producing any content")||t.includes("cli returned empty response")||t.includes("cli closed stdout without sending any response")||t.includes("kimi_stall_silent")?"transient":t.includes("credit balance is too low")||t.includes("credit balance too low")?"auth_failed":t.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_cli_too_old:")||t.startsWith("stream_json_cli_too_old:")?"provider_incompatible":t.includes("rate limit")||t.includes("429")||r.includes("ratelimit")?"rate_limited":t.includes("auth")||t.includes("401")||t.includes("403")||t.includes("unauthorized")||t.includes("forbidden")?"auth_failed":t.includes("timeout")||t.includes("timed out")||t.includes("aborted")||r==="aborterror"||r==="timeouterror"?"timeout":"unknown"}function ze(n){return [...n].sort((e,t)=>e.priority-t.priority)}var X=class n{healthMap=new Map;engineEvents=new J;static UNHEALTHY_TTL_DEFAULT_MS=300*1e3;static UNHEALTHY_TTL_AUTH_MS=30*1e3;getHealthStatus(e){let t=this.healthMap.get(e);if(!t)return "healthy";let r=t.ttlMs??n.UNHEALTHY_TTL_DEFAULT_MS;if(t.status==="unhealthy"&&Date.now()-t.updatedAt>=r){let s=Date.now()-t.updatedAt;return this.healthMap.delete(e),S("engine.recovered",{providerType:e,ageMs:s,ttlMs:r}),"healthy"}return t.status}markUnhealthy(e,t,r){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now(),ttlMs:r}),S("engine.unhealthy",{providerType:e,reason:t,ttlMs:r});}markDegraded(e,t){this.healthMap.set(e,{status:"degraded",lastError:t,updatedAt:Date.now()});}markHealthy(e){this.healthMap.set(e,{status:"healthy",updatedAt:Date.now()});}resetHealth(){this.healthMap.clear();}async execute(e,t,r){let s=ze(t),i=[],a=Je(e),o=crypto$1.randomUUID(),l=Date.now();for(let d of s){let c=d.type;if(this.getHealthStatus(c)==="unhealthy"){i.push(`${c}:skipped:unhealthy`);continue}if(a&&!d.supportsMultimodal){i.push(`${c}:skipped:no_multimodal`);continue}let m=oe(e.model);if(m&&m!==c&&je.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}let y=r?.maxSameProviderRetries??2,_=0,p=null,f=false;for(;!f;)try{let u=await d.execute(e,{signal:r?.signal});return f=!0,this.markHealthy(c),_>0&&i.push(`${c}:retry_success:${_}`),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:crypto$1.randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd??0}],provider:c,model:u.model,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd,durationMs:u.durationMs??Date.now()-l,stopReason:u.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...u,fallbackChain:i}}catch(u){if(u?.name==="AbortError"||r?.signal?.aborted)throw u;if(ce(u)==="transient"&&_<y){_++;let R=250*Math.pow(2,_-1);S("engine.transient-retry",{id:c,attempt:_,backoffMs:R,msg:String(u?.message||"").slice(0,120)}),i.push(`${c}:retry:${_}`),await new Promise(b=>setTimeout(b,R));continue}p=u;break}if(!f){let u=p;switch(ce(u)){case "rate_limited":d.reportRateLimit({provider:c,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(c,"rate_limited"),i.push(`${c}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(c,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),i.push(`${c}:failed:auth_failed`);break;case "timeout":i.push(`${c}:failed:timeout`);break;case "provider_incompatible":i.push(`${c}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(c,"gateway_unavailable"),i.push(le(c,u));break;case "request_too_large":i.push(`${c}:failed:request_too_large`);break;case "transient":this.markDegraded(c,"transient_exhausted"),i.push(`${c}:failed:transient_exhausted`);break;default:i.push(le(c,u));break}if(r?.subscriptionOnly&&c==="claude-cli"){i.push("subscription_only:cascade_halted");break}}}throw S("engine.cascade-exhausted",{chain:i,mode:"execute"}),qe(i)?new z(i):new U(i)}async stream(e,t,r){let s=crypto$1.randomUUID(),i=ze(t),a=Je(e),o=Date.now(),l=[],d=null,c=null;for(let u of i){let h=u.type;if(this.getHealthStatus(h)==="unhealthy"){l.push(`${h}:skipped:unhealthy`);continue}if(a&&!u.supportsMultimodal){l.push(`${h}:skipped:no_multimodal`);continue}if(!u.supportsStreaming){l.push(`${h}:skipped:no_streaming`);continue}let R=oe(e.model);if(R&&R!==h&&je.has(h)){l.push(`${h}:skipped:wrong_provider`);continue}try{c=await u.streamRaw(e,{signal:r?.signal}),d=u,l.push(`${h}:success`);break}catch(b){if(b?.name==="AbortError"||r?.signal?.aborted)throw b;switch(ce(b)){case "rate_limited":u.reportRateLimit({provider:h,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(h,"rate_limited"),l.push(`${h}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(h,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),l.push(`${h}:failed:auth_failed`);break;case "timeout":l.push(`${h}:failed:timeout`);break;case "provider_incompatible":l.push(`${h}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(h,"gateway_unavailable"),l.push(le(h,b));break;case "request_too_large":l.push(`${h}:failed:request_too_large`);break;case "transient":this.markDegraded(h,"transient_exhausted"),l.push(`${h}:failed:transient_exhausted`);break;default:l.push(le(h,b));break}if(r?.subscriptionOnly&&h==="claude-cli"){l.push("subscription_only:cascade_halted");break}}}if(!d||!c)throw S("engine.cascade-exhausted",{chain:l,mode:"stream"}),qe(l)?new z(l):new U(l);let m=this,y=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*p(){let u=d,h=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},b={segments:[]},T=Xe(u.type);b.segments.push(T);let Le=0,ee=null,te=false,be=y,H="",B="";for(m.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:u.type});;)try{for(;;){let A=await h.next();if(A.done)break;let L=A.value,k=Ut(L,Le,R,te,ee);if(k.action==="suppress"){"coalesceMode"in k&&(ee=k.coalesceMode),k.clearedJustFailedOver&&(te=!1);continue}k.coalesceModeCleared&&(ee=null),k.clearedJustFailedOver&&(te=!1);let v=k.event;if(Nt(R,v),v.type==="message_start"){if(b.segments.length>1)continue;H=v.message?.model||H,v.message?.usage?.input_tokens!=null&&(T.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(B=v.delta.stop_reason),v.usage)){Dt(T,u.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(R.content.length===0&&T.outputTokens===0)throw new Error("stream ended without producing any content");m.markHealthy(u.type),m.emitEngineEvent({kind:"segment_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:u.type,usage:{...T}});let w=Qe(b.segments);yield {type:"message_delta",delta:{stop_reason:B||"end_turn"},usage:w},yield {type:"message_stop"},m.emitEngineEvent({kind:"stream_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),stitched:b.segments.length>1,segments:b.segments.map(A=>({...A})),provider:b.segments.map(A=>A.provider).join("+"),model:H,inputTokens:w.input_tokens,outputTokens:w.output_tokens,costUsd:b.segments.reduce((A,L)=>A+L.costUsd,0),userCostUsd:b.segments.reduce((A,L)=>A+L.userCostUsd,0),durationMs:Date.now()-o,stopReason:B||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(w){if(w?.name==="AbortError"||r?.signal?.aborted)throw w;let A=ce(w);try{await h.return?.();}catch{}if(m.markUnhealthy(u.type,String(w)),m.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:u.type,bytesBuffered:Ze(R),errorClass:A,retriesLeft:be}),l.push(`${u.type}:partial(${Ze(R)}b)`),be<=0)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;let L=Ft(R.content),k=[...e.messages,{role:"assistant",content:L}],v=null,re=null,Oe=u;for(;;){let I=m.nextHealthyProvider(i,Oe,a,_);if(!I)break;Oe=I,_.add(I);let st={...e,messages:k,...I.type!=="anthropic-api"&&I.type!=="claude-cli"?{system:Ht(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{re=await I.streamRaw(st,{signal:r?.signal}),v=I;break}catch(Me){m.markUnhealthy(I.type,String(Me)),l.push(`${I.type}:failed_connect:${String(Me).slice(0,et)}`);}}if(!v||!re)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;l.push(`${v.type}:stitched`),m.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:u.type,to:v.type}),Le=Bt(R)+1,be--,u=v,h=re[Symbol.asyncIterator](),te=true,ee=null,T=Xe(u.type),b.segments.push(T),m.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:u.type});}}let f=p();return r?.licenseState==="SEC_DEGRADED"&&(f=Kt(f)),M(f)}nextHealthyProvider(e,t,r,s){let i=e.indexOf(t);if(i===-1)return null;for(let a=i+1;a<e.length;a++){let o=e[a];if(!s.has(o)&&!(r&&!o.supportsMultimodal)&&o.supportsStreaming)return o}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,s,i,a,o){let l=Qe(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:crypto$1.randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(d=>({...d})),provider:t.segments.map(d=>d.provider).join("+"),model:r,inputTokens:l.input_tokens,outputTokens:l.output_tokens,costUsd:t.segments.reduce((d,c)=>d+c.costUsd,0),userCostUsd:t.segments.reduce((d,c)=>d+c.userCostUsd,0),durationMs:Date.now()-a,stopReason:s||"error",fallbackChain:i,rateLimitHit:false,securityState:o});}};function Xe(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Dt(n,e,t){typeof t.input_tokens=="number"&&(n.inputTokens=t.input_tokens),typeof t.output_tokens=="number"&&(e==="anthropic-api"||e==="claude-cli"?n.outputTokens+=t.output_tokens:n.outputTokens=t.output_tokens);}function Qe(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function Nt(n,e){if(e.type==="content_block_start"){let t=e.content_block;t?.type==="text"?n.content.push({type:"text",text:t.text||"",open:true}):t?.type==="tool_use"&&n.content.push({type:"tool_use",id:t.id,name:t.name,input:{},_partialJson:"",open:true});}else if(e.type==="content_block_delta"){let t=n.content[n.content.length-1];if(!t)return;t.type==="text"&&e.delta?.type==="text_delta"?t.text+=e.delta.text||"":t.type==="tool_use"&&e.delta?.type==="input_json_delta"&&(t._partialJson=(t._partialJson||"")+(e.delta.partial_json||""));}else if(e.type==="content_block_stop"){for(let t=n.content.length-1;t>=0;t--)if(n.content[t].open){if(n.content[t].open=false,n.content[t].type==="tool_use"){let r=n.content[t];try{r.input=JSON.parse(r._partialJson||"{}");}catch{}delete r._partialJson;}break}}}function Ut(n,e,t,r,s){if(s&&n.type==="content_block_delta"&&n.index===s.fromIndex)return {action:"yield",event:{...n,index:s.toIndex}};if(s&&n.type==="content_block_stop"&&n.index===s.fromIndex)return {action:"suppress",coalesceMode:null,coalesceModeCleared:true};if(r&&n.type==="content_block_start"&&n.content_block?.type==="text"){let a=t.content[t.content.length-1];if(a?.type==="text"&&a.open===true)return {action:"suppress",coalesceMode:{fromIndex:n.index+e,toIndex:t.content.length-1},clearedJustFailedOver:true}}let i=r&&n.type==="content_block_start";return typeof n.index=="number"&&e>0?{action:"yield",event:{...n,index:n.index+e},clearedJustFailedOver:i}:{action:"yield",event:n,clearedJustFailedOver:i}}function Ft(n){let e=[];for(let t of n)t.type==="text"?t.text&&e.push({type:"text",text:t.text}):t.type==="tool_use"&&!t.open&&t.input&&Object.keys(t.input).length>0&&e.push({type:"tool_use",id:t.id,name:t.name,input:t.input});return e}function Ht(n,e){return n?`${n}
14
14
 
15
- ${e}`:e}function Ze(n){let e=0;for(let t of n.content)t.type==="text"?e+=t.text.length:t.type==="tool_use"&&(e+=(t._partialJson||"").length);return e}function Bt(n){return Math.max(0,n.content.length-1)}async function*Kt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}se();function ue(n,e){if(e==="prefer-user"){let s=n.filter(a=>a.type==="claude-cli"),i=n.filter(a=>a.type!=="claude-cli");return [...s,...i]}if(e==="prefer-app"){let s=n.filter(a=>a.type==="claude-cli");return [...n.filter(a=>a.type!=="claude-cli"),...s]}let t=n.filter(s=>s.type===e),r=n.filter(s=>s.type!==e);return [...t,...r]}function de(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var pe={"claude-fable-5":[10,50],"claude-mythos-5":[10,50],"claude-opus-5-5":[4,20],"claude-opus-5":[5,25],"claude-opus-4-8":[5,25],"claude-opus-4-7":[5,25],"claude-opus-4-6":[5,25],"claude-opus-4-5":[5,25],"claude-opus-4":[15,75],"claude-sonnet-5":[2,10],"claude-sonnet-4":[3,15],"claude-haiku-5-5":[.1,.5],"claude-haiku-4-5":[1,5],"claude-3-5-haiku":[.8,4],"claude-3-haiku":[.25,1.25],"kimi-k3":[3,15],"kimi-k2.7-code":[.95,4],"kimi-for-coding":[.95,4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"gpt-4-turbo":[10,30],"gpt-3.5-turbo":[.5,1.5],llama:[0,0],mistral:[0,0],codellama:[0,0]};function me(n){if(pe[n])return pe[n];let e=null;for(let t of Object.keys(pe))n.startsWith(t)&&(e===null||t.length>e.length)&&(e=t);return e!==null?pe[e]:[3,15]}function he(n){let e=0;for(let o of n.messages)if(typeof o.content=="string")e+=o.content.length;else if(Array.isArray(o.content))for(let l of o.content)l.type==="text"&&l.text&&(e+=l.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[s,i]=me(n.model),a=(t*s+r*i)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(a*1e4)/1e4,model:n.model,provider:""}}var F=class{endpoint;enabled;keyId;lineageBuffer=new Map;unsubscribers=[];constructor(e){this.endpoint=e.endpoint||"https://api.inference-relay.com/v1/events",this.enabled=e.enabled??true,this.keyId=e.keyId||"";}subscribeToEngine(e){let t=s=>this.bufferLineageEvent(s),r=s=>{s.kind==="stream_complete"&&this.flushLineageForCall(s);};e.engineEvents.onTyped("segment_start",t),e.engineEvents.onTyped("segment_complete",t),e.engineEvents.onTyped("mid_stream_failover_attempt",t),e.engineEvents.onTyped("mid_stream_failover_success",t),e.engineEvents.onTyped("stream_complete",r),this.unsubscribers.push(()=>{e.engineEvents.offTyped("segment_start",t),e.engineEvents.offTyped("segment_complete",t),e.engineEvents.offTyped("mid_stream_failover_attempt",t),e.engineEvents.offTyped("mid_stream_failover_success",t),e.engineEvents.offTyped("stream_complete",r);});}unsubscribe(){for(let e of this.unsubscribers)e();this.unsubscribers=[],this.lineageBuffer.clear();}bufferLineageEvent(e){let t=this.lineageBuffer.get(e.callId)??[];t.push(e),this.lineageBuffer.set(e.callId,t);}flushLineageForCall(e){let t=this.lineageBuffer.get(e.callId)??[];this.lineageBuffer.delete(e.callId);let r={timestamp:e.ts,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,userCostUsd:e.userCostUsd,durationMs:e.durationMs,stopReason:e.stopReason,fallbackChain:e.fallbackChain,rateLimitHit:e.rateLimitHit,securityState:e.securityState,stitched:e.stitched,segments:e.segments,lineage:t.map(s=>s.id),promptContent:false,completionContent:false};this.report(r);}report(e){!this.enabled||!this.keyId||fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({keyId:this.keyId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,...e.userCostUsd!==void 0?{userCostUsd:e.userCostUsd}:{},durationMs:e.durationMs,fallback:e.fallbackChain.length>1,timestamp:e.timestamp,...e.stitched?{stitched:true,segmentCount:e.segments?.length??0}:{},...e.lineage?{lineageIds:e.lineage}:{}})}).catch(()=>{});}};var Q="1.6.12",ye=Object.freeze({streamKeepsHistory:true,streamToolBlocks:true,streamBareToolNames:true,stopsWhenCallerGoes:true});function ke(){return {name:"inference-relay",version:Q,features:ye}}var Gt="https://api.inference-relay.com",Vt="/v1/validate",Yt=1440*60*1e3,$t=10080*60*1e3,Wt=`-----BEGIN PUBLIC KEY-----
15
+ ${e}`:e}function Ze(n){let e=0;for(let t of n.content)t.type==="text"?e+=t.text.length:t.type==="tool_use"&&(e+=(t._partialJson||"").length);return e}function Bt(n){return Math.max(0,n.content.length-1)}async function*Kt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}se();function ue(n,e){if(e==="prefer-user"){let s=n.filter(a=>a.type==="claude-cli"),i=n.filter(a=>a.type!=="claude-cli");return [...s,...i]}if(e==="prefer-app"){let s=n.filter(a=>a.type==="claude-cli");return [...n.filter(a=>a.type!=="claude-cli"),...s]}let t=n.filter(s=>s.type===e),r=n.filter(s=>s.type!==e);return [...t,...r]}function de(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var pe={"claude-fable-5":[10,50],"claude-mythos-5":[10,50],"claude-opus-5-5":[4,20],"claude-opus-5":[5,25],"claude-opus-4-8":[5,25],"claude-opus-4-7":[5,25],"claude-opus-4-6":[5,25],"claude-opus-4-5":[5,25],"claude-opus-4":[15,75],"claude-sonnet-5":[2,10],"claude-sonnet-4":[3,15],"claude-haiku-5-5":[.1,.5],"claude-haiku-4-5":[1,5],"claude-3-5-haiku":[.8,4],"claude-3-haiku":[.25,1.25],"kimi-k3":[3,15],"kimi-k2.7-code":[.95,4],"kimi-for-coding":[.95,4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"gpt-4-turbo":[10,30],"gpt-3.5-turbo":[.5,1.5],llama:[0,0],mistral:[0,0],codellama:[0,0]};function me(n){if(pe[n])return pe[n];let e=null;for(let t of Object.keys(pe))n.startsWith(t)&&(e===null||t.length>e.length)&&(e=t);return e!==null?pe[e]:[3,15]}function he(n){let e=0;for(let o of n.messages)if(typeof o.content=="string")e+=o.content.length;else if(Array.isArray(o.content))for(let l of o.content)l.type==="text"&&l.text&&(e+=l.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[s,i]=me(n.model),a=(t*s+r*i)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(a*1e4)/1e4,model:n.model,provider:""}}var F=class{endpoint;enabled;keyId;lineageBuffer=new Map;unsubscribers=[];constructor(e){this.endpoint=e.endpoint||"https://api.inference-relay.com/v1/events",this.enabled=e.enabled??true,this.keyId=e.keyId||"";}subscribeToEngine(e){let t=s=>this.bufferLineageEvent(s),r=s=>{s.kind==="stream_complete"&&this.flushLineageForCall(s);};e.engineEvents.onTyped("segment_start",t),e.engineEvents.onTyped("segment_complete",t),e.engineEvents.onTyped("mid_stream_failover_attempt",t),e.engineEvents.onTyped("mid_stream_failover_success",t),e.engineEvents.onTyped("stream_complete",r),this.unsubscribers.push(()=>{e.engineEvents.offTyped("segment_start",t),e.engineEvents.offTyped("segment_complete",t),e.engineEvents.offTyped("mid_stream_failover_attempt",t),e.engineEvents.offTyped("mid_stream_failover_success",t),e.engineEvents.offTyped("stream_complete",r);});}unsubscribe(){for(let e of this.unsubscribers)e();this.unsubscribers=[],this.lineageBuffer.clear();}bufferLineageEvent(e){let t=this.lineageBuffer.get(e.callId)??[];t.push(e),this.lineageBuffer.set(e.callId,t);}flushLineageForCall(e){let t=this.lineageBuffer.get(e.callId)??[];this.lineageBuffer.delete(e.callId);let r={timestamp:e.ts,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,userCostUsd:e.userCostUsd,durationMs:e.durationMs,stopReason:e.stopReason,fallbackChain:e.fallbackChain,rateLimitHit:e.rateLimitHit,securityState:e.securityState,stitched:e.stitched,segments:e.segments,lineage:t.map(s=>s.id),promptContent:false,completionContent:false};this.report(r);}report(e){!this.enabled||!this.keyId||fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({keyId:this.keyId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,...e.userCostUsd!==void 0?{userCostUsd:e.userCostUsd}:{},durationMs:e.durationMs,fallback:e.fallbackChain.length>1,timestamp:e.timestamp,...e.stitched?{stitched:true,segmentCount:e.segments?.length??0}:{},...e.lineage?{lineageIds:e.lineage}:{}})}).catch(()=>{});}};var Q="1.6.13",ye=Object.freeze({streamKeepsHistory:true,streamToolBlocks:true,streamBareToolNames:true,stopsWhenCallerGoes:true,stopsAtFirstCap:true});function ke(){return {name:"inference-relay",version:Q,features:ye}}var Gt="https://api.inference-relay.com",Vt="/v1/validate",Yt=1440*60*1e3,$t=10080*60*1e3,Wt=`-----BEGIN PUBLIC KEY-----
16
16
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
17
17
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
18
18
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
@@ -21,4 +21,4 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
21
21
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
22
22
  UQIDAQAB
23
23
  -----END PUBLIC KEY-----`,O=new Map,Ie=new Set,qt=n=>!!n&&typeof n.aborted=="boolean"&&typeof n.addEventListener=="function";function jt(n,e){let t=n?.signal;if(t===void 0)return {params:n,options:e};let{signal:r,...s}=n,i=s;if(!qt(t))return {params:i,options:e};let a=e?.signal;if(!a||a===t)return {params:i,options:{...e,signal:t}};let o=new AbortController,l=()=>{a.removeEventListener("abort",d),t.removeEventListener("abort",d);},d=()=>{l(),o.abort();};return a.aborted||t.aborted?o.abort():(a.addEventListener("abort",d,{once:true}),t.addEventListener("abort",d,{once:true})),{params:i,options:{...e,signal:o.signal},release:l}}async function Te(n,e){if(!n)return {valid:false,error:"License key required. Get one at inference-relay.com"};let t=O.get(n);if(t&&Date.now()-t.cachedAt<t.ttl)return t.result;let s=!O.has(n)?1e4:3e3,i=(e||Gt)+Vt,a=async()=>{let d=new AbortController,c=setTimeout(()=>d.abort(),s);try{return await(await fetch(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n}),signal:d.signal})).json()}finally{clearTimeout(c);}},o;try{o=await a();}catch{try{if(t)throw new Error("cached answer stands in");o=await a();}catch{return t&&Date.now()-t.cachedAt<$t?t.result:{valid:false,error:"License validation failed (network error). Visit inference-relay.com"}}}let l;if(o.jws)try{let{compactVerify:d,importSPKI:c}=await import('jose'),g=await c(Wt,"RS256"),{payload:m}=await d(o.jws,g);l=JSON.parse(new TextDecoder().decode(m));}catch{return O.delete(n),{valid:false,error:"License validation signature invalid. Possible MITM \u2014 refusing to start."}}else if(l=o,l.valid)return O.delete(n),{valid:false,error:"License validation response not signed. Possible MITM."};return O.set(n,{result:l,cachedAt:Date.now(),ttl:l.valid?Yt:6e4}),l}var xe=class n{static version=Q;get version(){return Q}get features(){return ye}hello(){return ke()}providers=[];config;fallbackEngine;telemetryReporter;routingFn=null;license=null;licensePromise=null;licenseValidatedAt=0;callsSinceValidation=0;manifestDecryptor=new D;capProbeTimer=null;capProbeTicksRemaining=0;messages;constructor(e){if(this.config=e,this.fallbackEngine=new X,this.telemetryReporter=new F({endpoint:e.endpoint?`${e.endpoint}/v1/events`:void 0,enabled:e.telemetry!==false,keyId:e.licenseKey}),this.telemetryReporter.subscribeToEngine(this.fallbackEngine),e.routing&&(this.routingFn=de(e.routing)),e.providers)for(let s of e.providers){let i=typeof s=="string"?{type:s}:s,a=this.createProvider(i);a&&(i.priority!==void 0&&(a.priority=i.priority),this.providers.push(a));}let t=100,r=3600*1e3;this.messages={create:async(s,i)=>{let{params:a,options:o,release:l}=jt(s,i),d=false;try{let c=this.license&&(this.callsSinceValidation>=t||Date.now()-this.licenseValidatedAt>=r);if(c&&(this.license=null),!this.license){this.licensePromise||(this.licensePromise=Te(this.config.licenseKey,this.config.endpoint));try{this.license=await this.licensePromise;}finally{this.licensePromise=null;}if(this.licenseValidatedAt=Date.now(),this.callsSinceValidation=0,this.license.valid){if(this.license.capExceeded)throw this.startCapProbe(),new K({tier:this.license.tier||"solo",baseCap:this.license.baseCap??this.license.usageCap??null,topUps:this.license.topUpGrants??0,effectiveCap:this.license.usageCap??null,usedThisCycle:this.license.usageThisMonth??0});!c&&!Ie.has(this.config.licenseKey)&&(Ie.add(this.config.licenseKey),console.log(`[inference-relay] LICENSE AUTHORIZED [${(this.license.tier||"unknown").toUpperCase()} TIER] \u2014 READY.`));}else throw new Error(`[inference-relay] ${this.license.error||"License key invalid or expired. Visit inference-relay.com"}`)}if(this.callsSinceValidation++,a.stream){let g=await this.streamMessage(a,o);return d=!0,g}return await this.executeMessage(a,o)}finally{d||l?.();}}};}startCapProbe(){if(this.capProbeTimer!==null)return;let e=15e3,t=20,r=4;this.capProbeTicksRemaining=t;let s=async()=>{this.capProbeTicksRemaining-=1;let i=Math.ceil(this.capProbeTicksRemaining*e/6e4);this.capProbeTicksRemaining>0&&this.capProbeTicksRemaining%r===0&&console.log(`[inference-relay] cap exceeded \u2014 checking for top-up every 15s (${i}m remaining)`),this.config.licenseKey&&O.delete(this.config.licenseKey);try{let a=await this.probeValidate();if(a.valid&&a.capExceeded===!1){console.log("[inference-relay] cap cleared \u2014 probe exiting, inference resuming"),this.license=a,this.licenseValidatedAt=Date.now(),this.callsSinceValidation=0,this.stopCapProbe();return}}catch{}this.capProbeTicksRemaining<=0&&(console.log("[inference-relay] cap probe exhausted (5 min) \u2014 stopping"),this.stopCapProbe());};this.capProbeTimer=setInterval(s,e),typeof this.capProbeTimer.unref=="function"&&this.capProbeTimer.unref();}async probeValidate(){return Te(this.config.licenseKey,this.config.endpoint)}stopCapProbe(){this.capProbeTimer!==null&&(clearInterval(this.capProbeTimer),this.capProbeTimer=null),this.capProbeTicksRemaining=0;}static async autoDetect(e){let t=[],r=await V();r.available&&r.authenticated!==false&&t.push({type:"claude-cli",priority:1});let s=e?.subscriptionOnly===true||process.env.IR_SUBSCRIPTION_ONLY==="1";return process.env.ANTHROPIC_API_KEY&&!s&&t.push({type:"anthropic-api",priority:2,apiKey:process.env.ANTHROPIC_API_KEY}),new n({licenseKey:e?.licenseKey||process.env.IR_LICENSE_KEY||"",providers:t,fallback:e?.fallback??true,subscriptionOnly:s,...e})}async warmup(){let e=this.providers.find(t=>t.type==="claude-cli");e&&"warmup"in e&&typeof e.warmup=="function"&&await e.warmup();}resetHealth(){this.fallbackEngine.resetHealth();}markHealthy(e){this.fallbackEngine.markHealthy(e);}dispose(){this.providers=[],this.config.licenseKey&&(O.delete(this.config.licenseKey),Ie.delete(this.config.licenseKey)),this.license=null,this.licensePromise=null,this.callsSinceValidation=0,this.stopCapProbe(),this.telemetryReporter.unsubscribe(),this.manifestDecryptor.clearCache(),De();}resolveProviders(e){if(!this.routingFn)return this.providers;let t=he(e),r=this.routingFn(e,t);return ue(this.providers,r)}async executeMessage(e,t){let r=this.resolveProviders(e);return this.fallbackEngine.execute(e,r,{signal:t?.signal,licenseState:this.manifestDecryptor.getSecurityState(),subscriptionOnly:this.config.subscriptionOnly,maxSameProviderRetries:this.config.maxSameProviderRetries})}async streamMessage(e,t){let r=this.resolveProviders(e);return this.fallbackEngine.stream(e,r,{signal:t?.signal,licenseState:this.manifestDecryptor.getSecurityState(),subscriptionOnly:this.config.subscriptionOnly,maxSameProviderRetries:this.config.maxSameProviderRetries})}createProvider(e){switch(e.type){case "claude-cli":return new ie(this.config.licenseKey,{retryDelaysMs:this.config.gatewayRetryDelaysMs});case "kimi-cli":return new ae(this.config.licenseKey,{retryDelaysMs:this.config.gatewayRetryDelaysMs});case "anthropic-api":return e.apiKey?new W({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "openai-api":return e.apiKey?new q({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "ollama":return new j({baseUrl:e.baseUrl});default:return null}}};function Jt(n){if(!n)return 0;if(typeof n=="string")return Math.ceil(n.length/4);if(!Array.isArray(n))return 0;let e=0;for(let t of n){if(!t||typeof t!="object")continue;let r=t;if(r.type==="image"||r.type==="image_url"){e+=1500;continue}if(typeof r.text=="string"){e+=Math.ceil(r.text.length/4);continue}try{e+=Math.ceil(JSON.stringify(t).length/4);}catch{e+=50;}}return e}function zt(n){return 8+Jt(n.content)}function Xt(n){let e=50;typeof n.system=="string"&&(e+=Math.ceil(n.system.length/4));for(let t of n.messages)e+=zt(t);return e}se();var Qt="https://api.anthropic.com/v1/messages",Zt="2023-06-01";async function tt(n){try{let e=await fetch(Qt,{method:"POST",headers:{"content-type":"application/json","x-api-key":n,"anthropic-version":Zt},body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{valid:!1,error:"Invalid API key (401)"}:e.ok?{valid:!0}:e.status===429?{valid:!0,error:"Rate limited (429)"}:e.status===529?{valid:!0,error:"API overloaded (529)"}:{valid:!1,error:`Unexpected status ${e.status}`}}catch(e){return {valid:false,error:`Network error: ${e.message}`}}}var ge=class{filePath;safeStorage=null;memoryFallback=new Map;constructor(e){let t=e?.storagePath||path.join(os.homedir(),".inference-relay");fs.existsSync(t)||fs.mkdirSync(t,{recursive:true}),this.filePath=path.join(t,"credentials.enc");try{let r=at("electron");r?.safeStorage?.isEncryptionAvailable?.()&&(this.safeStorage=r.safeStorage);}catch{}}readDisk(){if(!fs.existsSync(this.filePath))return {};try{let e=fs.readFileSync(this.filePath,"utf-8");return JSON.parse(e)}catch{return {}}}writeDisk(e){fs.writeFileSync(this.filePath,JSON.stringify(e,null,2),{mode:384});}async get(e){if(!this.safeStorage)return this.memoryFallback.get(e)??null;let r=this.readDisk()[e];if(!r)return null;try{let s=Buffer.from(r.data,"base64");return this.safeStorage.decryptString(s)}catch{return null}}async set(e,t){if(!this.safeStorage){this.memoryFallback.set(e,t);return}let r=this.readDisk(),s=this.safeStorage.encryptString(t);r[e]={data:s.toString("base64")},this.writeDisk(r);}async delete(e){if(!this.safeStorage){this.memoryFallback.delete(e);return}let t=this.readDisk();e in t&&(delete t[e],this.writeDisk(t));}async has(e){if(!this.safeStorage)return this.memoryFallback.has(e);let t=this.readDisk();return e in t}};var Z="AES-GCM";var fe=class{dbName="inference-relay-credentials";storeName="keys";cryptoKey=null;passphrase;initPromise=null;constructor(e){this.passphrase=e?.passphrase,e?.dbName&&(this.dbName=e.dbName);}async ensureReady(){if(!this.cryptoKey)return this.initPromise?this.initPromise:(this.initPromise=this.init(),this.initPromise)}async init(){if(await this.openDB(),this.passphrase)this.cryptoKey=await this.deriveKey(this.passphrase,this.getOrCreateSessionSalt());else {let e=typeof sessionStorage<"u"?sessionStorage.getItem("ir-cred-key"):null;if(e){let t=Uint8Array.from(atob(e),r=>r.charCodeAt(0));this.cryptoKey=await crypto.subtle.importKey("raw",t,Z,false,["encrypt","decrypt"]);}else {this.cryptoKey=await crypto.subtle.generateKey({name:Z,length:256},true,["encrypt","decrypt"]);let t=await crypto.subtle.exportKey("raw",this.cryptoKey),r=btoa(String.fromCharCode(...new Uint8Array(t)));typeof sessionStorage<"u"&&sessionStorage.setItem("ir-cred-key",r);}}}openDB(){return new Promise((e,t)=>{let r=indexedDB.open(this.dbName,1);r.onupgradeneeded=()=>{let s=r.result;s.objectStoreNames.contains(this.storeName)||s.createObjectStore(this.storeName);},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error);})}async idbGet(e){let t=await this.openDB();return new Promise((r,s)=>{let o=t.transaction(this.storeName,"readonly").objectStore(this.storeName).get(e);o.onsuccess=()=>r(o.result),o.onerror=()=>s(o.error);})}async idbPut(e,t){let r=await this.openDB();return new Promise((s,i)=>{let l=r.transaction(this.storeName,"readwrite").objectStore(this.storeName).put(t,e);l.onsuccess=()=>s(),l.onerror=()=>i(l.error);})}async idbDelete(e){let t=await this.openDB();return new Promise((r,s)=>{let o=t.transaction(this.storeName,"readwrite").objectStore(this.storeName).delete(e);o.onsuccess=()=>r(),o.onerror=()=>s(o.error);})}async idbHas(e){let t=await this.openDB();return new Promise((r,s)=>{let o=t.transaction(this.storeName,"readonly").objectStore(this.storeName).count(e);o.onsuccess=()=>r(o.result>0),o.onerror=()=>s(o.error);})}getOrCreateSessionSalt(){let e="ir-cred-salt";if(typeof sessionStorage<"u"){let r=sessionStorage.getItem(e);if(r)return Uint8Array.from(atob(r),s=>s.charCodeAt(0))}let t=crypto.getRandomValues(new Uint8Array(16));return typeof sessionStorage<"u"&&sessionStorage.setItem(e,btoa(String.fromCharCode(...t))),t}async deriveKey(e,t){let r=new TextEncoder,s=await crypto.subtle.importKey("raw",r.encode(e),"PBKDF2",false,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:t.buffer,iterations:1e5,hash:"SHA-256"},s,{name:Z,length:256},false,["encrypt","decrypt"])}async encrypt(e){let t=crypto.getRandomValues(new Uint8Array(12)),r=this.getOrCreateSessionSalt(),s=new TextEncoder().encode(e),i=await crypto.subtle.encrypt({name:Z,iv:t},this.cryptoKey,s);return {iv:btoa(String.fromCharCode(...t)),ciphertext:btoa(String.fromCharCode(...new Uint8Array(i))),salt:btoa(String.fromCharCode(...r))}}async decrypt(e){let t=Uint8Array.from(atob(e.iv),i=>i.charCodeAt(0)),r=Uint8Array.from(atob(e.ciphertext),i=>i.charCodeAt(0)),s=await crypto.subtle.decrypt({name:Z,iv:t},this.cryptoKey,r);return new TextDecoder().decode(s)}async get(e){await this.ensureReady();let t=await this.idbGet(e);if(!t)return null;try{return await this.decrypt(t)}catch{return null}}async set(e,t){await this.ensureReady();let r=await this.encrypt(t);await this.idbPut(e,r);}async delete(e){await this.ensureReady(),await this.idbDelete(e);}async has(e){return await this.ensureReady(),this.idbHas(e)}};var _e=class{store=new Map;async get(e){return this.store.get(e)??null}async set(e,t){this.store.set(e,t);}async delete(e){this.store.delete(e);}async has(e){return this.store.has(e)}};
24
- exports.AnthropicAPIProvider=W;exports.BaseProvider=S;exports.ElectronCredentialStore=ge;exports.EngineEventEmitter=J;exports.FallbackEngine=X;exports.GatewayLoader=N;exports.GatewayLoaderError=E;exports.GatewayUnavailableError=x;exports.IndexedDBCredentialStore=fe;exports.InferenceRelay=xe;exports.MODEL_ALIASES=$;exports.MODEL_REGISTRY=Y;exports.ManifestDecryptor=D;exports.MemoryCredentialStore=_e;exports.OllamaProvider=j;exports.OpenAIAPIProvider=q;exports.RELAY_FEATURES=ye;exports.RELAY_VERSION=Q;exports.RelayCapExceededError=K;exports.RelayError=U;exports.RequestTooLargeError=z;exports.TelemetryReporter=F;exports.applyRouting=ue;exports.createRelayStream=M;exports.createRoutingFunction=de;exports.detectCLI=V;exports.estimateCost=he;exports.estimateInputTokens=Xt;exports.findModel=St;exports.getLastKnownGoodManifest=ut;exports.getModelPricing=me;exports.getValue=dt;exports.modelsForProvider=Ct;exports.normalizeModel=Ce;exports.providerForModel=oe;exports.relayHello=ke;exports.validateAnthropicKey=tt;exports.validateLicense=Te;
24
+ exports.AnthropicAPIProvider=W;exports.BaseProvider=C;exports.ElectronCredentialStore=ge;exports.EngineEventEmitter=J;exports.FallbackEngine=X;exports.GatewayLoader=N;exports.GatewayLoaderError=E;exports.GatewayUnavailableError=x;exports.IndexedDBCredentialStore=fe;exports.InferenceRelay=xe;exports.MODEL_ALIASES=$;exports.MODEL_REGISTRY=Y;exports.ManifestDecryptor=D;exports.MemoryCredentialStore=_e;exports.OllamaProvider=j;exports.OpenAIAPIProvider=q;exports.RELAY_FEATURES=ye;exports.RELAY_VERSION=Q;exports.RelayCapExceededError=K;exports.RelayError=U;exports.RequestTooLargeError=z;exports.TelemetryReporter=F;exports.applyRouting=ue;exports.createRelayStream=M;exports.createRoutingFunction=de;exports.detectCLI=V;exports.estimateCost=he;exports.estimateInputTokens=Xt;exports.findModel=Ct;exports.getLastKnownGoodManifest=ut;exports.getModelPricing=me;exports.getValue=dt;exports.modelsForProvider=St;exports.normalizeModel=Se;exports.providerForModel=oe;exports.relayHello=ke;exports.validateAnthropicKey=tt;exports.validateLicense=Te;
package/dist/index.d.cts CHANGED
@@ -39,6 +39,10 @@ interface RelayFeatures {
39
39
  * before the call starts no run, and an aborted call fails as an AbortError, never a cut answer handed back as finished. The signal is read
40
40
  * from create(params, { signal }) and also from create({ ...params, signal }). Undefined on 1.6.11 and earlier. */
41
41
  readonly stopsWhenCallerGoes: boolean;
42
+ /** 1.6.13, the claude-cli provider only (kimi-cli unchanged): a call with max_tokens ends at the FIRST output cap, with the text written so
43
+ * far and stop_reason "max_tokens", on both roads. The CLI is stopped there, before its own "Resume directly" continuations (which ran
44
+ * a capped call to about 4 x max_tokens, ending end_turn when the model finished inside one). Undefined on 1.6.12 and earlier. */
45
+ readonly stopsAtFirstCap: boolean;
42
46
  }
43
47
  declare const RELAY_FEATURES: RelayFeatures;
44
48
  interface RelayHello {
package/dist/index.d.ts CHANGED
@@ -39,6 +39,10 @@ interface RelayFeatures {
39
39
  * before the call starts no run, and an aborted call fails as an AbortError, never a cut answer handed back as finished. The signal is read
40
40
  * from create(params, { signal }) and also from create({ ...params, signal }). Undefined on 1.6.11 and earlier. */
41
41
  readonly stopsWhenCallerGoes: boolean;
42
+ /** 1.6.13, the claude-cli provider only (kimi-cli unchanged): a call with max_tokens ends at the FIRST output cap, with the text written so
43
+ * far and stop_reason "max_tokens", on both roads. The CLI is stopped there, before its own "Resume directly" continuations (which ran
44
+ * a capped call to about 4 x max_tokens, ending end_turn when the model finished inside one). Undefined on 1.6.12 and earlier. */
45
+ readonly stopsAtFirstCap: boolean;
42
46
  }
43
47
  declare const RELAY_FEATURES: RelayFeatures;
44
48
  interface RelayHello {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import {execSync}from'child_process';import {mkdirSync,writeFileSync,existsSync,readFileSync}from'fs';import {join,dirname}from'path';import {homedir}from'os';import {createHash,randomUUID}from'crypto';import {compileFunction}from'vm';import {createRequire}from'module';import {EventEmitter}from'events';/*! inference-relay (c) 2026 L2B II LLC. Patent pending. Proprietary. See LICENSE. */
2
- var it=Object.defineProperty;var at=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var ot=(n,e)=>()=>(n&&(e=n(n=0)),e);var lt=(n,e)=>{for(var t in e)it(n,t,{get:e[t],enumerable:true});};var Ke={};lt(Ke,{detectCLI:()=>V});function At(n){let e=process.env.PATH;if(!e)return null;let t=process.platform==="win32",r=t?";":":",s=t?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(i=>i.toLowerCase()):[""];for(let i of e.split(r))if(i)for(let a of s){let o=join(i,n+a);if(existsSync(o))return o}return null}async function V(){if(!At("claude"))return {available:false,authenticated:false};let e=null;try{let r=execSync("claude --version",{encoding:"utf-8",timeout:5e3}).trim(),s=r.match(/(\d+\.\d+\.\d+)/);e=s?s[1]:r;}catch{}let t;return e&&!Rt.some(r=>e.startsWith(r.split(".").slice(0,2).join(".")))&&(t=`CLI version ${e} is not tested with this version of inference-relay. Streaming may be unstable.`),{available:true,authenticated:true,cliVersion:e||void 0,versionWarning:t}}var Rt,se=ot(()=>{Rt=["2.1.87"];});var K=class n extends Error{code="RELAY_CAP_EXCEEDED";tier;baseCap;topUps;effectiveCap;usedThisCycle;resolutionUrl;constructor(e){let t=e.resolutionUrl??"https://inference-relay.com/dashboard/billing?topup=1";super(`Cap reached (${e.usedThisCycle} / ${e.effectiveCap??"\u221E"} calls this cycle). Buy a top-up or upgrade at ${t}`),this.name="RelayCapExceededError",this.tier=e.tier,this.baseCap=e.baseCap,this.topUps=e.topUps,this.effectiveCap=e.effectiveCap,this.usedThisCycle=e.usedThisCycle,this.resolutionUrl=t,Object.setPrototypeOf(this,n.prototype);}};function M(n,e){let t=new Map,r=null,s=null,i=new Promise((p,f)=>{r=p,s=f;});i.catch(()=>{});let a=[],o=null,l="",d="";function c(p,...f){let u=t.get(p);u&&u.forEach(h=>h(...f));}async function*g(){try{for await(let p of n)if(yield p,p.type==="content_block_start")a[p.index]=p.content_block;else if(p.type==="content_block_delta"){let f=a[p.index];f&&p.delta?.type==="text_delta"&&(f.text=(f.text||"")+p.delta.text,c("text",p.delta.text));}else if(p.type==="message_start")l=p.message?.model||"",o=p.message?.usage;else if(p.type==="message_delta")d=p.delta?.stop_reason||"",p.usage&&(o={...o,...p.usage});else if(p.type==="message_stop"){let f={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d};c("message",f),r&&(r(f),r=null),e&&e(f);}if(r){let p={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d||"end_turn"};c("message",p),r(p),r=null,e&&e(p);}}catch(p){throw c("error",p),s&&(s(p),s=null),p}}let m=g(),y=false,_={[Symbol.asyncIterator](){if(y)throw new Error("[inference-relay] RelayStream can only be iterated once");return y=true,m},on(p,f){return t.has(p)||t.set(p,[]),t.get(p).push(f),_},finalMessage(){let p,f=new Promise((u,h)=>{p=setTimeout(()=>h(new Error("[inference-relay] finalMessage() timed out \u2014 no message_stop received after 5 minutes")),3e5);});return Promise.race([i,f]).finally(()=>clearTimeout(p))}};return _}var S=class{priority=100;async streamRaw(e,t){throw new Error(`[inference-relay] Provider '${this.type}' does not implement streamRaw(). Override either stream() or streamRaw() in the provider class.`)}async stream(e,t){return M(await this.streamRaw(e,t))}};var ve=`-----BEGIN PUBLIC KEY-----
2
+ var it=Object.defineProperty;var at=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var ot=(n,e)=>()=>(n&&(e=n(n=0)),e);var lt=(n,e)=>{for(var t in e)it(n,t,{get:e[t],enumerable:true});};var Ke={};lt(Ke,{detectCLI:()=>V});function At(n){let e=process.env.PATH;if(!e)return null;let t=process.platform==="win32",r=t?";":":",s=t?(process.env.PATHEXT??".COM;.EXE;.BAT;.CMD").split(";").map(i=>i.toLowerCase()):[""];for(let i of e.split(r))if(i)for(let a of s){let o=join(i,n+a);if(existsSync(o))return o}return null}async function V(){if(!At("claude"))return {available:false,authenticated:false};let e=null;try{let r=execSync("claude --version",{encoding:"utf-8",timeout:5e3}).trim(),s=r.match(/(\d+\.\d+\.\d+)/);e=s?s[1]:r;}catch{}let t;return e&&!Rt.some(r=>e.startsWith(r.split(".").slice(0,2).join(".")))&&(t=`CLI version ${e} is not tested with this version of inference-relay. Streaming may be unstable.`),{available:true,authenticated:true,cliVersion:e||void 0,versionWarning:t}}var Rt,se=ot(()=>{Rt=["2.1.87"];});var K=class n extends Error{code="RELAY_CAP_EXCEEDED";tier;baseCap;topUps;effectiveCap;usedThisCycle;resolutionUrl;constructor(e){let t=e.resolutionUrl??"https://inference-relay.com/dashboard/billing?topup=1";super(`Cap reached (${e.usedThisCycle} / ${e.effectiveCap??"\u221E"} calls this cycle). Buy a top-up or upgrade at ${t}`),this.name="RelayCapExceededError",this.tier=e.tier,this.baseCap=e.baseCap,this.topUps=e.topUps,this.effectiveCap=e.effectiveCap,this.usedThisCycle=e.usedThisCycle,this.resolutionUrl=t,Object.setPrototypeOf(this,n.prototype);}};function M(n,e){let t=new Map,r=null,s=null,i=new Promise((p,f)=>{r=p,s=f;});i.catch(()=>{});let a=[],o=null,l="",d="";function c(p,...f){let u=t.get(p);u&&u.forEach(h=>h(...f));}async function*g(){try{for await(let p of n)if(yield p,p.type==="content_block_start")a[p.index]=p.content_block;else if(p.type==="content_block_delta"){let f=a[p.index];f&&p.delta?.type==="text_delta"&&(f.text=(f.text||"")+p.delta.text,c("text",p.delta.text));}else if(p.type==="message_start")l=p.message?.model||"",o=p.message?.usage;else if(p.type==="message_delta")d=p.delta?.stop_reason||"",p.usage&&(o={...o,...p.usage});else if(p.type==="message_stop"){let f={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d};c("message",f),r&&(r(f),r=null),e&&e(f);}if(r){let p={role:"assistant",model:l,content:a.filter(Boolean),usage:o,stop_reason:d||"end_turn"};c("message",p),r(p),r=null,e&&e(p);}}catch(p){throw c("error",p),s&&(s(p),s=null),p}}let m=g(),y=false,_={[Symbol.asyncIterator](){if(y)throw new Error("[inference-relay] RelayStream can only be iterated once");return y=true,m},on(p,f){return t.has(p)||t.set(p,[]),t.get(p).push(f),_},finalMessage(){let p,f=new Promise((u,h)=>{p=setTimeout(()=>h(new Error("[inference-relay] finalMessage() timed out \u2014 no message_stop received after 5 minutes")),3e5);});return Promise.race([i,f]).finally(()=>clearTimeout(p))}};return _}var C=class{priority=100;async streamRaw(e,t){throw new Error(`[inference-relay] Provider '${this.type}' does not implement streamRaw(). Override either stream() or streamRaw() in the provider class.`)}async stream(e,t){return M(await this.streamRaw(e,t))}};var ve=`-----BEGIN PUBLIC KEY-----
3
3
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
4
4
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
5
5
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
@@ -7,12 +7,12 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
7
7
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
8
8
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
9
9
  UQIDAQAB
10
- -----END PUBLIC KEY-----`,Ee={version:"1.0.0",cliVersion:"2.1.87",eventTypes:{system:"system",streamEvent:"stream_event",assistant:"assistant",result:"result"},fieldMappings:{sessionId:"session_id",model:"model",cliVersion:"claude_code_version",content:"content",usage:"usage",inputTokens:"input_tokens",outputTokens:"output_tokens",stopReason:"stop_reason",isError:"is_error",totalCostUsd:"total_cost_usd",durationMs:"duration_ms",error:"error",event:"event"},syntheticModel:"<synthetic>"},D=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(ve,"RS256"),{payload:i}=await t(e,s),a=JSON.parse(new TextDecoder().decode(i));return this.verificationFailures=0,this.cachedManifest=a,this.currentSecurityState="SEC_NOMINAL",{manifest:a,securityState:"SEC_NOMINAL"}}catch{if(this.verificationFailures++,this.verificationFailures>=3){this.currentSecurityState="SEC_DEGRADED";let t=2e3+Math.random()*3e3;return await new Promise(r=>setTimeout(r,t)),console.warn("[inference-relay] Logic synchronization mismatch. Routing via local recovery."),{manifest:Ee,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Ee,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},ct=new D;function De(){ct.clearCache();}function ut(){return Ee}function dt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}function C(n,...e){process.env.IR_DEBUG==="1"&&console.error(`[ir-debug:${n}]`,...e);}var gt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function Se(n){return join(homedir(),".inference-relay","gateway",n)}function Fe(n){return join(Se(n),"bundle.js")}function He(n){return join(Se(n),"meta.json")}var E=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},x=class extends E{constructor(e,t){super(e,"GATEWAY_FETCH_FAILED",t);}},G=new Map,ft=[0,1e3,4e3];function _t(n){let e=(r,s)=>{if(!Array.isArray(r)||r.length===0)return null;let i=[];for(let a of r){let o=typeof a=="string"?Number(a):a;if(typeof o!="number"||!Number.isFinite(o)||o<0)return C("loader.retry-config-invalid",{source:s,badValue:a}),null;i.push(o);}return i};if(n!==void 0){let r=e(n,"option");if(r)return r}let t=process.env.IR_GATEWAY_RETRY_DELAYS_MS;if(t){let r=e(t.split(",").map(s=>s.trim()),"env");if(r)return r}return ft}var N=class{static async load(e,t,r=gt,s){let i=`${t}:${e.slice(-8)}`;if(G.has(i))return G.get(i);try{let m=await this.tryLoadFromDisk(t);if(m)return C("loader.cache-hit",{libraryVersion:t}),G.set(i,m),m}catch{}C("loader.cache-miss",{libraryVersion:t});let{bytes:a,sha256:o,signature:l,libraryVersion:d}=await this.fetchFromAuthority(e,t,r,s);if(createHash("sha256").update(a).digest("hex")!==o)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,d,o);try{let m=Se(t);mkdirSync(m,{recursive:!0}),writeFileSync(Fe(t),a),writeFileSync(He(t),JSON.stringify({sha256:o,signature:l,libraryVersion:d}));}catch{}let g=this.loadIntoVm(a.toString("utf-8"));return G.set(i,g),g}static async loadFromDisk(e){if(!existsSync(e))throw new E(`[ir-system]: GATEWAY_LOAD_FAILED (REASON: BUNDLE_NOT_FOUND at ${e})`,"GATEWAY_LOAD_FAILED");let t=readFileSync(e,"utf-8");return this.loadIntoVm(t)}static async tryLoadFromDisk(e){let t=Fe(e),r=He(e);if(!existsSync(t)||!existsSync(r))return null;let s=readFileSync(t),i=JSON.parse(readFileSync(r,"utf-8"));return createHash("sha256").update(s).digest("hex")!==i.sha256?null:(await this.verifySignature(i.signature,i.libraryVersion,i.sha256),this.loadIntoVm(s.toString("utf-8")))}static async fetchFromAuthority(e,t,r,s){let i,a=_t(s?.retryDelaysMs),o;for(let g=0;g<a.length;g++){let m=a[g];m>0&&await new Promise(y=>setTimeout(y,m)),C("loader.fetch",{url:`${r}/v1/gateway/fetch`,libraryVersion:t,attempt:g+1,delayMs:m});try{let y=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(C("loader.fetch-result",{status:y.status,attempt:g+1}),y.status===401||y.status===403)throw new E("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(y.status>=500&&y.status<600){o=new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);continue}if(!y.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);i=await y.json(),o=null;break}catch(y){if(y instanceof E&&y.code==="LICENSE_REJECTED")throw y;o=y;}}if(o||!i)throw o instanceof E?o:new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)",o);let l;try{l=await fetch(i.bundleUrl);}catch(g){throw new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)",g)}if(!l.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`);let d=await l.arrayBuffer();return {bytes:Buffer.from(d),sha256:i.sha256,signature:i.signature,libraryVersion:i.libraryVersion,bundleVersion:i.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(ve,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof E?s:new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SIGNATURE_INVALID)","GATEWAY_VERIFICATION_FAILED",s)}}static loadIntoVm(e){try{let t=join(homedir(),".inference-relay","gateway","runtime.cjs"),r=dirname(t),s=createRequire(t),i={exports:{}};compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(i.exports,s,i,t,r);let o=i.exports;if(!o.ClaudeCLIProvider)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof E?t:new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){G.clear();}};var Ge="1.6.12",ie=class extends S{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof E?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(se(),Ke));return e()}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let r=JSON.stringify(e.messages).length/4+5e3,s=(r*3+1e3*15)/1e6;return {estimatedInputTokens:Math.round(r),estimatedCost:Math.round(s*1e4)/1e4,model:e.model,provider:"claude-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}},ae=class extends S{type="kimi-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).KimiCLIProvider;if(!t)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: STALE_BUNDLE_NO_KIMI_CLI)","GATEWAY_LOAD_FAILED");let r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,this.health.lastError=e instanceof Error?e.message:String(e),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{existsSync:e}=await import('fs'),{homedir:t}=await import('os'),{join:r}=await import('path'),s=process.env.KIMI_CODE_HOME||r(t(),".kimi-code"),i=process.env.IR_KIMI_BIN||r(s,"bin","kimi"),a=e(i),o=e(r(s,"credentials"))||e(r(s,"oauth"));return {available:a,authenticated:o,subscriptionType:o?"kimi-code":void 0}}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let t=JSON.stringify(e.messages).length/4;return {estimatedInputTokens:Math.round(t+2e3),estimatedCost:0,model:e.model,provider:"kimi-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}};var Y=[{canonical:"claude-haiku-4-5",apiId:"claude-haiku-4-5-20251001",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[.8,4]},{canonical:"claude-sonnet-4-6",apiId:"claude-sonnet-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[3,15]},{canonical:"claude-opus-4-6",apiId:"claude-opus-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[15,75]},{canonical:"gpt-4.1",apiId:"gpt-4.1",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[2,8]},{canonical:"gpt-4.1-mini",apiId:"gpt-4.1-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.4,1.6]},{canonical:"gpt-4.1-nano",apiId:"gpt-4.1-nano",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.1,.4]},{canonical:"gpt-4o",apiId:"gpt-4o",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[2.5,10]},{canonical:"gpt-4o-mini",apiId:"gpt-4o-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[.15,.6]},{canonical:"o4-mini",apiId:"o4-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o3",apiId:"o3",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[.4,1.6]},{canonical:"o3-mini",apiId:"o3-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o1",apiId:"o1",provider:"openai-api",capabilities:{streaming:false,tools:false,multimodal:false,contextWindow:2e5},pricing:[15,60]},{canonical:"llama3.1",apiId:"llama3.1",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"mistral",apiId:"mistral",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}},{canonical:"mistral-nemo",apiId:"mistral-nemo",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"llava",apiId:"llava",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:true,contextWindow:32e3}},{canonical:"qwen2:0.5b",apiId:"qwen2:0.5b",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}}],$=Object.fromEntries(Y.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));$["claude-sonnet-4"]="claude-sonnet-4-20250514";$["claude-opus-4"]="claude-opus-4-20250514";$["claude-haiku-4"]="claude-haiku-4-5-20251001";function Ce(n){return $[n]||n}function St(n){return Y.find(e=>e.canonical===n)}function oe(n){return Y.find(e=>e.canonical===n)?.provider}function Ct(n){return Y.filter(e=>e.provider===n)}var wt="https://api.anthropic.com/v1/messages",Pt="2023-06-01",we={"claude-sonnet-4-5-20250514":[3,15],"claude-sonnet-4-20250514":[3,15],"claude-haiku-4-5-20250414":[.8,4],"claude-opus-4-20250514":[15,75]};function Ve(n){if(we[n])return we[n];for(let[e,t]of Object.entries(we))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var W=class extends S{type="anthropic-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;dangerousDirectBrowserAccess;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||wt,this.dangerousDirectBrowserAccess=e.dangerousDirectBrowserAccess??false;}async probe(){try{let e=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{available:!0,authenticated:!1}:e.ok||e.status===429?{available:!0,authenticated:!0,rateLimitTier:e.headers.get("anthropic-ratelimit-tier")??void 0}:e.status===529?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let[l,d]=Ve(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,g={},m=["request-id","x-request-id","anthropic-ratelimit-requests-limit","anthropic-ratelimit-requests-remaining","anthropic-ratelimit-requests-reset","anthropic-ratelimit-tokens-limit","anthropic-ratelimit-tokens-remaining","anthropic-ratelimit-tokens-reset","anthropic-ratelimit-tier"];for(let y of m){let _=i.headers.get(y);_&&(g[y]=_);}return {content:a.content||[],model:a.model||e.model,usage:{input_tokens:a.usage?.input_tokens||0,output_tokens:a.usage?.output_tokens||0},stop_reason:a.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:o,fallbackChain:["anthropic-api:success"],headers:Object.keys(g).length>0?g:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("ANTHROPIC_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder;return (async function*(){let o="",l=false;try{for(;;){let{done:d,value:c}=await i.read();if(d)break;o+=a.decode(c,{stream:!0});let g=o.split(`
11
- `);o=g.pop()||"";let m=null;for(let y of g)if(y.startsWith("event: "))m=y.slice(7).trim();else if(y.startsWith("data: ")){let _=y.slice(6);if(m&&_)try{let p=JSON.parse(_);p.type==="message_stop"&&(l=!0),yield p;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}m=null;}else y.trim()===""&&(m=null);}l||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=Ve(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"anthropic-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){let e={"content-type":"application/json","x-api-key":this.apiKey,"anthropic-version":Pt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:Ce(e.model),max_tokens:e.max_tokens,messages:e.messages};return t&&(r.stream=true),e.system&&(r.system=e.system),e.temperature!==void 0&&(r.temperature=e.temperature),e.tools&&e.tools.length>0&&(r.tools=e.tools),e.metadata&&(r.metadata=e.metadata),r}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw t===529?(this.health.status="degraded",this.health.lastError="API overloaded",this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_OVERLOADED: API is temporarily overloaded (529)")):(this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`ANTHROPIC_API_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var kt="https://api.openai.com/v1/chat/completions",Ye=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Pe={"gpt-4.1":[2,8],"gpt-4.1-mini":[.4,1.6],"gpt-4.1-nano":[.1,.4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"o4-mini":[1.1,4.4],o3:[.4,1.6],"o3-mini":[1.1,4.4],o1:[15,60],"o1-mini":[3,12],"gpt-4-turbo":[10,30],"gpt-4":[30,60],"gpt-3.5-turbo":[.5,1.5]};function $e(n){if(Pe[n])return Pe[n];for(let[e,t]of Object.entries(Pe))if(n.startsWith(e))return t;return [2.5,10]}function It(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Tt(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=It(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let i=r.content.filter(a=>a.type==="tool_use");if(i.length>0){t.push({role:"assistant",content:s||"",tool_calls:i.map(a=>({id:a.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:a.name,arguments:typeof a.input=="string"?a.input:JSON.stringify(a.input)}}))});continue}}t.push({role:r.role,content:s});}return t}function We(n){switch(n){case "stop":return "end_turn";case "length":return "max_tokens";case "tool_calls":case "function_call":return "tool_use";default:return "end_turn"}}var q=class extends S{type="openai-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||kt;}async probe(){try{let e=this.baseUrl.replace(/\/chat\/completions$/,"/models"),t=await fetch(e,{method:"GET",headers:this.buildHeaders()});return t.status===401?{available:!0,authenticated:!1}:t.ok||t.status===429?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=a.choices?.[0],d=[];if(l?.message?.content&&d.push({type:"text",text:l.message.content}),l?.message?.tool_calls)for(let u of l.message.tool_calls)d.push({type:"tool_use",id:u.id,name:u.function?.name,input:u.function?.arguments?JSON.parse(u.function.arguments):{}});let c=a.usage?.prompt_tokens||0,g=a.usage?.completion_tokens||0,[m,y]=$e(a.model||e.model),_=(c*m+g*y)/1e6,p={},f=["x-request-id","x-ratelimit-limit-requests","x-ratelimit-remaining-requests","x-ratelimit-limit-tokens","x-ratelimit-remaining-tokens","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];for(let u of f){let h=i.headers.get(u);h&&(p[u]=h);}return {content:d,model:a.model||e.model,usage:{input_tokens:c,output_tokens:g},stop_reason:We(l?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(p).length>0?p:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OPENAI_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false,g,m;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:y,value:_}=await i.read();if(y)break;l+=a.decode(_,{stream:!0});let p=l.split(`
12
- `);l=p.pop()||"";for(let f of p){if(!f.startsWith("data: "))continue;let u=f.slice(6).trim();if(u==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"},c=!0;return}try{let h=JSON.parse(u);h.usage&&(g={input_tokens:h.usage.prompt_tokens||0,output_tokens:h.usage.completion_tokens||0});let R=h.choices?.[0];if(!R)continue;let b=R.delta;b?.content&&!d&&(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),b?.content&&(yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:b.content}}),R.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),m=We(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=$e(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"openai-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}buildRequestBody(e,t){let r=e.model.toLowerCase();if(!Ye.some(o=>r.startsWith(o)))throw new Error(`OPENAI_MODEL_TRANSLATION_REQUIRED: The OpenAI provider received the model name '${e.model}', which does not match any known OpenAI model prefix (${Ye.join(", ")}). The relay does NOT auto-translate model names across providers in v1.3.x. Either (a) pass an OpenAI model name like 'gpt-4o-mini' when routing to this provider, or (b) route non-OpenAI models through a provider that understands them (e.g. 'anthropic-api' for Claude models).`);let i=Tt(e.messages,e.system),a={model:e.model,max_tokens:e.max_tokens,messages:i};return t&&(a.stream=true,a.stream_options={include_usage:true}),e.temperature!==void 0&&(a.temperature=e.temperature),e.tools&&e.tools.length>0&&(a.tools=e.tools),a}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("OPENAI_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`OPENAI_API_ERROR: Request failed with status ${t}`)}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var xt="http://localhost:11434";function Lt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ot(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:Lt(r.content)});return t}var j=class extends S{type="ollama";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.baseUrl=e?.baseUrl?.replace(/\/$/,"")||xt;}async probe(){try{return (await fetch(`${this.baseUrl}/api/tags`,{method:"GET"})).ok?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=[];a.message?.content&&l.push({type:"text",text:a.message.content});let d=a.prompt_eval_count||0,c=a.eval_count||0;return {content:l,model:a.model||e.model,usage:{input_tokens:d,output_tokens:c},stop_reason:(a.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:o,fallbackChain:["ollama:success"]}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OLLAMA_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:g,value:m}=await i.read();if(g)break;l+=a.decode(m,{stream:!0});let y=l.split(`
13
- `);l=y.pop()||"";for(let _ of y){let p=_.trim();if(p)try{let f=JSON.parse(p);if(f.message?.content&&(d||(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:f.message.content}}),f.done){d&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:f.prompt_eval_count||0,output_tokens:f.eval_count||0}},yield {type:"message_stop"},c=!0;return}}catch{}}}c||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0;return {estimatedInputTokens:t+r,estimatedCost:0,model:e.model,provider:"ollama"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildRequestBody(e,t){if(e.tools&&e.tools.length>0)throw new Error(`OLLAMA_TOOLS_NOT_SUPPORTED: The Ollama provider received ${e.tools.length} tool definition(s) in params.tools, but this provider does not implement function calling in v1.3.x. For tool-use workflows route to 'anthropic-api' or 'openai-api' instead. Tracking issue: 1.4.0 ships an Ollama tool-use shim for models that support native function calling (llama3.1, mistral-nemo, etc.).`);let r=Ot(e.messages,e.system),s={model:e.model,messages:r,stream:t};return e.temperature!==void 0&&(s.options={temperature:e.temperature}),s}handleErrorResponse(e){let t=e.status;throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),t===404?(this.health.status="unhealthy",this.health.lastError="Model not found",new Error("OLLAMA_MODEL_NOT_FOUND: Requested model is not available locally (404)")):(this.health.status="unhealthy",this.health.lastError=`Request failed with status ${t}`,new Error(`OLLAMA_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var J=class extends EventEmitter{constructor(){super(),this.setMaxListeners(50);}emitTyped(e){return this.emit(e.kind,e)}onTyped(e,t){return this.on(e,t)}offTyped(e,t){return this.off(e,t)}};var et=200;function le(n,e){if(e instanceof E)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,et)||"unknown"}`}function qe(n){let e=n.filter(t=>t.includes(":failed:"));return e.length===0?false:e.every(t=>t.endsWith(":failed:request_too_large"))}var je=new Set(["anthropic-api","openai-api","ollama"]),U=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}},z=class extends U{constructor(e){super(e);}};function Je(n){return n.messages.some(e=>typeof e.content=="string"?false:Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"))}function ce(n){if(!(n instanceof Error))return "unknown";let e=n.code;if(typeof e=="string"){if(e==="LICENSE_REJECTED")return "auth_failed";if(e==="GATEWAY_FETCH_FAILED"||e==="GATEWAY_VERIFICATION_FAILED"||e==="GATEWAY_LOAD_FAILED")return "gateway_unavailable"}let t=n.message.toLowerCase(),r=n.name.toLowerCase();return t.includes("prompt is too long")||t.includes("prompt too long")||t.includes("prompt_too_large")||t.includes("input length")||t.includes("input is too long")||t.includes("context_length_exceeded")||t.includes("context length exceeded")||t.includes("request too large")||t.includes("tokens exceed")||t.includes("exceeds the maximum")||t.includes("too many tokens")?"request_too_large":t.includes("code 3221226505")||t.includes("cli exited with code 3 ")||t.includes("cli stream exited with code 3 ")||t.includes("bun has crashed")||t.includes("illegal instruction")||t.includes("stream ended without producing any content")||t.includes("cli returned empty response")||t.includes("cli closed stdout without sending any response")||t.includes("kimi_stall_silent")?"transient":t.includes("credit balance is too low")||t.includes("credit balance too low")?"auth_failed":t.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_cli_too_old:")||t.startsWith("stream_json_cli_too_old:")?"provider_incompatible":t.includes("rate limit")||t.includes("429")||r.includes("ratelimit")?"rate_limited":t.includes("auth")||t.includes("401")||t.includes("403")||t.includes("unauthorized")||t.includes("forbidden")?"auth_failed":t.includes("timeout")||t.includes("timed out")||t.includes("aborted")||r==="aborterror"||r==="timeouterror"?"timeout":"unknown"}function ze(n){return [...n].sort((e,t)=>e.priority-t.priority)}var X=class n{healthMap=new Map;engineEvents=new J;static UNHEALTHY_TTL_DEFAULT_MS=300*1e3;static UNHEALTHY_TTL_AUTH_MS=30*1e3;getHealthStatus(e){let t=this.healthMap.get(e);if(!t)return "healthy";let r=t.ttlMs??n.UNHEALTHY_TTL_DEFAULT_MS;if(t.status==="unhealthy"&&Date.now()-t.updatedAt>=r){let s=Date.now()-t.updatedAt;return this.healthMap.delete(e),C("engine.recovered",{providerType:e,ageMs:s,ttlMs:r}),"healthy"}return t.status}markUnhealthy(e,t,r){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now(),ttlMs:r}),C("engine.unhealthy",{providerType:e,reason:t,ttlMs:r});}markDegraded(e,t){this.healthMap.set(e,{status:"degraded",lastError:t,updatedAt:Date.now()});}markHealthy(e){this.healthMap.set(e,{status:"healthy",updatedAt:Date.now()});}resetHealth(){this.healthMap.clear();}async execute(e,t,r){let s=ze(t),i=[],a=Je(e),o=randomUUID(),l=Date.now();for(let d of s){let c=d.type;if(this.getHealthStatus(c)==="unhealthy"){i.push(`${c}:skipped:unhealthy`);continue}if(a&&!d.supportsMultimodal){i.push(`${c}:skipped:no_multimodal`);continue}let m=oe(e.model);if(m&&m!==c&&je.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}let y=r?.maxSameProviderRetries??2,_=0,p=null,f=false;for(;!f;)try{let u=await d.execute(e,{signal:r?.signal});return f=!0,this.markHealthy(c),_>0&&i.push(`${c}:retry_success:${_}`),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd??0}],provider:c,model:u.model,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd,durationMs:u.durationMs??Date.now()-l,stopReason:u.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...u,fallbackChain:i}}catch(u){if(u?.name==="AbortError"||r?.signal?.aborted)throw u;if(ce(u)==="transient"&&_<y){_++;let R=250*Math.pow(2,_-1);C("engine.transient-retry",{id:c,attempt:_,backoffMs:R,msg:String(u?.message||"").slice(0,120)}),i.push(`${c}:retry:${_}`),await new Promise(b=>setTimeout(b,R));continue}p=u;break}if(!f){let u=p;switch(ce(u)){case "rate_limited":d.reportRateLimit({provider:c,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(c,"rate_limited"),i.push(`${c}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(c,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),i.push(`${c}:failed:auth_failed`);break;case "timeout":i.push(`${c}:failed:timeout`);break;case "provider_incompatible":i.push(`${c}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(c,"gateway_unavailable"),i.push(le(c,u));break;case "request_too_large":i.push(`${c}:failed:request_too_large`);break;case "transient":this.markDegraded(c,"transient_exhausted"),i.push(`${c}:failed:transient_exhausted`);break;default:i.push(le(c,u));break}if(r?.subscriptionOnly&&c==="claude-cli"){i.push("subscription_only:cascade_halted");break}}}throw C("engine.cascade-exhausted",{chain:i,mode:"execute"}),qe(i)?new z(i):new U(i)}async stream(e,t,r){let s=randomUUID(),i=ze(t),a=Je(e),o=Date.now(),l=[],d=null,c=null;for(let u of i){let h=u.type;if(this.getHealthStatus(h)==="unhealthy"){l.push(`${h}:skipped:unhealthy`);continue}if(a&&!u.supportsMultimodal){l.push(`${h}:skipped:no_multimodal`);continue}if(!u.supportsStreaming){l.push(`${h}:skipped:no_streaming`);continue}let R=oe(e.model);if(R&&R!==h&&je.has(h)){l.push(`${h}:skipped:wrong_provider`);continue}try{c=await u.streamRaw(e,{signal:r?.signal}),d=u,l.push(`${h}:success`);break}catch(b){if(b?.name==="AbortError"||r?.signal?.aborted)throw b;switch(ce(b)){case "rate_limited":u.reportRateLimit({provider:h,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(h,"rate_limited"),l.push(`${h}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(h,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),l.push(`${h}:failed:auth_failed`);break;case "timeout":l.push(`${h}:failed:timeout`);break;case "provider_incompatible":l.push(`${h}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(h,"gateway_unavailable"),l.push(le(h,b));break;case "request_too_large":l.push(`${h}:failed:request_too_large`);break;case "transient":this.markDegraded(h,"transient_exhausted"),l.push(`${h}:failed:transient_exhausted`);break;default:l.push(le(h,b));break}if(r?.subscriptionOnly&&h==="claude-cli"){l.push("subscription_only:cascade_halted");break}}}if(!d||!c)throw C("engine.cascade-exhausted",{chain:l,mode:"stream"}),qe(l)?new z(l):new U(l);let m=this,y=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*p(){let u=d,h=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},b={segments:[]},T=Xe(u.type);b.segments.push(T);let Le=0,ee=null,te=false,be=y,H="",B="";for(m.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:u.type});;)try{for(;;){let A=await h.next();if(A.done)break;let L=A.value,k=Ut(L,Le,R,te,ee);if(k.action==="suppress"){"coalesceMode"in k&&(ee=k.coalesceMode),k.clearedJustFailedOver&&(te=!1);continue}k.coalesceModeCleared&&(ee=null),k.clearedJustFailedOver&&(te=!1);let v=k.event;if(Nt(R,v),v.type==="message_start"){if(b.segments.length>1)continue;H=v.message?.model||H,v.message?.usage?.input_tokens!=null&&(T.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(B=v.delta.stop_reason),v.usage)){Dt(T,u.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(R.content.length===0&&T.outputTokens===0)throw new Error("stream ended without producing any content");m.markHealthy(u.type),m.emitEngineEvent({kind:"segment_complete",callId:s,id:randomUUID(),ts:Date.now(),provider:u.type,usage:{...T}});let w=Qe(b.segments);yield {type:"message_delta",delta:{stop_reason:B||"end_turn"},usage:w},yield {type:"message_stop"},m.emitEngineEvent({kind:"stream_complete",callId:s,id:randomUUID(),ts:Date.now(),stitched:b.segments.length>1,segments:b.segments.map(A=>({...A})),provider:b.segments.map(A=>A.provider).join("+"),model:H,inputTokens:w.input_tokens,outputTokens:w.output_tokens,costUsd:b.segments.reduce((A,L)=>A+L.costUsd,0),userCostUsd:b.segments.reduce((A,L)=>A+L.userCostUsd,0),durationMs:Date.now()-o,stopReason:B||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(w){if(w?.name==="AbortError"||r?.signal?.aborted)throw w;let A=ce(w);try{await h.return?.();}catch{}if(m.markUnhealthy(u.type,String(w)),m.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:randomUUID(),ts:Date.now(),from:u.type,bytesBuffered:Ze(R),errorClass:A,retriesLeft:be}),l.push(`${u.type}:partial(${Ze(R)}b)`),be<=0)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;let L=Ft(R.content),k=[...e.messages,{role:"assistant",content:L}],v=null,re=null,Oe=u;for(;;){let I=m.nextHealthyProvider(i,Oe,a,_);if(!I)break;Oe=I,_.add(I);let st={...e,messages:k,...I.type!=="anthropic-api"&&I.type!=="claude-cli"?{system:Ht(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{re=await I.streamRaw(st,{signal:r?.signal}),v=I;break}catch(Me){m.markUnhealthy(I.type,String(Me)),l.push(`${I.type}:failed_connect:${String(Me).slice(0,et)}`);}}if(!v||!re)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;l.push(`${v.type}:stitched`),m.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:randomUUID(),ts:Date.now(),from:u.type,to:v.type}),Le=Bt(R)+1,be--,u=v,h=re[Symbol.asyncIterator](),te=true,ee=null,T=Xe(u.type),b.segments.push(T),m.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:u.type});}}let f=p();return r?.licenseState==="SEC_DEGRADED"&&(f=Kt(f)),M(f)}nextHealthyProvider(e,t,r,s){let i=e.indexOf(t);if(i===-1)return null;for(let a=i+1;a<e.length;a++){let o=e[a];if(!s.has(o)&&!(r&&!o.supportsMultimodal)&&o.supportsStreaming)return o}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,s,i,a,o){let l=Qe(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(d=>({...d})),provider:t.segments.map(d=>d.provider).join("+"),model:r,inputTokens:l.input_tokens,outputTokens:l.output_tokens,costUsd:t.segments.reduce((d,c)=>d+c.costUsd,0),userCostUsd:t.segments.reduce((d,c)=>d+c.userCostUsd,0),durationMs:Date.now()-a,stopReason:s||"error",fallbackChain:i,rateLimitHit:false,securityState:o});}};function Xe(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Dt(n,e,t){typeof t.input_tokens=="number"&&(n.inputTokens=t.input_tokens),typeof t.output_tokens=="number"&&(e==="anthropic-api"||e==="claude-cli"?n.outputTokens+=t.output_tokens:n.outputTokens=t.output_tokens);}function Qe(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function Nt(n,e){if(e.type==="content_block_start"){let t=e.content_block;t?.type==="text"?n.content.push({type:"text",text:t.text||"",open:true}):t?.type==="tool_use"&&n.content.push({type:"tool_use",id:t.id,name:t.name,input:{},_partialJson:"",open:true});}else if(e.type==="content_block_delta"){let t=n.content[n.content.length-1];if(!t)return;t.type==="text"&&e.delta?.type==="text_delta"?t.text+=e.delta.text||"":t.type==="tool_use"&&e.delta?.type==="input_json_delta"&&(t._partialJson=(t._partialJson||"")+(e.delta.partial_json||""));}else if(e.type==="content_block_stop"){for(let t=n.content.length-1;t>=0;t--)if(n.content[t].open){if(n.content[t].open=false,n.content[t].type==="tool_use"){let r=n.content[t];try{r.input=JSON.parse(r._partialJson||"{}");}catch{}delete r._partialJson;}break}}}function Ut(n,e,t,r,s){if(s&&n.type==="content_block_delta"&&n.index===s.fromIndex)return {action:"yield",event:{...n,index:s.toIndex}};if(s&&n.type==="content_block_stop"&&n.index===s.fromIndex)return {action:"suppress",coalesceMode:null,coalesceModeCleared:true};if(r&&n.type==="content_block_start"&&n.content_block?.type==="text"){let a=t.content[t.content.length-1];if(a?.type==="text"&&a.open===true)return {action:"suppress",coalesceMode:{fromIndex:n.index+e,toIndex:t.content.length-1},clearedJustFailedOver:true}}let i=r&&n.type==="content_block_start";return typeof n.index=="number"&&e>0?{action:"yield",event:{...n,index:n.index+e},clearedJustFailedOver:i}:{action:"yield",event:n,clearedJustFailedOver:i}}function Ft(n){let e=[];for(let t of n)t.type==="text"?t.text&&e.push({type:"text",text:t.text}):t.type==="tool_use"&&!t.open&&t.input&&Object.keys(t.input).length>0&&e.push({type:"tool_use",id:t.id,name:t.name,input:t.input});return e}function Ht(n,e){return n?`${n}
10
+ -----END PUBLIC KEY-----`,Ee={version:"1.0.0",cliVersion:"2.1.87",eventTypes:{system:"system",streamEvent:"stream_event",assistant:"assistant",result:"result"},fieldMappings:{sessionId:"session_id",model:"model",cliVersion:"claude_code_version",content:"content",usage:"usage",inputTokens:"input_tokens",outputTokens:"output_tokens",stopReason:"stop_reason",isError:"is_error",totalCostUsd:"total_cost_usd",durationMs:"duration_ms",error:"error",event:"event"},syntheticModel:"<synthetic>"},D=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(ve,"RS256"),{payload:i}=await t(e,s),a=JSON.parse(new TextDecoder().decode(i));return this.verificationFailures=0,this.cachedManifest=a,this.currentSecurityState="SEC_NOMINAL",{manifest:a,securityState:"SEC_NOMINAL"}}catch{if(this.verificationFailures++,this.verificationFailures>=3){this.currentSecurityState="SEC_DEGRADED";let t=2e3+Math.random()*3e3;return await new Promise(r=>setTimeout(r,t)),console.warn("[inference-relay] Logic synchronization mismatch. Routing via local recovery."),{manifest:Ee,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Ee,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},ct=new D;function De(){ct.clearCache();}function ut(){return Ee}function dt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}function S(n,...e){process.env.IR_DEBUG==="1"&&console.error(`[ir-debug:${n}]`,...e);}var gt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function Ce(n){return join(homedir(),".inference-relay","gateway",n)}function Fe(n){return join(Ce(n),"bundle.js")}function He(n){return join(Ce(n),"meta.json")}var E=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},x=class extends E{constructor(e,t){super(e,"GATEWAY_FETCH_FAILED",t);}},G=new Map,ft=[0,1e3,4e3];function _t(n){let e=(r,s)=>{if(!Array.isArray(r)||r.length===0)return null;let i=[];for(let a of r){let o=typeof a=="string"?Number(a):a;if(typeof o!="number"||!Number.isFinite(o)||o<0)return S("loader.retry-config-invalid",{source:s,badValue:a}),null;i.push(o);}return i};if(n!==void 0){let r=e(n,"option");if(r)return r}let t=process.env.IR_GATEWAY_RETRY_DELAYS_MS;if(t){let r=e(t.split(",").map(s=>s.trim()),"env");if(r)return r}return ft}var N=class{static async load(e,t,r=gt,s){let i=`${t}:${e.slice(-8)}`;if(G.has(i))return G.get(i);try{let m=await this.tryLoadFromDisk(t);if(m)return S("loader.cache-hit",{libraryVersion:t}),G.set(i,m),m}catch{}S("loader.cache-miss",{libraryVersion:t});let{bytes:a,sha256:o,signature:l,libraryVersion:d}=await this.fetchFromAuthority(e,t,r,s);if(createHash("sha256").update(a).digest("hex")!==o)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,d,o);try{let m=Ce(t);mkdirSync(m,{recursive:!0}),writeFileSync(Fe(t),a),writeFileSync(He(t),JSON.stringify({sha256:o,signature:l,libraryVersion:d}));}catch{}let g=this.loadIntoVm(a.toString("utf-8"));return G.set(i,g),g}static async loadFromDisk(e){if(!existsSync(e))throw new E(`[ir-system]: GATEWAY_LOAD_FAILED (REASON: BUNDLE_NOT_FOUND at ${e})`,"GATEWAY_LOAD_FAILED");let t=readFileSync(e,"utf-8");return this.loadIntoVm(t)}static async tryLoadFromDisk(e){let t=Fe(e),r=He(e);if(!existsSync(t)||!existsSync(r))return null;let s=readFileSync(t),i=JSON.parse(readFileSync(r,"utf-8"));return createHash("sha256").update(s).digest("hex")!==i.sha256?null:(await this.verifySignature(i.signature,i.libraryVersion,i.sha256),this.loadIntoVm(s.toString("utf-8")))}static async fetchFromAuthority(e,t,r,s){let i,a=_t(s?.retryDelaysMs),o;for(let g=0;g<a.length;g++){let m=a[g];m>0&&await new Promise(y=>setTimeout(y,m)),S("loader.fetch",{url:`${r}/v1/gateway/fetch`,libraryVersion:t,attempt:g+1,delayMs:m});try{let y=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(S("loader.fetch-result",{status:y.status,attempt:g+1}),y.status===401||y.status===403)throw new E("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(y.status>=500&&y.status<600){o=new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);continue}if(!y.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${y.status})`);i=await y.json(),o=null;break}catch(y){if(y instanceof E&&y.code==="LICENSE_REJECTED")throw y;o=y;}}if(o||!i)throw o instanceof E?o:new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)",o);let l;try{l=await fetch(i.bundleUrl);}catch(g){throw new x("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)",g)}if(!l.ok)throw new x(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`);let d=await l.arrayBuffer();return {bytes:Buffer.from(d),sha256:i.sha256,signature:i.signature,libraryVersion:i.libraryVersion,bundleVersion:i.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(ve,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof E?s:new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SIGNATURE_INVALID)","GATEWAY_VERIFICATION_FAILED",s)}}static loadIntoVm(e){try{let t=join(homedir(),".inference-relay","gateway","runtime.cjs"),r=dirname(t),s=createRequire(t),i={exports:{}};compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(i.exports,s,i,t,r);let o=i.exports;if(!o.ClaudeCLIProvider)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof E?t:new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){G.clear();}};var Ge="1.6.13",ie=class extends C{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof E?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(se(),Ke));return e()}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let r=JSON.stringify(e.messages).length/4+5e3,s=(r*3+1e3*15)/1e6;return {estimatedInputTokens:Math.round(r),estimatedCost:Math.round(s*1e4)/1e4,model:e.model,provider:"claude-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}},ae=class extends C{type="kimi-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadOptions;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e,t){super(),this.licenseKey=e,this.loadOptions=t;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await N.load(this.licenseKey,Ge,void 0,this.loadOptions)).KimiCLIProvider;if(!t)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: STALE_BUNDLE_NO_KIMI_CLI)","GATEWAY_LOAD_FAILED");let r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,this.health.lastError=e instanceof Error?e.message:String(e),e}})(),this.loadingPromise)}async warmup(){await this.ensureLoaded();}async probe(){let{existsSync:e}=await import('fs'),{homedir:t}=await import('os'),{join:r}=await import('path'),s=process.env.KIMI_CODE_HOME||r(t(),".kimi-code"),i=process.env.IR_KIMI_BIN||r(s,"bin","kimi"),a=e(i),o=e(r(s,"credentials"))||e(r(s,"oauth"));return {available:a,authenticated:o,subscriptionType:o?"kimi-code":void 0}}async execute(e,t){return (await this.ensureLoaded()).execute(e,t)}async streamRaw(e,t){return (await this.ensureLoaded()).streamRaw(e,t)}estimateCost(e){if(this.loadedProvider)return this.loadedProvider.estimateCost(e);let t=JSON.stringify(e.messages).length/4;return {estimatedInputTokens:Math.round(t+2e3),estimatedCost:0,model:e.model,provider:"kimi-cli"}}getHealth(){return this.loadedProvider?this.loadedProvider.getHealth():{...this.health}}reportRateLimit(e){this.loadedProvider?this.loadedProvider.reportRateLimit(e):(this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now());}};var Y=[{canonical:"claude-haiku-4-5",apiId:"claude-haiku-4-5-20251001",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[.8,4]},{canonical:"claude-sonnet-4-6",apiId:"claude-sonnet-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[3,15]},{canonical:"claude-opus-4-6",apiId:"claude-opus-4-20250514",provider:"anthropic-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:2e5},pricing:[15,75]},{canonical:"gpt-4.1",apiId:"gpt-4.1",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[2,8]},{canonical:"gpt-4.1-mini",apiId:"gpt-4.1-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.4,1.6]},{canonical:"gpt-4.1-nano",apiId:"gpt-4.1-nano",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:1e6},pricing:[.1,.4]},{canonical:"gpt-4o",apiId:"gpt-4o",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[2.5,10]},{canonical:"gpt-4o-mini",apiId:"gpt-4o-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:true,contextWindow:128e3},pricing:[.15,.6]},{canonical:"o4-mini",apiId:"o4-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o3",apiId:"o3",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[.4,1.6]},{canonical:"o3-mini",apiId:"o3-mini",provider:"openai-api",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:2e5},pricing:[1.1,4.4]},{canonical:"o1",apiId:"o1",provider:"openai-api",capabilities:{streaming:false,tools:false,multimodal:false,contextWindow:2e5},pricing:[15,60]},{canonical:"llama3.1",apiId:"llama3.1",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"mistral",apiId:"mistral",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}},{canonical:"mistral-nemo",apiId:"mistral-nemo",provider:"ollama",capabilities:{streaming:true,tools:true,multimodal:false,contextWindow:128e3}},{canonical:"llava",apiId:"llava",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:true,contextWindow:32e3}},{canonical:"qwen2:0.5b",apiId:"qwen2:0.5b",provider:"ollama",capabilities:{streaming:true,tools:false,multimodal:false,contextWindow:32e3}}],$=Object.fromEntries(Y.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));$["claude-sonnet-4"]="claude-sonnet-4-20250514";$["claude-opus-4"]="claude-opus-4-20250514";$["claude-haiku-4"]="claude-haiku-4-5-20251001";function Se(n){return $[n]||n}function Ct(n){return Y.find(e=>e.canonical===n)}function oe(n){return Y.find(e=>e.canonical===n)?.provider}function St(n){return Y.filter(e=>e.provider===n)}var wt="https://api.anthropic.com/v1/messages",Pt="2023-06-01",we={"claude-sonnet-4-5-20250514":[3,15],"claude-sonnet-4-20250514":[3,15],"claude-haiku-4-5-20250414":[.8,4],"claude-opus-4-20250514":[15,75]};function Ve(n){if(we[n])return we[n];for(let[e,t]of Object.entries(we))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var W=class extends C{type="anthropic-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;dangerousDirectBrowserAccess;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||wt,this.dangerousDirectBrowserAccess=e.dangerousDirectBrowserAccess??false;}async probe(){try{let e=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{available:!0,authenticated:!1}:e.ok||e.status===429?{available:!0,authenticated:!0,rateLimitTier:e.headers.get("anthropic-ratelimit-tier")??void 0}:e.status===529?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let[l,d]=Ve(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,g={},m=["request-id","x-request-id","anthropic-ratelimit-requests-limit","anthropic-ratelimit-requests-remaining","anthropic-ratelimit-requests-reset","anthropic-ratelimit-tokens-limit","anthropic-ratelimit-tokens-remaining","anthropic-ratelimit-tokens-reset","anthropic-ratelimit-tier"];for(let y of m){let _=i.headers.get(y);_&&(g[y]=_);}return {content:a.content||[],model:a.model||e.model,usage:{input_tokens:a.usage?.input_tokens||0,output_tokens:a.usage?.output_tokens||0},stop_reason:a.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:o,fallbackChain:["anthropic-api:success"],headers:Object.keys(g).length>0?g:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("ANTHROPIC_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder;return (async function*(){let o="",l=false;try{for(;;){let{done:d,value:c}=await i.read();if(d)break;o+=a.decode(c,{stream:!0});let g=o.split(`
11
+ `);o=g.pop()||"";let m=null;for(let y of g)if(y.startsWith("event: "))m=y.slice(7).trim();else if(y.startsWith("data: ")){let _=y.slice(6);if(m&&_)try{let p=JSON.parse(_);p.type==="message_stop"&&(l=!0),yield p;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}m=null;}else y.trim()===""&&(m=null);}l||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=Ve(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"anthropic-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){let e={"content-type":"application/json","x-api-key":this.apiKey,"anthropic-version":Pt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:Se(e.model),max_tokens:e.max_tokens,messages:e.messages};return t&&(r.stream=true),e.system&&(r.system=e.system),e.temperature!==void 0&&(r.temperature=e.temperature),e.tools&&e.tools.length>0&&(r.tools=e.tools),e.metadata&&(r.metadata=e.metadata),r}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw t===529?(this.health.status="degraded",this.health.lastError="API overloaded",this.health.lastCheckAt=Date.now(),new Error("ANTHROPIC_OVERLOADED: API is temporarily overloaded (529)")):(this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`ANTHROPIC_API_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var kt="https://api.openai.com/v1/chat/completions",Ye=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Pe={"gpt-4.1":[2,8],"gpt-4.1-mini":[.4,1.6],"gpt-4.1-nano":[.1,.4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"o4-mini":[1.1,4.4],o3:[.4,1.6],"o3-mini":[1.1,4.4],o1:[15,60],"o1-mini":[3,12],"gpt-4-turbo":[10,30],"gpt-4":[30,60],"gpt-3.5-turbo":[.5,1.5]};function $e(n){if(Pe[n])return Pe[n];for(let[e,t]of Object.entries(Pe))if(n.startsWith(e))return t;return [2.5,10]}function It(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Tt(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=It(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let i=r.content.filter(a=>a.type==="tool_use");if(i.length>0){t.push({role:"assistant",content:s||"",tool_calls:i.map(a=>({id:a.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:a.name,arguments:typeof a.input=="string"?a.input:JSON.stringify(a.input)}}))});continue}}t.push({role:r.role,content:s});}return t}function We(n){switch(n){case "stop":return "end_turn";case "length":return "max_tokens";case "tool_calls":case "function_call":return "tool_use";default:return "end_turn"}}var q=class extends C{type="openai-api";supportsStreaming=true;supportsMultimodal=true;platformRequirement="any";apiKey;baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl?.replace(/\/$/,"")||kt;}async probe(){try{let e=this.baseUrl.replace(/\/chat\/completions$/,"/models"),t=await fetch(e,{method:"GET",headers:this.buildHeaders()});return t.status===401?{available:!0,authenticated:!1}:t.ok||t.status===429?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=a.choices?.[0],d=[];if(l?.message?.content&&d.push({type:"text",text:l.message.content}),l?.message?.tool_calls)for(let u of l.message.tool_calls)d.push({type:"tool_use",id:u.id,name:u.function?.name,input:u.function?.arguments?JSON.parse(u.function.arguments):{}});let c=a.usage?.prompt_tokens||0,g=a.usage?.completion_tokens||0,[m,y]=$e(a.model||e.model),_=(c*m+g*y)/1e6,p={},f=["x-request-id","x-ratelimit-limit-requests","x-ratelimit-remaining-requests","x-ratelimit-limit-tokens","x-ratelimit-remaining-tokens","x-ratelimit-reset-requests","x-ratelimit-reset-tokens"];for(let u of f){let h=i.headers.get(u);h&&(p[u]=h);}return {content:d,model:a.model||e.model,usage:{input_tokens:c,output_tokens:g},stop_reason:We(l?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(p).length>0?p:void 0}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OPENAI_API_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false,g,m;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:y,value:_}=await i.read();if(y)break;l+=a.decode(_,{stream:!0});let p=l.split(`
12
+ `);l=p.pop()||"";for(let f of p){if(!f.startsWith("data: "))continue;let u=f.slice(6).trim();if(u==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"},c=!0;return}try{let h=JSON.parse(u);h.usage&&(g={input_tokens:h.usage.prompt_tokens||0,output_tokens:h.usage.completion_tokens||0});let R=h.choices?.[0];if(!R)continue;let b=R.delta;b?.content&&!d&&(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),b?.content&&(yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:b.content}}),R.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),m=We(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:m||"end_turn"},usage:g||{}},yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0,s=t+r,[i,a]=$e(e.model),o=(s*i+1e3*a)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(o*1e4)/1e4,model:e.model,provider:"openai-api"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildHeaders(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}buildRequestBody(e,t){let r=e.model.toLowerCase();if(!Ye.some(o=>r.startsWith(o)))throw new Error(`OPENAI_MODEL_TRANSLATION_REQUIRED: The OpenAI provider received the model name '${e.model}', which does not match any known OpenAI model prefix (${Ye.join(", ")}). The relay does NOT auto-translate model names across providers in v1.3.x. Either (a) pass an OpenAI model name like 'gpt-4o-mini' when routing to this provider, or (b) route non-OpenAI models through a provider that understands them (e.g. 'anthropic-api' for Claude models).`);let i=Tt(e.messages,e.system),a={model:e.model,max_tokens:e.max_tokens,messages:i};return t&&(a.stream=true,a.stream_options={include_usage:true}),e.temperature!==void 0&&(a.temperature=e.temperature),e.tools&&e.tools.length>0&&(a.tools=e.tools),a}handleErrorResponse(e){let t=e.status;if(t===401)throw this.health.status="unhealthy",this.health.lastError="Authentication failed",this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error("OPENAI_AUTH_ERROR: Invalid API key (401)");if(t===429){let r=e.headers.get("retry-after"),s=r?parseInt(r,10)*1e3:6e4;this.health.status="degraded",this.health.lastError=`Rate limited \u2014 retry after ${s}ms`,this.health.lastCheckAt=Date.now();let i=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw i.retryAfterMs=s,i}throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),new Error(`OPENAI_API_ERROR: Request failed with status ${t}`)}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var xt="http://localhost:11434";function Lt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ot(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:Lt(r.content)});return t}var j=class extends C{type="ollama";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";baseUrl;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.baseUrl=e?.baseUrl?.replace(/\/$/,"")||xt;}async probe(){try{return (await fetch(`${this.baseUrl}/api/tags`,{method:"GET"})).ok?{available:!0,authenticated:!0}:{available:!1,authenticated:!1}}catch{return {available:false,authenticated:false}}}async execute(e,t){let r=Date.now(),s=this.buildRequestBody(e,false),i=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),signal:t?.signal});if(!i.ok)throw this.handleErrorResponse(i),new Error("unreachable");let a=await i.json(),o=Date.now()-r;this.recordSuccess();let l=[];a.message?.content&&l.push({type:"text",text:a.message.content});let d=a.prompt_eval_count||0,c=a.eval_count||0;return {content:l,model:a.model||e.model,usage:{input_tokens:d,output_tokens:c},stop_reason:(a.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:o,fallbackChain:["ollama:success"]}}async streamRaw(e,t){let r=this.buildRequestBody(e,true),s=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),signal:t?.signal});if(s.ok||this.handleErrorResponse(s),!s.body)throw new Error("OLLAMA_ERROR: Response body is null \u2014 streaming unavailable");let i=s.body.getReader(),a=new TextDecoder,o=e.model;return (async function*(){let l="",d=false,c=false;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:g,value:m}=await i.read();if(g)break;l+=a.decode(m,{stream:!0});let y=l.split(`
13
+ `);l=y.pop()||"";for(let _ of y){let p=_.trim();if(p)try{let f=JSON.parse(p);if(f.message?.content&&(d||(d=!0,yield {type:"content_block_start",index:0,content_block:{type:"text",text:""}}),yield {type:"content_block_delta",index:0,delta:{type:"text_delta",text:f.message.content}}),f.done){d&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:f.prompt_eval_count||0,output_tokens:f.eval_count||0}},yield {type:"message_stop"},c=!0;return}}catch{}}}c||(yield {type:"message_stop"});}finally{try{i.releaseLock();}catch{}}})()}estimateCost(e){let t=Math.round(JSON.stringify(e.messages).length/4),r=e.system?Math.round(e.system.length/4):0;return {estimatedInputTokens:t+r,estimatedCost:0,model:e.model,provider:"ollama"}}getHealth(){return {...this.health}}reportRateLimit(e){this.health.status="degraded",this.health.lastError=`Rate limited: ${e.utilization*100}% utilization`,this.health.lastCheckAt=Date.now();}buildRequestBody(e,t){if(e.tools&&e.tools.length>0)throw new Error(`OLLAMA_TOOLS_NOT_SUPPORTED: The Ollama provider received ${e.tools.length} tool definition(s) in params.tools, but this provider does not implement function calling in v1.3.x. For tool-use workflows route to 'anthropic-api' or 'openai-api' instead. Tracking issue: 1.4.0 ships an Ollama tool-use shim for models that support native function calling (llama3.1, mistral-nemo, etc.).`);let r=Ot(e.messages,e.system),s={model:e.model,messages:r,stream:t};return e.temperature!==void 0&&(s.options={temperature:e.temperature}),s}handleErrorResponse(e){let t=e.status;throw this.health.errorCount++,this.health.lastCheckAt=Date.now(),t===404?(this.health.status="unhealthy",this.health.lastError="Model not found",new Error("OLLAMA_MODEL_NOT_FOUND: Requested model is not available locally (404)")):(this.health.status="unhealthy",this.health.lastError=`Request failed with status ${t}`,new Error(`OLLAMA_ERROR: Request failed with status ${t}`))}recordSuccess(){this.health.status="healthy",this.health.lastCheckAt=Date.now(),this.health.errorCount=0,this.health.lastError=void 0;}};var J=class extends EventEmitter{constructor(){super(),this.setMaxListeners(50);}emitTyped(e){return this.emit(e.kind,e)}onTyped(e,t){return this.on(e,t)}offTyped(e,t){return this.off(e,t)}};var et=200;function le(n,e){if(e instanceof E)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,et)||"unknown"}`}function qe(n){let e=n.filter(t=>t.includes(":failed:"));return e.length===0?false:e.every(t=>t.endsWith(":failed:request_too_large"))}var je=new Set(["anthropic-api","openai-api","ollama"]),U=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}},z=class extends U{constructor(e){super(e);}};function Je(n){return n.messages.some(e=>typeof e.content=="string"?false:Array.isArray(e.content)&&e.content.some(t=>t.type==="image"||t.type==="image_url"))}function ce(n){if(!(n instanceof Error))return "unknown";let e=n.code;if(typeof e=="string"){if(e==="LICENSE_REJECTED")return "auth_failed";if(e==="GATEWAY_FETCH_FAILED"||e==="GATEWAY_VERIFICATION_FAILED"||e==="GATEWAY_LOAD_FAILED")return "gateway_unavailable"}let t=n.message.toLowerCase(),r=n.name.toLowerCase();return t.includes("prompt is too long")||t.includes("prompt too long")||t.includes("prompt_too_large")||t.includes("input length")||t.includes("input is too long")||t.includes("context_length_exceeded")||t.includes("context length exceeded")||t.includes("request too large")||t.includes("tokens exceed")||t.includes("exceeds the maximum")||t.includes("too many tokens")?"request_too_large":t.includes("code 3221226505")||t.includes("cli exited with code 3 ")||t.includes("cli stream exited with code 3 ")||t.includes("bun has crashed")||t.includes("illegal instruction")||t.includes("stream ended without producing any content")||t.includes("cli returned empty response")||t.includes("cli closed stdout without sending any response")||t.includes("kimi_stall_silent")?"transient":t.includes("credit balance is too low")||t.includes("credit balance too low")?"auth_failed":t.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_cli_too_old:")||t.startsWith("stream_json_cli_too_old:")?"provider_incompatible":t.includes("rate limit")||t.includes("429")||r.includes("ratelimit")?"rate_limited":t.includes("auth")||t.includes("401")||t.includes("403")||t.includes("unauthorized")||t.includes("forbidden")?"auth_failed":t.includes("timeout")||t.includes("timed out")||t.includes("aborted")||r==="aborterror"||r==="timeouterror"?"timeout":"unknown"}function ze(n){return [...n].sort((e,t)=>e.priority-t.priority)}var X=class n{healthMap=new Map;engineEvents=new J;static UNHEALTHY_TTL_DEFAULT_MS=300*1e3;static UNHEALTHY_TTL_AUTH_MS=30*1e3;getHealthStatus(e){let t=this.healthMap.get(e);if(!t)return "healthy";let r=t.ttlMs??n.UNHEALTHY_TTL_DEFAULT_MS;if(t.status==="unhealthy"&&Date.now()-t.updatedAt>=r){let s=Date.now()-t.updatedAt;return this.healthMap.delete(e),S("engine.recovered",{providerType:e,ageMs:s,ttlMs:r}),"healthy"}return t.status}markUnhealthy(e,t,r){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now(),ttlMs:r}),S("engine.unhealthy",{providerType:e,reason:t,ttlMs:r});}markDegraded(e,t){this.healthMap.set(e,{status:"degraded",lastError:t,updatedAt:Date.now()});}markHealthy(e){this.healthMap.set(e,{status:"healthy",updatedAt:Date.now()});}resetHealth(){this.healthMap.clear();}async execute(e,t,r){let s=ze(t),i=[],a=Je(e),o=randomUUID(),l=Date.now();for(let d of s){let c=d.type;if(this.getHealthStatus(c)==="unhealthy"){i.push(`${c}:skipped:unhealthy`);continue}if(a&&!d.supportsMultimodal){i.push(`${c}:skipped:no_multimodal`);continue}let m=oe(e.model);if(m&&m!==c&&je.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}let y=r?.maxSameProviderRetries??2,_=0,p=null,f=false;for(;!f;)try{let u=await d.execute(e,{signal:r?.signal});return f=!0,this.markHealthy(c),_>0&&i.push(`${c}:retry_success:${_}`),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd??0}],provider:c,model:u.model,inputTokens:u.usage.input_tokens,outputTokens:u.usage.output_tokens,costUsd:u.costUsd,userCostUsd:u.userCostUsd,durationMs:u.durationMs??Date.now()-l,stopReason:u.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...u,fallbackChain:i}}catch(u){if(u?.name==="AbortError"||r?.signal?.aborted)throw u;if(ce(u)==="transient"&&_<y){_++;let R=250*Math.pow(2,_-1);S("engine.transient-retry",{id:c,attempt:_,backoffMs:R,msg:String(u?.message||"").slice(0,120)}),i.push(`${c}:retry:${_}`),await new Promise(b=>setTimeout(b,R));continue}p=u;break}if(!f){let u=p;switch(ce(u)){case "rate_limited":d.reportRateLimit({provider:c,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(c,"rate_limited"),i.push(`${c}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(c,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),i.push(`${c}:failed:auth_failed`);break;case "timeout":i.push(`${c}:failed:timeout`);break;case "provider_incompatible":i.push(`${c}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(c,"gateway_unavailable"),i.push(le(c,u));break;case "request_too_large":i.push(`${c}:failed:request_too_large`);break;case "transient":this.markDegraded(c,"transient_exhausted"),i.push(`${c}:failed:transient_exhausted`);break;default:i.push(le(c,u));break}if(r?.subscriptionOnly&&c==="claude-cli"){i.push("subscription_only:cascade_halted");break}}}throw S("engine.cascade-exhausted",{chain:i,mode:"execute"}),qe(i)?new z(i):new U(i)}async stream(e,t,r){let s=randomUUID(),i=ze(t),a=Je(e),o=Date.now(),l=[],d=null,c=null;for(let u of i){let h=u.type;if(this.getHealthStatus(h)==="unhealthy"){l.push(`${h}:skipped:unhealthy`);continue}if(a&&!u.supportsMultimodal){l.push(`${h}:skipped:no_multimodal`);continue}if(!u.supportsStreaming){l.push(`${h}:skipped:no_streaming`);continue}let R=oe(e.model);if(R&&R!==h&&je.has(h)){l.push(`${h}:skipped:wrong_provider`);continue}try{c=await u.streamRaw(e,{signal:r?.signal}),d=u,l.push(`${h}:success`);break}catch(b){if(b?.name==="AbortError"||r?.signal?.aborted)throw b;switch(ce(b)){case "rate_limited":u.reportRateLimit({provider:h,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(h,"rate_limited"),l.push(`${h}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(h,"auth_failed",n.UNHEALTHY_TTL_AUTH_MS),l.push(`${h}:failed:auth_failed`);break;case "timeout":l.push(`${h}:failed:timeout`);break;case "provider_incompatible":l.push(`${h}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(h,"gateway_unavailable"),l.push(le(h,b));break;case "request_too_large":l.push(`${h}:failed:request_too_large`);break;case "transient":this.markDegraded(h,"transient_exhausted"),l.push(`${h}:failed:transient_exhausted`);break;default:l.push(le(h,b));break}if(r?.subscriptionOnly&&h==="claude-cli"){l.push("subscription_only:cascade_halted");break}}}if(!d||!c)throw S("engine.cascade-exhausted",{chain:l,mode:"stream"}),qe(l)?new z(l):new U(l);let m=this,y=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*p(){let u=d,h=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},b={segments:[]},T=Xe(u.type);b.segments.push(T);let Le=0,ee=null,te=false,be=y,H="",B="";for(m.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:u.type});;)try{for(;;){let A=await h.next();if(A.done)break;let L=A.value,k=Ut(L,Le,R,te,ee);if(k.action==="suppress"){"coalesceMode"in k&&(ee=k.coalesceMode),k.clearedJustFailedOver&&(te=!1);continue}k.coalesceModeCleared&&(ee=null),k.clearedJustFailedOver&&(te=!1);let v=k.event;if(Nt(R,v),v.type==="message_start"){if(b.segments.length>1)continue;H=v.message?.model||H,v.message?.usage?.input_tokens!=null&&(T.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(B=v.delta.stop_reason),v.usage)){Dt(T,u.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(R.content.length===0&&T.outputTokens===0)throw new Error("stream ended without producing any content");m.markHealthy(u.type),m.emitEngineEvent({kind:"segment_complete",callId:s,id:randomUUID(),ts:Date.now(),provider:u.type,usage:{...T}});let w=Qe(b.segments);yield {type:"message_delta",delta:{stop_reason:B||"end_turn"},usage:w},yield {type:"message_stop"},m.emitEngineEvent({kind:"stream_complete",callId:s,id:randomUUID(),ts:Date.now(),stitched:b.segments.length>1,segments:b.segments.map(A=>({...A})),provider:b.segments.map(A=>A.provider).join("+"),model:H,inputTokens:w.input_tokens,outputTokens:w.output_tokens,costUsd:b.segments.reduce((A,L)=>A+L.costUsd,0),userCostUsd:b.segments.reduce((A,L)=>A+L.userCostUsd,0),durationMs:Date.now()-o,stopReason:B||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(w){if(w?.name==="AbortError"||r?.signal?.aborted)throw w;let A=ce(w);try{await h.return?.();}catch{}if(m.markUnhealthy(u.type,String(w)),m.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:randomUUID(),ts:Date.now(),from:u.type,bytesBuffered:Ze(R),errorClass:A,retriesLeft:be}),l.push(`${u.type}:partial(${Ze(R)}b)`),be<=0)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;let L=Ft(R.content),k=[...e.messages,{role:"assistant",content:L}],v=null,re=null,Oe=u;for(;;){let I=m.nextHealthyProvider(i,Oe,a,_);if(!I)break;Oe=I,_.add(I);let st={...e,messages:k,...I.type!=="anthropic-api"&&I.type!=="claude-cli"?{system:Ht(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{re=await I.streamRaw(st,{signal:r?.signal}),v=I;break}catch(Me){m.markUnhealthy(I.type,String(Me)),l.push(`${I.type}:failed_connect:${String(Me).slice(0,et)}`);}}if(!v||!re)throw m.emitTerminalExhaustion(s,b,H,B,l,o,r?.licenseState),w;l.push(`${v.type}:stitched`),m.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:randomUUID(),ts:Date.now(),from:u.type,to:v.type}),Le=Bt(R)+1,be--,u=v,h=re[Symbol.asyncIterator](),te=true,ee=null,T=Xe(u.type),b.segments.push(T),m.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:u.type});}}let f=p();return r?.licenseState==="SEC_DEGRADED"&&(f=Kt(f)),M(f)}nextHealthyProvider(e,t,r,s){let i=e.indexOf(t);if(i===-1)return null;for(let a=i+1;a<e.length;a++){let o=e[a];if(!s.has(o)&&!(r&&!o.supportsMultimodal)&&o.supportsStreaming)return o}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,s,i,a,o){let l=Qe(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(d=>({...d})),provider:t.segments.map(d=>d.provider).join("+"),model:r,inputTokens:l.input_tokens,outputTokens:l.output_tokens,costUsd:t.segments.reduce((d,c)=>d+c.costUsd,0),userCostUsd:t.segments.reduce((d,c)=>d+c.userCostUsd,0),durationMs:Date.now()-a,stopReason:s||"error",fallbackChain:i,rateLimitHit:false,securityState:o});}};function Xe(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Dt(n,e,t){typeof t.input_tokens=="number"&&(n.inputTokens=t.input_tokens),typeof t.output_tokens=="number"&&(e==="anthropic-api"||e==="claude-cli"?n.outputTokens+=t.output_tokens:n.outputTokens=t.output_tokens);}function Qe(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function Nt(n,e){if(e.type==="content_block_start"){let t=e.content_block;t?.type==="text"?n.content.push({type:"text",text:t.text||"",open:true}):t?.type==="tool_use"&&n.content.push({type:"tool_use",id:t.id,name:t.name,input:{},_partialJson:"",open:true});}else if(e.type==="content_block_delta"){let t=n.content[n.content.length-1];if(!t)return;t.type==="text"&&e.delta?.type==="text_delta"?t.text+=e.delta.text||"":t.type==="tool_use"&&e.delta?.type==="input_json_delta"&&(t._partialJson=(t._partialJson||"")+(e.delta.partial_json||""));}else if(e.type==="content_block_stop"){for(let t=n.content.length-1;t>=0;t--)if(n.content[t].open){if(n.content[t].open=false,n.content[t].type==="tool_use"){let r=n.content[t];try{r.input=JSON.parse(r._partialJson||"{}");}catch{}delete r._partialJson;}break}}}function Ut(n,e,t,r,s){if(s&&n.type==="content_block_delta"&&n.index===s.fromIndex)return {action:"yield",event:{...n,index:s.toIndex}};if(s&&n.type==="content_block_stop"&&n.index===s.fromIndex)return {action:"suppress",coalesceMode:null,coalesceModeCleared:true};if(r&&n.type==="content_block_start"&&n.content_block?.type==="text"){let a=t.content[t.content.length-1];if(a?.type==="text"&&a.open===true)return {action:"suppress",coalesceMode:{fromIndex:n.index+e,toIndex:t.content.length-1},clearedJustFailedOver:true}}let i=r&&n.type==="content_block_start";return typeof n.index=="number"&&e>0?{action:"yield",event:{...n,index:n.index+e},clearedJustFailedOver:i}:{action:"yield",event:n,clearedJustFailedOver:i}}function Ft(n){let e=[];for(let t of n)t.type==="text"?t.text&&e.push({type:"text",text:t.text}):t.type==="tool_use"&&!t.open&&t.input&&Object.keys(t.input).length>0&&e.push({type:"tool_use",id:t.id,name:t.name,input:t.input});return e}function Ht(n,e){return n?`${n}
14
14
 
15
- ${e}`:e}function Ze(n){let e=0;for(let t of n.content)t.type==="text"?e+=t.text.length:t.type==="tool_use"&&(e+=(t._partialJson||"").length);return e}function Bt(n){return Math.max(0,n.content.length-1)}async function*Kt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}se();function ue(n,e){if(e==="prefer-user"){let s=n.filter(a=>a.type==="claude-cli"),i=n.filter(a=>a.type!=="claude-cli");return [...s,...i]}if(e==="prefer-app"){let s=n.filter(a=>a.type==="claude-cli");return [...n.filter(a=>a.type!=="claude-cli"),...s]}let t=n.filter(s=>s.type===e),r=n.filter(s=>s.type!==e);return [...t,...r]}function de(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var pe={"claude-fable-5":[10,50],"claude-mythos-5":[10,50],"claude-opus-5-5":[4,20],"claude-opus-5":[5,25],"claude-opus-4-8":[5,25],"claude-opus-4-7":[5,25],"claude-opus-4-6":[5,25],"claude-opus-4-5":[5,25],"claude-opus-4":[15,75],"claude-sonnet-5":[2,10],"claude-sonnet-4":[3,15],"claude-haiku-5-5":[.1,.5],"claude-haiku-4-5":[1,5],"claude-3-5-haiku":[.8,4],"claude-3-haiku":[.25,1.25],"kimi-k3":[3,15],"kimi-k2.7-code":[.95,4],"kimi-for-coding":[.95,4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"gpt-4-turbo":[10,30],"gpt-3.5-turbo":[.5,1.5],llama:[0,0],mistral:[0,0],codellama:[0,0]};function me(n){if(pe[n])return pe[n];let e=null;for(let t of Object.keys(pe))n.startsWith(t)&&(e===null||t.length>e.length)&&(e=t);return e!==null?pe[e]:[3,15]}function he(n){let e=0;for(let o of n.messages)if(typeof o.content=="string")e+=o.content.length;else if(Array.isArray(o.content))for(let l of o.content)l.type==="text"&&l.text&&(e+=l.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[s,i]=me(n.model),a=(t*s+r*i)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(a*1e4)/1e4,model:n.model,provider:""}}var F=class{endpoint;enabled;keyId;lineageBuffer=new Map;unsubscribers=[];constructor(e){this.endpoint=e.endpoint||"https://api.inference-relay.com/v1/events",this.enabled=e.enabled??true,this.keyId=e.keyId||"";}subscribeToEngine(e){let t=s=>this.bufferLineageEvent(s),r=s=>{s.kind==="stream_complete"&&this.flushLineageForCall(s);};e.engineEvents.onTyped("segment_start",t),e.engineEvents.onTyped("segment_complete",t),e.engineEvents.onTyped("mid_stream_failover_attempt",t),e.engineEvents.onTyped("mid_stream_failover_success",t),e.engineEvents.onTyped("stream_complete",r),this.unsubscribers.push(()=>{e.engineEvents.offTyped("segment_start",t),e.engineEvents.offTyped("segment_complete",t),e.engineEvents.offTyped("mid_stream_failover_attempt",t),e.engineEvents.offTyped("mid_stream_failover_success",t),e.engineEvents.offTyped("stream_complete",r);});}unsubscribe(){for(let e of this.unsubscribers)e();this.unsubscribers=[],this.lineageBuffer.clear();}bufferLineageEvent(e){let t=this.lineageBuffer.get(e.callId)??[];t.push(e),this.lineageBuffer.set(e.callId,t);}flushLineageForCall(e){let t=this.lineageBuffer.get(e.callId)??[];this.lineageBuffer.delete(e.callId);let r={timestamp:e.ts,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,userCostUsd:e.userCostUsd,durationMs:e.durationMs,stopReason:e.stopReason,fallbackChain:e.fallbackChain,rateLimitHit:e.rateLimitHit,securityState:e.securityState,stitched:e.stitched,segments:e.segments,lineage:t.map(s=>s.id),promptContent:false,completionContent:false};this.report(r);}report(e){!this.enabled||!this.keyId||fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({keyId:this.keyId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,...e.userCostUsd!==void 0?{userCostUsd:e.userCostUsd}:{},durationMs:e.durationMs,fallback:e.fallbackChain.length>1,timestamp:e.timestamp,...e.stitched?{stitched:true,segmentCount:e.segments?.length??0}:{},...e.lineage?{lineageIds:e.lineage}:{}})}).catch(()=>{});}};var Q="1.6.12",ye=Object.freeze({streamKeepsHistory:true,streamToolBlocks:true,streamBareToolNames:true,stopsWhenCallerGoes:true});function ke(){return {name:"inference-relay",version:Q,features:ye}}var Gt="https://api.inference-relay.com",Vt="/v1/validate",Yt=1440*60*1e3,$t=10080*60*1e3,Wt=`-----BEGIN PUBLIC KEY-----
15
+ ${e}`:e}function Ze(n){let e=0;for(let t of n.content)t.type==="text"?e+=t.text.length:t.type==="tool_use"&&(e+=(t._partialJson||"").length);return e}function Bt(n){return Math.max(0,n.content.length-1)}async function*Kt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}se();function ue(n,e){if(e==="prefer-user"){let s=n.filter(a=>a.type==="claude-cli"),i=n.filter(a=>a.type!=="claude-cli");return [...s,...i]}if(e==="prefer-app"){let s=n.filter(a=>a.type==="claude-cli");return [...n.filter(a=>a.type!=="claude-cli"),...s]}let t=n.filter(s=>s.type===e),r=n.filter(s=>s.type!==e);return [...t,...r]}function de(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var pe={"claude-fable-5":[10,50],"claude-mythos-5":[10,50],"claude-opus-5-5":[4,20],"claude-opus-5":[5,25],"claude-opus-4-8":[5,25],"claude-opus-4-7":[5,25],"claude-opus-4-6":[5,25],"claude-opus-4-5":[5,25],"claude-opus-4":[15,75],"claude-sonnet-5":[2,10],"claude-sonnet-4":[3,15],"claude-haiku-5-5":[.1,.5],"claude-haiku-4-5":[1,5],"claude-3-5-haiku":[.8,4],"claude-3-haiku":[.25,1.25],"kimi-k3":[3,15],"kimi-k2.7-code":[.95,4],"kimi-for-coding":[.95,4],"gpt-4o":[2.5,10],"gpt-4o-mini":[.15,.6],"gpt-4-turbo":[10,30],"gpt-3.5-turbo":[.5,1.5],llama:[0,0],mistral:[0,0],codellama:[0,0]};function me(n){if(pe[n])return pe[n];let e=null;for(let t of Object.keys(pe))n.startsWith(t)&&(e===null||t.length>e.length)&&(e=t);return e!==null?pe[e]:[3,15]}function he(n){let e=0;for(let o of n.messages)if(typeof o.content=="string")e+=o.content.length;else if(Array.isArray(o.content))for(let l of o.content)l.type==="text"&&l.text&&(e+=l.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[s,i]=me(n.model),a=(t*s+r*i)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(a*1e4)/1e4,model:n.model,provider:""}}var F=class{endpoint;enabled;keyId;lineageBuffer=new Map;unsubscribers=[];constructor(e){this.endpoint=e.endpoint||"https://api.inference-relay.com/v1/events",this.enabled=e.enabled??true,this.keyId=e.keyId||"";}subscribeToEngine(e){let t=s=>this.bufferLineageEvent(s),r=s=>{s.kind==="stream_complete"&&this.flushLineageForCall(s);};e.engineEvents.onTyped("segment_start",t),e.engineEvents.onTyped("segment_complete",t),e.engineEvents.onTyped("mid_stream_failover_attempt",t),e.engineEvents.onTyped("mid_stream_failover_success",t),e.engineEvents.onTyped("stream_complete",r),this.unsubscribers.push(()=>{e.engineEvents.offTyped("segment_start",t),e.engineEvents.offTyped("segment_complete",t),e.engineEvents.offTyped("mid_stream_failover_attempt",t),e.engineEvents.offTyped("mid_stream_failover_success",t),e.engineEvents.offTyped("stream_complete",r);});}unsubscribe(){for(let e of this.unsubscribers)e();this.unsubscribers=[],this.lineageBuffer.clear();}bufferLineageEvent(e){let t=this.lineageBuffer.get(e.callId)??[];t.push(e),this.lineageBuffer.set(e.callId,t);}flushLineageForCall(e){let t=this.lineageBuffer.get(e.callId)??[];this.lineageBuffer.delete(e.callId);let r={timestamp:e.ts,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,userCostUsd:e.userCostUsd,durationMs:e.durationMs,stopReason:e.stopReason,fallbackChain:e.fallbackChain,rateLimitHit:e.rateLimitHit,securityState:e.securityState,stitched:e.stitched,segments:e.segments,lineage:t.map(s=>s.id),promptContent:false,completionContent:false};this.report(r);}report(e){!this.enabled||!this.keyId||fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({keyId:this.keyId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,costUsd:e.costUsd,...e.userCostUsd!==void 0?{userCostUsd:e.userCostUsd}:{},durationMs:e.durationMs,fallback:e.fallbackChain.length>1,timestamp:e.timestamp,...e.stitched?{stitched:true,segmentCount:e.segments?.length??0}:{},...e.lineage?{lineageIds:e.lineage}:{}})}).catch(()=>{});}};var Q="1.6.13",ye=Object.freeze({streamKeepsHistory:true,streamToolBlocks:true,streamBareToolNames:true,stopsWhenCallerGoes:true,stopsAtFirstCap:true});function ke(){return {name:"inference-relay",version:Q,features:ye}}var Gt="https://api.inference-relay.com",Vt="/v1/validate",Yt=1440*60*1e3,$t=10080*60*1e3,Wt=`-----BEGIN PUBLIC KEY-----
16
16
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
17
17
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
18
18
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
@@ -21,4 +21,4 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
21
21
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
22
22
  UQIDAQAB
23
23
  -----END PUBLIC KEY-----`,O=new Map,Ie=new Set,qt=n=>!!n&&typeof n.aborted=="boolean"&&typeof n.addEventListener=="function";function jt(n,e){let t=n?.signal;if(t===void 0)return {params:n,options:e};let{signal:r,...s}=n,i=s;if(!qt(t))return {params:i,options:e};let a=e?.signal;if(!a||a===t)return {params:i,options:{...e,signal:t}};let o=new AbortController,l=()=>{a.removeEventListener("abort",d),t.removeEventListener("abort",d);},d=()=>{l(),o.abort();};return a.aborted||t.aborted?o.abort():(a.addEventListener("abort",d,{once:true}),t.addEventListener("abort",d,{once:true})),{params:i,options:{...e,signal:o.signal},release:l}}async function Te(n,e){if(!n)return {valid:false,error:"License key required. Get one at inference-relay.com"};let t=O.get(n);if(t&&Date.now()-t.cachedAt<t.ttl)return t.result;let s=!O.has(n)?1e4:3e3,i=(e||Gt)+Vt,a=async()=>{let d=new AbortController,c=setTimeout(()=>d.abort(),s);try{return await(await fetch(i,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n}),signal:d.signal})).json()}finally{clearTimeout(c);}},o;try{o=await a();}catch{try{if(t)throw new Error("cached answer stands in");o=await a();}catch{return t&&Date.now()-t.cachedAt<$t?t.result:{valid:false,error:"License validation failed (network error). Visit inference-relay.com"}}}let l;if(o.jws)try{let{compactVerify:d,importSPKI:c}=await import('jose'),g=await c(Wt,"RS256"),{payload:m}=await d(o.jws,g);l=JSON.parse(new TextDecoder().decode(m));}catch{return O.delete(n),{valid:false,error:"License validation signature invalid. Possible MITM \u2014 refusing to start."}}else if(l=o,l.valid)return O.delete(n),{valid:false,error:"License validation response not signed. Possible MITM."};return O.set(n,{result:l,cachedAt:Date.now(),ttl:l.valid?Yt:6e4}),l}var xe=class n{static version=Q;get version(){return Q}get features(){return ye}hello(){return ke()}providers=[];config;fallbackEngine;telemetryReporter;routingFn=null;license=null;licensePromise=null;licenseValidatedAt=0;callsSinceValidation=0;manifestDecryptor=new D;capProbeTimer=null;capProbeTicksRemaining=0;messages;constructor(e){if(this.config=e,this.fallbackEngine=new X,this.telemetryReporter=new F({endpoint:e.endpoint?`${e.endpoint}/v1/events`:void 0,enabled:e.telemetry!==false,keyId:e.licenseKey}),this.telemetryReporter.subscribeToEngine(this.fallbackEngine),e.routing&&(this.routingFn=de(e.routing)),e.providers)for(let s of e.providers){let i=typeof s=="string"?{type:s}:s,a=this.createProvider(i);a&&(i.priority!==void 0&&(a.priority=i.priority),this.providers.push(a));}let t=100,r=3600*1e3;this.messages={create:async(s,i)=>{let{params:a,options:o,release:l}=jt(s,i),d=false;try{let c=this.license&&(this.callsSinceValidation>=t||Date.now()-this.licenseValidatedAt>=r);if(c&&(this.license=null),!this.license){this.licensePromise||(this.licensePromise=Te(this.config.licenseKey,this.config.endpoint));try{this.license=await this.licensePromise;}finally{this.licensePromise=null;}if(this.licenseValidatedAt=Date.now(),this.callsSinceValidation=0,this.license.valid){if(this.license.capExceeded)throw this.startCapProbe(),new K({tier:this.license.tier||"solo",baseCap:this.license.baseCap??this.license.usageCap??null,topUps:this.license.topUpGrants??0,effectiveCap:this.license.usageCap??null,usedThisCycle:this.license.usageThisMonth??0});!c&&!Ie.has(this.config.licenseKey)&&(Ie.add(this.config.licenseKey),console.log(`[inference-relay] LICENSE AUTHORIZED [${(this.license.tier||"unknown").toUpperCase()} TIER] \u2014 READY.`));}else throw new Error(`[inference-relay] ${this.license.error||"License key invalid or expired. Visit inference-relay.com"}`)}if(this.callsSinceValidation++,a.stream){let g=await this.streamMessage(a,o);return d=!0,g}return await this.executeMessage(a,o)}finally{d||l?.();}}};}startCapProbe(){if(this.capProbeTimer!==null)return;let e=15e3,t=20,r=4;this.capProbeTicksRemaining=t;let s=async()=>{this.capProbeTicksRemaining-=1;let i=Math.ceil(this.capProbeTicksRemaining*e/6e4);this.capProbeTicksRemaining>0&&this.capProbeTicksRemaining%r===0&&console.log(`[inference-relay] cap exceeded \u2014 checking for top-up every 15s (${i}m remaining)`),this.config.licenseKey&&O.delete(this.config.licenseKey);try{let a=await this.probeValidate();if(a.valid&&a.capExceeded===!1){console.log("[inference-relay] cap cleared \u2014 probe exiting, inference resuming"),this.license=a,this.licenseValidatedAt=Date.now(),this.callsSinceValidation=0,this.stopCapProbe();return}}catch{}this.capProbeTicksRemaining<=0&&(console.log("[inference-relay] cap probe exhausted (5 min) \u2014 stopping"),this.stopCapProbe());};this.capProbeTimer=setInterval(s,e),typeof this.capProbeTimer.unref=="function"&&this.capProbeTimer.unref();}async probeValidate(){return Te(this.config.licenseKey,this.config.endpoint)}stopCapProbe(){this.capProbeTimer!==null&&(clearInterval(this.capProbeTimer),this.capProbeTimer=null),this.capProbeTicksRemaining=0;}static async autoDetect(e){let t=[],r=await V();r.available&&r.authenticated!==false&&t.push({type:"claude-cli",priority:1});let s=e?.subscriptionOnly===true||process.env.IR_SUBSCRIPTION_ONLY==="1";return process.env.ANTHROPIC_API_KEY&&!s&&t.push({type:"anthropic-api",priority:2,apiKey:process.env.ANTHROPIC_API_KEY}),new n({licenseKey:e?.licenseKey||process.env.IR_LICENSE_KEY||"",providers:t,fallback:e?.fallback??true,subscriptionOnly:s,...e})}async warmup(){let e=this.providers.find(t=>t.type==="claude-cli");e&&"warmup"in e&&typeof e.warmup=="function"&&await e.warmup();}resetHealth(){this.fallbackEngine.resetHealth();}markHealthy(e){this.fallbackEngine.markHealthy(e);}dispose(){this.providers=[],this.config.licenseKey&&(O.delete(this.config.licenseKey),Ie.delete(this.config.licenseKey)),this.license=null,this.licensePromise=null,this.callsSinceValidation=0,this.stopCapProbe(),this.telemetryReporter.unsubscribe(),this.manifestDecryptor.clearCache(),De();}resolveProviders(e){if(!this.routingFn)return this.providers;let t=he(e),r=this.routingFn(e,t);return ue(this.providers,r)}async executeMessage(e,t){let r=this.resolveProviders(e);return this.fallbackEngine.execute(e,r,{signal:t?.signal,licenseState:this.manifestDecryptor.getSecurityState(),subscriptionOnly:this.config.subscriptionOnly,maxSameProviderRetries:this.config.maxSameProviderRetries})}async streamMessage(e,t){let r=this.resolveProviders(e);return this.fallbackEngine.stream(e,r,{signal:t?.signal,licenseState:this.manifestDecryptor.getSecurityState(),subscriptionOnly:this.config.subscriptionOnly,maxSameProviderRetries:this.config.maxSameProviderRetries})}createProvider(e){switch(e.type){case "claude-cli":return new ie(this.config.licenseKey,{retryDelaysMs:this.config.gatewayRetryDelaysMs});case "kimi-cli":return new ae(this.config.licenseKey,{retryDelaysMs:this.config.gatewayRetryDelaysMs});case "anthropic-api":return e.apiKey?new W({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "openai-api":return e.apiKey?new q({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "ollama":return new j({baseUrl:e.baseUrl});default:return null}}};function Jt(n){if(!n)return 0;if(typeof n=="string")return Math.ceil(n.length/4);if(!Array.isArray(n))return 0;let e=0;for(let t of n){if(!t||typeof t!="object")continue;let r=t;if(r.type==="image"||r.type==="image_url"){e+=1500;continue}if(typeof r.text=="string"){e+=Math.ceil(r.text.length/4);continue}try{e+=Math.ceil(JSON.stringify(t).length/4);}catch{e+=50;}}return e}function zt(n){return 8+Jt(n.content)}function Xt(n){let e=50;typeof n.system=="string"&&(e+=Math.ceil(n.system.length/4));for(let t of n.messages)e+=zt(t);return e}se();var Qt="https://api.anthropic.com/v1/messages",Zt="2023-06-01";async function tt(n){try{let e=await fetch(Qt,{method:"POST",headers:{"content-type":"application/json","x-api-key":n,"anthropic-version":Zt},body:JSON.stringify({model:"claude-haiku-4-5-20250414",max_tokens:1,messages:[{role:"user",content:"hi"}]})});return e.status===401?{valid:!1,error:"Invalid API key (401)"}:e.ok?{valid:!0}:e.status===429?{valid:!0,error:"Rate limited (429)"}:e.status===529?{valid:!0,error:"API overloaded (529)"}:{valid:!1,error:`Unexpected status ${e.status}`}}catch(e){return {valid:false,error:`Network error: ${e.message}`}}}var ge=class{filePath;safeStorage=null;memoryFallback=new Map;constructor(e){let t=e?.storagePath||join(homedir(),".inference-relay");existsSync(t)||mkdirSync(t,{recursive:true}),this.filePath=join(t,"credentials.enc");try{let r=at("electron");r?.safeStorage?.isEncryptionAvailable?.()&&(this.safeStorage=r.safeStorage);}catch{}}readDisk(){if(!existsSync(this.filePath))return {};try{let e=readFileSync(this.filePath,"utf-8");return JSON.parse(e)}catch{return {}}}writeDisk(e){writeFileSync(this.filePath,JSON.stringify(e,null,2),{mode:384});}async get(e){if(!this.safeStorage)return this.memoryFallback.get(e)??null;let r=this.readDisk()[e];if(!r)return null;try{let s=Buffer.from(r.data,"base64");return this.safeStorage.decryptString(s)}catch{return null}}async set(e,t){if(!this.safeStorage){this.memoryFallback.set(e,t);return}let r=this.readDisk(),s=this.safeStorage.encryptString(t);r[e]={data:s.toString("base64")},this.writeDisk(r);}async delete(e){if(!this.safeStorage){this.memoryFallback.delete(e);return}let t=this.readDisk();e in t&&(delete t[e],this.writeDisk(t));}async has(e){if(!this.safeStorage)return this.memoryFallback.has(e);let t=this.readDisk();return e in t}};var Z="AES-GCM";var fe=class{dbName="inference-relay-credentials";storeName="keys";cryptoKey=null;passphrase;initPromise=null;constructor(e){this.passphrase=e?.passphrase,e?.dbName&&(this.dbName=e.dbName);}async ensureReady(){if(!this.cryptoKey)return this.initPromise?this.initPromise:(this.initPromise=this.init(),this.initPromise)}async init(){if(await this.openDB(),this.passphrase)this.cryptoKey=await this.deriveKey(this.passphrase,this.getOrCreateSessionSalt());else {let e=typeof sessionStorage<"u"?sessionStorage.getItem("ir-cred-key"):null;if(e){let t=Uint8Array.from(atob(e),r=>r.charCodeAt(0));this.cryptoKey=await crypto.subtle.importKey("raw",t,Z,false,["encrypt","decrypt"]);}else {this.cryptoKey=await crypto.subtle.generateKey({name:Z,length:256},true,["encrypt","decrypt"]);let t=await crypto.subtle.exportKey("raw",this.cryptoKey),r=btoa(String.fromCharCode(...new Uint8Array(t)));typeof sessionStorage<"u"&&sessionStorage.setItem("ir-cred-key",r);}}}openDB(){return new Promise((e,t)=>{let r=indexedDB.open(this.dbName,1);r.onupgradeneeded=()=>{let s=r.result;s.objectStoreNames.contains(this.storeName)||s.createObjectStore(this.storeName);},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error);})}async idbGet(e){let t=await this.openDB();return new Promise((r,s)=>{let o=t.transaction(this.storeName,"readonly").objectStore(this.storeName).get(e);o.onsuccess=()=>r(o.result),o.onerror=()=>s(o.error);})}async idbPut(e,t){let r=await this.openDB();return new Promise((s,i)=>{let l=r.transaction(this.storeName,"readwrite").objectStore(this.storeName).put(t,e);l.onsuccess=()=>s(),l.onerror=()=>i(l.error);})}async idbDelete(e){let t=await this.openDB();return new Promise((r,s)=>{let o=t.transaction(this.storeName,"readwrite").objectStore(this.storeName).delete(e);o.onsuccess=()=>r(),o.onerror=()=>s(o.error);})}async idbHas(e){let t=await this.openDB();return new Promise((r,s)=>{let o=t.transaction(this.storeName,"readonly").objectStore(this.storeName).count(e);o.onsuccess=()=>r(o.result>0),o.onerror=()=>s(o.error);})}getOrCreateSessionSalt(){let e="ir-cred-salt";if(typeof sessionStorage<"u"){let r=sessionStorage.getItem(e);if(r)return Uint8Array.from(atob(r),s=>s.charCodeAt(0))}let t=crypto.getRandomValues(new Uint8Array(16));return typeof sessionStorage<"u"&&sessionStorage.setItem(e,btoa(String.fromCharCode(...t))),t}async deriveKey(e,t){let r=new TextEncoder,s=await crypto.subtle.importKey("raw",r.encode(e),"PBKDF2",false,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",salt:t.buffer,iterations:1e5,hash:"SHA-256"},s,{name:Z,length:256},false,["encrypt","decrypt"])}async encrypt(e){let t=crypto.getRandomValues(new Uint8Array(12)),r=this.getOrCreateSessionSalt(),s=new TextEncoder().encode(e),i=await crypto.subtle.encrypt({name:Z,iv:t},this.cryptoKey,s);return {iv:btoa(String.fromCharCode(...t)),ciphertext:btoa(String.fromCharCode(...new Uint8Array(i))),salt:btoa(String.fromCharCode(...r))}}async decrypt(e){let t=Uint8Array.from(atob(e.iv),i=>i.charCodeAt(0)),r=Uint8Array.from(atob(e.ciphertext),i=>i.charCodeAt(0)),s=await crypto.subtle.decrypt({name:Z,iv:t},this.cryptoKey,r);return new TextDecoder().decode(s)}async get(e){await this.ensureReady();let t=await this.idbGet(e);if(!t)return null;try{return await this.decrypt(t)}catch{return null}}async set(e,t){await this.ensureReady();let r=await this.encrypt(t);await this.idbPut(e,r);}async delete(e){await this.ensureReady(),await this.idbDelete(e);}async has(e){return await this.ensureReady(),this.idbHas(e)}};var _e=class{store=new Map;async get(e){return this.store.get(e)??null}async set(e,t){this.store.set(e,t);}async delete(e){this.store.delete(e);}async has(e){return this.store.has(e)}};
24
- export{W as AnthropicAPIProvider,S as BaseProvider,ge as ElectronCredentialStore,J as EngineEventEmitter,X as FallbackEngine,N as GatewayLoader,E as GatewayLoaderError,x as GatewayUnavailableError,fe as IndexedDBCredentialStore,xe as InferenceRelay,$ as MODEL_ALIASES,Y as MODEL_REGISTRY,D as ManifestDecryptor,_e as MemoryCredentialStore,j as OllamaProvider,q as OpenAIAPIProvider,ye as RELAY_FEATURES,Q as RELAY_VERSION,K as RelayCapExceededError,U as RelayError,z as RequestTooLargeError,F as TelemetryReporter,ue as applyRouting,M as createRelayStream,de as createRoutingFunction,V as detectCLI,he as estimateCost,Xt as estimateInputTokens,St as findModel,ut as getLastKnownGoodManifest,me as getModelPricing,dt as getValue,Ct as modelsForProvider,Ce as normalizeModel,oe as providerForModel,ke as relayHello,tt as validateAnthropicKey,Te as validateLicense};
24
+ export{W as AnthropicAPIProvider,C as BaseProvider,ge as ElectronCredentialStore,J as EngineEventEmitter,X as FallbackEngine,N as GatewayLoader,E as GatewayLoaderError,x as GatewayUnavailableError,fe as IndexedDBCredentialStore,xe as InferenceRelay,$ as MODEL_ALIASES,Y as MODEL_REGISTRY,D as ManifestDecryptor,_e as MemoryCredentialStore,j as OllamaProvider,q as OpenAIAPIProvider,ye as RELAY_FEATURES,Q as RELAY_VERSION,K as RelayCapExceededError,U as RelayError,z as RequestTooLargeError,F as TelemetryReporter,ue as applyRouting,M as createRelayStream,de as createRoutingFunction,V as detectCLI,he as estimateCost,Xt as estimateInputTokens,Ct as findModel,ut as getLastKnownGoodManifest,me as getModelPricing,dt as getValue,St as modelsForProvider,Se as normalizeModel,oe as providerForModel,ke as relayHello,tt as validateAnthropicKey,Te as validateLicense};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inference-relay",
3
- "version": "1.6.12",
3
+ "version": "1.6.13",
4
4
  "private": false,
5
5
  "description": "Route AI inference to the user's existing subscription",
6
6
  "type": "module",