@chenpu17/cc-gw 0.8.19 → 0.8.20

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.
Files changed (23) hide show
  1. package/package.json +5 -5
  2. package/src/web/dist/assets/{About-i7u6NHg9.js → About-E813AXIS.js} +1 -1
  3. package/src/web/dist/assets/{ApiKeys-Dor6MgN0.js → ApiKeys-CHoWjny5.js} +1 -1
  4. package/src/web/dist/assets/{ConfirmDialog-CPJRlYPi.js → ConfirmDialog-BuV2d3aQ.js} +1 -1
  5. package/src/web/dist/assets/{Dashboard-DgThbhmI.js → Dashboard-B0KXfDqB.js} +1 -1
  6. package/src/web/dist/assets/{Events-Bt9mPjdt.js → Events-CQ47M36I.js} +1 -1
  7. package/src/web/dist/assets/{Help-Cp7WK4jE.js → Help-DlkNELd-.js} +1 -1
  8. package/src/web/dist/assets/{Login-DdXAfpU_.js → Login-Cnx2XHdt.js} +1 -1
  9. package/src/web/dist/assets/{Logs-DOmV2017.js → Logs-MHwalvMS.js} +1 -1
  10. package/src/web/dist/assets/{ModelManagement-DestXjpI.js → ModelManagement-DBUODkXB.js} +1 -1
  11. package/src/web/dist/assets/{Profiler-CuJSuVJx.js → Profiler-C-LEcskT.js} +1 -1
  12. package/src/web/dist/assets/{RoutingManagement-DUYn00nU.js → RoutingManagement-CUzrRFdV.js} +1 -1
  13. package/src/web/dist/assets/{Settings-BXrnXhxH.js → Settings-kC8ItAD8.js} +1 -1
  14. package/src/web/dist/assets/{app-CSrXQQoX.js → app-BF0X4ljN.js} +2 -2
  15. package/src/web/dist/assets/{gateway-Du8IjjRN.js → gateway-Bo9FVYfn.js} +1 -1
  16. package/src/web/dist/assets/{landing-2m5QuvwF.js → landing-D5PpgO3n.js} +1 -1
  17. package/src/web/dist/assets/package-BeIzyZKv.js +1 -0
  18. package/src/web/dist/assets/{useApiQuery-CvFOQBkt.js → useApiQuery-DaxeBDln.js} +1 -1
  19. package/src/web/dist/assets/{useAppMutation-Db7I627Q.js → useAppMutation-C8scr-Sv.js} +1 -1
  20. package/src/web/dist/assets/{useModelManagementState-C-dnZNnf.js → useModelManagementState-B3Ht0eWY.js} +1 -1
  21. package/src/web/dist/index.html +1 -1
  22. package/src/web/dist/landing.html +2 -2
  23. package/src/web/dist/assets/package-jQyl_aXJ.js +0 -1
@@ -1,4 +1,4 @@
1
- import{B as v,c as p}from"./global-CsDL9Nt2.js";import{r as u,j as e,a6 as O,aa as T,ab as N,ac as g,ad as b,ae as w,P as L,af as P,ag as _,ah as K,ai as R,aj as E,ak as D,al as q,am as k,a9 as U,q as B}from"./vendor-DdPBfMMb.js";import{c as A}from"./clipboard-CALi6bTW.js";import{p as F}from"./package-jQyl_aXJ.js";const S="/assets/live-dashboard-B7vLOY_S.png",G="/assets/live-logs-PRpgTV6S.png",W="/assets/live-model-management-xkBDeuLk.png",Y="/assets/live-api-keys-CJUuaCev.png",H="/assets/live-events-D_njD291.png",C="/assets/live-en-dashboard-CJoX7IQT.png",$="/assets/live-en-logs-BGGL53ab.png",M="/assets/live-en-model-management-BpjNblfR.png",Q="/assets/live-en-api-keys-Bx8N-eoh.png",J="/assets/live-en-events-DJwaP-WW.png",j=F.version,Z=(l,r)=>r[l],s={nav:{why:{zh:"现状",en:"The mess"},how:{zh:"怎么用",en:"How"},debug:{zh:"排查",en:"Debug"},local:{zh:"本地优先",en:"Local-first"},start:{zh:"开始",en:"Start"},faq:{zh:"FAQ",en:"FAQ"}},ctaConsole:{zh:"打开控制台",en:"Open console"},ctaInstall:{zh:"立即安装",en:"Install now"},ctaPreview:{zh:"看看控制台长什么样",en:"Preview the console"},hero:{badge:{zh:"v"+j+" · Rust 内核 · 完全开源",en:"v"+j+" · Rust core · Open source"},h1Top:{zh:"你的 API Key",en:"Your API key"},h1Bottom:{zh:"不该躺在 30 个 .env 里",en:"shouldn’t live in 30 .env files"},lead:{zh:"cc-gw 在你的机器上跑一个本地网关。Claude Code、OpenAI SDK、Anthropic SDK 全部指向同一个地址。换模型、换 provider、查日志,再也不用翻业务代码。",en:"cc-gw runs a small gateway right on your machine. Point Claude Code, the OpenAI SDK, and the Anthropic SDK at one address — then swap models, switch providers, and trace requests without touching your app code."},note:{zh:"不需要本机有 Rust 环境,npm 自动拉对应平台的预编译二进制。",en:"No Rust toolchain needed — npm pulls the right prebuilt binary for your platform."},proof:[{zh:"一条命令装好,本机就能跑",en:"One command to install, runs on your laptop"},{zh:"客户端只改 baseURL,不动业务逻辑",en:"Clients only change baseURL — your code stays put"},{zh:"所有数据都在 ~/.cc-gw 下,不走云",en:"Everything lives under ~/.cc-gw — nothing leaves your box"}],works:{zh:"已经在以下客户端里跑通",en:"Tested with"}},why:{eyebrow:{zh:"现状",en:"The mess"},title:{zh:"AI 接进来不难,难的是接进来之后",en:"Wiring up AI is easy. Living with it isn’t."},description:{zh:"你大概率已经踩过下面这三件事里的至少两件。这就是为什么有了 cc-gw。",en:"You’ve probably hit at least two of these. That’s why cc-gw exists."},cards:[{title:{zh:"Key 散在各个 .env 里",en:"Keys scattered across .env files"},body:{zh:"每个项目自己一份 baseURL、自己一份 key、自己一份模型名。时间一长,没人敢动,也没人记得清。",en:"Every project keeps its own baseURL, its own key, its own model name. Six months in, nobody dares touch it."},sample:`OPENAI_BASE_URL=https://...
1
+ import{B as v,c as p}from"./global-CsDL9Nt2.js";import{r as u,j as e,a6 as O,aa as T,ab as N,ac as g,ad as b,ae as w,P as L,af as P,ag as _,ah as K,ai as R,aj as E,ak as D,al as q,am as k,a9 as U,q as B}from"./vendor-DdPBfMMb.js";import{c as A}from"./clipboard-CALi6bTW.js";import{p as F}from"./package-BeIzyZKv.js";const S="/assets/live-dashboard-B7vLOY_S.png",G="/assets/live-logs-PRpgTV6S.png",W="/assets/live-model-management-xkBDeuLk.png",Y="/assets/live-api-keys-CJUuaCev.png",H="/assets/live-events-D_njD291.png",C="/assets/live-en-dashboard-CJoX7IQT.png",$="/assets/live-en-logs-BGGL53ab.png",M="/assets/live-en-model-management-BpjNblfR.png",Q="/assets/live-en-api-keys-Bx8N-eoh.png",J="/assets/live-en-events-DJwaP-WW.png",j=F.version,Z=(l,r)=>r[l],s={nav:{why:{zh:"现状",en:"The mess"},how:{zh:"怎么用",en:"How"},debug:{zh:"排查",en:"Debug"},local:{zh:"本地优先",en:"Local-first"},start:{zh:"开始",en:"Start"},faq:{zh:"FAQ",en:"FAQ"}},ctaConsole:{zh:"打开控制台",en:"Open console"},ctaInstall:{zh:"立即安装",en:"Install now"},ctaPreview:{zh:"看看控制台长什么样",en:"Preview the console"},hero:{badge:{zh:"v"+j+" · Rust 内核 · 完全开源",en:"v"+j+" · Rust core · Open source"},h1Top:{zh:"你的 API Key",en:"Your API key"},h1Bottom:{zh:"不该躺在 30 个 .env 里",en:"shouldn’t live in 30 .env files"},lead:{zh:"cc-gw 在你的机器上跑一个本地网关。Claude Code、OpenAI SDK、Anthropic SDK 全部指向同一个地址。换模型、换 provider、查日志,再也不用翻业务代码。",en:"cc-gw runs a small gateway right on your machine. Point Claude Code, the OpenAI SDK, and the Anthropic SDK at one address — then swap models, switch providers, and trace requests without touching your app code."},note:{zh:"不需要本机有 Rust 环境,npm 自动拉对应平台的预编译二进制。",en:"No Rust toolchain needed — npm pulls the right prebuilt binary for your platform."},proof:[{zh:"一条命令装好,本机就能跑",en:"One command to install, runs on your laptop"},{zh:"客户端只改 baseURL,不动业务逻辑",en:"Clients only change baseURL — your code stays put"},{zh:"所有数据都在 ~/.cc-gw 下,不走云",en:"Everything lives under ~/.cc-gw — nothing leaves your box"}],works:{zh:"已经在以下客户端里跑通",en:"Tested with"}},why:{eyebrow:{zh:"现状",en:"The mess"},title:{zh:"AI 接进来不难,难的是接进来之后",en:"Wiring up AI is easy. Living with it isn’t."},description:{zh:"你大概率已经踩过下面这三件事里的至少两件。这就是为什么有了 cc-gw。",en:"You’ve probably hit at least two of these. That’s why cc-gw exists."},cards:[{title:{zh:"Key 散在各个 .env 里",en:"Keys scattered across .env files"},body:{zh:"每个项目自己一份 baseURL、自己一份 key、自己一份模型名。时间一长,没人敢动,也没人记得清。",en:"Every project keeps its own baseURL, its own key, its own model name. Six months in, nobody dares touch it."},sample:`OPENAI_BASE_URL=https://...
2
2
  ANTHROPIC_API_KEY=sk-ant-...
3
3
  MODEL=gpt-4o-2024-08-06`},{title:{zh:"出错只能猜",en:"Debugging is just guessing"},body:{zh:"是 payload 错?协议不对?上游挂了?key 被收回了?没有统一日志,只能 curl 一遍试一遍。",en:"Bad payload? Wrong protocol? Upstream down? Key revoked? Without one log to look at, you curl your way through every theory."},sample:`$ curl ... 401
4
4
  # 是 key 过期?还是 endpoint 写错了?
@@ -0,0 +1 @@
1
+ const o="0.8.20",s={version:o};export{s as p};
@@ -1 +1 @@
1
- import{aR as o}from"./vendor-DdPBfMMb.js";import{a as u}from"./query-QCek5MsK.js";import{r as s,t as i}from"./app-CSrXQQoX.js";function m(r,e,a){return u({queryKey:r,placeholderData:o,...a,queryFn:async()=>{try{return await s(e)}catch(t){throw i(t)}}})}export{m as u};
1
+ import{aR as o}from"./vendor-DdPBfMMb.js";import{a as u}from"./query-QCek5MsK.js";import{r as s,t as i}from"./app-BF0X4ljN.js";function m(r,e,a){return u({queryKey:r,placeholderData:o,...a,queryFn:async()=>{try{return await s(e)}catch(t){throw i(t)}}})}export{m as u};
@@ -1 +1 @@
1
- import{u as o,b as q}from"./query-QCek5MsK.js";import{u as x,t as y}from"./app-CSrXQQoX.js";function j({mutationFn:C,successToast:a,errorToast:p,invalidateKeys:n,onSuccess:m,onError:f,...M}){const Q=o(),{pushToast:A}=x();return q({...M,mutationFn:async t=>{try{return await C(t)}catch(u){throw y(u)}},onSuccess:async(t,u,w,h)=>{n!=null&&n.length&&await Promise.all(n.map(g=>Q.invalidateQueries({queryKey:g})));const i=a==null?void 0:a(t,u);i&&A({...i,variant:"success"}),await(m==null?void 0:m(t,u,w,h))},onError:async(t,u,w,h)=>{const i=p==null?void 0:p(t,u);i&&A({...i,variant:"error"}),await(f==null?void 0:f(t,u,w,h))}})}export{j as u};
1
+ import{u as o,b as q}from"./query-QCek5MsK.js";import{u as x,t as y}from"./app-BF0X4ljN.js";function j({mutationFn:C,successToast:a,errorToast:p,invalidateKeys:n,onSuccess:m,onError:f,...M}){const Q=o(),{pushToast:A}=x();return q({...M,mutationFn:async t=>{try{return await C(t)}catch(u){throw y(u)}},onSuccess:async(t,u,w,h)=>{n!=null&&n.length&&await Promise.all(n.map(g=>Q.invalidateQueries({queryKey:g})));const i=a==null?void 0:a(t,u);i&&A({...i,variant:"success"}),await(m==null?void 0:m(t,u,w,h))},onError:async(t,u,w,h)=>{const i=p==null?void 0:p(t,u);i&&A({...i,variant:"error"}),await(f==null?void 0:f(t,u,w,h))}})}export{j as u};
@@ -1 +1 @@
1
- import{r as m}from"./vendor-DdPBfMMb.js";import{u as Nt,a as Ut}from"./query-QCek5MsK.js";import{g as K,b as H,u as Vt,t as G,c as ie}from"./app-CSrXQQoX.js";import{g as I}from"./gateway-Du8IjjRN.js";import{q as U}from"./queryKeys-0HDa7byL.js";import{u as Ie}from"./useAppMutation-Db7I627Q.js";import{u as Qt}from"./useApiQuery-CvFOQBkt.js";import{u as zt}from"./i18n-C8tBby0x.js";const _={savePreset(n,i){return K(H.post(`/api/routing-presets/${n}`,{name:i}))},applyPreset(n,i){return K(H.post(`/api/routing-presets/${n}/apply`,{name:i}))},deletePreset(n,i){return K(H.delete(`/api/routing-presets/${n}/${encodeURIComponent(i)}`))},testProvider(n,i){return K(H.post(`/api/providers/${n}/test`,i??{}))}},tn=["claude-sonnet-4-5-20250929","claude-sonnet-4-5-20250929-thinking","claude-sonnet-4-20250514","claude-opus-4-1-20250805","claude-opus-4-1-20250805-thinking","claude-haiku-4-5-20251001","claude-haiku-4-5-20251001-thinking","claude-3-5-haiku-20241022"],nn=["gpt-4o-mini","gpt-4o","o4-mini","o4-large","gpt-5-codex"];function O(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():Math.random().toString(36).slice(2,10)}function J(n,i){var p;return(p=n==null?void 0:n.customEndpoints)!=null&&p.length?n.customEndpoints:i}function le(n){return n?Object.entries(n).map(([i,p])=>({id:O(),source:i,target:p})):[]}function ue(n,i){var v,f,g;if(!n)return{};const p={},d=n.endpointRouting??{};p.anthropic=le(((v=d.anthropic)==null?void 0:v.modelRoutes)??n.modelRoutes??{}),p.openai=le(((f=d.openai)==null?void 0:f.modelRoutes)??{});for(const y of J(n,i))(g=y.routing)!=null&&g.modelRoutes?p[y.id]=le(y.routing.modelRoutes):p[y.id]=[];return p}function Fe(n,i,p){var f,g,y;const d=J(n,i).find(F=>F.id===p);if(d)return((f=d.routing)==null?void 0:f.modelRoutes)??{};const v=n.endpointRouting??{};return p==="anthropic"?((g=v.anthropic)==null?void 0:g.modelRoutes)??n.modelRoutes??{}:p==="openai"?((y=v.openai)==null?void 0:y.modelRoutes)??{}:{}}function At(n){const i={};for(const p of n){const d=p.source.trim(),v=p.target.trim();d&&v&&(i[d]=v)}return i}function Le(n,i){return JSON.stringify(At(n))!==JSON.stringify(i)}function on(n,i){if(n==="anthropic")return!0;const p=i.find(d=>d.id===n);return p?p.paths&&p.paths.length>0?p.paths.some(d=>d.protocol==="anthropic"):p.protocol==="anthropic":!1}function sn(n,i,p){var v,f,g;if(!i)return;if(n==="anthropic"||n==="openai")return(f=(v=i.endpointRouting)==null?void 0:v[n])==null?void 0:f.validation;const d=J(i,p).find(y=>y.id===n);return(g=d==null?void 0:d.routing)==null?void 0:g.validation}function an(n,i,p){var v,f,g;if(!i)return;if(n==="anthropic"||n==="openai")return(f=(v=i.endpointRouting)==null?void 0:v[n])==null?void 0:f.compatibility;const d=J(i,p).find(y=>y.id===n);return(g=d==null?void 0:d.routing)==null?void 0:g.compatibility}function Kt(n,i){const p=[{key:"providers",label:n("modelManagement.tabs.providers"),description:n("modelManagement.tabs.providersDesc"),isSystem:!0,canDelete:!1},{key:"anthropic",label:n("modelManagement.tabs.anthropic"),description:n("modelManagement.tabs.anthropicDesc"),isSystem:!0,canDelete:!1,protocols:["anthropic"]},{key:"openai",label:n("modelManagement.tabs.openai"),description:n("modelManagement.tabs.openaiDesc"),isSystem:!0,canDelete:!1,protocols:["openai-auto","openai-chat","openai-responses"]}],d=i.map(v=>{let f=n("modelManagement.tabs.customEndpoint"),g=[];if(v.paths&&v.paths.length>0)f=`${n("modelManagement.tabs.customEndpoint")}: ${v.paths.map(y=>`${y.path} (${y.protocol})`).join(", ")}`,g=[...new Set(v.paths.map(y=>y.protocol))];else if(v.path){const y=v.protocol||"anthropic";f=`${n("modelManagement.tabs.customEndpoint")}: ${v.path} (${y})`,g=[y]}return{key:v.id,label:v.label||v.id,description:f,isSystem:!1,canDelete:v.deletable!==!1,protocols:g}});return[...p,...d]}function Ht(n){return n.label&&n.label.trim().length>0?`${n.label} (${n.id})`:n.id}function je(n,i){var d,v,f;const p={anthropic:((d=n.routingPresets)==null?void 0:d.anthropic)??[],openai:((v=n.routingPresets)==null?void 0:v.openai)??[]};for(const g of i){const y=(f=n.customEndpoints)==null?void 0:f.find(F=>F.id===g.id);p[g.id]=(y==null?void 0:y.routingPresets)??g.routingPresets??[]}return p}function rn(){var Te;const{t:n}=zt(),{pushToast:i}=Vt(),p=Nt(),d=Qt(U.config.full(),I.configRequest()),f=((Te=Ut({queryKey:U.customEndpoints.all(),queryFn:ie.list,refetchInterval:1e4}).data)==null?void 0:Te.endpoints)??[],g=m.useMemo(()=>Kt(n,f),[f,n]),[y,F]=m.useState("providers"),[l,k]=m.useState(null),[Be,W]=m.useState(!1),[X,Y]=m.useState("create"),[V,Z]=m.useState(void 0),[qe,ee]=m.useState(void 0),[Ne,de]=m.useState(null),[Ue,te]=m.useState(!1),[L,D]=m.useState({}),[Ve,T]=m.useState({}),[Qe,ce]=m.useState(null),[me,ne]=m.useState({}),[pe,fe]=m.useState({}),[ze,Q]=m.useState({}),[Ae,ge]=m.useState(null),[Ke,he]=m.useState(null),[He,ve]=m.useState(null),[Ge,ye]=m.useState(!1),[oe,Ee]=m.useState(null),[se,ae]=m.useState(!0),[be,Re]=m.useState({}),[_e,Se]=m.useState(null),[Je,Me]=m.useState(!1),[We,we]=m.useState(!1),[Xe,Ye]=m.useState({}),[Ze,et]=m.useState(null),[c,Ce]=m.useState(null),[tt,Pe]=m.useState(!1),[re,nt]=m.useState(""),[z,ot]=m.useState("all"),st=m.useMemo(()=>g.filter(e=>e.isSystem),[g]),at=m.useMemo(()=>g.filter(e=>!e.isSystem),[g]),rt=m.useMemo(()=>g.find(e=>e.key===y)??g[0]??null,[y,g]),x=(l==null?void 0:l.providers)??[],it=x.length,lt=m.useMemo(()=>x.filter(e=>{var a;if(!(z==="all"||(e.type??"custom")===z))return!1;const t=re.trim().toLowerCase();return t?[e.id,e.label??"",e.baseUrl,e.defaultModel??"",...((a=e.models)==null?void 0:a.map(r=>r.id))??[]].join(" ").toLowerCase().includes(t):!0}),[re,z,x]),N=m.useMemo(()=>[{key:"anthropic-beta",value:"claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",label:n("providers.testDialog.options.beta.label"),description:n("providers.testDialog.options.beta.description")}],[n]);m.useEffect(()=>{if(!d.data)return;const e=d.data;k(e),D(s=>{const t=ue(e,f);if(!s||Object.keys(s).length===0)return t;const o={...t};for(const[a,r]of Object.entries(s)){if(!(a in t))continue;const u=Fe(e,f,a);Le(r,u)&&(o[a]=r)}return o}),T({}),ne(je(e,f))},[d.data,f]),m.useEffect(()=>{!d.isError||!d.error||i({title:n("providers.toast.loadFailure",{message:d.error.message}),variant:"error"})},[d.error,d.isError,i,n]),m.useEffect(()=>{g.some(e=>e.key===y)||F("providers")},[y,g]);const ut=m.useMemo(()=>{const e=new Map;for(const s of x){if(!s.defaultModel||!s.models)continue;const t=s.models.find(o=>o.id===s.defaultModel);t&&e.set(s.id,Ht(t))}return e},[x]),dt=m.useMemo(()=>{const e=[],s=new Set;for(const t of x){const o=t.label&&t.label!==t.id?`${t.label} (${t.id})`:t.id,a=t.models??[];if(a.length>0)for(const u of a){const h=`${t.id}:${u.id}`;s.has(h)||(s.add(h),e.push({value:h,label:`${o} · ${u.label??u.id}`,providerId:t.id,providerLabel:o,modelId:u.id,modelLabel:u.label??u.id,kind:"model",isDefault:t.defaultModel===u.id}))}else if(t.defaultModel){const u=`${t.id}:${t.defaultModel}`;s.has(u)||(s.add(u),e.push({value:u,label:`${o} · ${t.defaultModel}`,providerId:t.id,providerLabel:o,modelId:t.defaultModel,modelLabel:t.defaultModel,kind:"model",isDefault:!0}))}const r=`${t.id}:*`;s.has(r)||(s.add(r),e.push({value:r,label:n("settings.routing.providerPassthroughOption",{provider:o}),providerId:t.id,providerLabel:o,modelId:"*",modelLabel:"*",kind:"passthrough"}))}for(const t of Object.values(L).flat()){const o=t.target.trim();o&&!s.has(o)&&(s.add(o),e.push({value:o,label:o,modelId:o,modelLabel:o,kind:"custom"}))}return e},[x,L,n]),ct=()=>{ee(void 0),te(!0)},mt=e=>{ee(e),te(!0)},pt=e=>l?Fe(l,f,e):{},ft=m.useMemo(()=>{const e={};for(const s of g){if(s.key==="providers")continue;const t=L[s.key]||[];e[s.key]=Le(t,pt(s.key))}return e},[l,f,L,g]),ke=(e,s)=>{ne(t=>({...t,[e]:s})),k(t=>{if(!t)return t;if(e==="anthropic"||e==="openai")return{...t,routingPresets:{...t.routingPresets,[e]:s}};const o=[...t.customEndpoints??[]],a=o.findIndex(r=>r.id===e);return a===-1?t:(o[a]={...o[a],routingPresets:s},{...t,customEndpoints:o})})},$=()=>l?!0:(i({title:n("settings.toast.missingConfig"),variant:"error"}),d.refetch(),!1),gt=(e,s)=>{fe(t=>({...t,[e]:s})),s.trim()&&Q(t=>({...t,[e]:null}))},ht=async e=>{if(!$())return;const s=(pe[e]??"").trim();if(!s){Q(t=>({...t,[e]:n("modelManagement.validation.presetName")}));return}if((me[e]??[]).some(t=>t.name.toLowerCase()===s.toLowerCase())){Q(t=>({...t,[e]:n("modelManagement.validation.presetDuplicate",{name:s})}));return}ge(e);try{const o=(await _.savePreset(e,s)).presets??[];ke(e,o),fe(a=>({...a,[e]:""})),Q(a=>({...a,[e]:null})),i({title:n("modelManagement.toast.presetSaved",{name:s}),variant:"success"})}catch(t){i({title:n("modelManagement.toast.presetSaveFailure",{message:t instanceof Error?t.message:"unknown"}),variant:"error"})}finally{ge(null),d.refetch()}},vt=async(e,s)=>{if($()){he({endpoint:e,name:s.name});try{const o=(await _.applyPreset(e,s.name)).config;if(o)k(o),D(ue(o,f)),ne(je(o,f));else{const a=s.modelRoutes??{};D(r=>({...r,[e]:Object.entries(a).map(([u,h])=>({id:O(),source:u,target:h}))})),k(r=>{var h,E,R,S;if(!r)return r;const u=(r.customEndpoints??[]).findIndex(b=>b.id===e);if(u!==-1){const b=[...r.customEndpoints??[]],M=b[u];return b[u]={...M,routing:{defaults:((h=M.routing)==null?void 0:h.defaults)??r.defaults,...M.routing??{},modelRoutes:a}},{...r,customEndpoints:b}}return e==="anthropic"||e==="openai"?{...r,endpointRouting:{...r.endpointRouting??{},[e]:{defaults:((R=(E=r.endpointRouting)==null?void 0:E[e])==null?void 0:R.defaults)??r.defaults,...((S=r.endpointRouting)==null?void 0:S[e])??{},modelRoutes:a}},modelRoutes:e==="anthropic"?a:r.modelRoutes??{}}:r})}e!=="anthropic"&&e!=="openai"&&await p.invalidateQueries({queryKey:U.customEndpoints.all()}),i({title:n("modelManagement.toast.presetApplySuccess",{name:s.name}),variant:"success"})}catch(t){i({title:n("modelManagement.toast.presetApplyFailure",{message:t instanceof Error?t.message:"unknown"}),variant:"error"})}finally{he(null),d.refetch()}}},yt=async(e,s)=>{if($()){ve({endpoint:e,name:s.name});try{const t=await _.deletePreset(e,s.name);ke(e,t.presets??[]),i({title:n("modelManagement.toast.presetDeleteSuccess",{name:s.name}),variant:"success"})}catch(t){i({title:n("modelManagement.toast.presetDeleteFailure",{message:t instanceof Error?t.message:"unknown"}),variant:"error"})}finally{ve(null),d.refetch()}}},Et=()=>{$()&&(Y("create"),Z(void 0),W(!0))},bt=e=>{$()&&(Y("edit"),Z(e),W(!0))},Rt=async e=>{if(!l)throw new Error(n("settings.toast.missingConfig"));const s=X==="create"?[...x,e]:x.map(o=>V&&o.id===V.id?{...e,id:V.id}:o),t={...l,providers:s};await I.saveConfig(t),k(t),D(ue(t,f)),d.refetch(),i({title:X==="create"?n("providers.toast.createSuccess",{name:e.label||e.id}):n("providers.toast.updateSuccess",{name:e.label||e.id}),variant:"success"})},St=async e=>{const s=f.find(t=>t.id===e);if(!(!s||s.deletable===!1))try{await ie.delete(e),await p.invalidateQueries({queryKey:U.customEndpoints.all()}),i({title:n("modelManagement.deleteEndpointSuccess"),variant:"success"}),y===e&&F("providers")}catch(t){const o=G(t);i({title:n("modelManagement.deleteEndpointError",{error:o.message}),variant:"error"})}},De=async(e,s)=>{de(e.id);try{const t=s&&(s.headers||s.query)?{headers:s.headers&&Object.keys(s.headers).length>0?s.headers:void 0,query:s.query&&s.query.trim().length>0?s.query.trim():void 0}:void 0,o=await _.testProvider(e.id,t);if(o.ok){i({title:n("providers.toast.testSuccess"),description:n("providers.toast.testSuccessDesc",{status:o.status,duration:o.durationMs?`${o.durationMs} ms`:"—"}),variant:"success"});return}i({title:n("providers.toast.testFailure",{message:`${o.status} ${o.statusText}`}),variant:"error"})}catch(t){const o=G(t);i({title:n("providers.toast.testFailure",{message:o.status?`${o.status} ${o.message}`:o.message}),variant:"error"})}finally{de(null)}},Mt=e=>{var u,h;if(!(!!((u=e.defaultModel)!=null&&u.trim())||!!((h=e.models)!=null&&h.some(E=>E.id.trim().length>0)))){Se(e);return}if(e.type!=="anthropic"){De(e);return}const t=e.extraHeaders??{},o=new Map(N.map(E=>[E.key.toLowerCase(),E])),a={};let r=!0;for(const E of N){const R=Object.entries(t).find(([M])=>M.toLowerCase()===E.key.toLowerCase());if(!R)continue;const[S,b]=R;String(b??"")!==E.value&&(r=!1,a[S]=String(b??""))}for(const[E,R]of Object.entries(t))o.has(E.toLowerCase())||(a[E]=String(R??""));Re(a),ae(r),Ee(e),ye(!0)},xe=()=>{ye(!1),Ee(null),ae(!0),Re({})},wt=async()=>{if(!oe)return;const e={};if(se)for(const o of N)e[o.key]=o.value;const s=new Map(N.map(o=>[o.key.toLowerCase(),o]));for(const[o,a]of Object.entries(be))s.get(o.toLowerCase())&&se||(e[o]=a);const t=oe;xe(),await De(t,{headers:Object.keys(e).length>0?e:void 0})},Oe=async e=>{var E,R,S,b,M,P,j,A;if(!$())return;const s=x.filter(w=>w.id!==e.id),t=w=>{const C={};if(!w)return C;for(const[B,q]of Object.entries(w)){if(!q)continue;const[$e]=q.split(":");$e&&$e===e.id||q===e.id||(C[B]=q)}return C},o=(l==null?void 0:l.endpointRouting)??{},a=t(((E=o.anthropic)==null?void 0:E.modelRoutes)??(l==null?void 0:l.modelRoutes)??{}),r=t(((R=o.openai)==null?void 0:R.modelRoutes)??{}),u=((l==null?void 0:l.customEndpoints)??f).map(w=>{const C=w.routing,B=C==null?void 0:C.modelRoutes;return B?{...w,routing:{...C,defaults:C.defaults??l.defaults,modelRoutes:t(B)}}:w}),h={...l,providers:s,modelRoutes:a,customEndpoints:u,endpointRouting:{anthropic:{defaults:((S=o.anthropic)==null?void 0:S.defaults)??l.defaults,modelRoutes:a,validation:(b=o.anthropic)==null?void 0:b.validation,compatibility:(M=o.anthropic)==null?void 0:M.compatibility},openai:{defaults:((P=o.openai)==null?void 0:P.defaults)??l.defaults,modelRoutes:r,validation:(j=o.openai)==null?void 0:j.validation,compatibility:(A=o.openai)==null?void 0:A.compatibility}}};try{await I.saveConfig(h),k(h),D({anthropic:Object.entries(a).map(([w,C])=>({id:O(),source:w,target:C})),openai:Object.entries(r).map(([w,C])=>({id:O(),source:w,target:C})),...Object.fromEntries(u.map(w=>{var C;return[w.id,Object.entries(((C=w.routing)==null?void 0:C.modelRoutes)??{}).map(([B,q])=>({id:O(),source:B,target:q}))]}))}),i({title:n("providers.toast.deleteSuccess",{name:e.label||e.id}),variant:"success"}),d.refetch()}catch(w){i({title:n("providers.toast.deleteFailure",{message:w instanceof Error?w.message:"unknown"}),variant:"error"})}},Ct=async()=>{if(c){Pe(!0);try{c.kind==="provider"?await Oe(c.provider):c.kind==="preset"?await yt(c.endpoint,c.preset):await St(c.endpoint.id),Ce(null)}finally{Pe(!1)}}},Pt=e=>{D(s=>({...s,[e]:[...s[e]||[],{id:O(),source:"",target:""}]})),T(s=>({...s,[e]:null}))},kt=async(e,s)=>{var t,o;if($()){Me(!0);try{if(e==="anthropic"||e==="openai"){const a=e,r=l.endpointRouting?{...l.endpointRouting}:{},u=r[a]??{defaults:l.defaults,modelRoutes:(a==="anthropic"?l.modelRoutes:{})??{}},h={defaults:u.defaults??l.defaults,modelRoutes:u.modelRoutes??{},compatibility:u.compatibility},E=s==="off"?void 0:{...u.validation??{},mode:s,allowExperimentalBlocks:((t=u.validation)==null?void 0:t.allowExperimentalBlocks)??!0},R={...l,endpointRouting:{...r,[a]:E?{...h,validation:E}:{...h}}};await I.saveConfig(R),k(R)}else{const a=[...l.customEndpoints??[]],r=a.findIndex(S=>S.id===e);if(r===-1)throw new Error(n("modelManagement.toast.endpointNotFound"));const u=a[r],h=u.routing??{defaults:l.defaults,modelRoutes:{}},E=s==="off"?void 0:{...h.validation??{},mode:s,allowExperimentalBlocks:((o=h.validation)==null?void 0:o.allowExperimentalBlocks)??!0};a[r]={...u,routing:E?{...h,validation:E}:{defaults:h.defaults,modelRoutes:h.modelRoutes,compatibility:h.compatibility}};const R={...l,customEndpoints:a};await I.saveConfig(R),k(R)}i({title:n("modelManagement.toast.validationModeSaved",{mode:n(`modelManagement.claudeValidation.options.${s}.label`)}),variant:"success"}),d.refetch()}catch(a){const r=G(a);i({title:n("modelManagement.toast.validationModeFailure",{message:r.message}),variant:"error"})}finally{Me(!1)}}},Dt=async(e,s)=>{if($()){we(!0);try{if(e==="anthropic"||e==="openai"){const t=e,o=l.endpointRouting?{...l.endpointRouting}:{},a=o[t]??{defaults:l.defaults,modelRoutes:(t==="anthropic"?l.modelRoutes:{})??{}},r={defaults:a.defaults??l.defaults,modelRoutes:a.modelRoutes??{},validation:a.validation},u={...l,endpointRouting:{...o,[t]:s?{...r,compatibility:{enabled:!0}}:{...r}}};await I.saveConfig(u),k(u)}else{const t=[...l.customEndpoints??[]],o=t.findIndex(h=>h.id===e);if(o===-1)throw new Error(n("modelManagement.toast.endpointNotFound"));const a=t[o],r=a.routing??{defaults:l.defaults,modelRoutes:{}};t[o]={...a,routing:s?{...r,compatibility:{enabled:!0}}:{defaults:r.defaults,modelRoutes:r.modelRoutes,validation:r.validation}};const u={...l,customEndpoints:t};await I.saveConfig(u),k(u)}i({title:n("modelManagement.toast.compatibilitySaved",{state:n(s?"common.enabled":"common.disabled")}),variant:"success"}),d.refetch()}catch(t){const o=G(t);i({title:n("modelManagement.toast.compatibilitySaveFailure",{message:o.message}),variant:"error"})}finally{we(!1)}}},xt=(e,s)=>{D(t=>{const o=t[e]||[];return o.some(a=>a.source.trim()===s.trim())?t:{...t,[e]:[...o,{id:O(),source:s,target:""}]}}),T(t=>({...t,[e]:null}))},Ot=(e,s,t,o)=>{D(a=>({...a,[e]:(a[e]||[]).map(r=>r.id===s?{...r,[t]:o}:r)})),T(a=>({...a,[e]:null}))},Tt=(e,s)=>{D(t=>({...t,[e]:(t[e]||[]).filter(o=>o.id!==s)})),T(t=>({...t,[e]:null}))},$t=e=>{var t;if(!l)return;const s=(l.customEndpoints??f).find(o=>o.id===e);if(s)D(o=>{var a;return{...o,[e]:Object.entries(((a=s.routing)==null?void 0:a.modelRoutes)??{}).map(([r,u])=>({id:O(),source:r,target:u}))}});else{const o=l.endpointRouting??{},a=e,r=a==="anthropic"?l.modelRoutes??{}:{},u=((t=o[a])==null?void 0:t.modelRoutes)??r;D(h=>({...h,[e]:Object.entries(u).map(([E,R])=>({id:O(),source:E,target:R}))}))}T(o=>({...o,[e]:null}))},It=Ie({mutationFn:async e=>(await I.saveConfig(e.nextConfig),e)}),Ft=Ie({mutationFn:async e=>(await ie.update(e.endpoint,{routing:e.routing}),e)}),Lt=async e=>{var o,a,r,u,h,E,R;if(!$())return;const s=L[e]||[],t={};for(const S of s){const b=S.source.trim(),M=S.target.trim();if(!(!b&&!M)){if(!b||!M){T(P=>({...P,[e]:n("settings.validation.routePair")}));return}if(t[b]){T(P=>({...P,[e]:n("settings.validation.routeDuplicate",{model:b})}));return}t[b]=M}}T(S=>({...S,[e]:null})),ce(e);try{const S=f.find(b=>b.id===e);if(S){const b={...S.routing??{},modelRoutes:t,defaults:((o=S.routing)==null?void 0:o.defaults)||l.defaults};await Ft.mutateAsync({endpoint:e,routing:b}),k(M=>{if(!M)return M;const P=[...M.customEndpoints??[]],j=P.findIndex(A=>A.id===e);return j===-1?M:(P[j]={...P[j],routing:b},{...M,customEndpoints:P})}),await p.invalidateQueries({queryKey:U.customEndpoints.all()})}else{const b={...l,endpointRouting:{...l.endpointRouting??{},[e]:{defaults:((r=(a=l.endpointRouting)==null?void 0:a[e])==null?void 0:r.defaults)??l.defaults,modelRoutes:t,validation:(h=(u=l.endpointRouting)==null?void 0:u[e])==null?void 0:h.validation,compatibility:(R=(E=l.endpointRouting)==null?void 0:E[e])==null?void 0:R.compatibility}},modelRoutes:e==="anthropic"?t:l.modelRoutes??{}};await It.mutateAsync({endpoint:e,nextConfig:b}),k(b)}D(b=>({...b,[e]:Object.entries(t).map(([M,P])=>({id:O(),source:M,target:P}))})),i({title:n("modelManagement.toast.routesSaved"),variant:"success"}),d.refetch()}catch(S){i({title:n("modelManagement.toast.routesSaveFailure",{message:S instanceof Error?S.message:"unknown"}),variant:"error"})}finally{ce(null)}},jt=(c==null?void 0:c.kind)==="provider"?n("providers.actions.delete"):(c==null?void 0:c.kind)==="preset"?n("modelManagement.presets.delete"):(c==null?void 0:c.kind)==="endpoint"?n("common.delete"):"",Bt=(c==null?void 0:c.kind)==="provider"?n("providers.confirm.delete",{name:c.provider.label||c.provider.id}):(c==null?void 0:c.kind)==="preset"?n("modelManagement.confirm.deletePreset",{name:c.preset.name}):(c==null?void 0:c.kind)==="endpoint"?n("modelManagement.deleteEndpointConfirm",{label:c.endpoint.label}):"",qt=(c==null?void 0:c.kind)==="provider"?c.provider.label||c.provider.id:(c==null?void 0:c.kind)==="preset"?c.preset.name:(c==null?void 0:c.kind)==="endpoint"?c.endpoint.label:"";return{activeTab:y,activeTabInfo:rt,anthropicTestHeaderOptions:N,applyingPreset:Ke,config:l,configQuery:d,confirmAction:c,confirmDialogDescription:Bt,confirmDialogName:qt,confirmDialogTitle:jt,confirmingAction:tt,customEndpoints:f,customTabs:at,defaultLabels:ut,deletingPreset:He,drawerMode:X,drawerOpen:Be,editingEndpoint:qe,editingProvider:V,endpointDrawerOpen:Ue,filteredProviders:lt,noModelDialogProvider:_e,handleAddRoute:Pt,handleAddSuggestion:xt,handleApplyPreset:vt,handleCompatibilityEnabledChange:Dt,handleConfirmDialog:Ct,handleDeleteProvider:Oe,handleOpenCreate:Et,handleOpenCreateEndpoint:ct,handleOpenEditEndpoint:mt,handleOpenEdit:bt,handlePresetNameChange:gt,handleProviderSubmit:Rt,handleRemoveRoute:Tt,handleResetRoutes:$t,handleRouteChange:Ot,handleSavePreset:ht,handleSaveRoutes:Lt,handleValidationModeChange:kt,initiateTestConnection:Mt,isDirtyByEndpoint:ft,presetDiffDialog:Ze,presetErrorByEndpoint:ze,presetNameByEndpoint:pe,presetsByEndpoint:me,presetsExpanded:Xe,providerCount:it,providerModelOptions:dt,providerSearch:re,providerTypeFilter:z,providers:x,pushToast:i,routeError:Ve,routesByEndpoint:L,savingClaudeValidation:Je,savingCompatibilityPolicy:We,savingPresetFor:Ae,savingRouteFor:Qe,setActiveTab:F,setConfirmAction:Ce,setDrawerMode:Y,setDrawerOpen:W,setEditingEndpoint:ee,setEditingProvider:Z,setEndpointDrawerOpen:te,setNoModelDialogProvider:Se,setPresetDiffDialog:et,setPresetsExpanded:Ye,setProviderSearch:nt,setProviderTypeFilter:ot,setTestDialogUsePreset:ae,systemTabs:st,tabs:g,testDialogOpen:Ge,testDialogPreservedExtras:be,testDialogProvider:oe,testDialogUsePreset:se,testingProviderId:Ne,closeTestDialog:xe,confirmTestDialog:wt}}export{tn as C,nn as O,an as a,sn as g,on as i,rn as u};
1
+ import{r as m}from"./vendor-DdPBfMMb.js";import{u as Nt,a as Ut}from"./query-QCek5MsK.js";import{g as K,b as H,u as Vt,t as G,c as ie}from"./app-BF0X4ljN.js";import{g as I}from"./gateway-Bo9FVYfn.js";import{q as U}from"./queryKeys-0HDa7byL.js";import{u as Ie}from"./useAppMutation-C8scr-Sv.js";import{u as Qt}from"./useApiQuery-DaxeBDln.js";import{u as zt}from"./i18n-C8tBby0x.js";const _={savePreset(n,i){return K(H.post(`/api/routing-presets/${n}`,{name:i}))},applyPreset(n,i){return K(H.post(`/api/routing-presets/${n}/apply`,{name:i}))},deletePreset(n,i){return K(H.delete(`/api/routing-presets/${n}/${encodeURIComponent(i)}`))},testProvider(n,i){return K(H.post(`/api/providers/${n}/test`,i??{}))}},tn=["claude-sonnet-4-5-20250929","claude-sonnet-4-5-20250929-thinking","claude-sonnet-4-20250514","claude-opus-4-1-20250805","claude-opus-4-1-20250805-thinking","claude-haiku-4-5-20251001","claude-haiku-4-5-20251001-thinking","claude-3-5-haiku-20241022"],nn=["gpt-4o-mini","gpt-4o","o4-mini","o4-large","gpt-5-codex"];function O(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():Math.random().toString(36).slice(2,10)}function J(n,i){var p;return(p=n==null?void 0:n.customEndpoints)!=null&&p.length?n.customEndpoints:i}function le(n){return n?Object.entries(n).map(([i,p])=>({id:O(),source:i,target:p})):[]}function ue(n,i){var v,f,g;if(!n)return{};const p={},d=n.endpointRouting??{};p.anthropic=le(((v=d.anthropic)==null?void 0:v.modelRoutes)??n.modelRoutes??{}),p.openai=le(((f=d.openai)==null?void 0:f.modelRoutes)??{});for(const y of J(n,i))(g=y.routing)!=null&&g.modelRoutes?p[y.id]=le(y.routing.modelRoutes):p[y.id]=[];return p}function Fe(n,i,p){var f,g,y;const d=J(n,i).find(F=>F.id===p);if(d)return((f=d.routing)==null?void 0:f.modelRoutes)??{};const v=n.endpointRouting??{};return p==="anthropic"?((g=v.anthropic)==null?void 0:g.modelRoutes)??n.modelRoutes??{}:p==="openai"?((y=v.openai)==null?void 0:y.modelRoutes)??{}:{}}function At(n){const i={};for(const p of n){const d=p.source.trim(),v=p.target.trim();d&&v&&(i[d]=v)}return i}function Le(n,i){return JSON.stringify(At(n))!==JSON.stringify(i)}function on(n,i){if(n==="anthropic")return!0;const p=i.find(d=>d.id===n);return p?p.paths&&p.paths.length>0?p.paths.some(d=>d.protocol==="anthropic"):p.protocol==="anthropic":!1}function sn(n,i,p){var v,f,g;if(!i)return;if(n==="anthropic"||n==="openai")return(f=(v=i.endpointRouting)==null?void 0:v[n])==null?void 0:f.validation;const d=J(i,p).find(y=>y.id===n);return(g=d==null?void 0:d.routing)==null?void 0:g.validation}function an(n,i,p){var v,f,g;if(!i)return;if(n==="anthropic"||n==="openai")return(f=(v=i.endpointRouting)==null?void 0:v[n])==null?void 0:f.compatibility;const d=J(i,p).find(y=>y.id===n);return(g=d==null?void 0:d.routing)==null?void 0:g.compatibility}function Kt(n,i){const p=[{key:"providers",label:n("modelManagement.tabs.providers"),description:n("modelManagement.tabs.providersDesc"),isSystem:!0,canDelete:!1},{key:"anthropic",label:n("modelManagement.tabs.anthropic"),description:n("modelManagement.tabs.anthropicDesc"),isSystem:!0,canDelete:!1,protocols:["anthropic"]},{key:"openai",label:n("modelManagement.tabs.openai"),description:n("modelManagement.tabs.openaiDesc"),isSystem:!0,canDelete:!1,protocols:["openai-auto","openai-chat","openai-responses"]}],d=i.map(v=>{let f=n("modelManagement.tabs.customEndpoint"),g=[];if(v.paths&&v.paths.length>0)f=`${n("modelManagement.tabs.customEndpoint")}: ${v.paths.map(y=>`${y.path} (${y.protocol})`).join(", ")}`,g=[...new Set(v.paths.map(y=>y.protocol))];else if(v.path){const y=v.protocol||"anthropic";f=`${n("modelManagement.tabs.customEndpoint")}: ${v.path} (${y})`,g=[y]}return{key:v.id,label:v.label||v.id,description:f,isSystem:!1,canDelete:v.deletable!==!1,protocols:g}});return[...p,...d]}function Ht(n){return n.label&&n.label.trim().length>0?`${n.label} (${n.id})`:n.id}function je(n,i){var d,v,f;const p={anthropic:((d=n.routingPresets)==null?void 0:d.anthropic)??[],openai:((v=n.routingPresets)==null?void 0:v.openai)??[]};for(const g of i){const y=(f=n.customEndpoints)==null?void 0:f.find(F=>F.id===g.id);p[g.id]=(y==null?void 0:y.routingPresets)??g.routingPresets??[]}return p}function rn(){var Te;const{t:n}=zt(),{pushToast:i}=Vt(),p=Nt(),d=Qt(U.config.full(),I.configRequest()),f=((Te=Ut({queryKey:U.customEndpoints.all(),queryFn:ie.list,refetchInterval:1e4}).data)==null?void 0:Te.endpoints)??[],g=m.useMemo(()=>Kt(n,f),[f,n]),[y,F]=m.useState("providers"),[l,k]=m.useState(null),[Be,W]=m.useState(!1),[X,Y]=m.useState("create"),[V,Z]=m.useState(void 0),[qe,ee]=m.useState(void 0),[Ne,de]=m.useState(null),[Ue,te]=m.useState(!1),[L,D]=m.useState({}),[Ve,T]=m.useState({}),[Qe,ce]=m.useState(null),[me,ne]=m.useState({}),[pe,fe]=m.useState({}),[ze,Q]=m.useState({}),[Ae,ge]=m.useState(null),[Ke,he]=m.useState(null),[He,ve]=m.useState(null),[Ge,ye]=m.useState(!1),[oe,Ee]=m.useState(null),[se,ae]=m.useState(!0),[be,Re]=m.useState({}),[_e,Se]=m.useState(null),[Je,Me]=m.useState(!1),[We,we]=m.useState(!1),[Xe,Ye]=m.useState({}),[Ze,et]=m.useState(null),[c,Ce]=m.useState(null),[tt,Pe]=m.useState(!1),[re,nt]=m.useState(""),[z,ot]=m.useState("all"),st=m.useMemo(()=>g.filter(e=>e.isSystem),[g]),at=m.useMemo(()=>g.filter(e=>!e.isSystem),[g]),rt=m.useMemo(()=>g.find(e=>e.key===y)??g[0]??null,[y,g]),x=(l==null?void 0:l.providers)??[],it=x.length,lt=m.useMemo(()=>x.filter(e=>{var a;if(!(z==="all"||(e.type??"custom")===z))return!1;const t=re.trim().toLowerCase();return t?[e.id,e.label??"",e.baseUrl,e.defaultModel??"",...((a=e.models)==null?void 0:a.map(r=>r.id))??[]].join(" ").toLowerCase().includes(t):!0}),[re,z,x]),N=m.useMemo(()=>[{key:"anthropic-beta",value:"claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",label:n("providers.testDialog.options.beta.label"),description:n("providers.testDialog.options.beta.description")}],[n]);m.useEffect(()=>{if(!d.data)return;const e=d.data;k(e),D(s=>{const t=ue(e,f);if(!s||Object.keys(s).length===0)return t;const o={...t};for(const[a,r]of Object.entries(s)){if(!(a in t))continue;const u=Fe(e,f,a);Le(r,u)&&(o[a]=r)}return o}),T({}),ne(je(e,f))},[d.data,f]),m.useEffect(()=>{!d.isError||!d.error||i({title:n("providers.toast.loadFailure",{message:d.error.message}),variant:"error"})},[d.error,d.isError,i,n]),m.useEffect(()=>{g.some(e=>e.key===y)||F("providers")},[y,g]);const ut=m.useMemo(()=>{const e=new Map;for(const s of x){if(!s.defaultModel||!s.models)continue;const t=s.models.find(o=>o.id===s.defaultModel);t&&e.set(s.id,Ht(t))}return e},[x]),dt=m.useMemo(()=>{const e=[],s=new Set;for(const t of x){const o=t.label&&t.label!==t.id?`${t.label} (${t.id})`:t.id,a=t.models??[];if(a.length>0)for(const u of a){const h=`${t.id}:${u.id}`;s.has(h)||(s.add(h),e.push({value:h,label:`${o} · ${u.label??u.id}`,providerId:t.id,providerLabel:o,modelId:u.id,modelLabel:u.label??u.id,kind:"model",isDefault:t.defaultModel===u.id}))}else if(t.defaultModel){const u=`${t.id}:${t.defaultModel}`;s.has(u)||(s.add(u),e.push({value:u,label:`${o} · ${t.defaultModel}`,providerId:t.id,providerLabel:o,modelId:t.defaultModel,modelLabel:t.defaultModel,kind:"model",isDefault:!0}))}const r=`${t.id}:*`;s.has(r)||(s.add(r),e.push({value:r,label:n("settings.routing.providerPassthroughOption",{provider:o}),providerId:t.id,providerLabel:o,modelId:"*",modelLabel:"*",kind:"passthrough"}))}for(const t of Object.values(L).flat()){const o=t.target.trim();o&&!s.has(o)&&(s.add(o),e.push({value:o,label:o,modelId:o,modelLabel:o,kind:"custom"}))}return e},[x,L,n]),ct=()=>{ee(void 0),te(!0)},mt=e=>{ee(e),te(!0)},pt=e=>l?Fe(l,f,e):{},ft=m.useMemo(()=>{const e={};for(const s of g){if(s.key==="providers")continue;const t=L[s.key]||[];e[s.key]=Le(t,pt(s.key))}return e},[l,f,L,g]),ke=(e,s)=>{ne(t=>({...t,[e]:s})),k(t=>{if(!t)return t;if(e==="anthropic"||e==="openai")return{...t,routingPresets:{...t.routingPresets,[e]:s}};const o=[...t.customEndpoints??[]],a=o.findIndex(r=>r.id===e);return a===-1?t:(o[a]={...o[a],routingPresets:s},{...t,customEndpoints:o})})},$=()=>l?!0:(i({title:n("settings.toast.missingConfig"),variant:"error"}),d.refetch(),!1),gt=(e,s)=>{fe(t=>({...t,[e]:s})),s.trim()&&Q(t=>({...t,[e]:null}))},ht=async e=>{if(!$())return;const s=(pe[e]??"").trim();if(!s){Q(t=>({...t,[e]:n("modelManagement.validation.presetName")}));return}if((me[e]??[]).some(t=>t.name.toLowerCase()===s.toLowerCase())){Q(t=>({...t,[e]:n("modelManagement.validation.presetDuplicate",{name:s})}));return}ge(e);try{const o=(await _.savePreset(e,s)).presets??[];ke(e,o),fe(a=>({...a,[e]:""})),Q(a=>({...a,[e]:null})),i({title:n("modelManagement.toast.presetSaved",{name:s}),variant:"success"})}catch(t){i({title:n("modelManagement.toast.presetSaveFailure",{message:t instanceof Error?t.message:"unknown"}),variant:"error"})}finally{ge(null),d.refetch()}},vt=async(e,s)=>{if($()){he({endpoint:e,name:s.name});try{const o=(await _.applyPreset(e,s.name)).config;if(o)k(o),D(ue(o,f)),ne(je(o,f));else{const a=s.modelRoutes??{};D(r=>({...r,[e]:Object.entries(a).map(([u,h])=>({id:O(),source:u,target:h}))})),k(r=>{var h,E,R,S;if(!r)return r;const u=(r.customEndpoints??[]).findIndex(b=>b.id===e);if(u!==-1){const b=[...r.customEndpoints??[]],M=b[u];return b[u]={...M,routing:{defaults:((h=M.routing)==null?void 0:h.defaults)??r.defaults,...M.routing??{},modelRoutes:a}},{...r,customEndpoints:b}}return e==="anthropic"||e==="openai"?{...r,endpointRouting:{...r.endpointRouting??{},[e]:{defaults:((R=(E=r.endpointRouting)==null?void 0:E[e])==null?void 0:R.defaults)??r.defaults,...((S=r.endpointRouting)==null?void 0:S[e])??{},modelRoutes:a}},modelRoutes:e==="anthropic"?a:r.modelRoutes??{}}:r})}e!=="anthropic"&&e!=="openai"&&await p.invalidateQueries({queryKey:U.customEndpoints.all()}),i({title:n("modelManagement.toast.presetApplySuccess",{name:s.name}),variant:"success"})}catch(t){i({title:n("modelManagement.toast.presetApplyFailure",{message:t instanceof Error?t.message:"unknown"}),variant:"error"})}finally{he(null),d.refetch()}}},yt=async(e,s)=>{if($()){ve({endpoint:e,name:s.name});try{const t=await _.deletePreset(e,s.name);ke(e,t.presets??[]),i({title:n("modelManagement.toast.presetDeleteSuccess",{name:s.name}),variant:"success"})}catch(t){i({title:n("modelManagement.toast.presetDeleteFailure",{message:t instanceof Error?t.message:"unknown"}),variant:"error"})}finally{ve(null),d.refetch()}}},Et=()=>{$()&&(Y("create"),Z(void 0),W(!0))},bt=e=>{$()&&(Y("edit"),Z(e),W(!0))},Rt=async e=>{if(!l)throw new Error(n("settings.toast.missingConfig"));const s=X==="create"?[...x,e]:x.map(o=>V&&o.id===V.id?{...e,id:V.id}:o),t={...l,providers:s};await I.saveConfig(t),k(t),D(ue(t,f)),d.refetch(),i({title:X==="create"?n("providers.toast.createSuccess",{name:e.label||e.id}):n("providers.toast.updateSuccess",{name:e.label||e.id}),variant:"success"})},St=async e=>{const s=f.find(t=>t.id===e);if(!(!s||s.deletable===!1))try{await ie.delete(e),await p.invalidateQueries({queryKey:U.customEndpoints.all()}),i({title:n("modelManagement.deleteEndpointSuccess"),variant:"success"}),y===e&&F("providers")}catch(t){const o=G(t);i({title:n("modelManagement.deleteEndpointError",{error:o.message}),variant:"error"})}},De=async(e,s)=>{de(e.id);try{const t=s&&(s.headers||s.query)?{headers:s.headers&&Object.keys(s.headers).length>0?s.headers:void 0,query:s.query&&s.query.trim().length>0?s.query.trim():void 0}:void 0,o=await _.testProvider(e.id,t);if(o.ok){i({title:n("providers.toast.testSuccess"),description:n("providers.toast.testSuccessDesc",{status:o.status,duration:o.durationMs?`${o.durationMs} ms`:"—"}),variant:"success"});return}i({title:n("providers.toast.testFailure",{message:`${o.status} ${o.statusText}`}),variant:"error"})}catch(t){const o=G(t);i({title:n("providers.toast.testFailure",{message:o.status?`${o.status} ${o.message}`:o.message}),variant:"error"})}finally{de(null)}},Mt=e=>{var u,h;if(!(!!((u=e.defaultModel)!=null&&u.trim())||!!((h=e.models)!=null&&h.some(E=>E.id.trim().length>0)))){Se(e);return}if(e.type!=="anthropic"){De(e);return}const t=e.extraHeaders??{},o=new Map(N.map(E=>[E.key.toLowerCase(),E])),a={};let r=!0;for(const E of N){const R=Object.entries(t).find(([M])=>M.toLowerCase()===E.key.toLowerCase());if(!R)continue;const[S,b]=R;String(b??"")!==E.value&&(r=!1,a[S]=String(b??""))}for(const[E,R]of Object.entries(t))o.has(E.toLowerCase())||(a[E]=String(R??""));Re(a),ae(r),Ee(e),ye(!0)},xe=()=>{ye(!1),Ee(null),ae(!0),Re({})},wt=async()=>{if(!oe)return;const e={};if(se)for(const o of N)e[o.key]=o.value;const s=new Map(N.map(o=>[o.key.toLowerCase(),o]));for(const[o,a]of Object.entries(be))s.get(o.toLowerCase())&&se||(e[o]=a);const t=oe;xe(),await De(t,{headers:Object.keys(e).length>0?e:void 0})},Oe=async e=>{var E,R,S,b,M,P,j,A;if(!$())return;const s=x.filter(w=>w.id!==e.id),t=w=>{const C={};if(!w)return C;for(const[B,q]of Object.entries(w)){if(!q)continue;const[$e]=q.split(":");$e&&$e===e.id||q===e.id||(C[B]=q)}return C},o=(l==null?void 0:l.endpointRouting)??{},a=t(((E=o.anthropic)==null?void 0:E.modelRoutes)??(l==null?void 0:l.modelRoutes)??{}),r=t(((R=o.openai)==null?void 0:R.modelRoutes)??{}),u=((l==null?void 0:l.customEndpoints)??f).map(w=>{const C=w.routing,B=C==null?void 0:C.modelRoutes;return B?{...w,routing:{...C,defaults:C.defaults??l.defaults,modelRoutes:t(B)}}:w}),h={...l,providers:s,modelRoutes:a,customEndpoints:u,endpointRouting:{anthropic:{defaults:((S=o.anthropic)==null?void 0:S.defaults)??l.defaults,modelRoutes:a,validation:(b=o.anthropic)==null?void 0:b.validation,compatibility:(M=o.anthropic)==null?void 0:M.compatibility},openai:{defaults:((P=o.openai)==null?void 0:P.defaults)??l.defaults,modelRoutes:r,validation:(j=o.openai)==null?void 0:j.validation,compatibility:(A=o.openai)==null?void 0:A.compatibility}}};try{await I.saveConfig(h),k(h),D({anthropic:Object.entries(a).map(([w,C])=>({id:O(),source:w,target:C})),openai:Object.entries(r).map(([w,C])=>({id:O(),source:w,target:C})),...Object.fromEntries(u.map(w=>{var C;return[w.id,Object.entries(((C=w.routing)==null?void 0:C.modelRoutes)??{}).map(([B,q])=>({id:O(),source:B,target:q}))]}))}),i({title:n("providers.toast.deleteSuccess",{name:e.label||e.id}),variant:"success"}),d.refetch()}catch(w){i({title:n("providers.toast.deleteFailure",{message:w instanceof Error?w.message:"unknown"}),variant:"error"})}},Ct=async()=>{if(c){Pe(!0);try{c.kind==="provider"?await Oe(c.provider):c.kind==="preset"?await yt(c.endpoint,c.preset):await St(c.endpoint.id),Ce(null)}finally{Pe(!1)}}},Pt=e=>{D(s=>({...s,[e]:[...s[e]||[],{id:O(),source:"",target:""}]})),T(s=>({...s,[e]:null}))},kt=async(e,s)=>{var t,o;if($()){Me(!0);try{if(e==="anthropic"||e==="openai"){const a=e,r=l.endpointRouting?{...l.endpointRouting}:{},u=r[a]??{defaults:l.defaults,modelRoutes:(a==="anthropic"?l.modelRoutes:{})??{}},h={defaults:u.defaults??l.defaults,modelRoutes:u.modelRoutes??{},compatibility:u.compatibility},E=s==="off"?void 0:{...u.validation??{},mode:s,allowExperimentalBlocks:((t=u.validation)==null?void 0:t.allowExperimentalBlocks)??!0},R={...l,endpointRouting:{...r,[a]:E?{...h,validation:E}:{...h}}};await I.saveConfig(R),k(R)}else{const a=[...l.customEndpoints??[]],r=a.findIndex(S=>S.id===e);if(r===-1)throw new Error(n("modelManagement.toast.endpointNotFound"));const u=a[r],h=u.routing??{defaults:l.defaults,modelRoutes:{}},E=s==="off"?void 0:{...h.validation??{},mode:s,allowExperimentalBlocks:((o=h.validation)==null?void 0:o.allowExperimentalBlocks)??!0};a[r]={...u,routing:E?{...h,validation:E}:{defaults:h.defaults,modelRoutes:h.modelRoutes,compatibility:h.compatibility}};const R={...l,customEndpoints:a};await I.saveConfig(R),k(R)}i({title:n("modelManagement.toast.validationModeSaved",{mode:n(`modelManagement.claudeValidation.options.${s}.label`)}),variant:"success"}),d.refetch()}catch(a){const r=G(a);i({title:n("modelManagement.toast.validationModeFailure",{message:r.message}),variant:"error"})}finally{Me(!1)}}},Dt=async(e,s)=>{if($()){we(!0);try{if(e==="anthropic"||e==="openai"){const t=e,o=l.endpointRouting?{...l.endpointRouting}:{},a=o[t]??{defaults:l.defaults,modelRoutes:(t==="anthropic"?l.modelRoutes:{})??{}},r={defaults:a.defaults??l.defaults,modelRoutes:a.modelRoutes??{},validation:a.validation},u={...l,endpointRouting:{...o,[t]:s?{...r,compatibility:{enabled:!0}}:{...r}}};await I.saveConfig(u),k(u)}else{const t=[...l.customEndpoints??[]],o=t.findIndex(h=>h.id===e);if(o===-1)throw new Error(n("modelManagement.toast.endpointNotFound"));const a=t[o],r=a.routing??{defaults:l.defaults,modelRoutes:{}};t[o]={...a,routing:s?{...r,compatibility:{enabled:!0}}:{defaults:r.defaults,modelRoutes:r.modelRoutes,validation:r.validation}};const u={...l,customEndpoints:t};await I.saveConfig(u),k(u)}i({title:n("modelManagement.toast.compatibilitySaved",{state:n(s?"common.enabled":"common.disabled")}),variant:"success"}),d.refetch()}catch(t){const o=G(t);i({title:n("modelManagement.toast.compatibilitySaveFailure",{message:o.message}),variant:"error"})}finally{we(!1)}}},xt=(e,s)=>{D(t=>{const o=t[e]||[];return o.some(a=>a.source.trim()===s.trim())?t:{...t,[e]:[...o,{id:O(),source:s,target:""}]}}),T(t=>({...t,[e]:null}))},Ot=(e,s,t,o)=>{D(a=>({...a,[e]:(a[e]||[]).map(r=>r.id===s?{...r,[t]:o}:r)})),T(a=>({...a,[e]:null}))},Tt=(e,s)=>{D(t=>({...t,[e]:(t[e]||[]).filter(o=>o.id!==s)})),T(t=>({...t,[e]:null}))},$t=e=>{var t;if(!l)return;const s=(l.customEndpoints??f).find(o=>o.id===e);if(s)D(o=>{var a;return{...o,[e]:Object.entries(((a=s.routing)==null?void 0:a.modelRoutes)??{}).map(([r,u])=>({id:O(),source:r,target:u}))}});else{const o=l.endpointRouting??{},a=e,r=a==="anthropic"?l.modelRoutes??{}:{},u=((t=o[a])==null?void 0:t.modelRoutes)??r;D(h=>({...h,[e]:Object.entries(u).map(([E,R])=>({id:O(),source:E,target:R}))}))}T(o=>({...o,[e]:null}))},It=Ie({mutationFn:async e=>(await I.saveConfig(e.nextConfig),e)}),Ft=Ie({mutationFn:async e=>(await ie.update(e.endpoint,{routing:e.routing}),e)}),Lt=async e=>{var o,a,r,u,h,E,R;if(!$())return;const s=L[e]||[],t={};for(const S of s){const b=S.source.trim(),M=S.target.trim();if(!(!b&&!M)){if(!b||!M){T(P=>({...P,[e]:n("settings.validation.routePair")}));return}if(t[b]){T(P=>({...P,[e]:n("settings.validation.routeDuplicate",{model:b})}));return}t[b]=M}}T(S=>({...S,[e]:null})),ce(e);try{const S=f.find(b=>b.id===e);if(S){const b={...S.routing??{},modelRoutes:t,defaults:((o=S.routing)==null?void 0:o.defaults)||l.defaults};await Ft.mutateAsync({endpoint:e,routing:b}),k(M=>{if(!M)return M;const P=[...M.customEndpoints??[]],j=P.findIndex(A=>A.id===e);return j===-1?M:(P[j]={...P[j],routing:b},{...M,customEndpoints:P})}),await p.invalidateQueries({queryKey:U.customEndpoints.all()})}else{const b={...l,endpointRouting:{...l.endpointRouting??{},[e]:{defaults:((r=(a=l.endpointRouting)==null?void 0:a[e])==null?void 0:r.defaults)??l.defaults,modelRoutes:t,validation:(h=(u=l.endpointRouting)==null?void 0:u[e])==null?void 0:h.validation,compatibility:(R=(E=l.endpointRouting)==null?void 0:E[e])==null?void 0:R.compatibility}},modelRoutes:e==="anthropic"?t:l.modelRoutes??{}};await It.mutateAsync({endpoint:e,nextConfig:b}),k(b)}D(b=>({...b,[e]:Object.entries(t).map(([M,P])=>({id:O(),source:M,target:P}))})),i({title:n("modelManagement.toast.routesSaved"),variant:"success"}),d.refetch()}catch(S){i({title:n("modelManagement.toast.routesSaveFailure",{message:S instanceof Error?S.message:"unknown"}),variant:"error"})}finally{ce(null)}},jt=(c==null?void 0:c.kind)==="provider"?n("providers.actions.delete"):(c==null?void 0:c.kind)==="preset"?n("modelManagement.presets.delete"):(c==null?void 0:c.kind)==="endpoint"?n("common.delete"):"",Bt=(c==null?void 0:c.kind)==="provider"?n("providers.confirm.delete",{name:c.provider.label||c.provider.id}):(c==null?void 0:c.kind)==="preset"?n("modelManagement.confirm.deletePreset",{name:c.preset.name}):(c==null?void 0:c.kind)==="endpoint"?n("modelManagement.deleteEndpointConfirm",{label:c.endpoint.label}):"",qt=(c==null?void 0:c.kind)==="provider"?c.provider.label||c.provider.id:(c==null?void 0:c.kind)==="preset"?c.preset.name:(c==null?void 0:c.kind)==="endpoint"?c.endpoint.label:"";return{activeTab:y,activeTabInfo:rt,anthropicTestHeaderOptions:N,applyingPreset:Ke,config:l,configQuery:d,confirmAction:c,confirmDialogDescription:Bt,confirmDialogName:qt,confirmDialogTitle:jt,confirmingAction:tt,customEndpoints:f,customTabs:at,defaultLabels:ut,deletingPreset:He,drawerMode:X,drawerOpen:Be,editingEndpoint:qe,editingProvider:V,endpointDrawerOpen:Ue,filteredProviders:lt,noModelDialogProvider:_e,handleAddRoute:Pt,handleAddSuggestion:xt,handleApplyPreset:vt,handleCompatibilityEnabledChange:Dt,handleConfirmDialog:Ct,handleDeleteProvider:Oe,handleOpenCreate:Et,handleOpenCreateEndpoint:ct,handleOpenEditEndpoint:mt,handleOpenEdit:bt,handlePresetNameChange:gt,handleProviderSubmit:Rt,handleRemoveRoute:Tt,handleResetRoutes:$t,handleRouteChange:Ot,handleSavePreset:ht,handleSaveRoutes:Lt,handleValidationModeChange:kt,initiateTestConnection:Mt,isDirtyByEndpoint:ft,presetDiffDialog:Ze,presetErrorByEndpoint:ze,presetNameByEndpoint:pe,presetsByEndpoint:me,presetsExpanded:Xe,providerCount:it,providerModelOptions:dt,providerSearch:re,providerTypeFilter:z,providers:x,pushToast:i,routeError:Ve,routesByEndpoint:L,savingClaudeValidation:Je,savingCompatibilityPolicy:We,savingPresetFor:Ae,savingRouteFor:Qe,setActiveTab:F,setConfirmAction:Ce,setDrawerMode:Y,setDrawerOpen:W,setEditingEndpoint:ee,setEditingProvider:Z,setEndpointDrawerOpen:te,setNoModelDialogProvider:Se,setPresetDiffDialog:et,setPresetsExpanded:Ye,setProviderSearch:nt,setProviderTypeFilter:ot,setTestDialogUsePreset:ae,systemTabs:st,tabs:g,testDialogOpen:Ge,testDialogPreservedExtras:be,testDialogProvider:oe,testDialogUsePreset:se,testingProviderId:Ne,closeTestDialog:xe,confirmTestDialog:wt}}export{tn as C,nn as O,an as a,sn as g,on as i,rn as u};
@@ -8,7 +8,7 @@
8
8
  <link rel="apple-touch-icon" href="/cc-gw-mark.svg" />
9
9
  <link rel="manifest" href="/site.webmanifest" />
10
10
  <title>cc-gw 控制台</title>
11
- <script type="module" crossorigin src="/assets/app-CSrXQQoX.js"></script>
11
+ <script type="module" crossorigin src="/assets/app-BF0X4ljN.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="/assets/vendor-DdPBfMMb.js">
13
13
  <link rel="modulepreload" crossorigin href="/assets/global-CsDL9Nt2.js">
14
14
  <link rel="modulepreload" crossorigin href="/assets/query-QCek5MsK.js">
@@ -42,11 +42,11 @@
42
42
  }
43
43
  </script>
44
44
  <title>cc-gw | 你的 API Key 不该躺在 30 个 .env 里 · local-first AI gateway</title>
45
- <script type="module" crossorigin src="/assets/landing-2m5QuvwF.js"></script>
45
+ <script type="module" crossorigin src="/assets/landing-D5PpgO3n.js"></script>
46
46
  <link rel="modulepreload" crossorigin href="/assets/vendor-DdPBfMMb.js">
47
47
  <link rel="modulepreload" crossorigin href="/assets/global-CsDL9Nt2.js">
48
48
  <link rel="modulepreload" crossorigin href="/assets/clipboard-CALi6bTW.js">
49
- <link rel="modulepreload" crossorigin href="/assets/package-jQyl_aXJ.js">
49
+ <link rel="modulepreload" crossorigin href="/assets/package-BeIzyZKv.js">
50
50
  <link rel="stylesheet" crossorigin href="/assets/global-Dcdq4qY7.css">
51
51
  </head>
52
52
  <body class="bg-slate-50 text-slate-900">
@@ -1 +0,0 @@
1
- const o="0.8.19",s={version:o};export{s as p};