inference-relay 1.4.2 → 1.5.1

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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {existsSync,mkdirSync,writeFileSync,readFileSync}from'fs';import {homedir}from'os';import {join,dirname}from'path';import {randomUUID,createHash}from'crypto';import {compileFunction}from'vm';import {createRequire}from'module';import {execSync}from'child_process';import {EventEmitter}from'events';/*! inference-relay CLI (c) 2026 L2B II LLC. Patent pending. */
3
- var vt=Object.defineProperty;var v=(n,e)=>()=>(n&&(e=n(n=0)),e);var xe=(n,e)=>{for(var t in e)vt(n,t,{get:e[t],enumerable:true});};var U,me=v(()=>{U=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 q(n,e){let t=new Map,r=null,s=null,a=new Promise((u,y)=>{r=u,s=y;});a.catch(()=>{});let i=[],l=null,o="",p="";function c(u,...y){let g=t.get(u);g&&g.forEach(f=>f(...y));}async function*d(){try{for await(let u of n)if(yield u,u.type==="content_block_start")i[u.index]=u.content_block;else if(u.type==="content_block_delta"){let y=i[u.index];y&&u.delta?.type==="text_delta"&&(y.text=(y.text||"")+u.delta.text,c("text",u.delta.text));}else if(u.type==="message_start")o=u.message?.model||"",l=u.message?.usage;else if(u.type==="message_delta")p=u.delta?.stop_reason||"",u.usage&&(l={...l,...u.usage});else if(u.type==="message_stop"){let y={role:"assistant",model:o,content:i.filter(Boolean),usage:l,stop_reason:p};c("message",y),r&&(r(y),r=null),e&&e(y);}if(r){let u={role:"assistant",model:o,content:i.filter(Boolean),usage:l,stop_reason:p||"end_turn"};c("message",u),r(u),r=null,e&&e(u);}}catch(u){throw c("error",u),s&&(s(u),s=null),u}}let h=d(),m=false,_={[Symbol.asyncIterator](){if(m)throw new Error("[inference-relay] RelayStream can only be iterated once");return m=true,h},on(u,y){return t.has(u)||t.set(u,[]),t.get(u).push(y),_},finalMessage(){let u,y=new Promise((g,f)=>{u=setTimeout(()=>f(new Error("[inference-relay] finalMessage() timed out \u2014 no message_stop received after 5 minutes")),3e5);});return Promise.race([a,y]).finally(()=>clearTimeout(u))}};return _}var he=v(()=>{});var w,V=v(()=>{he();w=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 q(await this.streamRaw(e,t))}};});function Me(){Ct.clearCache();}var ge,Le,$,Ct,fe=v(()=>{ge=`-----BEGIN PUBLIC KEY-----
3
+ var vt=Object.defineProperty;var C=(n,e)=>()=>(n&&(e=n(n=0)),e);var xe=(n,e)=>{for(var t in e)vt(n,t,{get:e[t],enumerable:true});};var U,me=C(()=>{U=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 J(n,e){let t=new Map,r=null,s=null,a=new Promise((u,y)=>{r=u,s=y;});a.catch(()=>{});let i=[],l=null,o="",p="";function c(u,...y){let g=t.get(u);g&&g.forEach(f=>f(...y));}async function*d(){try{for await(let u of n)if(yield u,u.type==="content_block_start")i[u.index]=u.content_block;else if(u.type==="content_block_delta"){let y=i[u.index];y&&u.delta?.type==="text_delta"&&(y.text=(y.text||"")+u.delta.text,c("text",u.delta.text));}else if(u.type==="message_start")o=u.message?.model||"",l=u.message?.usage;else if(u.type==="message_delta")p=u.delta?.stop_reason||"",u.usage&&(l={...l,...u.usage});else if(u.type==="message_stop"){let y={role:"assistant",model:o,content:i.filter(Boolean),usage:l,stop_reason:p};c("message",y),r&&(r(y),r=null),e&&e(y);}if(r){let u={role:"assistant",model:o,content:i.filter(Boolean),usage:l,stop_reason:p||"end_turn"};c("message",u),r(u),r=null,e&&e(u);}}catch(u){throw c("error",u),s&&(s(u),s=null),u}}let h=d(),m=false,E={[Symbol.asyncIterator](){if(m)throw new Error("[inference-relay] RelayStream can only be iterated once");return m=true,h},on(u,y){return t.has(u)||t.set(u,[]),t.get(u).push(y),E},finalMessage(){let u,y=new Promise((g,f)=>{u=setTimeout(()=>f(new Error("[inference-relay] finalMessage() timed out \u2014 no message_stop received after 5 minutes")),3e5);});return Promise.race([a,y]).finally(()=>clearTimeout(u))}};return E}var he=C(()=>{});var w,$=C(()=>{he();w=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 J(await this.streamRaw(e,t))}};});function Me(){Ct.clearCache();}var ge,Le,V,Ct,fe=C(()=>{ge=`-----BEGIN PUBLIC KEY-----
4
4
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
5
5
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
6
6
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
@@ -8,12 +8,12 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
8
8
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
9
9
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
10
10
  UQIDAQAB
11
- -----END PUBLIC KEY-----`,Le={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>"},$=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(ge,"RS256"),{payload:a}=await t(e,s),i=JSON.parse(new TextDecoder().decode(a));return this.verificationFailures=0,this.cachedManifest=i,this.currentSecurityState="SEC_NOMINAL",{manifest:i,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:Le,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Le,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Ct=new $;});function _e(n){return join(homedir(),".inference-relay","gateway",n)}function Ue(n){return join(_e(n),"bundle.js")}function Ne(n){return join(_e(n),"meta.json")}var wt,E,W,J,be=v(()=>{fe();wt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";E=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},W=new Map,J=class{static async load(e,t,r=wt){let s=`${t}:${e.slice(-8)}`;if(W.has(s))return W.get(s);try{let d=await this.tryLoadFromDisk(t);if(d)return W.set(s,d),d}catch{}let{bytes:a,sha256:i,signature:l,libraryVersion:o}=await this.fetchFromAuthority(e,t,r);if(createHash("sha256").update(a).digest("hex")!==i)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,o,i);try{let d=_e(t);mkdirSync(d,{recursive:!0}),writeFileSync(Ue(t),a),writeFileSync(Ne(t),JSON.stringify({sha256:i,signature:l,libraryVersion:o}));}catch{}let c=this.loadIntoVm(a.toString("utf-8"));return W.set(s,c),c}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=Ue(e),r=Ne(e);if(!existsSync(t)||!existsSync(r))return null;let s=readFileSync(t),a=JSON.parse(readFileSync(r,"utf-8"));return createHash("sha256").update(s).digest("hex")!==a.sha256?null:(await this.verifySignature(a.signature,a.libraryVersion,a.sha256),this.loadIntoVm(s.toString("utf-8")))}static async fetchFromAuthority(e,t,r){let s,a=[0,1e3,4e3],i;for(let c of a){c>0&&await new Promise(d=>setTimeout(d,c));try{let d=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(d.status===401||d.status===403)throw new E("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(d.status>=500&&d.status<600){i=new E(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${d.status})`,"GATEWAY_FETCH_FAILED");continue}if(!d.ok)throw new E(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${d.status})`,"GATEWAY_FETCH_FAILED");s=await d.json(),i=null;break}catch(d){if(d instanceof E&&d.code==="LICENSE_REJECTED")throw d;i=d;}}if(i||!s)throw i instanceof E?i:new E("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)","GATEWAY_FETCH_FAILED",i);let l;try{l=await fetch(s.bundleUrl);}catch(c){throw new E("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)","GATEWAY_FETCH_FAILED",c)}if(!l.ok)throw new E(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`,"GATEWAY_FETCH_FAILED");let o=await l.arrayBuffer();return {bytes:Buffer.from(o),sha256:s.sha256,signature:s.signature,libraryVersion:s.libraryVersion,bundleVersion:s.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:a}=await import('jose'),i=await a(ge,"RS256"),{payload:l}=await s(e,i),o=JSON.parse(new TextDecoder().decode(l));if(o.purpose!=="gateway-bundle")throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(o.libraryVersion!==t)throw new E("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(o.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),a={exports:{}};compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(a.exports,s,a,t,r);let l=a.exports;if(!l.ClaudeCLIProvider)throw new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return l}catch(t){throw t instanceof E?t:new E("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){W.clear();}};});var He={};xe(He,{detectCLI:()=>N});function Lt(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(a=>a.toLowerCase()):[""];for(let a of e.split(r))if(a)for(let i of s){let l=join(a,n+i);if(existsSync(l))return l}return null}async function N(){if(!Lt("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&&!xt.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 xt,X=v(()=>{xt=["2.1.87"];});var Mt,Q,Be=v(()=>{V();be();Mt="1.4.2",Q=class extends w{type="claude-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.licenseKey=e;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await J.load(this.licenseKey,Mt)).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 probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(X(),He));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());}};});function $e(n){return Z[n]||n}function ve(n){return Ve.find(e=>e.canonical===n)?.provider}var Ve,Z,Ce=v(()=>{Ve=[{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}}],Z=Object.fromEntries(Ve.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));Z["claude-sonnet-4"]="claude-sonnet-4-20250514";Z["claude-opus-4"]="claude-opus-4-20250514";Z["claude-haiku-4"]="claude-haiku-4-5-20251001";});function We(n){if(Ae[n])return Ae[n];for(let[e,t]of Object.entries(Ae))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var Dt,Ot,Ae,ee,Ge=v(()=>{V();Ce();Dt="https://api.anthropic.com/v1/messages",Ot="2023-06-01",Ae={"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]};ee=class extends w{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(/\/$/,"")||Dt,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),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let i=await a.json(),l=Date.now()-r;this.recordSuccess();let[o,p]=We(i.model||e.model),c=((i.usage?.input_tokens||0)*o+(i.usage?.output_tokens||0)*p)/1e6,d={},h=["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 m of h){let _=a.headers.get(m);_&&(d[m]=_);}return {content:i.content||[],model:i.model||e.model,usage:{input_tokens:i.usage?.input_tokens||0,output_tokens:i.usage?.output_tokens||0},stop_reason:i.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:l,fallbackChain:["anthropic-api:success"],headers:Object.keys(d).length>0?d: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 a=s.body.getReader(),i=new TextDecoder;return (async function*(){let l="",o=false;try{for(;;){let{done:p,value:c}=await a.read();if(p)break;l+=i.decode(c,{stream:!0});let d=l.split(`
12
- `);l=d.pop()||"";let h=null;for(let m of d)if(m.startsWith("event: "))h=m.slice(7).trim();else if(m.startsWith("data: ")){let _=m.slice(6);if(h&&_)try{let u=JSON.parse(_);u.type==="message_stop"&&(o=!0),yield u;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}h=null;}else m.trim()===""&&(h=null);}o||(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,s=t+r,[a,i]=We(e.model),l=(s*a+1e3*i)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(l*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":Ot};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:$e(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 a=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw a.retryAfterMs=s,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 Ke(n){if(Re[n])return Re[n];for(let[e,t]of Object.entries(Re))if(n.startsWith(e))return t;return [2.5,10]}function Nt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ft(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=Nt(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let a=r.content.filter(i=>i.type==="tool_use");if(a.length>0){t.push({role:"assistant",content:s||"",tool_calls:a.map(i=>({id:i.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:i.name,arguments:typeof i.input=="string"?i.input:JSON.stringify(i.input)}}))});continue}}t.push({role:r.role,content:s});}return t}function je(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 Ut,Ye,Re,te,qe=v(()=>{V();Ut="https://api.openai.com/v1/chat/completions",Ye=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Re={"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]};te=class extends w{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(/\/$/,"")||Ut;}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),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let i=await a.json(),l=Date.now()-r;this.recordSuccess();let o=i.choices?.[0],p=[];if(o?.message?.content&&p.push({type:"text",text:o.message.content}),o?.message?.tool_calls)for(let g of o.message.tool_calls)p.push({type:"tool_use",id:g.id,name:g.function?.name,input:g.function?.arguments?JSON.parse(g.function.arguments):{}});let c=i.usage?.prompt_tokens||0,d=i.usage?.completion_tokens||0,[h,m]=Ke(i.model||e.model),_=(c*h+d*m)/1e6,u={},y=["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 g of y){let f=a.headers.get(g);f&&(u[g]=f);}return {content:p,model:i.model||e.model,usage:{input_tokens:c,output_tokens:d},stop_reason:je(o?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:l,fallbackChain:["openai-api:success"],headers:Object.keys(u).length>0?u: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 a=s.body.getReader(),i=new TextDecoder,l=e.model;return (async function*(){let o="",p=false,c=false,d,h;yield {type:"message_start",message:{model:l,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:m,value:_}=await a.read();if(m)break;o+=i.decode(_,{stream:!0});let u=o.split(`
13
- `);o=u.pop()||"";for(let y of u){if(!y.startsWith("data: "))continue;let g=y.slice(6).trim();if(g==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:h||"end_turn"},usage:d||{}},yield {type:"message_stop"},c=!0;return}try{let f=JSON.parse(g);f.usage&&(d={input_tokens:f.usage.prompt_tokens||0,output_tokens:f.usage.completion_tokens||0});let R=f.choices?.[0];if(!R)continue;let b=R.delta;b?.content&&!p&&(p=!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&&(p&&(yield {type:"content_block_stop",index:0}),h=je(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:h||"end_turn"},usage:d||{}},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,s=t+r,[a,i]=Ke(e.model),l=(s*a+1e3*i)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(l*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(l=>r.startsWith(l)))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 a=Ft(e.messages,e.system),i={model:e.model,max_tokens:e.max_tokens,messages:a};return t&&(i.stream=true,i.stream_options={include_usage:true}),e.temperature!==void 0&&(i.temperature=e.temperature),e.tools&&e.tools.length>0&&(i.tools=e.tools),i}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 a=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw a.retryAfterMs=s,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 Bt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Vt(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:Bt(r.content)});return t}var Ht,ne,Je=v(()=>{V();Ht="http://localhost:11434";ne=class extends w{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(/\/$/,"")||Ht;}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),a=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let i=await a.json(),l=Date.now()-r;this.recordSuccess();let o=[];i.message?.content&&o.push({type:"text",text:i.message.content});let p=i.prompt_eval_count||0,c=i.eval_count||0;return {content:o,model:i.model||e.model,usage:{input_tokens:p,output_tokens:c},stop_reason:(i.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:l,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 a=s.body.getReader(),i=new TextDecoder,l=e.model;return (async function*(){let o="",p=false,c=false;yield {type:"message_start",message:{model:l,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:d,value:h}=await a.read();if(d)break;o+=i.decode(h,{stream:!0});let m=o.split(`
14
- `);o=m.pop()||"";for(let _ of m){let u=_.trim();if(u)try{let y=JSON.parse(u);if(y.message?.content&&(p||(p=!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:y.message.content}}),y.done){p&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:y.prompt_eval_count||0,output_tokens:y.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=Vt(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 re,ze=v(()=>{re=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 se(n,e){if(e instanceof E)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,rt)||"unknown"}`}function Qe(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 ke(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.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")?"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)}function et(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Wt(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 tt(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function Gt(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 Yt(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 i=t.content[t.content.length-1];if(i?.type==="text"&&i.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 Kt(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 jt(n,e){return n?`${n}
11
+ -----END PUBLIC KEY-----`,Le={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>"},V=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(ge,"RS256"),{payload:a}=await t(e,s),i=JSON.parse(new TextDecoder().decode(a));return this.verificationFailures=0,this.cachedManifest=i,this.currentSecurityState="SEC_NOMINAL",{manifest:i,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:Le,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:Le,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Ct=new V;});function Ee(n){return join(homedir(),".inference-relay","gateway",n)}function Ue(n){return join(Ee(n),"bundle.js")}function Ne(n){return join(Ee(n),"meta.json")}var wt,_,W,z,be=C(()=>{fe();wt=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";_=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},W=new Map,z=class{static async load(e,t,r=wt){let s=`${t}:${e.slice(-8)}`;if(W.has(s))return W.get(s);try{let d=await this.tryLoadFromDisk(t);if(d)return W.set(s,d),d}catch{}let{bytes:a,sha256:i,signature:l,libraryVersion:o}=await this.fetchFromAuthority(e,t,r);if(createHash("sha256").update(a).digest("hex")!==i)throw new _("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(l,o,i);try{let d=Ee(t);mkdirSync(d,{recursive:!0}),writeFileSync(Ue(t),a),writeFileSync(Ne(t),JSON.stringify({sha256:i,signature:l,libraryVersion:o}));}catch{}let c=this.loadIntoVm(a.toString("utf-8"));return W.set(s,c),c}static async loadFromDisk(e){if(!existsSync(e))throw new _(`[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=Ue(e),r=Ne(e);if(!existsSync(t)||!existsSync(r))return null;let s=readFileSync(t),a=JSON.parse(readFileSync(r,"utf-8"));return createHash("sha256").update(s).digest("hex")!==a.sha256?null:(await this.verifySignature(a.signature,a.libraryVersion,a.sha256),this.loadIntoVm(s.toString("utf-8")))}static async fetchFromAuthority(e,t,r){let s,a=[0,1e3,4e3],i;for(let c of a){c>0&&await new Promise(d=>setTimeout(d,c));try{let d=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(d.status===401||d.status===403)throw new _("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(d.status>=500&&d.status<600){i=new _(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${d.status})`,"GATEWAY_FETCH_FAILED");continue}if(!d.ok)throw new _(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${d.status})`,"GATEWAY_FETCH_FAILED");s=await d.json(),i=null;break}catch(d){if(d instanceof _&&d.code==="LICENSE_REJECTED")throw d;i=d;}}if(i||!s)throw i instanceof _?i:new _("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)","GATEWAY_FETCH_FAILED",i);let l;try{l=await fetch(s.bundleUrl);}catch(c){throw new _("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)","GATEWAY_FETCH_FAILED",c)}if(!l.ok)throw new _(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${l.status})`,"GATEWAY_FETCH_FAILED");let o=await l.arrayBuffer();return {bytes:Buffer.from(o),sha256:s.sha256,signature:s.signature,libraryVersion:s.libraryVersion,bundleVersion:s.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:a}=await import('jose'),i=await a(ge,"RS256"),{payload:l}=await s(e,i),o=JSON.parse(new TextDecoder().decode(l));if(o.purpose!=="gateway-bundle")throw new _("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(o.libraryVersion!==t)throw new _("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(o.sha256!==r)throw new _("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof _?s:new _("[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),a={exports:{}};compileFunction(e,["exports","require","module","__filename","__dirname"],{filename:"<gateway-bundle>"})(a.exports,s,a,t,r);let l=a.exports;if(!l.ClaudeCLIProvider)throw new _("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return l}catch(t){throw t instanceof _?t:new _("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){W.clear();}};});var He={};xe(He,{detectCLI:()=>N});function Lt(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(a=>a.toLowerCase()):[""];for(let a of e.split(r))if(a)for(let i of s){let l=join(a,n+i);if(existsSync(l))return l}return null}async function N(){if(!Lt("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&&!xt.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 xt,Q=C(()=>{xt=["2.1.87"];});var Mt,Z,Be=C(()=>{$();be();Mt="1.5.1",Z=class extends w{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.licenseKey=e;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await z.load(this.licenseKey,Mt)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof _?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(Q(),He));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());}};});function Ve(n){return ee[n]||n}function ve(n){return $e.find(e=>e.canonical===n)?.provider}var $e,ee,Ce=C(()=>{$e=[{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}}],ee=Object.fromEntries($e.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));ee["claude-sonnet-4"]="claude-sonnet-4-20250514";ee["claude-opus-4"]="claude-opus-4-20250514";ee["claude-haiku-4"]="claude-haiku-4-5-20251001";});function We(n){if(Ae[n])return Ae[n];for(let[e,t]of Object.entries(Ae))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var Dt,Ot,Ae,te,Ge=C(()=>{$();Ce();Dt="https://api.anthropic.com/v1/messages",Ot="2023-06-01",Ae={"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]};te=class extends w{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(/\/$/,"")||Dt,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),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let i=await a.json(),l=Date.now()-r;this.recordSuccess();let[o,p]=We(i.model||e.model),c=((i.usage?.input_tokens||0)*o+(i.usage?.output_tokens||0)*p)/1e6,d={},h=["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 m of h){let E=a.headers.get(m);E&&(d[m]=E);}return {content:i.content||[],model:i.model||e.model,usage:{input_tokens:i.usage?.input_tokens||0,output_tokens:i.usage?.output_tokens||0},stop_reason:i.stop_reason||"end_turn",provider:"anthropic-api",costUsd:Math.round(c*1e6)/1e6,durationMs:l,fallbackChain:["anthropic-api:success"],headers:Object.keys(d).length>0?d: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 a=s.body.getReader(),i=new TextDecoder;return (async function*(){let l="",o=false;try{for(;;){let{done:p,value:c}=await a.read();if(p)break;l+=i.decode(c,{stream:!0});let d=l.split(`
12
+ `);l=d.pop()||"";let h=null;for(let m of d)if(m.startsWith("event: "))h=m.slice(7).trim();else if(m.startsWith("data: ")){let E=m.slice(6);if(h&&E)try{let u=JSON.parse(E);u.type==="message_stop"&&(o=!0),yield u;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",E.substring(0,100));}h=null;}else m.trim()===""&&(h=null);}o||(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,s=t+r,[a,i]=We(e.model),l=(s*a+1e3*i)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(l*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":Ot};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:Ve(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 a=new Error(`ANTHROPIC_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw a.retryAfterMs=s,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 Ke(n){if(Re[n])return Re[n];for(let[e,t]of Object.entries(Re))if(n.startsWith(e))return t;return [2.5,10]}function Nt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ft(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=Nt(r.content);if(r.role==="assistant"&&Array.isArray(r.content)){let a=r.content.filter(i=>i.type==="tool_use");if(a.length>0){t.push({role:"assistant",content:s||"",tool_calls:a.map(i=>({id:i.id||`call_${Math.random().toString(36).slice(2)}`,type:"function",function:{name:i.name,arguments:typeof i.input=="string"?i.input:JSON.stringify(i.input)}}))});continue}}t.push({role:r.role,content:s});}return t}function je(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 Ut,Ye,Re,ne,qe=C(()=>{$();Ut="https://api.openai.com/v1/chat/completions",Ye=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Re={"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]};ne=class extends w{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(/\/$/,"")||Ut;}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),a=await fetch(this.baseUrl,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify(s),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let i=await a.json(),l=Date.now()-r;this.recordSuccess();let o=i.choices?.[0],p=[];if(o?.message?.content&&p.push({type:"text",text:o.message.content}),o?.message?.tool_calls)for(let g of o.message.tool_calls)p.push({type:"tool_use",id:g.id,name:g.function?.name,input:g.function?.arguments?JSON.parse(g.function.arguments):{}});let c=i.usage?.prompt_tokens||0,d=i.usage?.completion_tokens||0,[h,m]=Ke(i.model||e.model),E=(c*h+d*m)/1e6,u={},y=["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 g of y){let f=a.headers.get(g);f&&(u[g]=f);}return {content:p,model:i.model||e.model,usage:{input_tokens:c,output_tokens:d},stop_reason:je(o?.finish_reason),provider:"openai-api",costUsd:Math.round(E*1e6)/1e6,durationMs:l,fallbackChain:["openai-api:success"],headers:Object.keys(u).length>0?u: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 a=s.body.getReader(),i=new TextDecoder,l=e.model;return (async function*(){let o="",p=false,c=false,d,h;yield {type:"message_start",message:{model:l,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:m,value:E}=await a.read();if(m)break;o+=i.decode(E,{stream:!0});let u=o.split(`
13
+ `);o=u.pop()||"";for(let y of u){if(!y.startsWith("data: "))continue;let g=y.slice(6).trim();if(g==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:h||"end_turn"},usage:d||{}},yield {type:"message_stop"},c=!0;return}try{let f=JSON.parse(g);f.usage&&(d={input_tokens:f.usage.prompt_tokens||0,output_tokens:f.usage.completion_tokens||0});let R=f.choices?.[0];if(!R)continue;let b=R.delta;b?.content&&!p&&(p=!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&&(p&&(yield {type:"content_block_stop",index:0}),h=je(R.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:h||"end_turn"},usage:d||{}},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,s=t+r,[a,i]=Ke(e.model),l=(s*a+1e3*i)/1e6;return {estimatedInputTokens:s,estimatedCost:Math.round(l*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(l=>r.startsWith(l)))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 a=Ft(e.messages,e.system),i={model:e.model,max_tokens:e.max_tokens,messages:a};return t&&(i.stream=true,i.stream_options={include_usage:true}),e.temperature!==void 0&&(i.temperature=e.temperature),e.tools&&e.tools.length>0&&(i.tools=e.tools),i}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 a=new Error(`OPENAI_RATE_LIMIT: Too many requests (429). Retry after ${s}ms`);throw a.retryAfterMs=s,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 Bt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function $t(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:Bt(r.content)});return t}var Ht,re,Je=C(()=>{$();Ht="http://localhost:11434";re=class extends w{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(/\/$/,"")||Ht;}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),a=await fetch(`${this.baseUrl}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),signal:t?.signal});if(!a.ok)throw this.handleErrorResponse(a),new Error("unreachable");let i=await a.json(),l=Date.now()-r;this.recordSuccess();let o=[];i.message?.content&&o.push({type:"text",text:i.message.content});let p=i.prompt_eval_count||0,c=i.eval_count||0;return {content:o,model:i.model||e.model,usage:{input_tokens:p,output_tokens:c},stop_reason:(i.done,"end_turn"),provider:"ollama",costUsd:0,durationMs:l,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 a=s.body.getReader(),i=new TextDecoder,l=e.model;return (async function*(){let o="",p=false,c=false;yield {type:"message_start",message:{model:l,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:d,value:h}=await a.read();if(d)break;o+=i.decode(h,{stream:!0});let m=o.split(`
14
+ `);o=m.pop()||"";for(let E of m){let u=E.trim();if(u)try{let y=JSON.parse(u);if(y.message?.content&&(p||(p=!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:y.message.content}}),y.done){p&&(yield {type:"content_block_stop",index:0}),yield {type:"message_delta",delta:{stop_reason:"end_turn"},usage:{input_tokens:y.prompt_eval_count||0,output_tokens:y.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=$t(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 se,ze=C(()=>{se=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 ie(n,e){if(e instanceof _)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,rt)||"unknown"}`}function Qe(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 ke(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.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_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)}function et(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Wt(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 tt(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function Gt(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 Yt(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 i=t.content[t.content.length-1];if(i?.type==="text"&&i.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 Kt(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 jt(n,e){return n?`${n}
15
15
 
16
- ${e}`:e}function nt(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 qt(n){return Math.max(0,n.content.length-1)}async function*Jt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}var rt,Xe,F,ie,Ie=v(()=>{he();ze();Ce();be();rt=200;Xe=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;}};ie=class n{healthMap=new Map;engineEvents=new re;static UNHEALTHY_TTL_MS=300*1e3;getHealthStatus(e){let t=this.healthMap.get(e);return t?t.status==="unhealthy"&&Date.now()-t.updatedAt>=n.UNHEALTHY_TTL_MS?(this.healthMap.delete(e),"healthy"):t.status:"healthy"}markUnhealthy(e,t){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now()});}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),a=[],i=Qe(e),l=randomUUID(),o=Date.now();for(let p of s){let c=p.type;if(this.getHealthStatus(c)==="unhealthy"){a.push(`${c}:skipped:unhealthy`);continue}if(i&&!p.supportsMultimodal){a.push(`${c}:skipped:no_multimodal`);continue}let h=ve(e.model);if(h&&h!==c&&Xe.has(c)){a.push(`${c}:skipped:wrong_provider`);continue}try{let m=await p.execute(e,{signal:r?.signal});return this.markHealthy(c),a.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:l,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd??0}],provider:c,model:m.model,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd,durationMs:m.durationMs??Date.now()-o,stopReason:m.stop_reason,fallbackChain:a,rateLimitHit:!1,securityState:r?.licenseState}),{...m,fallbackChain:a}}catch(m){if(m?.name==="AbortError"||r?.signal?.aborted)throw m;switch(ke(m)){case "rate_limited":p.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"),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(se(c,m));break;default:a.push(se(c,m));break}}}throw new F(a)}async stream(e,t,r){let s=randomUUID(),a=Ze(t),i=Qe(e),l=Date.now(),o=[],p=null,c=null;for(let g of a){let f=g.type;if(this.getHealthStatus(f)==="unhealthy"){o.push(`${f}:skipped:unhealthy`);continue}if(i&&!g.supportsMultimodal){o.push(`${f}:skipped:no_multimodal`);continue}if(!g.supportsStreaming){o.push(`${f}:skipped:no_streaming`);continue}let R=ve(e.model);if(R&&R!==f&&Xe.has(f)){o.push(`${f}:skipped:wrong_provider`);continue}try{c=await g.streamRaw(e,{signal:r?.signal}),p=g,o.push(`${f}:success`);break}catch(b){if(b?.name==="AbortError"||r?.signal?.aborted)throw b;switch(ke(b)){case "rate_limited":g.reportRateLimit({provider:f,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(f,"rate_limited"),o.push(`${f}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(f,"auth_failed"),o.push(`${f}:failed:auth_failed`);break;case "timeout":o.push(`${f}:failed:timeout`);break;case "provider_incompatible":o.push(`${f}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(f,"gateway_unavailable"),o.push(se(f,b));break;default:o.push(se(f,b));break}}}if(!p||!c)throw new F(o);let h=this,m=r?.maxMidStreamFailovers??2,_=new Set([p]);async function*u(){let g=p,f=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},b={segments:[]},L=et(g.type);b.segments.push(L);let Te=0,Y=null,K=false,pe=m,H="",B="";for(h.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:g.type});;)try{for(;;){let k=await f.next();if(k.done)break;let D=k.value,P=Yt(D,Te,R,K,Y);if(P.action==="suppress"){"coalesceMode"in P&&(Y=P.coalesceMode),P.clearedJustFailedOver&&(K=!1);continue}P.coalesceModeCleared&&(Y=null),P.clearedJustFailedOver&&(K=!1);let A=P.event;if(Gt(R,A),A.type==="message_start"){if(b.segments.length>1)continue;H=A.message?.model||H,A.message?.usage?.input_tokens!=null&&(L.inputTokens=A.message.usage.input_tokens);}if(A.type==="message_delta"&&(A.delta?.stop_reason&&(B=A.delta.stop_reason),A.usage)){Wt(L,g.type,A.usage),yield {...A,usage:void 0};continue}if(A.type==="message_stop")break;yield A;}if(R.content.length===0&&L.outputTokens===0)throw new Error("stream ended without producing any content");h.markHealthy(g.type),h.emitEngineEvent({kind:"segment_complete",callId:s,id:randomUUID(),ts:Date.now(),provider:g.type,usage:{...L}});let I=tt(b.segments);yield {type:"message_delta",delta:{stop_reason:B||"end_turn"},usage:I},yield {type:"message_stop"},h.emitEngineEvent({kind:"stream_complete",callId:s,id:randomUUID(),ts:Date.now(),stitched:b.segments.length>1,segments:b.segments.map(k=>({...k})),provider:b.segments.map(k=>k.provider).join("+"),model:H,inputTokens:I.input_tokens,outputTokens:I.output_tokens,costUsd:b.segments.reduce((k,D)=>k+D.costUsd,0),userCostUsd:b.segments.reduce((k,D)=>k+D.userCostUsd,0),durationMs:Date.now()-l,stopReason:B||"end_turn",fallbackChain:o,rateLimitHit:!1,securityState:r?.licenseState});return}catch(I){if(I?.name==="AbortError"||r?.signal?.aborted)throw I;let k=ke(I);try{await f.return?.();}catch{}if(h.markUnhealthy(g.type,String(I)),h.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:randomUUID(),ts:Date.now(),from:g.type,bytesBuffered:nt(R),errorClass:k,retriesLeft:pe}),o.push(`${g.type}:partial(${nt(R)}b)`),pe<=0)throw h.emitTerminalExhaustion(s,b,H,B,o,l,r?.licenseState),I;let D=Kt(R.content),P=[...e.messages,{role:"assistant",content:D}],A=null,j=null,Se=g;for(;;){let x=h.nextHealthyProvider(a,Se,i,_);if(!x)break;Se=x,_.add(x);let bt={...e,messages:P,...x.type!=="anthropic-api"&&x.type!=="claude-cli"?{system:jt(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{j=await x.streamRaw(bt,{signal:r?.signal}),A=x;break}catch(Pe){h.markUnhealthy(x.type,String(Pe)),o.push(`${x.type}:failed_connect:${String(Pe).slice(0,rt)}`);}}if(!A||!j)throw h.emitTerminalExhaustion(s,b,H,B,o,l,r?.licenseState),I;o.push(`${A.type}:stitched`),h.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:randomUUID(),ts:Date.now(),from:g.type,to:A.type}),Te=qt(R)+1,pe--,g=A,f=j[Symbol.asyncIterator](),K=true,Y=null,L=et(g.type),b.segments.push(L),h.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:g.type});}}let y=u();return r?.licenseState==="SEC_DEGRADED"&&(y=Jt(y)),q(y)}nextHealthyProvider(e,t,r,s){let a=e.indexOf(t);if(a===-1)return null;for(let i=a+1;i<e.length;i++){let l=e[i];if(!s.has(l)&&!(r&&!l.supportsMultimodal)&&l.supportsStreaming)return l}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,s,a,i,l){let o=tt(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(p=>({...p})),provider:t.segments.map(p=>p.provider).join("+"),model:r,inputTokens:o.input_tokens,outputTokens:o.output_tokens,costUsd:t.segments.reduce((p,c)=>p+c.costUsd,0),userCostUsd:t.segments.reduce((p,c)=>p+c.userCostUsd,0),durationMs:Date.now()-i,stopReason:s||"error",fallbackChain:a,rateLimitHit:false,securityState:l});}};});function st(n,e){if(e==="prefer-user"){let s=n.filter(i=>i.type==="claude-cli"),a=n.filter(i=>i.type!=="claude-cli");return [...s,...a]}if(e==="prefer-app"){let s=n.filter(i=>i.type==="claude-cli");return [...n.filter(i=>i.type!=="claude-cli"),...s]}let t=n.filter(s=>s.type===e),r=n.filter(s=>s.type!==e);return [...t,...r]}function it(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var at=v(()=>{});function ot(n){if(we[n])return we[n];for(let[e,t]of Object.entries(we))if(n.startsWith(e))return t;return [3,15]}var we,lt=v(()=>{we={"claude-opus-4":[15,75],"claude-sonnet-4":[3,15],"claude-haiku-4":[.8,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 ct(n){let e=0;for(let l of n.messages)if(typeof l.content=="string")e+=l.content.length;else if(Array.isArray(l.content))for(let o of l.content)o.type==="text"&&o.text&&(e+=o.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[s,a]=ot(n.model),i=(t*s+r*a)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(i*1e4)/1e4,model:n.model,provider:""}}var ut=v(()=>{lt();});var ae,dt=v(()=>{ae=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(()=>{});}};});async function oe(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 r=new AbortController,a=!O.has(n)?3e3:1e3,i=setTimeout(()=>r.abort(),a),l;try{let p=(e||zt)+Xt;l=await(await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n}),signal:r.signal})).json();}catch{return clearTimeout(i),t&&Date.now()-t.cachedAt<Zt?t.result:{valid:false,error:"License validation failed (network error). Visit inference-relay.com"}}clearTimeout(i);let o;if(l.jws)try{let{compactVerify:p,importSPKI:c}=await import('jose'),d=await c(en,"RS256"),{payload:h}=await p(l.jws,d);o=JSON.parse(new TextDecoder().decode(h));}catch{return O.delete(n),{valid:false,error:"License validation signature invalid. Possible MITM \u2014 refusing to start."}}else if(o=l,o.valid)return O.delete(n),{valid:false,error:"License validation response not signed. Possible MITM."};return O.set(n,{result:o,cachedAt:Date.now(),ttl:o.valid?Qt:6e4}),o}var zt,Xt,Qt,Zt,en,O,le,pt=v(()=>{me();Be();Ge();qe();Je();Ie();X();at();ut();fe();dt();zt="https://api.inference-relay.com",Xt="/v1/validate",Qt=1440*60*1e3,Zt=10080*60*1e3,en=`-----BEGIN PUBLIC KEY-----
16
+ ${e}`:e}function nt(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 qt(n){return Math.max(0,n.content.length-1)}async function*Jt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}var rt,Xe,F,ae,Ie=C(()=>{he();ze();Ce();be();rt=200;Xe=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;}};ae=class n{healthMap=new Map;engineEvents=new se;static UNHEALTHY_TTL_MS=300*1e3;getHealthStatus(e){let t=this.healthMap.get(e);return t?t.status==="unhealthy"&&Date.now()-t.updatedAt>=n.UNHEALTHY_TTL_MS?(this.healthMap.delete(e),"healthy"):t.status:"healthy"}markUnhealthy(e,t){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now()});}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),a=[],i=Qe(e),l=randomUUID(),o=Date.now();for(let p of s){let c=p.type;if(this.getHealthStatus(c)==="unhealthy"){a.push(`${c}:skipped:unhealthy`);continue}if(i&&!p.supportsMultimodal){a.push(`${c}:skipped:no_multimodal`);continue}let h=ve(e.model);if(h&&h!==c&&Xe.has(c)){a.push(`${c}:skipped:wrong_provider`);continue}try{let m=await p.execute(e,{signal:r?.signal});return this.markHealthy(c),a.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:l,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd??0}],provider:c,model:m.model,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd,durationMs:m.durationMs??Date.now()-o,stopReason:m.stop_reason,fallbackChain:a,rateLimitHit:!1,securityState:r?.licenseState}),{...m,fallbackChain:a}}catch(m){if(m?.name==="AbortError"||r?.signal?.aborted)throw m;switch(ke(m)){case "rate_limited":p.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"),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(ie(c,m));break;default:a.push(ie(c,m));break}}}throw new F(a)}async stream(e,t,r){let s=randomUUID(),a=Ze(t),i=Qe(e),l=Date.now(),o=[],p=null,c=null;for(let g of a){let f=g.type;if(this.getHealthStatus(f)==="unhealthy"){o.push(`${f}:skipped:unhealthy`);continue}if(i&&!g.supportsMultimodal){o.push(`${f}:skipped:no_multimodal`);continue}if(!g.supportsStreaming){o.push(`${f}:skipped:no_streaming`);continue}let R=ve(e.model);if(R&&R!==f&&Xe.has(f)){o.push(`${f}:skipped:wrong_provider`);continue}try{c=await g.streamRaw(e,{signal:r?.signal}),p=g,o.push(`${f}:success`);break}catch(b){if(b?.name==="AbortError"||r?.signal?.aborted)throw b;switch(ke(b)){case "rate_limited":g.reportRateLimit({provider:f,utilization:1,resetsAt:Date.now()+6e4}),this.markDegraded(f,"rate_limited"),o.push(`${f}:failed:rate_limited`);break;case "auth_failed":this.markUnhealthy(f,"auth_failed"),o.push(`${f}:failed:auth_failed`);break;case "timeout":o.push(`${f}:failed:timeout`);break;case "provider_incompatible":o.push(`${f}:incompatible`);break;case "gateway_unavailable":this.markUnhealthy(f,"gateway_unavailable"),o.push(ie(f,b));break;default:o.push(ie(f,b));break}}}if(!p||!c)throw new F(o);let h=this,m=r?.maxMidStreamFailovers??2,E=new Set([p]);async function*u(){let g=p,f=c[Symbol.asyncIterator](),R={role:"assistant",content:[]},b={segments:[]},L=et(g.type);b.segments.push(L);let Te=0,K=null,j=false,pe=m,H="",B="";for(h.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:g.type});;)try{for(;;){let k=await f.next();if(k.done)break;let D=k.value,P=Yt(D,Te,R,j,K);if(P.action==="suppress"){"coalesceMode"in P&&(K=P.coalesceMode),P.clearedJustFailedOver&&(j=!1);continue}P.coalesceModeCleared&&(K=null),P.clearedJustFailedOver&&(j=!1);let A=P.event;if(Gt(R,A),A.type==="message_start"){if(b.segments.length>1)continue;H=A.message?.model||H,A.message?.usage?.input_tokens!=null&&(L.inputTokens=A.message.usage.input_tokens);}if(A.type==="message_delta"&&(A.delta?.stop_reason&&(B=A.delta.stop_reason),A.usage)){Wt(L,g.type,A.usage),yield {...A,usage:void 0};continue}if(A.type==="message_stop")break;yield A;}if(R.content.length===0&&L.outputTokens===0)throw new Error("stream ended without producing any content");h.markHealthy(g.type),h.emitEngineEvent({kind:"segment_complete",callId:s,id:randomUUID(),ts:Date.now(),provider:g.type,usage:{...L}});let I=tt(b.segments);yield {type:"message_delta",delta:{stop_reason:B||"end_turn"},usage:I},yield {type:"message_stop"},h.emitEngineEvent({kind:"stream_complete",callId:s,id:randomUUID(),ts:Date.now(),stitched:b.segments.length>1,segments:b.segments.map(k=>({...k})),provider:b.segments.map(k=>k.provider).join("+"),model:H,inputTokens:I.input_tokens,outputTokens:I.output_tokens,costUsd:b.segments.reduce((k,D)=>k+D.costUsd,0),userCostUsd:b.segments.reduce((k,D)=>k+D.userCostUsd,0),durationMs:Date.now()-l,stopReason:B||"end_turn",fallbackChain:o,rateLimitHit:!1,securityState:r?.licenseState});return}catch(I){if(I?.name==="AbortError"||r?.signal?.aborted)throw I;let k=ke(I);try{await f.return?.();}catch{}if(h.markUnhealthy(g.type,String(I)),h.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:randomUUID(),ts:Date.now(),from:g.type,bytesBuffered:nt(R),errorClass:k,retriesLeft:pe}),o.push(`${g.type}:partial(${nt(R)}b)`),pe<=0)throw h.emitTerminalExhaustion(s,b,H,B,o,l,r?.licenseState),I;let D=Kt(R.content),P=[...e.messages,{role:"assistant",content:D}],A=null,q=null,Se=g;for(;;){let x=h.nextHealthyProvider(a,Se,i,E);if(!x)break;Se=x,E.add(x);let bt={...e,messages:P,...x.type!=="anthropic-api"&&x.type!=="claude-cli"?{system:jt(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{q=await x.streamRaw(bt,{signal:r?.signal}),A=x;break}catch(Pe){h.markUnhealthy(x.type,String(Pe)),o.push(`${x.type}:failed_connect:${String(Pe).slice(0,rt)}`);}}if(!A||!q)throw h.emitTerminalExhaustion(s,b,H,B,o,l,r?.licenseState),I;o.push(`${A.type}:stitched`),h.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:randomUUID(),ts:Date.now(),from:g.type,to:A.type}),Te=qt(R)+1,pe--,g=A,f=q[Symbol.asyncIterator](),j=true,K=null,L=et(g.type),b.segments.push(L),h.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:g.type});}}let y=u();return r?.licenseState==="SEC_DEGRADED"&&(y=Jt(y)),J(y)}nextHealthyProvider(e,t,r,s){let a=e.indexOf(t);if(a===-1)return null;for(let i=a+1;i<e.length;i++){let l=e[i];if(!s.has(l)&&!(r&&!l.supportsMultimodal)&&l.supportsStreaming)return l}return null}emitEngineEvent(e){this.engineEvents.emitTyped(e);}emitTerminalExhaustion(e,t,r,s,a,i,l){let o=tt(t.segments);this.emitEngineEvent({kind:"stream_complete",callId:e,id:randomUUID(),ts:Date.now(),stitched:t.segments.length>1,segments:t.segments.map(p=>({...p})),provider:t.segments.map(p=>p.provider).join("+"),model:r,inputTokens:o.input_tokens,outputTokens:o.output_tokens,costUsd:t.segments.reduce((p,c)=>p+c.costUsd,0),userCostUsd:t.segments.reduce((p,c)=>p+c.userCostUsd,0),durationMs:Date.now()-i,stopReason:s||"error",fallbackChain:a,rateLimitHit:false,securityState:l});}};});function st(n,e){if(e==="prefer-user"){let s=n.filter(i=>i.type==="claude-cli"),a=n.filter(i=>i.type!=="claude-cli");return [...s,...a]}if(e==="prefer-app"){let s=n.filter(i=>i.type==="claude-cli");return [...n.filter(i=>i.type!=="claude-cli"),...s]}let t=n.filter(s=>s.type===e),r=n.filter(s=>s.type!==e);return [...t,...r]}function it(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var at=C(()=>{});function ot(n){if(we[n])return we[n];for(let[e,t]of Object.entries(we))if(n.startsWith(e))return t;return [3,15]}var we,lt=C(()=>{we={"claude-opus-4":[15,75],"claude-sonnet-4":[3,15],"claude-haiku-4":[.8,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 ct(n){let e=0;for(let l of n.messages)if(typeof l.content=="string")e+=l.content.length;else if(Array.isArray(l.content))for(let o of l.content)o.type==="text"&&o.text&&(e+=o.text.length);n.system&&(e+=n.system.length);let t=Math.ceil(e/4),r=Math.min(n.max_tokens||1024,4096),[s,a]=ot(n.model),i=(t*s+r*a)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(i*1e4)/1e4,model:n.model,provider:""}}var ut=C(()=>{lt();});var oe,dt=C(()=>{oe=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(()=>{});}};});async function le(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 r=new AbortController,a=!O.has(n)?3e3:1e3,i=setTimeout(()=>r.abort(),a),l;try{let p=(e||zt)+Xt;l=await(await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:n}),signal:r.signal})).json();}catch{return clearTimeout(i),t&&Date.now()-t.cachedAt<Zt?t.result:{valid:false,error:"License validation failed (network error). Visit inference-relay.com"}}clearTimeout(i);let o;if(l.jws)try{let{compactVerify:p,importSPKI:c}=await import('jose'),d=await c(en,"RS256"),{payload:h}=await p(l.jws,d);o=JSON.parse(new TextDecoder().decode(h));}catch{return O.delete(n),{valid:false,error:"License validation signature invalid. Possible MITM \u2014 refusing to start."}}else if(o=l,o.valid)return O.delete(n),{valid:false,error:"License validation response not signed. Possible MITM."};return O.set(n,{result:o,cachedAt:Date.now(),ttl:o.valid?Qt:6e4}),o}var zt,Xt,Qt,Zt,en,O,ce,pt=C(()=>{me();Be();Ge();qe();Je();Ie();Q();at();ut();fe();dt();zt="https://api.inference-relay.com",Xt="/v1/validate",Qt=1440*60*1e3,Zt=10080*60*1e3,en=`-----BEGIN PUBLIC KEY-----
17
17
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
18
18
  EGNiPB+r8u1ZinBvMM4qX8dp4kzJEC/47L1RYrrxCphD05HToREjljbj+upH6rZH
19
19
  t6D/5funYPi2TO1IOSC6BRVRwMqqTmJGVJcLcG/WF3gTE+2UQ3q5EppWJCEKcz6x
@@ -21,4 +21,4 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
21
21
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
22
22
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
23
23
  UQIDAQAB
24
- -----END PUBLIC KEY-----`,O=new Map;le=class n{providers=[];config;fallbackEngine;telemetryReporter;routingFn=null;license=null;licensePromise=null;licenseValidatedAt=0;callsSinceValidation=0;manifestDecryptor=new $;capProbeTimer=null;capProbeTicksRemaining=0;messages;constructor(e){if(this.config=e,this.fallbackEngine=new ie,this.telemetryReporter=new ae({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=it(e.routing)),e.providers)for(let s of e.providers){let a=typeof s=="string"?{type:s}:s,i=this.createProvider(a);i&&(a.priority!==void 0&&(i.priority=a.priority),this.providers.push(i));}let t=100,r=3600*1e3;this.messages={create:async(s,a)=>{let i=this.license&&(this.callsSinceValidation>=t||Date.now()-this.licenseValidatedAt>=r);if(i&&(this.license=null),!this.license){this.licensePromise||(this.licensePromise=oe(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 U({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});i||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"}`)}return this.callsSinceValidation++,s.stream?this.streamMessage(s,a):this.executeMessage(s,a)}};}startCapProbe(){if(this.capProbeTimer!==null)return;let e=15e3,t=20,r=4;this.capProbeTicksRemaining=t;let s=async()=>{this.capProbeTicksRemaining-=1;let a=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 (${a}m remaining)`),this.config.licenseKey&&O.delete(this.config.licenseKey);try{let i=await this.probeValidate();if(i.valid&&i.capExceeded===!1){console.log("[inference-relay] cap cleared \u2014 probe exiting, inference resuming"),this.license=i,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 oe(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 N();return r.available&&r.authenticated!==false&&t.push({type:"claude-cli",priority:1}),process.env.ANTHROPIC_API_KEY&&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,...e})}dispose(){this.providers=[],this.config.licenseKey&&O.delete(this.config.licenseKey),this.license=null,this.licensePromise=null,this.callsSinceValidation=0,this.stopCapProbe(),this.telemetryReporter.unsubscribe(),this.manifestDecryptor.clearCache(),Me();}resolveProviders(e){if(!this.routingFn)return this.providers;let t=ct(e),r=this.routingFn(e,t);return st(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()})}async streamMessage(e,t){let r=this.resolveProviders(e);return this.fallbackEngine.stream(e,r,{signal:t?.signal,licenseState:this.manifestDecryptor.getSecurityState()})}createProvider(e){switch(e.type){case "claude-cli":return new Q(this.config.licenseKey);case "anthropic-api":return e.apiKey?new ee({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "openai-api":return e.apiKey?new te({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "ollama":return new ne({baseUrl:e.baseUrl});default:return null}}};});var mt=v(()=>{X();});var ft={};xe(ft,{runVerify:()=>sn});function S(n,e){let t=n.padEnd(13);console.log(`${C("[ir]")} ${t}${e}`);}function rn(n){if(n instanceof U)return {label:"CAP_EXCEEDED",hint:"Monthly cap reached. Buy a top-up at https://inference-relay.com/dashboard/billing",code:1};if(n instanceof F)return {label:"ALL_PROVIDERS_FAILED",hint:`Fallback chain exhausted: ${n.fallbackChain.join(" \u2192 ")}`,code:1};if(!(n instanceof Error))return {label:"FAILED",hint:String(n).slice(0,120),code:1};let e=n.message.toLowerCase(),t=n.name.toLowerCase();return e.includes("keychain_access_denied")||e.includes("keychain access denied")?{label:"KEYCHAIN_DENIED",hint:'macOS denied keychain access. Re-run and click "Always Allow" on the prompt.',code:1}:e.includes("rate limit")||e.includes("429")||t.includes("ratelimit")?{label:"RATE_LIMITED",hint:"Claude subscription is currently rate-limited. Wait a minute and re-run.",code:1}:e.includes("auth")||e.includes("401")||e.includes("403")||e.includes("unauthorized")||e.includes("forbidden")?{label:"AUTH_FAILED",hint:"Claude CLI OAuth token rejected. Run `claude` to refresh, then re-run verify.",code:1}:e.includes("timeout")||e.includes("timed out")||e.includes("aborted")||e.includes("etimedout")||e.includes("econnrefused")||e.includes("econnreset")||t==="aborterror"||t==="timeouterror"?{label:"TIMEOUT",hint:`No response within ${gt/1e3}s. Network issue, hung CLI, or keychain prompt waiting for input. Try \`curl -I api.anthropic.com\` to test connectivity.`,code:1}:e.includes("empty response")||e.includes("returned empty")?{label:"EMPTY_RESPONSE",hint:"CLI returned an empty body \u2014 possible truncation, model error, or stale CLI version.",code:1}:{label:"FAILED",hint:n.message.slice(0,120),code:1}}function ht(n){if(n.usageCap!==null&&n.usageCap!==void 0){let e=n.usageThisMonth??0,t=n.usageCap;if(t===0)console.log(C(` Usage: ${e.toLocaleString()} (unmetered)`));else {let r=Math.round(e/t*1e3)/10;console.log(C(` Usage: ${e.toLocaleString()} / ${t.toLocaleString()} (${r}%)`));}}}async function sn(n=process.argv.slice(2),e=process.env){let t=n.includes("--credentials-only"),r=e.IR_LICENSE_KEY;if(!r)return console.error(G("[ir] IR_LICENSE_KEY environment variable is not set.")),console.error(" Get a key at https://inference-relay.com/pricing"),console.error(" Then: export IR_LICENSE_KEY=ir_live_xxxx"),2;if(!/^ir_(live|test)_[a-f0-9]{32}$/.test(r))return console.error(G("[ir] IR_LICENSE_KEY does not look like a valid key.")),console.error(" Expected format: ir_live_<32 hex chars>"),console.error(` Got: ${r.slice(0,8)}... (${r.length} chars)`),2;let s;try{s=await oe(r);}catch(_){return S("IDENTITY:",G("FAILED")),console.error(` ${_.message||"unknown error"}`),1}if(!s.valid)return S("IDENTITY:",G("REJECTED")),s.error&&console.error(` ${s.error}`),1;S("IDENTITY:",ce("VALIDATED"));let a=(s.tier??"unknown").toUpperCase();S("TIER:",ce(a));let i;try{i=await N();}catch{i=null;}if(!i||!i.available)return S("RELAY:",ue("INACTIVE")),console.log(C(" Claude CLI not detected. The relay will fall back")),console.log(C(" to direct API providers using your API keys.")),console.log(C(" For zero-cost routing, install Claude Code:")),console.log(C(" npm install -g @anthropic-ai/claude-code")),1;if(!i.authenticated)return S("RELAY:",ue("CLI_UNAUTHED")),console.log(C(" Claude CLI is installed but not authenticated.")),console.log(C(" Run `claude` once to sign in, then re-run verify.")),1;if(i.versionWarning&&console.log(ue(` Warning: ${i.versionWarning}`)),t)return S("RELAY:",ce("READY")),console.log(C(" Credentials present. Round-trip skipped (--credentials-only).")),i.cliVersion&&console.log(C(` Claude CLI: v${i.cliVersion}`)),i.subscriptionType&&i.subscriptionType!=="unknown"&&console.log(C(` Tier: ${i.subscriptionType}`)),ht(s),0;let l=new le({licenseKey:r,providers:[{type:"claude-cli",priority:1}],fallback:false,telemetry:false}),o=new AbortController,p=setTimeout(()=>o.abort(),gt),c=Date.now(),d;try{d=await l.messages.create(nn,{signal:o.signal});}catch(_){clearTimeout(p),l.dispose();let{label:u,hint:y}=rn(_);return S("RELAY:",G(`DEGRADED \u2014 ${u}`)),console.log(C(` ${y}`)),i.cliVersion&&console.log(C(` Claude CLI: v${i.cliVersion}`)),1}clearTimeout(p),l.dispose();let h=Date.now()-c;return d.fallbackChain?.[0]?.startsWith("claude-cli:success")?(S("RELAY:",ce("ACTIVE")),console.log(C(` Round-trip: ${h}ms via ${d.provider}`)),console.log(C(` Model echo: ${d.model}`)),console.log(C(` Tokens: ${d.usage.input_tokens} in / ${d.usage.output_tokens} out`)),i.cliVersion&&console.log(C(` Claude CLI: v${i.cliVersion}`)),i.subscriptionType&&i.subscriptionType!=="unknown"&&console.log(C(` Tier: ${i.subscriptionType}`)),ht(s),0):(S("RELAY:",ue("UNEXPECTED")),console.log(C(` Native Gateway did not handle the call. Chain: ${d.fallbackChain?.join(" \u2192 ")}`)),1)}var tn,de,ce,G,ue,C,gt,nn,yt=v(()=>{pt();Ie();me();mt();tn=process.stdout.isTTY===true,de=(n,e)=>tn?`\x1B[${n}m${e}\x1B[0m`:e,ce=n=>de("32",n),G=n=>de("31",n),ue=n=>de("33",n),C=n=>de("2",n);gt=15e3,nn={model:"claude-haiku-4-5",max_tokens:1,messages:[{role:"user",content:"Reply with exactly the single character k and nothing else."}]};});var Et={verify:async()=>{let{runVerify:n}=await Promise.resolve().then(()=>(yt(),ft));return n()}};function _t(){console.error("Usage: inference-relay <command>"),console.error(""),console.error("Commands:"),console.error(" verify Smoke-test your installation (license + relay availability)"),console.error(""),console.error("Docs: https://inference-relay.com/docs");}var M=process.argv[2];(!M||M==="--help"||M==="-h")&&(_t(),process.exit(M?0:2));M in Et||(console.error(`Unknown command: ${M}`),console.error(""),_t(),process.exit(1));Et[M]().then(n=>process.exit(n)).catch(n=>{console.error(`[ir] failed to run command "${M}":`),console.error(n),process.exit(99);});
24
+ -----END PUBLIC KEY-----`,O=new Map;ce=class n{providers=[];config;fallbackEngine;telemetryReporter;routingFn=null;license=null;licensePromise=null;licenseValidatedAt=0;callsSinceValidation=0;manifestDecryptor=new V;capProbeTimer=null;capProbeTicksRemaining=0;messages;constructor(e){if(this.config=e,this.fallbackEngine=new ae,this.telemetryReporter=new oe({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=it(e.routing)),e.providers)for(let s of e.providers){let a=typeof s=="string"?{type:s}:s,i=this.createProvider(a);i&&(a.priority!==void 0&&(i.priority=a.priority),this.providers.push(i));}let t=100,r=3600*1e3;this.messages={create:async(s,a)=>{let i=this.license&&(this.callsSinceValidation>=t||Date.now()-this.licenseValidatedAt>=r);if(i&&(this.license=null),!this.license){this.licensePromise||(this.licensePromise=le(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 U({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});i||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"}`)}return this.callsSinceValidation++,s.stream?this.streamMessage(s,a):this.executeMessage(s,a)}};}startCapProbe(){if(this.capProbeTimer!==null)return;let e=15e3,t=20,r=4;this.capProbeTicksRemaining=t;let s=async()=>{this.capProbeTicksRemaining-=1;let a=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 (${a}m remaining)`),this.config.licenseKey&&O.delete(this.config.licenseKey);try{let i=await this.probeValidate();if(i.valid&&i.capExceeded===!1){console.log("[inference-relay] cap cleared \u2014 probe exiting, inference resuming"),this.license=i,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 le(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 N();return r.available&&r.authenticated!==false&&t.push({type:"claude-cli",priority:1}),process.env.ANTHROPIC_API_KEY&&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,...e})}dispose(){this.providers=[],this.config.licenseKey&&O.delete(this.config.licenseKey),this.license=null,this.licensePromise=null,this.callsSinceValidation=0,this.stopCapProbe(),this.telemetryReporter.unsubscribe(),this.manifestDecryptor.clearCache(),Me();}resolveProviders(e){if(!this.routingFn)return this.providers;let t=ct(e),r=this.routingFn(e,t);return st(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()})}async streamMessage(e,t){let r=this.resolveProviders(e);return this.fallbackEngine.stream(e,r,{signal:t?.signal,licenseState:this.manifestDecryptor.getSecurityState()})}createProvider(e){switch(e.type){case "claude-cli":return new Z(this.config.licenseKey);case "anthropic-api":return e.apiKey?new te({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "openai-api":return e.apiKey?new ne({apiKey:e.apiKey,baseUrl:e.baseUrl}):null;case "ollama":return new re({baseUrl:e.baseUrl});default:return null}}};});var mt=C(()=>{Q();});var ft={};xe(ft,{runVerify:()=>sn});function S(n,e){let t=n.padEnd(13);console.log(`${v("[ir]")} ${t}${e}`);}function rn(n){if(n instanceof U)return {label:"CAP_EXCEEDED",hint:"Monthly cap reached. Buy a top-up at https://inference-relay.com/dashboard/billing",code:1};if(n instanceof F)return {label:"ALL_PROVIDERS_FAILED",hint:`Fallback chain exhausted: ${n.fallbackChain.join(" \u2192 ")}`,code:1};if(!(n instanceof Error))return {label:"FAILED",hint:String(n).slice(0,120),code:1};let e=n.message.toLowerCase(),t=n.name.toLowerCase();return e.includes("keychain_access_denied")||e.includes("keychain access denied")?{label:"KEYCHAIN_DENIED",hint:'macOS denied keychain access. Re-run and click "Always Allow" on the prompt.',code:1}:e.includes("rate limit")||e.includes("429")||t.includes("ratelimit")?{label:"RATE_LIMITED",hint:"Claude subscription is currently rate-limited. Wait a minute and re-run.",code:1}:e.includes("auth")||e.includes("401")||e.includes("403")||e.includes("unauthorized")||e.includes("forbidden")?{label:"AUTH_FAILED",hint:"Claude CLI OAuth token rejected. Run `claude` to refresh, then re-run verify.",code:1}:e.includes("timeout")||e.includes("timed out")||e.includes("aborted")||e.includes("etimedout")||e.includes("econnrefused")||e.includes("econnreset")||t==="aborterror"||t==="timeouterror"?{label:"TIMEOUT",hint:`No response within ${gt/1e3}s. Network issue, hung CLI, or keychain prompt waiting for input. Try \`curl -I api.anthropic.com\` to test connectivity.`,code:1}:e.includes("empty response")||e.includes("returned empty")?{label:"EMPTY_RESPONSE",hint:"CLI returned an empty body \u2014 possible truncation, model error, or stale CLI version.",code:1}:{label:"FAILED",hint:n.message.slice(0,120),code:1}}function ht(n){if(n.usageCap!==null&&n.usageCap!==void 0){let e=n.usageThisMonth??0,t=n.usageCap;if(t===0)console.log(v(` Usage: ${e.toLocaleString()} (unmetered)`));else {let r=Math.round(e/t*1e3)/10;console.log(v(` Usage: ${e.toLocaleString()} / ${t.toLocaleString()} (${r}%)`));}}}async function sn(n=process.argv.slice(2),e=process.env){let t=n.includes("--credentials-only"),r=e.IR_LICENSE_KEY;if(!r)return console.error(Y("[ir] IR_LICENSE_KEY environment variable is not set.")),console.error(" Get a key at https://inference-relay.com/pricing"),console.error(" Then: export IR_LICENSE_KEY=ir_live_xxxx"),2;if(!/^ir_(live|test)_[a-f0-9]{32}$/.test(r))return console.error(Y("[ir] IR_LICENSE_KEY does not look like a valid key.")),console.error(" Expected format: ir_live_<32 hex chars>"),console.error(` Got: ${r.slice(0,8)}... (${r.length} chars)`),2;let s;try{s=await le(r);}catch(E){return S("IDENTITY:",Y("FAILED")),console.error(` ${E.message||"unknown error"}`),1}if(!s.valid)return S("IDENTITY:",Y("REJECTED")),s.error&&console.error(` ${s.error}`),1;S("IDENTITY:",G("VALIDATED"));let a=(s.tier??"unknown").toUpperCase();S("TIER:",G(a));let i;try{i=await N();}catch{i=null;}if(!i||!i.available)return S("RELAY:",ue("INACTIVE")),console.log(v(" Claude CLI not detected. The relay will fall back")),console.log(v(" to direct API providers using your API keys.")),console.log(v(" For zero-cost routing, install Claude Code:")),console.log(v(" npm install -g @anthropic-ai/claude-code")),1;if(!i.authenticated)return S("RELAY:",ue("CLI_UNAUTHED")),console.log(v(" Claude CLI is installed but not authenticated.")),console.log(v(" Run `claude` once to sign in, then re-run verify.")),1;if(i.versionWarning&&console.log(ue(` Warning: ${i.versionWarning}`)),t)return S("RELAY:",G("READY")),console.log(v(" Credentials present. Round-trip skipped (--credentials-only).")),i.cliVersion&&console.log(v(` Claude CLI: v${i.cliVersion}`)),i.subscriptionType&&i.subscriptionType!=="unknown"&&console.log(v(` Tier: ${i.subscriptionType}`)),ht(s),0;let l=new ce({licenseKey:r,providers:[{type:"claude-cli",priority:1}],fallback:false,telemetry:false}),o=new AbortController,p=setTimeout(()=>o.abort(),gt),c=Date.now(),d;try{d=await l.messages.create(nn,{signal:o.signal});}catch(E){clearTimeout(p),l.dispose();let{label:u,hint:y}=rn(E);return S("RELAY:",Y(`DEGRADED \u2014 ${u}`)),console.log(v(` ${y}`)),i.cliVersion&&console.log(v(` Claude CLI: v${i.cliVersion}`)),1}clearTimeout(p),l.dispose();let h=Date.now()-c;return d.fallbackChain?.[0]?.startsWith("claude-cli:success")?(S("RELAY:",G("ACTIVE")),console.log(v(` Round-trip: ${h}ms via ${d.provider}`)),console.log(v(` Model echo: ${d.model}`)),console.log(v(` Tokens: ${d.usage.input_tokens} in / ${d.usage.output_tokens} out`)),i.cliVersion&&console.log(v(` Claude CLI: v${i.cliVersion}`)),console.log(v(` Multimodal: ${G("\u2713")} via claude-cli (subscription)`)),i.subscriptionType&&i.subscriptionType!=="unknown"&&console.log(v(` Tier: ${i.subscriptionType}`)),ht(s),0):(S("RELAY:",ue("UNEXPECTED")),console.log(v(` Native Gateway did not handle the call. Chain: ${d.fallbackChain?.join(" \u2192 ")}`)),1)}var tn,de,G,Y,ue,v,gt,nn,yt=C(()=>{pt();Ie();me();mt();tn=process.stdout.isTTY===true,de=(n,e)=>tn?`\x1B[${n}m${e}\x1B[0m`:e,G=n=>de("32",n),Y=n=>de("31",n),ue=n=>de("33",n),v=n=>de("2",n);gt=15e3,nn={model:"claude-haiku-4-5",max_tokens:1,messages:[{role:"user",content:"Reply with exactly the single character k and nothing else."}]};});var _t={verify:async()=>{let{runVerify:n}=await Promise.resolve().then(()=>(yt(),ft));return n()}};function Et(){console.error("Usage: inference-relay <command>"),console.error(""),console.error("Commands:"),console.error(" verify Smoke-test your installation (license + relay availability)"),console.error(""),console.error("Docs: https://inference-relay.com/docs");}var M=process.argv[2];(!M||M==="--help"||M==="-h")&&(Et(),process.exit(M?0:2));M in _t||(console.error(`Unknown command: ${M}`),console.error(""),Et(),process.exit(1));_t[M]().then(n=>process.exit(n)).catch(n=>{console.error(`[ir] failed to run command "${M}":`),console.error(n),process.exit(99);});
package/dist/index.cjs CHANGED
@@ -7,10 +7,10 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
7
7
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
8
8
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
9
9
  UQIDAQAB
10
- -----END PUBLIC KEY-----`,pe={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>"},M=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(me,"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:pe,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:pe,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Ze=new M;function ke(){Ze.clearCache();}function et(){return pe}function tt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}var at=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function ge(n){return path.join(os.homedir(),".inference-relay","gateway",n)}function Te(n){return path.join(ge(n),"bundle.js")}function xe(n){return path.join(ge(n),"meta.json")}var b=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},F=new Map,B=class{static async load(e,t,r=at){let s=`${t}:${e.slice(-8)}`;if(F.has(s))return F.get(s);try{let p=await this.tryLoadFromDisk(t);if(p)return F.set(s,p),p}catch{}let{bytes:i,sha256:a,signature:o,libraryVersion:l}=await this.fetchFromAuthority(e,t,r);if(crypto$1.createHash("sha256").update(i).digest("hex")!==a)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(o,l,a);try{let p=ge(t);fs.mkdirSync(p,{recursive:!0}),fs.writeFileSync(Te(t),i),fs.writeFileSync(xe(t),JSON.stringify({sha256:a,signature:o,libraryVersion:l}));}catch{}let c=this.loadIntoVm(i.toString("utf-8"));return F.set(s,c),c}static async loadFromDisk(e){if(!fs.existsSync(e))throw new b(`[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=Te(e),r=xe(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){let s,i=[0,1e3,4e3],a;for(let c of i){c>0&&await new Promise(p=>setTimeout(p,c));try{let p=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(p.status===401||p.status===403)throw new b("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(p.status>=500&&p.status<600){a=new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");continue}if(!p.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");s=await p.json(),a=null;break}catch(p){if(p instanceof b&&p.code==="LICENSE_REJECTED")throw p;a=p;}}if(a||!s)throw a instanceof b?a:new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)","GATEWAY_FETCH_FAILED",a);let o;try{o=await fetch(s.bundleUrl);}catch(c){throw new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)","GATEWAY_FETCH_FAILED",c)}if(!o.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${o.status})`,"GATEWAY_FETCH_FAILED");let l=await o.arrayBuffer();return {bytes:Buffer.from(l),sha256:s.sha256,signature:s.signature,libraryVersion:s.libraryVersion,bundleVersion:s.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(me,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof b?s:new b("[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 b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof b?t:new b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){F.clear();}};var pt="1.4.2",te=class extends R{type="claude-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.licenseKey=e;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await B.load(this.licenseKey,pt)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof b?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(ee(),Me));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());}};var G=[{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}}],K=Object.fromEntries(G.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));K["claude-sonnet-4"]="claude-sonnet-4-20250514";K["claude-opus-4"]="claude-opus-4-20250514";K["claude-haiku-4"]="claude-haiku-4-5-20251001";function fe(n){return K[n]||n}function mt(n){return G.find(e=>e.canonical===n)}function re(n){return G.find(e=>e.canonical===n)?.provider}function ht(n){return G.filter(e=>e.provider===n)}var yt="https://api.anthropic.com/v1/messages",gt="2023-06-01",be={"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 De(n){if(be[n])return be[n];for(let[e,t]of Object.entries(be))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var V=class extends R{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(/\/$/,"")||yt,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]=De(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,p={},y=["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 m of y){let _=i.headers.get(m);_&&(p[m]=_);}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(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("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 p=o.split(`
10
+ -----END PUBLIC KEY-----`,pe={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>"},M=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(me,"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:pe,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:pe,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Ze=new M;function ke(){Ze.clearCache();}function et(){return pe}function tt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}var at=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function ge(n){return path.join(os.homedir(),".inference-relay","gateway",n)}function Te(n){return path.join(ge(n),"bundle.js")}function xe(n){return path.join(ge(n),"meta.json")}var b=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},F=new Map,B=class{static async load(e,t,r=at){let s=`${t}:${e.slice(-8)}`;if(F.has(s))return F.get(s);try{let p=await this.tryLoadFromDisk(t);if(p)return F.set(s,p),p}catch{}let{bytes:i,sha256:a,signature:o,libraryVersion:l}=await this.fetchFromAuthority(e,t,r);if(crypto$1.createHash("sha256").update(i).digest("hex")!==a)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(o,l,a);try{let p=ge(t);fs.mkdirSync(p,{recursive:!0}),fs.writeFileSync(Te(t),i),fs.writeFileSync(xe(t),JSON.stringify({sha256:a,signature:o,libraryVersion:l}));}catch{}let c=this.loadIntoVm(i.toString("utf-8"));return F.set(s,c),c}static async loadFromDisk(e){if(!fs.existsSync(e))throw new b(`[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=Te(e),r=xe(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){let s,i=[0,1e3,4e3],a;for(let c of i){c>0&&await new Promise(p=>setTimeout(p,c));try{let p=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(p.status===401||p.status===403)throw new b("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(p.status>=500&&p.status<600){a=new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");continue}if(!p.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");s=await p.json(),a=null;break}catch(p){if(p instanceof b&&p.code==="LICENSE_REJECTED")throw p;a=p;}}if(a||!s)throw a instanceof b?a:new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)","GATEWAY_FETCH_FAILED",a);let o;try{o=await fetch(s.bundleUrl);}catch(c){throw new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)","GATEWAY_FETCH_FAILED",c)}if(!o.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${o.status})`,"GATEWAY_FETCH_FAILED");let l=await o.arrayBuffer();return {bytes:Buffer.from(l),sha256:s.sha256,signature:s.signature,libraryVersion:s.libraryVersion,bundleVersion:s.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(me,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof b?s:new b("[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 b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof b?t:new b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){F.clear();}};var pt="1.5.1",te=class extends R{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.licenseKey=e;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await B.load(this.licenseKey,pt)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof b?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(ee(),Me));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());}};var G=[{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}}],K=Object.fromEntries(G.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));K["claude-sonnet-4"]="claude-sonnet-4-20250514";K["claude-opus-4"]="claude-opus-4-20250514";K["claude-haiku-4"]="claude-haiku-4-5-20251001";function fe(n){return K[n]||n}function mt(n){return G.find(e=>e.canonical===n)}function re(n){return G.find(e=>e.canonical===n)?.provider}function ht(n){return G.filter(e=>e.provider===n)}var yt="https://api.anthropic.com/v1/messages",gt="2023-06-01",be={"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 De(n){if(be[n])return be[n];for(let[e,t]of Object.entries(be))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var V=class extends R{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(/\/$/,"")||yt,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]=De(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,p={},y=["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 m of y){let _=i.headers.get(m);_&&(p[m]=_);}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(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("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 p=o.split(`
11
11
  `);o=p.pop()||"";let y=null;for(let m of p)if(m.startsWith("event: "))y=m.slice(7).trim();else if(m.startsWith("data: ")){let _=m.slice(6);if(y&&_)try{let u=JSON.parse(_);u.type==="message_stop"&&(l=!0),yield u;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}y=null;}else m.trim()===""&&(y=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]=De(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":gt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:fe(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 ft="https://api.openai.com/v1/chat/completions",Oe=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Ee={"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 Ne(n){if(Ee[n])return Ee[n];for(let[e,t]of Object.entries(Ee))if(n.startsWith(e))return t;return [2.5,10]}function bt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Et(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=bt(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 Ue(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 W=class extends R{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(/\/$/,"")||ft;}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 h of l.message.tool_calls)d.push({type:"tool_use",id:h.id,name:h.function?.name,input:h.function?.arguments?JSON.parse(h.function.arguments):{}});let c=a.usage?.prompt_tokens||0,p=a.usage?.completion_tokens||0,[y,m]=Ne(a.model||e.model),_=(c*y+p*m)/1e6,u={},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 h of f){let g=i.headers.get(h);g&&(u[h]=g);}return {content:d,model:a.model||e.model,usage:{input_tokens:c,output_tokens:p},stop_reason:Ue(l?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(u).length>0?u: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,p,y;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:m,value:_}=await i.read();if(m)break;l+=a.decode(_,{stream:!0});let u=l.split(`
12
12
  `);l=u.pop()||"";for(let f of u){if(!f.startsWith("data: "))continue;let h=f.slice(6).trim();if(h==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:y||"end_turn"},usage:p||{}},yield {type:"message_stop"},c=!0;return}try{let g=JSON.parse(h);g.usage&&(p={input_tokens:g.usage.prompt_tokens||0,output_tokens:g.usage.completion_tokens||0});let C=g.choices?.[0];if(!C)continue;let E=C.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}}),C.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),y=Ue(C.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:y||"end_turn"},usage:p||{}},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]=Ne(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(!Oe.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 (${Oe.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=Et(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 _t="http://localhost:11434";function vt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ct(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:vt(r.content)});return t}var Y=class extends R{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(/\/$/,"")||_t;}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:p,value:y}=await i.read();if(p)break;l+=a.decode(y,{stream:!0});let m=l.split(`
13
- `);l=m.pop()||"";for(let _ of m){let u=_.trim();if(u)try{let f=JSON.parse(u);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=Ct(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 $=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 We=200;function ne(n,e){if(e instanceof b)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,We)||"unknown"}`}var Fe=new Set(["anthropic-api","openai-api","ollama"]),q=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}};function Be(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 _e(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.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")?"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 He(n){return [...n].sort((e,t)=>e.priority-t.priority)}var j=class n{healthMap=new Map;engineEvents=new $;static UNHEALTHY_TTL_MS=300*1e3;getHealthStatus(e){let t=this.healthMap.get(e);return t?t.status==="unhealthy"&&Date.now()-t.updatedAt>=n.UNHEALTHY_TTL_MS?(this.healthMap.delete(e),"healthy"):t.status:"healthy"}markUnhealthy(e,t){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now()});}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=He(t),i=[],a=Be(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 y=re(e.model);if(y&&y!==c&&Fe.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}try{let m=await d.execute(e,{signal:r?.signal});return this.markHealthy(c),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:crypto$1.randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd??0}],provider:c,model:m.model,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd,durationMs:m.durationMs??Date.now()-l,stopReason:m.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...m,fallbackChain:i}}catch(m){if(m?.name==="AbortError"||r?.signal?.aborted)throw m;switch(_e(m)){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"),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(ne(c,m));break;default:i.push(ne(c,m));break}}}throw new q(i)}async stream(e,t,r){let s=crypto$1.randomUUID(),i=He(t),a=Be(e),o=Date.now(),l=[],d=null,c=null;for(let h of i){let g=h.type;if(this.getHealthStatus(g)==="unhealthy"){l.push(`${g}:skipped:unhealthy`);continue}if(a&&!h.supportsMultimodal){l.push(`${g}:skipped:no_multimodal`);continue}if(!h.supportsStreaming){l.push(`${g}:skipped:no_streaming`);continue}let C=re(e.model);if(C&&C!==g&&Fe.has(g)){l.push(`${g}:skipped:wrong_provider`);continue}try{c=await h.streamRaw(e,{signal:r?.signal}),d=h,l.push(`${g}:success`);break}catch(E){if(E?.name==="AbortError"||r?.signal?.aborted)throw E;switch(_e(E)){case "rate_limited":h.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"),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(ne(g,E));break;default:l.push(ne(g,E));break}}}if(!d||!c)throw new q(l);let y=this,m=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*u(){let h=d,g=c[Symbol.asyncIterator](),C={role:"assistant",content:[]},E={segments:[]},I=Ge(h.type);E.segments.push(I);let Re=0,z=null,X=false,de=m,O="",N="";for(y.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:h.type});;)try{for(;;){let A=await g.next();if(A.done)break;let T=A.value,k=Pt(T,Re,C,X,z);if(k.action==="suppress"){"coalesceMode"in k&&(z=k.coalesceMode),k.clearedJustFailedOver&&(X=!1);continue}k.coalesceModeCleared&&(z=null),k.clearedJustFailedOver&&(X=!1);let v=k.event;if(St(C,v),v.type==="message_start"){if(E.segments.length>1)continue;O=v.message?.model||O,v.message?.usage?.input_tokens!=null&&(I.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(N=v.delta.stop_reason),v.usage)){Rt(I,h.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(C.content.length===0&&I.outputTokens===0)throw new Error("stream ended without producing any content");y.markHealthy(h.type),y.emitEngineEvent({kind:"segment_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:h.type,usage:{...I}});let S=Ke(E.segments);yield {type:"message_delta",delta:{stop_reason:N||"end_turn"},usage:S},yield {type:"message_stop"},y.emitEngineEvent({kind:"stream_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),stitched:E.segments.length>1,segments:E.segments.map(A=>({...A})),provider:E.segments.map(A=>A.provider).join("+"),model:O,inputTokens:S.input_tokens,outputTokens:S.output_tokens,costUsd:E.segments.reduce((A,T)=>A+T.costUsd,0),userCostUsd:E.segments.reduce((A,T)=>A+T.userCostUsd,0),durationMs:Date.now()-o,stopReason:N||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(S){if(S?.name==="AbortError"||r?.signal?.aborted)throw S;let A=_e(S);try{await g.return?.();}catch{}if(y.markUnhealthy(h.type,String(S)),y.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:h.type,bytesBuffered:Ve(C),errorClass:A,retriesLeft:de}),l.push(`${h.type}:partial(${Ve(C)}b)`),de<=0)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;let T=kt(C.content),k=[...e.messages,{role:"assistant",content:T}],v=null,Q=null,Se=h;for(;;){let w=y.nextHealthyProvider(i,Se,a,_);if(!w)break;Se=w,_.add(w);let je={...e,messages:k,...w.type!=="anthropic-api"&&w.type!=="claude-cli"?{system:wt(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{Q=await w.streamRaw(je,{signal:r?.signal}),v=w;break}catch(Pe){y.markUnhealthy(w.type,String(Pe)),l.push(`${w.type}:failed_connect:${String(Pe).slice(0,We)}`);}}if(!v||!Q)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;l.push(`${v.type}:stitched`),y.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:h.type,to:v.type}),Re=It(C)+1,de--,h=v,g=Q[Symbol.asyncIterator](),X=true,z=null,I=Ge(h.type),E.segments.push(I),y.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:h.type});}}let f=u();return r?.licenseState==="SEC_DEGRADED"&&(f=Tt(f)),L(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=Ke(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 Ge(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Rt(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 Ke(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function St(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 Pt(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 kt(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 wt(n,e){return n?`${n}
13
+ `);l=m.pop()||"";for(let _ of m){let u=_.trim();if(u)try{let f=JSON.parse(u);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=Ct(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 $=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 We=200;function ne(n,e){if(e instanceof b)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,We)||"unknown"}`}var Fe=new Set(["anthropic-api","openai-api","ollama"]),q=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}};function Be(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 _e(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.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_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 He(n){return [...n].sort((e,t)=>e.priority-t.priority)}var j=class n{healthMap=new Map;engineEvents=new $;static UNHEALTHY_TTL_MS=300*1e3;getHealthStatus(e){let t=this.healthMap.get(e);return t?t.status==="unhealthy"&&Date.now()-t.updatedAt>=n.UNHEALTHY_TTL_MS?(this.healthMap.delete(e),"healthy"):t.status:"healthy"}markUnhealthy(e,t){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now()});}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=He(t),i=[],a=Be(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 y=re(e.model);if(y&&y!==c&&Fe.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}try{let m=await d.execute(e,{signal:r?.signal});return this.markHealthy(c),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:crypto$1.randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd??0}],provider:c,model:m.model,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd,durationMs:m.durationMs??Date.now()-l,stopReason:m.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...m,fallbackChain:i}}catch(m){if(m?.name==="AbortError"||r?.signal?.aborted)throw m;switch(_e(m)){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"),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(ne(c,m));break;default:i.push(ne(c,m));break}}}throw new q(i)}async stream(e,t,r){let s=crypto$1.randomUUID(),i=He(t),a=Be(e),o=Date.now(),l=[],d=null,c=null;for(let h of i){let g=h.type;if(this.getHealthStatus(g)==="unhealthy"){l.push(`${g}:skipped:unhealthy`);continue}if(a&&!h.supportsMultimodal){l.push(`${g}:skipped:no_multimodal`);continue}if(!h.supportsStreaming){l.push(`${g}:skipped:no_streaming`);continue}let C=re(e.model);if(C&&C!==g&&Fe.has(g)){l.push(`${g}:skipped:wrong_provider`);continue}try{c=await h.streamRaw(e,{signal:r?.signal}),d=h,l.push(`${g}:success`);break}catch(E){if(E?.name==="AbortError"||r?.signal?.aborted)throw E;switch(_e(E)){case "rate_limited":h.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"),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(ne(g,E));break;default:l.push(ne(g,E));break}}}if(!d||!c)throw new q(l);let y=this,m=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*u(){let h=d,g=c[Symbol.asyncIterator](),C={role:"assistant",content:[]},E={segments:[]},I=Ge(h.type);E.segments.push(I);let Re=0,z=null,X=false,de=m,O="",N="";for(y.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:h.type});;)try{for(;;){let A=await g.next();if(A.done)break;let T=A.value,k=Pt(T,Re,C,X,z);if(k.action==="suppress"){"coalesceMode"in k&&(z=k.coalesceMode),k.clearedJustFailedOver&&(X=!1);continue}k.coalesceModeCleared&&(z=null),k.clearedJustFailedOver&&(X=!1);let v=k.event;if(St(C,v),v.type==="message_start"){if(E.segments.length>1)continue;O=v.message?.model||O,v.message?.usage?.input_tokens!=null&&(I.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(N=v.delta.stop_reason),v.usage)){Rt(I,h.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(C.content.length===0&&I.outputTokens===0)throw new Error("stream ended without producing any content");y.markHealthy(h.type),y.emitEngineEvent({kind:"segment_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:h.type,usage:{...I}});let S=Ke(E.segments);yield {type:"message_delta",delta:{stop_reason:N||"end_turn"},usage:S},yield {type:"message_stop"},y.emitEngineEvent({kind:"stream_complete",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),stitched:E.segments.length>1,segments:E.segments.map(A=>({...A})),provider:E.segments.map(A=>A.provider).join("+"),model:O,inputTokens:S.input_tokens,outputTokens:S.output_tokens,costUsd:E.segments.reduce((A,T)=>A+T.costUsd,0),userCostUsd:E.segments.reduce((A,T)=>A+T.userCostUsd,0),durationMs:Date.now()-o,stopReason:N||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(S){if(S?.name==="AbortError"||r?.signal?.aborted)throw S;let A=_e(S);try{await g.return?.();}catch{}if(y.markUnhealthy(h.type,String(S)),y.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:h.type,bytesBuffered:Ve(C),errorClass:A,retriesLeft:de}),l.push(`${h.type}:partial(${Ve(C)}b)`),de<=0)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;let T=kt(C.content),k=[...e.messages,{role:"assistant",content:T}],v=null,Q=null,Se=h;for(;;){let w=y.nextHealthyProvider(i,Se,a,_);if(!w)break;Se=w,_.add(w);let je={...e,messages:k,...w.type!=="anthropic-api"&&w.type!=="claude-cli"?{system:wt(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{Q=await w.streamRaw(je,{signal:r?.signal}),v=w;break}catch(Pe){y.markUnhealthy(w.type,String(Pe)),l.push(`${w.type}:failed_connect:${String(Pe).slice(0,We)}`);}}if(!v||!Q)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;l.push(`${v.type}:stitched`),y.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),from:h.type,to:v.type}),Re=It(C)+1,de--,h=v,g=Q[Symbol.asyncIterator](),X=true,z=null,I=Ge(h.type),E.segments.push(I),y.emitEngineEvent({kind:"segment_start",callId:s,id:crypto$1.randomUUID(),ts:Date.now(),provider:h.type});}}let f=u();return r?.licenseState==="SEC_DEGRADED"&&(f=Tt(f)),L(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=Ke(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 Ge(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Rt(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 Ke(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function St(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 Pt(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 kt(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 wt(n,e){return n?`${n}
14
14
 
15
15
  ${e}`:e}function Ve(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 It(n){return Math.max(0,n.content.length-1)}async function*Tt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}ee();function se(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 ie(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var ve={"claude-opus-4":[15,75],"claude-sonnet-4":[3,15],"claude-haiku-4":[.8,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 ae(n){if(ve[n])return ve[n];for(let[e,t]of Object.entries(ve))if(n.startsWith(e))return t;return [3,15]}function oe(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]=ae(n.model),a=(t*s+r*i)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(a*1e4)/1e4,model:n.model,provider:""}}var D=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 xt="https://api.inference-relay.com",Lt="/v1/validate",Mt=1440*60*1e3,Dt=10080*60*1e3,Ot=`-----BEGIN PUBLIC KEY-----
16
16
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
package/dist/index.js CHANGED
@@ -7,10 +7,10 @@ kfynZEzOcLikoQALIxEjxRfi6g83wNJS+WBwAJQ68s7N9FHE3rkLzEqv3FJRP+ZR
7
7
  7lqwqIyuCLr9j9yc4XqF6VY9yooD2hyw/n1EVFejzjDgntWTqIkaCIXwh8lDzRrK
8
8
  Rxn07gcI6ea2Eym9sXh4xZLFudXfAT2DFsH/XboDUuMKAV1YHc1NsIGApesWe2M+
9
9
  UQIDAQAB
10
- -----END PUBLIC KEY-----`,pe={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>"},M=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(me,"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:pe,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:pe,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Ze=new M;function ke(){Ze.clearCache();}function et(){return pe}function tt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}var at=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function ge(n){return join(homedir(),".inference-relay","gateway",n)}function Te(n){return join(ge(n),"bundle.js")}function xe(n){return join(ge(n),"meta.json")}var b=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},F=new Map,B=class{static async load(e,t,r=at){let s=`${t}:${e.slice(-8)}`;if(F.has(s))return F.get(s);try{let p=await this.tryLoadFromDisk(t);if(p)return F.set(s,p),p}catch{}let{bytes:i,sha256:a,signature:o,libraryVersion:l}=await this.fetchFromAuthority(e,t,r);if(createHash("sha256").update(i).digest("hex")!==a)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(o,l,a);try{let p=ge(t);mkdirSync(p,{recursive:!0}),writeFileSync(Te(t),i),writeFileSync(xe(t),JSON.stringify({sha256:a,signature:o,libraryVersion:l}));}catch{}let c=this.loadIntoVm(i.toString("utf-8"));return F.set(s,c),c}static async loadFromDisk(e){if(!existsSync(e))throw new b(`[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=Te(e),r=xe(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){let s,i=[0,1e3,4e3],a;for(let c of i){c>0&&await new Promise(p=>setTimeout(p,c));try{let p=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(p.status===401||p.status===403)throw new b("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(p.status>=500&&p.status<600){a=new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");continue}if(!p.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");s=await p.json(),a=null;break}catch(p){if(p instanceof b&&p.code==="LICENSE_REJECTED")throw p;a=p;}}if(a||!s)throw a instanceof b?a:new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)","GATEWAY_FETCH_FAILED",a);let o;try{o=await fetch(s.bundleUrl);}catch(c){throw new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)","GATEWAY_FETCH_FAILED",c)}if(!o.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${o.status})`,"GATEWAY_FETCH_FAILED");let l=await o.arrayBuffer();return {bytes:Buffer.from(l),sha256:s.sha256,signature:s.signature,libraryVersion:s.libraryVersion,bundleVersion:s.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(me,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof b?s:new b("[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 b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof b?t:new b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){F.clear();}};var pt="1.4.2",te=class extends R{type="claude-cli";supportsStreaming=true;supportsMultimodal=false;platformRequirement="desktop";licenseKey;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.licenseKey=e;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await B.load(this.licenseKey,pt)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof b?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(ee(),Me));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());}};var G=[{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}}],K=Object.fromEntries(G.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));K["claude-sonnet-4"]="claude-sonnet-4-20250514";K["claude-opus-4"]="claude-opus-4-20250514";K["claude-haiku-4"]="claude-haiku-4-5-20251001";function fe(n){return K[n]||n}function mt(n){return G.find(e=>e.canonical===n)}function re(n){return G.find(e=>e.canonical===n)?.provider}function ht(n){return G.filter(e=>e.provider===n)}var yt="https://api.anthropic.com/v1/messages",gt="2023-06-01",be={"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 De(n){if(be[n])return be[n];for(let[e,t]of Object.entries(be))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var V=class extends R{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(/\/$/,"")||yt,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]=De(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,p={},y=["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 m of y){let _=i.headers.get(m);_&&(p[m]=_);}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(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("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 p=o.split(`
10
+ -----END PUBLIC KEY-----`,pe={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>"},M=class{verificationFailures=0;cachedManifest=null;currentSecurityState="SEC_NOMINAL";async verifyManifest(e){try{let{compactVerify:t,importSPKI:r}=await import('jose'),s=await r(me,"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:pe,securityState:"SEC_DEGRADED"}}return this.cachedManifest?(this.currentSecurityState="SEC_CACHE",{manifest:this.cachedManifest,securityState:"SEC_CACHE"}):(this.currentSecurityState="SEC_RECOVERY",{manifest:pe,securityState:"SEC_RECOVERY"})}}getSecurityState(){return this.currentSecurityState}clearCache(){this.cachedManifest=null,this.verificationFailures=0,this.currentSecurityState="SEC_NOMINAL";}},Ze=new M;function ke(){Ze.clearCache();}function et(){return pe}function tt(n,e){return e.split(".").reduce((t,r)=>{if(!(r==="__proto__"||r==="constructor"||r==="prototype"))return t&&t[r]},n)}var at=process.env.IR_GATEWAY_URL||"https://api.inference-relay.com";function ge(n){return join(homedir(),".inference-relay","gateway",n)}function Te(n){return join(ge(n),"bundle.js")}function xe(n){return join(ge(n),"meta.json")}var b=class extends Error{constructor(t,r,s){super(t);this.code=r;this.cause=s;this.name="GatewayLoaderError";}code;cause},F=new Map,B=class{static async load(e,t,r=at){let s=`${t}:${e.slice(-8)}`;if(F.has(s))return F.get(s);try{let p=await this.tryLoadFromDisk(t);if(p)return F.set(s,p),p}catch{}let{bytes:i,sha256:a,signature:o,libraryVersion:l}=await this.fetchFromAuthority(e,t,r);if(createHash("sha256").update(i).digest("hex")!==a)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: HASH_MISMATCH)","GATEWAY_VERIFICATION_FAILED");await this.verifySignature(o,l,a);try{let p=ge(t);mkdirSync(p,{recursive:!0}),writeFileSync(Te(t),i),writeFileSync(xe(t),JSON.stringify({sha256:a,signature:o,libraryVersion:l}));}catch{}let c=this.loadIntoVm(i.toString("utf-8"));return F.set(s,c),c}static async loadFromDisk(e){if(!existsSync(e))throw new b(`[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=Te(e),r=xe(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){let s,i=[0,1e3,4e3],a;for(let c of i){c>0&&await new Promise(p=>setTimeout(p,c));try{let p=await fetch(`${r}/v1/gateway/fetch`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({libraryVersion:t})});if(p.status===401||p.status===403)throw new b("[ir-system]: LICENSE_REJECTED (REASON: GATEWAY_FETCH_UNAUTHORIZED)","LICENSE_REJECTED");if(p.status>=500&&p.status<600){a=new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");continue}if(!p.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: HTTP_${p.status})`,"GATEWAY_FETCH_FAILED");s=await p.json(),a=null;break}catch(p){if(p instanceof b&&p.code==="LICENSE_REJECTED")throw p;a=p;}}if(a||!s)throw a instanceof b?a:new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: NETWORK_ERROR)","GATEWAY_FETCH_FAILED",a);let o;try{o=await fetch(s.bundleUrl);}catch(c){throw new b("[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_DOWNLOAD_FAILED)","GATEWAY_FETCH_FAILED",c)}if(!o.ok)throw new b(`[ir-system]: GATEWAY_FETCH_FAILED (REASON: BUNDLE_HTTP_${o.status})`,"GATEWAY_FETCH_FAILED");let l=await o.arrayBuffer();return {bytes:Buffer.from(l),sha256:s.sha256,signature:s.signature,libraryVersion:s.libraryVersion,bundleVersion:s.bundleVersion}}static async verifySignature(e,t,r){try{let{compactVerify:s,importSPKI:i}=await import('jose'),a=await i(me,"RS256"),{payload:o}=await s(e,a),l=JSON.parse(new TextDecoder().decode(o));if(l.purpose!=="gateway-bundle")throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: PURPOSE_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.libraryVersion!==t)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: LIBRARY_VERSION_MISMATCH)","GATEWAY_VERIFICATION_FAILED");if(l.sha256!==r)throw new b("[ir-system]: GATEWAY_VERIFICATION_FAILED (REASON: SHA256_MISMATCH)","GATEWAY_VERIFICATION_FAILED")}catch(s){throw s instanceof b?s:new b("[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 b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: MISSING_CLAUDE_CLI_EXPORT)","GATEWAY_LOAD_FAILED");return o}catch(t){throw t instanceof b?t:new b("[ir-system]: GATEWAY_LOAD_FAILED (REASON: VM_EXECUTION_ERROR)","GATEWAY_LOAD_FAILED",t)}}static clearCache(){F.clear();}};var pt="1.5.1",te=class extends R{type="claude-cli";supportsStreaming=true;supportsMultimodal=true;platformRequirement="desktop";licenseKey;loadedProvider=null;loadingPromise=null;health={status:"healthy",lastCheckAt:Date.now(),errorCount:0};constructor(e){super(),this.licenseKey=e;}async ensureLoaded(){return this.loadedProvider?this.loadedProvider:this.loadingPromise?this.loadingPromise:(this.loadingPromise=(async()=>{try{let t=(await B.load(this.licenseKey,pt)).ClaudeCLIProvider,r=new t;return this.loadedProvider=r,r}catch(e){throw this.loadingPromise=null,this.health.status="unhealthy",this.health.errorCount++,e instanceof b?this.health.lastError=e.message:e instanceof Error&&(this.health.lastError=e.message),e}})(),this.loadingPromise)}async probe(){let{detectCLI:e}=await Promise.resolve().then(()=>(ee(),Me));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());}};var G=[{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}}],K=Object.fromEntries(G.filter(n=>n.canonical!==n.apiId).map(n=>[n.canonical,n.apiId]));K["claude-sonnet-4"]="claude-sonnet-4-20250514";K["claude-opus-4"]="claude-opus-4-20250514";K["claude-haiku-4"]="claude-haiku-4-5-20251001";function fe(n){return K[n]||n}function mt(n){return G.find(e=>e.canonical===n)}function re(n){return G.find(e=>e.canonical===n)?.provider}function ht(n){return G.filter(e=>e.provider===n)}var yt="https://api.anthropic.com/v1/messages",gt="2023-06-01",be={"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 De(n){if(be[n])return be[n];for(let[e,t]of Object.entries(be))if(n.startsWith(e.split("-20")[0]))return t;return [3,15]}var V=class extends R{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(/\/$/,"")||yt,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]=De(a.model||e.model),c=((a.usage?.input_tokens||0)*l+(a.usage?.output_tokens||0)*d)/1e6,p={},y=["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 m of y){let _=i.headers.get(m);_&&(p[m]=_);}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(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("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 p=o.split(`
11
11
  `);o=p.pop()||"";let y=null;for(let m of p)if(m.startsWith("event: "))y=m.slice(7).trim();else if(m.startsWith("data: ")){let _=m.slice(6);if(y&&_)try{let u=JSON.parse(_);u.type==="message_stop"&&(l=!0),yield u;}catch{console.warn("[inference-relay] Skipped malformed SSE data:",_.substring(0,100));}y=null;}else m.trim()===""&&(y=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]=De(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":gt};return this.dangerousDirectBrowserAccess&&(e["anthropic-dangerous-direct-browser-access"]="true"),e}buildRequestBody(e,t){let r={model:fe(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 ft="https://api.openai.com/v1/chat/completions",Oe=["gpt-","o1","o3","o4","chatgpt-","text-","davinci","babbage","ft:"],Ee={"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 Ne(n){if(Ee[n])return Ee[n];for(let[e,t]of Object.entries(Ee))if(n.startsWith(e))return t;return [2.5,10]}function bt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Et(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n){let s=bt(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 Ue(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 W=class extends R{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(/\/$/,"")||ft;}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 h of l.message.tool_calls)d.push({type:"tool_use",id:h.id,name:h.function?.name,input:h.function?.arguments?JSON.parse(h.function.arguments):{}});let c=a.usage?.prompt_tokens||0,p=a.usage?.completion_tokens||0,[y,m]=Ne(a.model||e.model),_=(c*y+p*m)/1e6,u={},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 h of f){let g=i.headers.get(h);g&&(u[h]=g);}return {content:d,model:a.model||e.model,usage:{input_tokens:c,output_tokens:p},stop_reason:Ue(l?.finish_reason),provider:"openai-api",costUsd:Math.round(_*1e6)/1e6,durationMs:o,fallbackChain:["openai-api:success"],headers:Object.keys(u).length>0?u: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,p,y;yield {type:"message_start",message:{model:o,usage:{input_tokens:0,output_tokens:0}}};try{for(;;){let{done:m,value:_}=await i.read();if(m)break;l+=a.decode(_,{stream:!0});let u=l.split(`
12
12
  `);l=u.pop()||"";for(let f of u){if(!f.startsWith("data: "))continue;let h=f.slice(6).trim();if(h==="[DONE]"){yield {type:"message_delta",delta:{stop_reason:y||"end_turn"},usage:p||{}},yield {type:"message_stop"},c=!0;return}try{let g=JSON.parse(h);g.usage&&(p={input_tokens:g.usage.prompt_tokens||0,output_tokens:g.usage.completion_tokens||0});let C=g.choices?.[0];if(!C)continue;let E=C.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}}),C.finish_reason&&(d&&(yield {type:"content_block_stop",index:0}),y=Ue(C.finish_reason));}catch{}}}c||(yield {type:"message_delta",delta:{stop_reason:y||"end_turn"},usage:p||{}},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]=Ne(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(!Oe.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 (${Oe.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=Et(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 _t="http://localhost:11434";function vt(n){return typeof n=="string"?n:n.filter(e=>e.type==="text"&&e.text).map(e=>e.text).join("")}function Ct(n,e){let t=[];e&&t.push({role:"system",content:e});for(let r of n)t.push({role:r.role,content:vt(r.content)});return t}var Y=class extends R{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(/\/$/,"")||_t;}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:p,value:y}=await i.read();if(p)break;l+=a.decode(y,{stream:!0});let m=l.split(`
13
- `);l=m.pop()||"";for(let _ of m){let u=_.trim();if(u)try{let f=JSON.parse(u);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=Ct(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 $=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 We=200;function ne(n,e){if(e instanceof b)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,We)||"unknown"}`}var Fe=new Set(["anthropic-api","openai-api","ollama"]),q=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}};function Be(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 _e(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.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")?"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 He(n){return [...n].sort((e,t)=>e.priority-t.priority)}var j=class n{healthMap=new Map;engineEvents=new $;static UNHEALTHY_TTL_MS=300*1e3;getHealthStatus(e){let t=this.healthMap.get(e);return t?t.status==="unhealthy"&&Date.now()-t.updatedAt>=n.UNHEALTHY_TTL_MS?(this.healthMap.delete(e),"healthy"):t.status:"healthy"}markUnhealthy(e,t){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now()});}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=He(t),i=[],a=Be(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 y=re(e.model);if(y&&y!==c&&Fe.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}try{let m=await d.execute(e,{signal:r?.signal});return this.markHealthy(c),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd??0}],provider:c,model:m.model,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd,durationMs:m.durationMs??Date.now()-l,stopReason:m.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...m,fallbackChain:i}}catch(m){if(m?.name==="AbortError"||r?.signal?.aborted)throw m;switch(_e(m)){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"),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(ne(c,m));break;default:i.push(ne(c,m));break}}}throw new q(i)}async stream(e,t,r){let s=randomUUID(),i=He(t),a=Be(e),o=Date.now(),l=[],d=null,c=null;for(let h of i){let g=h.type;if(this.getHealthStatus(g)==="unhealthy"){l.push(`${g}:skipped:unhealthy`);continue}if(a&&!h.supportsMultimodal){l.push(`${g}:skipped:no_multimodal`);continue}if(!h.supportsStreaming){l.push(`${g}:skipped:no_streaming`);continue}let C=re(e.model);if(C&&C!==g&&Fe.has(g)){l.push(`${g}:skipped:wrong_provider`);continue}try{c=await h.streamRaw(e,{signal:r?.signal}),d=h,l.push(`${g}:success`);break}catch(E){if(E?.name==="AbortError"||r?.signal?.aborted)throw E;switch(_e(E)){case "rate_limited":h.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"),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(ne(g,E));break;default:l.push(ne(g,E));break}}}if(!d||!c)throw new q(l);let y=this,m=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*u(){let h=d,g=c[Symbol.asyncIterator](),C={role:"assistant",content:[]},E={segments:[]},I=Ge(h.type);E.segments.push(I);let Re=0,z=null,X=false,de=m,O="",N="";for(y.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:h.type});;)try{for(;;){let A=await g.next();if(A.done)break;let T=A.value,k=Pt(T,Re,C,X,z);if(k.action==="suppress"){"coalesceMode"in k&&(z=k.coalesceMode),k.clearedJustFailedOver&&(X=!1);continue}k.coalesceModeCleared&&(z=null),k.clearedJustFailedOver&&(X=!1);let v=k.event;if(St(C,v),v.type==="message_start"){if(E.segments.length>1)continue;O=v.message?.model||O,v.message?.usage?.input_tokens!=null&&(I.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(N=v.delta.stop_reason),v.usage)){Rt(I,h.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(C.content.length===0&&I.outputTokens===0)throw new Error("stream ended without producing any content");y.markHealthy(h.type),y.emitEngineEvent({kind:"segment_complete",callId:s,id:randomUUID(),ts:Date.now(),provider:h.type,usage:{...I}});let S=Ke(E.segments);yield {type:"message_delta",delta:{stop_reason:N||"end_turn"},usage:S},yield {type:"message_stop"},y.emitEngineEvent({kind:"stream_complete",callId:s,id:randomUUID(),ts:Date.now(),stitched:E.segments.length>1,segments:E.segments.map(A=>({...A})),provider:E.segments.map(A=>A.provider).join("+"),model:O,inputTokens:S.input_tokens,outputTokens:S.output_tokens,costUsd:E.segments.reduce((A,T)=>A+T.costUsd,0),userCostUsd:E.segments.reduce((A,T)=>A+T.userCostUsd,0),durationMs:Date.now()-o,stopReason:N||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(S){if(S?.name==="AbortError"||r?.signal?.aborted)throw S;let A=_e(S);try{await g.return?.();}catch{}if(y.markUnhealthy(h.type,String(S)),y.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:randomUUID(),ts:Date.now(),from:h.type,bytesBuffered:Ve(C),errorClass:A,retriesLeft:de}),l.push(`${h.type}:partial(${Ve(C)}b)`),de<=0)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;let T=kt(C.content),k=[...e.messages,{role:"assistant",content:T}],v=null,Q=null,Se=h;for(;;){let w=y.nextHealthyProvider(i,Se,a,_);if(!w)break;Se=w,_.add(w);let je={...e,messages:k,...w.type!=="anthropic-api"&&w.type!=="claude-cli"?{system:wt(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{Q=await w.streamRaw(je,{signal:r?.signal}),v=w;break}catch(Pe){y.markUnhealthy(w.type,String(Pe)),l.push(`${w.type}:failed_connect:${String(Pe).slice(0,We)}`);}}if(!v||!Q)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;l.push(`${v.type}:stitched`),y.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:randomUUID(),ts:Date.now(),from:h.type,to:v.type}),Re=It(C)+1,de--,h=v,g=Q[Symbol.asyncIterator](),X=true,z=null,I=Ge(h.type),E.segments.push(I),y.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:h.type});}}let f=u();return r?.licenseState==="SEC_DEGRADED"&&(f=Tt(f)),L(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=Ke(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 Ge(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Rt(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 Ke(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function St(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 Pt(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 kt(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 wt(n,e){return n?`${n}
13
+ `);l=m.pop()||"";for(let _ of m){let u=_.trim();if(u)try{let f=JSON.parse(u);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=Ct(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 $=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 We=200;function ne(n,e){if(e instanceof b)return `${n}:failed:${e.code}:${e.message}`;let t=e?.message;return `${n}:failed:${t?.slice(0,We)||"unknown"}`}var Fe=new Set(["anthropic-api","openai-api","ollama"]),q=class extends Error{code="ALL_PROVIDERS_FAILED";fallbackChain;constructor(e){super(`All providers failed. Chain: ${e.join(" \u2192 ")}`),this.name="RelayError",this.fallbackChain=e;}};function Be(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 _e(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.startsWith("openai_model_translation_required:")||t.startsWith("ollama_tools_not_supported:")||t.startsWith("multimodal_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 He(n){return [...n].sort((e,t)=>e.priority-t.priority)}var j=class n{healthMap=new Map;engineEvents=new $;static UNHEALTHY_TTL_MS=300*1e3;getHealthStatus(e){let t=this.healthMap.get(e);return t?t.status==="unhealthy"&&Date.now()-t.updatedAt>=n.UNHEALTHY_TTL_MS?(this.healthMap.delete(e),"healthy"):t.status:"healthy"}markUnhealthy(e,t){this.healthMap.set(e,{status:"unhealthy",lastError:t,updatedAt:Date.now()});}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=He(t),i=[],a=Be(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 y=re(e.model);if(y&&y!==c&&Fe.has(c)){i.push(`${c}:skipped:wrong_provider`);continue}try{let m=await d.execute(e,{signal:r?.signal});return this.markHealthy(c),i.push(`${c}:success`),this.emitEngineEvent({kind:"stream_complete",callId:o,id:randomUUID(),ts:Date.now(),stitched:!1,segments:[{provider:c,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd??0}],provider:c,model:m.model,inputTokens:m.usage.input_tokens,outputTokens:m.usage.output_tokens,costUsd:m.costUsd,userCostUsd:m.userCostUsd,durationMs:m.durationMs??Date.now()-l,stopReason:m.stop_reason,fallbackChain:i,rateLimitHit:!1,securityState:r?.licenseState}),{...m,fallbackChain:i}}catch(m){if(m?.name==="AbortError"||r?.signal?.aborted)throw m;switch(_e(m)){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"),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(ne(c,m));break;default:i.push(ne(c,m));break}}}throw new q(i)}async stream(e,t,r){let s=randomUUID(),i=He(t),a=Be(e),o=Date.now(),l=[],d=null,c=null;for(let h of i){let g=h.type;if(this.getHealthStatus(g)==="unhealthy"){l.push(`${g}:skipped:unhealthy`);continue}if(a&&!h.supportsMultimodal){l.push(`${g}:skipped:no_multimodal`);continue}if(!h.supportsStreaming){l.push(`${g}:skipped:no_streaming`);continue}let C=re(e.model);if(C&&C!==g&&Fe.has(g)){l.push(`${g}:skipped:wrong_provider`);continue}try{c=await h.streamRaw(e,{signal:r?.signal}),d=h,l.push(`${g}:success`);break}catch(E){if(E?.name==="AbortError"||r?.signal?.aborted)throw E;switch(_e(E)){case "rate_limited":h.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"),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(ne(g,E));break;default:l.push(ne(g,E));break}}}if(!d||!c)throw new q(l);let y=this,m=r?.maxMidStreamFailovers??2,_=new Set([d]);async function*u(){let h=d,g=c[Symbol.asyncIterator](),C={role:"assistant",content:[]},E={segments:[]},I=Ge(h.type);E.segments.push(I);let Re=0,z=null,X=false,de=m,O="",N="";for(y.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:h.type});;)try{for(;;){let A=await g.next();if(A.done)break;let T=A.value,k=Pt(T,Re,C,X,z);if(k.action==="suppress"){"coalesceMode"in k&&(z=k.coalesceMode),k.clearedJustFailedOver&&(X=!1);continue}k.coalesceModeCleared&&(z=null),k.clearedJustFailedOver&&(X=!1);let v=k.event;if(St(C,v),v.type==="message_start"){if(E.segments.length>1)continue;O=v.message?.model||O,v.message?.usage?.input_tokens!=null&&(I.inputTokens=v.message.usage.input_tokens);}if(v.type==="message_delta"&&(v.delta?.stop_reason&&(N=v.delta.stop_reason),v.usage)){Rt(I,h.type,v.usage),yield {...v,usage:void 0};continue}if(v.type==="message_stop")break;yield v;}if(C.content.length===0&&I.outputTokens===0)throw new Error("stream ended without producing any content");y.markHealthy(h.type),y.emitEngineEvent({kind:"segment_complete",callId:s,id:randomUUID(),ts:Date.now(),provider:h.type,usage:{...I}});let S=Ke(E.segments);yield {type:"message_delta",delta:{stop_reason:N||"end_turn"},usage:S},yield {type:"message_stop"},y.emitEngineEvent({kind:"stream_complete",callId:s,id:randomUUID(),ts:Date.now(),stitched:E.segments.length>1,segments:E.segments.map(A=>({...A})),provider:E.segments.map(A=>A.provider).join("+"),model:O,inputTokens:S.input_tokens,outputTokens:S.output_tokens,costUsd:E.segments.reduce((A,T)=>A+T.costUsd,0),userCostUsd:E.segments.reduce((A,T)=>A+T.userCostUsd,0),durationMs:Date.now()-o,stopReason:N||"end_turn",fallbackChain:l,rateLimitHit:!1,securityState:r?.licenseState});return}catch(S){if(S?.name==="AbortError"||r?.signal?.aborted)throw S;let A=_e(S);try{await g.return?.();}catch{}if(y.markUnhealthy(h.type,String(S)),y.emitEngineEvent({kind:"mid_stream_failover_attempt",callId:s,id:randomUUID(),ts:Date.now(),from:h.type,bytesBuffered:Ve(C),errorClass:A,retriesLeft:de}),l.push(`${h.type}:partial(${Ve(C)}b)`),de<=0)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;let T=kt(C.content),k=[...e.messages,{role:"assistant",content:T}],v=null,Q=null,Se=h;for(;;){let w=y.nextHealthyProvider(i,Se,a,_);if(!w)break;Se=w,_.add(w);let je={...e,messages:k,...w.type!=="anthropic-api"&&w.type!=="claude-cli"?{system:wt(e.system,"[SYSTEM]: CONTINUE_LAST_RESPONSE_WITHOUT_REPEATING")}:{}};try{Q=await w.streamRaw(je,{signal:r?.signal}),v=w;break}catch(Pe){y.markUnhealthy(w.type,String(Pe)),l.push(`${w.type}:failed_connect:${String(Pe).slice(0,We)}`);}}if(!v||!Q)throw y.emitTerminalExhaustion(s,E,O,N,l,o,r?.licenseState),S;l.push(`${v.type}:stitched`),y.emitEngineEvent({kind:"mid_stream_failover_success",callId:s,id:randomUUID(),ts:Date.now(),from:h.type,to:v.type}),Re=It(C)+1,de--,h=v,g=Q[Symbol.asyncIterator](),X=true,z=null,I=Ge(h.type),E.segments.push(I),y.emitEngineEvent({kind:"segment_start",callId:s,id:randomUUID(),ts:Date.now(),provider:h.type});}}let f=u();return r?.licenseState==="SEC_DEGRADED"&&(f=Tt(f)),L(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=Ke(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 Ge(n){return {provider:n,inputTokens:0,outputTokens:0,costUsd:0,userCostUsd:0}}function Rt(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 Ke(n){return {input_tokens:n[n.length-1]?.inputTokens??0,output_tokens:n.reduce((e,t)=>e+t.outputTokens,0)}}function St(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 Pt(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 kt(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 wt(n,e){return n?`${n}
14
14
 
15
15
  ${e}`:e}function Ve(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 It(n){return Math.max(0,n.content.length-1)}async function*Tt(n){for await(let e of n)await new Promise(t=>setTimeout(t,50+Math.random()*50)),yield e;}ee();function se(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 ie(n){return (e,t)=>n.maxCostPerCall!==void 0&&t.estimatedCost>n.maxCostPerCall?"prefer-user":n.preferLocal?"ollama":"prefer-user"}var ve={"claude-opus-4":[15,75],"claude-sonnet-4":[3,15],"claude-haiku-4":[.8,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 ae(n){if(ve[n])return ve[n];for(let[e,t]of Object.entries(ve))if(n.startsWith(e))return t;return [3,15]}function oe(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]=ae(n.model),a=(t*s+r*i)/1e6;return {estimatedInputTokens:t,estimatedCost:Math.round(a*1e4)/1e4,model:n.model,provider:""}}var D=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 xt="https://api.inference-relay.com",Lt="/v1/validate",Mt=1440*60*1e3,Dt=10080*60*1e3,Ot=`-----BEGIN PUBLIC KEY-----
16
16
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzk88Bt9LZSmuSd8ulKqy
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inference-relay",
3
- "version": "1.4.2",
3
+ "version": "1.5.1",
4
4
  "private": false,
5
5
  "description": "Route AI inference to the user's existing subscription",
6
6
  "type": "module",
@@ -59,7 +59,7 @@
59
59
  "lint": "eslint src/",
60
60
  "typecheck": "tsc --noEmit",
61
61
  "clean": "rm -rf dist",
62
- "prepublishOnly": "echo '[publish] 1.4.2 release — guard intentionally relaxed for this publish' && exit 0"
62
+ "prepublishOnly": "echo '[publish] 1.5.1 release — guard intentionally relaxed for this publish' && exit 0"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@types/node": "^22.0.0",