xling 0.9.4 → 0.9.5

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.
@@ -1,4 +1,4 @@
1
- import{c as e,u as t}from"../../validators-C8tI-QBw.js";import"../../errors-Bjek6jHm.js";import"../../editor-BfE8c36f.js";import"../../config-FuKh2Fd0.js";import"../../fsStore-DVJLVT4G.js";import"../../base-CEyMUsWC.js";import"../../template-DD8Cc4Zo.js";import"../../xling-BReZTlb3.js";import"../../loadBalancer-DUCjd5HG.js";import"../../errorClassifier-CXL0O9lB.js";import"../../transformer-CKTY0r0_.js";import{n,t as r}from"../../server-BlnCdJPS.js";import{Command as i,Flags as a}from"@oclif/core";var o=class o extends i{static summary=`Start an OpenAI-compatible proxy server with load balancing and key rotation`;static description=`Boot a local proxy server that forwards requests to configured upstream AI providers.
1
+ import{c as e,u as t}from"../../validators-C8tI-QBw.js";import"../../errors-Bjek6jHm.js";import"../../editor-BfE8c36f.js";import"../../config-FuKh2Fd0.js";import"../../fsStore-DVJLVT4G.js";import"../../base-CEyMUsWC.js";import"../../template-DD8Cc4Zo.js";import"../../xling-BReZTlb3.js";import"../../loadBalancer-DUCjd5HG.js";import"../../errorClassifier-CXL0O9lB.js";import"../../transformer-CKTY0r0_.js";import{a as n,t as r}from"../../server-Bt2qmyZ_.js";import{Command as i,Flags as a}from"@oclif/core";var o=class o extends i{static summary=`Start an OpenAI-compatible proxy server with load balancing and key rotation`;static description=`Boot a local proxy server that forwards requests to configured upstream AI providers.
2
2
 
3
3
  Features:
4
4
  - OpenAI-compatible API endpoints (/v1/chat/completions, /v1/messages, etc.)
@@ -1 +1 @@
1
- import{Command as e}from"@oclif/core";var t=`0.9.4`,n=class extends e{static summary=`Show the current xling version`;static description=`Displays the version from package.json.`;static examples=[{description:`Print the installed CLI version`,command:`<%= config.bin %> <%= command.id %>`},{description:`Shortcut using the built-in flag`,command:`<%= config.bin %> --version`}];async run(){this.log(t??`unknown`)}};export{n as default};
1
+ import{Command as e}from"@oclif/core";var t=`0.9.5`,n=class extends e{static summary=`Show the current xling version`;static description=`Displays the version from package.json.`;static examples=[{description:`Print the installed CLI version`,command:`<%= config.bin %> <%= command.id %>`},{description:`Shortcut using the built-in flag`,command:`<%= config.bin %> --version`}];async run(){this.log(t??`unknown`)}};export{n as default};
@@ -1 +1 @@
1
- import{p as e}from"./config-FuKh2Fd0.js";import{m as t}from"./fsStore-DVJLVT4G.js";import{t as n}from"./xling-BReZTlb3.js";import{t as r}from"./loadBalancer-DUCjd5HG.js";import{t as i}from"./errorClassifier-CXL0O9lB.js";import{c as a,i as o,l as s,n as c,o as l,r as u,s as d,t as f}from"./transformer-CKTY0r0_.js";import{watch as p}from"node:fs";const m=4320;function h(){return`req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}function g(e){if(typeof e==`string`)return e;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(e==null)return``;if(typeof e==`object`)try{return JSON.stringify(e)}catch{return`[object Object]`}return typeof e==`symbol`?e.toString():typeof e==`function`?e.name||`[function]`:``}async function _(e={}){let i=new n,a=i.resolvePath(`user`),o=i.readConfig(a);if(!o.providers?.length)throw Error(`No providers configured in ~/.claude/xling.json. Add a 'providers' array.`);let s=()=>o,c=o.proxy??{},l=e.host??c.host??`127.0.0.1`,u=e.port??c.port??m,d=e.accessKey??c.accessKey,f=new r(c.loadBalance??`failover`,c.keyRotation?.cooldownMs??6e4),h=Bun.serve({hostname:l,port:u,async fetch(t){let n=new URL(t.url).pathname;if(t.method===`OPTIONS`)return new Response(null,{status:204,headers:T()});if(n===`/health`||n===`/`){let e=s();return Response.json({status:`ok`,providers:e.providers.map(e=>e.name),loadBalance:e.proxy?.loadBalance??`failover`},{headers:T()})}if(n===`/stats`)return Response.json({stats:f.getStats()},{headers:T()});if(n===`/v1/models`||n===`/models`){let e=D(s().providers);return Response.json(e,{headers:T()})}if(d){let r=t.headers.get(`authorization`)?.replace(/^Bearer\s+/i,``);if(r!==d)return e.logger&&(console.log(`[auth] Access key validation failed for path: ${n}`),console.log(`[auth] Expected: ${d.slice(0,4)}...`),console.log(`[auth] Received: ${r?r.slice(0,4)+`...`:`(none)`}`)),Response.json({error:{message:`Invalid access key`,type:`auth_error`}},{status:401,headers:T()})}if(n.startsWith(`/v1/`)||n.startsWith(`/claude/`)||n.startsWith(`/openai/`)||n===`/responses`||n===`/messages`||n===`/chat/completions`){e.logger&&console.log(`[proxy] Handling request: ${t.method} ${n}`);let r=s();return v(t,n,{providers:r.providers,modelMapping:r.proxy?.modelMapping,defaultModel:r.defaultModel,passthroughResponsesAPI:r.proxy?.passthroughResponsesAPI,keyRotation:r.proxy?.keyRotation},f,e.logger??!0)}return e.logger&&console.log(`[proxy] 404 Not Found: ${t.method} ${n}`),Response.json({error:{message:`Not found`,type:`not_found`}},{status:404,headers:T()})}}),g=t(a),_=null;try{_=p(g,t=>{if(t===`change`)try{let t=i.readConfig(a);t.providers?.length&&(o=t,e.logger&&console.log(`[proxy] Config reloaded`))}catch(t){e.logger&&console.error(`[proxy] Failed to reload config:`,t)}})}catch(t){e.logger&&console.warn(`[proxy] Failed to watch config file:`,t)}return{baseUrl:`http://${l}:${u}`,providers:o.providers.map(e=>e.name),models:o.providers.flatMap(e=>e.models.map(t=>`${e.name},${t}`)),server:h,shutdown:async()=>{_?.close(),await h.stop()}}}async function v(t,n,r,a,c){let u={requestId:h(),startTime:Date.now(),retryCount:0},d=n;n.startsWith(`/claude/`)?d=n.replace(`/claude`,``):n.startsWith(`/openai/`)&&(d=n.replace(`/openai`,``)),d.startsWith(`/v1/v1/`)&&(d=d.replace(`/v1/v1/`,`/v1/`));let p;if(t.headers.get(`content-type`)?.includes(`application/json`))try{p=await t.json()}catch{return Response.json({error:{message:`Invalid JSON body`,type:`invalid_request`}},{status:400,headers:T()})}let m=o(p),_=l(p),v=p,D=!1,O=`openai`,k=b(p),A=x(k,r.modelMapping,r.defaultModel,r.providers);if(m&&p&&typeof p==`object`){let e=p;e.model=A||k,D=e.stream===!0,O=`anthropic`,v=f(e),(d===`/v1/messages`||d===`/messages`)&&(d=`/v1/chat/completions`),c&&console.log(`[${u.requestId}] Converting Anthropic -> OpenAI format (path: ${d})`)}else if(_&&p&&typeof p==`object`){let e=p;if(e.model=A||k,D=e.stream===!0,(r.passthroughResponsesAPI??[]).some(t=>t.endsWith(`*`)?String(e.model).startsWith(t.slice(0,-1)):e.model===t))O=`openai`,v=e,c&&console.log(`[${u.requestId}] Responses API passthrough (native support): model=${g(e.model)}`);else{if(O=`responses`,c){let t=g(e.model);if(console.log(`[${u.requestId}] Responses API request: stream=${D}, model=${t}`),e.tools){let t=e.tools;console.log(`[${u.requestId}] Tools count: ${t.length}`),t.slice(0,5).forEach((e,t)=>{let n=e,r=g(n.type),i=g(n.function?.name??n.name??`N/A`);console.log(`[${u.requestId}] Tool[${t}]: type=${r}, name=${i}, keys=${Object.keys(n).join(`,`)}`)})}else console.log(`[${u.requestId}] No tools in request`)}if(v=s(e),(d===`/v1/responses`||d===`/responses`)&&(d=`/v1/chat/completions`),c){console.log(`[${u.requestId}] Converting Responses API -> OpenAI format (path: ${d})`);let e=v?.tools;e?console.log(`[${u.requestId}] Converted tools count: ${e.length}`):console.log(`[${u.requestId}] No tools after conversion`)}}}else p&&typeof p==`object`&&A&&A!==k&&(p.model=A,v=p,D=p.stream===!0);let j=A,M=r.keyRotation?.enabled===!1?1:r.providers.length*2,N=null;for(;u.retryCount<M;){let n=w(r.providers,a,j);if(!n)return Response.json({error:{message:`No available providers`,type:`service_unavailable`}},{status:503,headers:T()});u.provider=n.name;let o=e(n),s=a.getProviderState(n.name),l=s?a.selectKey({...n,apiKeys:o},s):o[0];if(!l){u.retryCount++;continue}let f=o.indexOf(l);u.keyIndex=f,c&&(A&&A!==k&&console.log(`[${u.requestId}] Model mapped: ${k??`unknown`} -> ${A} (provider: ${n.name})`),console.log(`[${u.requestId}] -> ${n.name} (key ${f+1}/${o.length})`));try{let e=await y(t,n,l,d,v);if(e.ok){if(a.reportSuccess(n.name,f),c){let t=Date.now()-u.startTime;console.log(`[${u.requestId}] <- ${e.status} (${t}ms)`)}return O===`anthropic`?await S(e,k||`unknown`,D,c,u.requestId):O===`responses`?await C(e,k||`unknown`,D,c,u.requestId):E(e)}let o=await e.clone().json().catch(()=>null),s=i(e.status,o);if(a.reportError(n.name,f,s),c&&console.log(`[${u.requestId}] Error: ${s.type} - ${s.message}`),s.retryable&&r.keyRotation?.onError!==!1){u.retryCount++,N=e;continue}return E(e)}catch(e){let t=i(0,void 0,e);if(a.reportError(n.name,f,t),c&&console.log(`[${u.requestId}] Network error: ${t.message}`),t.retryable){u.retryCount++;continue}return Response.json({error:{message:t.message,type:t.type}},{status:502,headers:T()})}}return N?E(N):Response.json({error:{message:`All providers failed after retries`,type:`service_unavailable`}},{status:503,headers:T()})}async function y(e,t,n,r,i){let a=t.baseUrl.replace(/\/+$/,``),o=r;a.endsWith(`/v1`)&&r.startsWith(`/v1/`)&&(o=r.slice(3));let s=`${a}${o}`,c={"Content-Type":`application/json`,Authorization:`Bearer ${n}`};t.headers&&Object.assign(c,t.headers);for(let t of[`accept`,`accept-encoding`,`x-request-id`]){let n=e.headers.get(t);n&&(c[t]=n)}let l={method:e.method,headers:c};if(i&&e.method!==`GET`&&e.method!==`HEAD`&&(l.body=JSON.stringify(i)),t.timeout){let e=new AbortController,n=setTimeout(()=>e.abort(),t.timeout);l.signal=e.signal;try{let e=await fetch(s,l);return clearTimeout(n),e}catch(e){throw clearTimeout(n),e}}return fetch(s,l)}function b(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.model==`string`)return t.model}function x(e,t,n,r){if(!e)return n;if(!t||Object.keys(t).length===0)return e;if(t[e])return t[e];if(r?.some(t=>t.models.some(t=>t===e||e.startsWith(t))))return e;for(let[n,r]of Object.entries(t))if(n.endsWith(`*`)){let t=n.slice(0,-1);if(e.startsWith(t))return r}return t[`*`]?t[`*`]:n??e}async function S(e,t,n,r,i){if(n){r&&console.log(`[${i}] Converting streaming response OpenAI -> Anthropic`);let n=u(t),a=e.body?.pipeThrough(n);return new Response(a,{status:200,headers:{...T(),"Content-Type":`text/event-stream`,"Cache-Control":`no-cache, no-transform`,Connection:`keep-alive`,"X-Accel-Buffering":`no`}})}try{let n=await e.text(),a;try{a=JSON.parse(n)}catch{r&&console.log(`[${i}] Response is not JSON, wrapping as text`),a={content:n}}r&&console.log(`[${i}] Response type: ${typeof a}, keys: ${Object.keys(a).join(`, `)}`);let o=d(a,t);return r&&console.log(`[${i}] Converted response OpenAI -> Anthropic`),Response.json(o,{status:200,headers:T()})}catch(e){return console.error(`[${i}] Response conversion failed:`,e),Response.json({type:`error`,error:{type:`api_error`,message:`Response conversion failed: ${e.message}`}},{status:500,headers:T()})}}async function C(e,t,n,r,i){if(n){r&&console.log(`[${i}] Converting streaming response OpenAI -> Responses API`);let n=c(t),a=e.body?.pipeThrough(n);return new Response(a,{status:200,headers:{...T(),"Content-Type":`text/event-stream`,"Cache-Control":`no-cache, no-transform`,Connection:`keep-alive`,"X-Accel-Buffering":`no`}})}try{let n=await e.text(),o;try{o=JSON.parse(n)}catch{r&&console.log(`[${i}] Response is not JSON, wrapping as text`),o={content:n}}r&&console.log(`[${i}] Response type: ${typeof o}, keys: ${Object.keys(o).join(`, `)}`);let s=a(o,t);return r&&console.log(`[${i}] Converted response OpenAI -> Responses API`),Response.json(s,{status:200,headers:T()})}catch(e){return console.error(`[${i}] Response conversion failed:`,e),Response.json({id:`resp_${Date.now()}`,object:`response`,created_at:Math.floor(Date.now()/1e3),model:t,output:[],status:`failed`,error:{code:`api_error`,message:`Response conversion failed: ${e.message}`}},{status:500,headers:T()})}}function w(t,n,r){let i=t.map(t=>({...t,apiKeys:e(t)}));if(r?.includes(`,`)){let[e]=r.split(`,`),t=i.find(t=>t.name===e);if(t)return t}if(r){let e=i.filter(e=>e.models.some(e=>e===r||r.startsWith(e)));if(e.length>0)return n.selectProvider(e)}return n.selectProvider(i)}function T(){return{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`GET, POST, PUT, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, X-Request-ID`,"Access-Control-Max-Age":`86400`}}function E(e){let t=new Headers(e.headers);for(let[e,n]of Object.entries(T()))t.set(e,n);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function D(e){let t=Math.floor(Date.now()/1e3),n=[],r=new Set;for(let i of e)for(let e of i.models){let a=`${i.name},${e}`;r.has(a)||(r.add(a),n.push({id:a,object:`model`,created:t,owned_by:i.name})),r.has(e)||(r.add(e),n.push({id:e,object:`model`,created:t,owned_by:i.name}))}return{object:`list`,data:n}}export{_ as n,m as t};
1
+ import{p as e}from"./config-FuKh2Fd0.js";import{m as t}from"./fsStore-DVJLVT4G.js";import{t as n}from"./xling-BReZTlb3.js";import{t as r}from"./loadBalancer-DUCjd5HG.js";import{t as i}from"./errorClassifier-CXL0O9lB.js";import{c as a,i as o,l as s,n as c,o as l,r as u,s as d,t as f}from"./transformer-CKTY0r0_.js";import{watch as p}from"node:fs";const m=4320;function h(){return`req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}function g(e){if(typeof e==`string`)return e;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(e==null)return``;if(typeof e==`object`)try{return JSON.stringify(e)}catch{return`[object Object]`}return typeof e==`symbol`?e.toString():typeof e==`function`?e.name||`[function]`:``}async function _(e={}){let i=new n,a=i.resolvePath(`user`),o=i.readConfig(a);if(!o.providers?.length)throw Error(`No providers configured in ~/.claude/xling.json. Add a 'providers' array.`);let s=()=>o,c=o.proxy??{},l=e.host??c.host??`127.0.0.1`,u=e.port??c.port??m,d=e.accessKey??c.accessKey,f=new r(c.loadBalance??`failover`,c.keyRotation?.cooldownMs??6e4),h=Bun.serve({hostname:l,port:u,async fetch(t){let n=new URL(t.url).pathname;if(t.method===`OPTIONS`)return new Response(null,{status:204,headers:E()});if(n===`/health`||n===`/`){let e=s();return Response.json({status:`ok`,providers:e.providers.map(e=>e.name),loadBalance:e.proxy?.loadBalance??`failover`},{headers:E()})}if(n===`/stats`)return Response.json({stats:f.getStats()},{headers:E()});if(n===`/v1/models`||n===`/models`){let e=O(s().providers);return Response.json(e,{headers:E()})}if(d){let r=t.headers.get(`authorization`)?.replace(/^Bearer\s+/i,``);if(r!==d)return e.logger&&(console.log(`[auth] Access key validation failed for path: ${n}`),console.log(`[auth] Expected: ${d.slice(0,4)}...`),console.log(`[auth] Received: ${r?r.slice(0,4)+`...`:`(none)`}`)),Response.json({error:{message:`Invalid access key`,type:`auth_error`}},{status:401,headers:E()})}if(n.startsWith(`/v1/`)||n.startsWith(`/claude/`)||n.startsWith(`/openai/`)||n===`/responses`||n===`/messages`||n===`/chat/completions`){e.logger&&console.log(`[proxy] Handling request: ${t.method} ${n}`);let r=s();return v(t,n,{providers:r.providers,modelMapping:r.proxy?.modelMapping,defaultModel:r.defaultModel,passthroughResponsesAPI:r.proxy?.passthroughResponsesAPI,keyRotation:r.proxy?.keyRotation},f,e.logger??!0)}return e.logger&&console.log(`[proxy] 404 Not Found: ${t.method} ${n}`),Response.json({error:{message:`Not found`,type:`not_found`}},{status:404,headers:E()})}}),g=t(a),_=null;try{_=p(g,t=>{if(t===`change`)try{let t=i.readConfig(a);t.providers?.length&&(o=t,e.logger&&console.log(`[proxy] Config reloaded`))}catch(t){e.logger&&console.error(`[proxy] Failed to reload config:`,t)}})}catch(t){e.logger&&console.warn(`[proxy] Failed to watch config file:`,t)}return{baseUrl:`http://${l}:${u}`,providers:o.providers.map(e=>e.name),models:o.providers.flatMap(e=>e.models.map(t=>`${e.name},${t}`)),server:h,shutdown:async()=>{_?.close(),await h.stop()}}}async function v(t,n,r,a,c){let u={requestId:h(),startTime:Date.now(),retryCount:0},d=n;n.startsWith(`/claude/`)?d=n.replace(`/claude`,``):n.startsWith(`/openai/`)&&(d=n.replace(`/openai`,``)),d.startsWith(`/v1/v1/`)&&(d=d.replace(`/v1/v1/`,`/v1/`));let p;if(t.headers.get(`content-type`)?.includes(`application/json`))try{p=await t.json()}catch{return Response.json({error:{message:`Invalid JSON body`,type:`invalid_request`}},{status:400,headers:E()})}let m=o(p),_=l(p),v=p,x=!1,O=`openai`,k=b(p),A=S(k,r.modelMapping,r.defaultModel,r.providers);if(m&&p&&typeof p==`object`){let e=p;e.model=A||k,x=e.stream===!0,O=`anthropic`,v=f(e),(d===`/v1/messages`||d===`/messages`)&&(d=`/v1/chat/completions`),c&&console.log(`[${u.requestId}] Converting Anthropic -> OpenAI format (path: ${d})`)}else if(_&&p&&typeof p==`object`){let e=p;if(e.model=A||k,x=e.stream===!0,(r.passthroughResponsesAPI??[]).some(t=>t.endsWith(`*`)?String(e.model).startsWith(t.slice(0,-1)):e.model===t))O=`openai`,v=e,c&&console.log(`[${u.requestId}] Responses API passthrough (native support): model=${g(e.model)}`);else{if(O=`responses`,c){let t=g(e.model);if(console.log(`[${u.requestId}] Responses API request: stream=${x}, model=${t}`),e.tools){let t=e.tools;console.log(`[${u.requestId}] Tools count: ${t.length}`),t.slice(0,5).forEach((e,t)=>{let n=e,r=g(n.type),i=g(n.function?.name??n.name??`N/A`);console.log(`[${u.requestId}] Tool[${t}]: type=${r}, name=${i}, keys=${Object.keys(n).join(`,`)}`)})}else console.log(`[${u.requestId}] No tools in request`)}if(v=s(e),(d===`/v1/responses`||d===`/responses`)&&(d=`/v1/chat/completions`),c){console.log(`[${u.requestId}] Converting Responses API -> OpenAI format (path: ${d})`);let e=v?.tools;e?console.log(`[${u.requestId}] Converted tools count: ${e.length}`):console.log(`[${u.requestId}] No tools after conversion`)}}}else p&&typeof p==`object`&&A&&A!==k&&(p.model=A,v=p,x=p.stream===!0);let j=A,M=r.keyRotation?.enabled===!1?1:r.providers.length*2,N=null;for(;u.retryCount<M;){let n=T(r.providers,a,j);if(!n)return Response.json({error:{message:`No available providers`,type:`service_unavailable`}},{status:503,headers:E()});u.provider=n.name;let o=e(n),s=a.getProviderState(n.name),l=s?a.selectKey({...n,apiKeys:o},s):o[0];if(!l){u.retryCount++;continue}let f=o.indexOf(l);u.keyIndex=f,c&&(A&&A!==k&&console.log(`[${u.requestId}] Model mapped: ${k??`unknown`} -> ${A} (provider: ${n.name})`),console.log(`[${u.requestId}] -> ${n.name} (key ${f+1}/${o.length})`));try{let e=await y(t,n,l,d,v);if(e.ok){if(a.reportSuccess(n.name,f),c){let t=Date.now()-u.startTime;console.log(`[${u.requestId}] <- ${e.status} (${t}ms)`)}return O===`anthropic`?await C(e,k||`unknown`,x,c,u.requestId):O===`responses`?await w(e,k||`unknown`,x,c,u.requestId):D(e)}let o=await e.clone().json().catch(()=>null),s=i(e.status,o);if(a.reportError(n.name,f,s),c&&console.log(`[${u.requestId}] Error: ${s.type} - ${s.message}`),s.retryable&&r.keyRotation?.onError!==!1){u.retryCount++,N=e;continue}return D(e)}catch(e){let t=i(0,void 0,e);if(a.reportError(n.name,f,t),c&&console.log(`[${u.requestId}] Network error: ${t.message}`),t.retryable){u.retryCount++;continue}return Response.json({error:{message:t.message,type:t.type}},{status:502,headers:E()})}}return N?D(N):Response.json({error:{message:`All providers failed after retries`,type:`service_unavailable`}},{status:503,headers:E()})}async function y(e,t,n,r,i){let a=t.baseUrl.replace(/\/+$/,``),o=r;a.endsWith(`/v1`)&&r.startsWith(`/v1/`)&&(o=r.slice(3));let s=`${a}${o}`,c={"Content-Type":`application/json`,Authorization:`Bearer ${n}`};t.headers&&Object.assign(c,t.headers);for(let t of[`accept`,`accept-encoding`,`x-request-id`]){let n=e.headers.get(t);n&&(c[t]=n)}let l={method:e.method,headers:c};if(i&&e.method!==`GET`&&e.method!==`HEAD`&&(l.body=JSON.stringify(i)),t.timeout){let e=new AbortController,n=setTimeout(()=>e.abort(),t.timeout);l.signal=e.signal;try{let e=await fetch(s,l);return clearTimeout(n),e}catch(e){throw clearTimeout(n),e}}return fetch(s,l)}function b(e){if(!e||typeof e!=`object`)return;let t=e;if(typeof t.model==`string`)return t.model}function x(e,t){return e.models.some(e=>e===t||t.startsWith(e)||e.startsWith(t))}function S(e,t,n,r){if(!e)return n;if(!t||Object.keys(t).length===0)return e;if(t[e])return t[e];for(let[n,r]of Object.entries(t))if(n!==`*`&&n.endsWith(`*`)){let t=n.slice(0,-1);if(e.startsWith(t))return r}return r?.some(t=>x(t,e))?e:t[`*`]?t[`*`]:n??e}async function C(e,t,n,r,i){if(n){r&&console.log(`[${i}] Converting streaming response OpenAI -> Anthropic`);let n=u(t),a=e.body?.pipeThrough(n);return new Response(a,{status:200,headers:{...E(),"Content-Type":`text/event-stream`,"Cache-Control":`no-cache, no-transform`,Connection:`keep-alive`,"X-Accel-Buffering":`no`}})}try{let n=await e.text(),a;try{a=JSON.parse(n)}catch{r&&console.log(`[${i}] Response is not JSON, wrapping as text`),a={content:n}}r&&console.log(`[${i}] Response type: ${typeof a}, keys: ${Object.keys(a).join(`, `)}`);let o=d(a,t);return r&&console.log(`[${i}] Converted response OpenAI -> Anthropic`),Response.json(o,{status:200,headers:E()})}catch(e){return console.error(`[${i}] Response conversion failed:`,e),Response.json({type:`error`,error:{type:`api_error`,message:`Response conversion failed: ${e.message}`}},{status:500,headers:E()})}}async function w(e,t,n,r,i){if(n){r&&console.log(`[${i}] Converting streaming response OpenAI -> Responses API`);let n=c(t),a=e.body?.pipeThrough(n);return new Response(a,{status:200,headers:{...E(),"Content-Type":`text/event-stream`,"Cache-Control":`no-cache, no-transform`,Connection:`keep-alive`,"X-Accel-Buffering":`no`}})}try{let n=await e.text(),o;try{o=JSON.parse(n)}catch{r&&console.log(`[${i}] Response is not JSON, wrapping as text`),o={content:n}}r&&console.log(`[${i}] Response type: ${typeof o}, keys: ${Object.keys(o).join(`, `)}`);let s=a(o,t);return r&&console.log(`[${i}] Converted response OpenAI -> Responses API`),Response.json(s,{status:200,headers:E()})}catch(e){return console.error(`[${i}] Response conversion failed:`,e),Response.json({id:`resp_${Date.now()}`,object:`response`,created_at:Math.floor(Date.now()/1e3),model:t,output:[],status:`failed`,error:{code:`api_error`,message:`Response conversion failed: ${e.message}`}},{status:500,headers:E()})}}function T(t,n,r){let i=t.map(t=>({...t,apiKeys:e(t)}));if(r?.includes(`,`)){let[e]=r.split(`,`),t=i.find(t=>t.name===e);if(t)return t}if(r){let e=i.filter(e=>x(e,r));if(e.length>0)return n.selectProvider(e)}return n.selectProvider(i)}function E(){return{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`GET, POST, PUT, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, X-Request-ID`,"Access-Control-Max-Age":`86400`}}function D(e){let t=new Headers(e.headers);for(let[e,n]of Object.entries(E()))t.set(e,n);return new Response(e.body,{status:e.status,statusText:e.statusText,headers:t})}function O(e){let t=Math.floor(Date.now()/1e3),n=[],r=new Set;for(let i of e)for(let e of i.models){let a=`${i.name},${e}`;r.has(a)||(r.add(a),n.push({id:a,object:`model`,created:t,owned_by:i.name})),r.has(e)||(r.add(e),n.push({id:e,object:`model`,created:t,owned_by:i.name}))}return{object:`list`,data:n}}export{_ as a,T as i,S as n,x as r,m as t};
@@ -0,0 +1,27 @@
1
+ import { m as ProviderConfig } from "./config-CZ03ghwF.js";
2
+ import { c as ProxyServerContext, l as ProxyServerOptions } from "./types-BUZTxIIw.js";
3
+ import { t as ProxyLoadBalancer } from "./loadBalancer-CvpnwHns.js";
4
+
5
+ //#region src/services/proxy/server.d.ts
6
+ declare const DEFAULT_PROXY_PORT = 4320;
7
+ /**
8
+ * Start the proxy server
9
+ */
10
+ declare function startProxyServer(options?: ProxyServerOptions): Promise<ProxyServerContext>;
11
+ /**
12
+ * Check whether a provider model is compatible with the requested model.
13
+ * Supports both directions so versioned aliases still match (e.g. foo-2025
14
+ * matches foo and foo matches foo-2025).
15
+ */
16
+ declare function providerSupportsModel(provider: ProviderConfig, model: string): boolean;
17
+ /**
18
+ * Map model name using modelMapping config
19
+ * Supports exact match, prefix match (claude-* -> gpt-4o), and wildcard (*)
20
+ */
21
+ declare function mapModel(model: string | undefined, mapping?: Record<string, string>, defaultModel?: string, providers?: ProviderConfig[]): string | undefined;
22
+ /**
23
+ * Select provider for the requested model
24
+ */
25
+ declare function selectProviderForModel(providers: ProviderConfig[], loadBalancer: ProxyLoadBalancer, model?: string): ProviderConfig | null;
26
+ //#endregion
27
+ export { startProxyServer as a, selectProviderForModel as i, mapModel as n, providerSupportsModel as r, DEFAULT_PROXY_PORT as t };
@@ -2,5 +2,5 @@ import "../../config-CZ03ghwF.js";
2
2
  import { a as ProxyErrorType, c as ProxyServerContext, d as UpstreamResponse, i as ProxyError, l as ProxyServerOptions, n as LoadBalancer, r as ProviderState, s as ProxyRequestContext, t as KeyState, u as UpstreamRequestOptions } from "../../types-BUZTxIIw.js";
3
3
  import { i as shouldRotateKey, r as isRetryable, t as classifyError } from "../../errorClassifier-BGYR4YzP.js";
4
4
  import { t as ProxyLoadBalancer } from "../../loadBalancer-CvpnwHns.js";
5
- import { n as startProxyServer, t as DEFAULT_PROXY_PORT } from "../../server-Big8iXBi.js";
5
+ import { a as startProxyServer, t as DEFAULT_PROXY_PORT } from "../../server-CWmflSUF.js";
6
6
  export { DEFAULT_PROXY_PORT, type KeyState, type LoadBalancer, type ProviderState, type ProxyError, type ProxyErrorType, ProxyLoadBalancer, type ProxyRequestContext, type ProxyServerContext, type ProxyServerOptions, type UpstreamRequestOptions, type UpstreamResponse, classifyError, isRetryable, shouldRotateKey, startProxyServer };
@@ -1 +1 @@
1
- import"../../errors-Bjek6jHm.js";import"../../editor-BfE8c36f.js";import"../../config-FuKh2Fd0.js";import"../../fsStore-DVJLVT4G.js";import"../../base-CEyMUsWC.js";import"../../template-DD8Cc4Zo.js";import"../../xling-BReZTlb3.js";import{t as e}from"../../loadBalancer-DUCjd5HG.js";import{i as t,r as n,t as r}from"../../errorClassifier-CXL0O9lB.js";import"../../transformer-CKTY0r0_.js";import{n as i,t as a}from"../../server-BlnCdJPS.js";export{a as DEFAULT_PROXY_PORT,e as ProxyLoadBalancer,r as classifyError,n as isRetryable,t as shouldRotateKey,i as startProxyServer};
1
+ import"../../errors-Bjek6jHm.js";import"../../editor-BfE8c36f.js";import"../../config-FuKh2Fd0.js";import"../../fsStore-DVJLVT4G.js";import"../../base-CEyMUsWC.js";import"../../template-DD8Cc4Zo.js";import"../../xling-BReZTlb3.js";import{t as e}from"../../loadBalancer-DUCjd5HG.js";import{i as t,r as n,t as r}from"../../errorClassifier-CXL0O9lB.js";import"../../transformer-CKTY0r0_.js";import{a as i,t as a}from"../../server-Bt2qmyZ_.js";export{a as DEFAULT_PROXY_PORT,e as ProxyLoadBalancer,r as classifyError,n as isRetryable,t as shouldRotateKey,i as startProxyServer};
@@ -1,4 +1,5 @@
1
1
  import "../../config-CZ03ghwF.js";
2
2
  import "../../types-BUZTxIIw.js";
3
- import { n as startProxyServer, t as DEFAULT_PROXY_PORT } from "../../server-Big8iXBi.js";
4
- export { DEFAULT_PROXY_PORT, startProxyServer };
3
+ import "../../loadBalancer-CvpnwHns.js";
4
+ import { a as startProxyServer, i as selectProviderForModel, n as mapModel, r as providerSupportsModel, t as DEFAULT_PROXY_PORT } from "../../server-CWmflSUF.js";
5
+ export { DEFAULT_PROXY_PORT, mapModel, providerSupportsModel, selectProviderForModel, startProxyServer };
@@ -1 +1 @@
1
- import"../../errors-Bjek6jHm.js";import"../../editor-BfE8c36f.js";import"../../config-FuKh2Fd0.js";import"../../fsStore-DVJLVT4G.js";import"../../base-CEyMUsWC.js";import"../../template-DD8Cc4Zo.js";import"../../xling-BReZTlb3.js";import"../../loadBalancer-DUCjd5HG.js";import"../../errorClassifier-CXL0O9lB.js";import"../../transformer-CKTY0r0_.js";import{n as e,t}from"../../server-BlnCdJPS.js";export{t as DEFAULT_PROXY_PORT,e as startProxyServer};
1
+ import"../../errors-Bjek6jHm.js";import"../../editor-BfE8c36f.js";import"../../config-FuKh2Fd0.js";import"../../fsStore-DVJLVT4G.js";import"../../base-CEyMUsWC.js";import"../../template-DD8Cc4Zo.js";import"../../xling-BReZTlb3.js";import"../../loadBalancer-DUCjd5HG.js";import"../../errorClassifier-CXL0O9lB.js";import"../../transformer-CKTY0r0_.js";import{a as e,i as t,n,r,t as i}from"../../server-Bt2qmyZ_.js";export{i as DEFAULT_PROXY_PORT,n as mapModel,r as providerSupportsModel,t as selectProviderForModel,e as startProxyServer};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xling",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Unified CLI for managing AI tool settings",
5
5
  "homepage": "https://github.com/kingsword09/xling/tree/main#readme",
6
6
  "bugs": {
@@ -1,10 +0,0 @@
1
- import { c as ProxyServerContext, l as ProxyServerOptions } from "./types-BUZTxIIw.js";
2
-
3
- //#region src/services/proxy/server.d.ts
4
- declare const DEFAULT_PROXY_PORT = 4320;
5
- /**
6
- * Start the proxy server
7
- */
8
- declare function startProxyServer(options?: ProxyServerOptions): Promise<ProxyServerContext>;
9
- //#endregion
10
- export { startProxyServer as n, DEFAULT_PROXY_PORT as t };